summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/javascript_builds.yml (renamed from .github/workflows/javascript_builds.disabled)6
-rw-r--r--.github/workflows/linux_builds.yml8
-rw-r--r--AUTHORS.md2
-rw-r--r--DONORS.md75
-rw-r--r--SConstruct15
-rw-r--r--core/SCsub1
-rw-r--r--core/config/engine.cpp5
-rw-r--r--core/config/engine.h3
-rw-r--r--core/config/project_settings.cpp8
-rw-r--r--core/core_bind.cpp3
-rw-r--r--core/core_constants.cpp2
-rw-r--r--core/crypto/crypto.h1
-rw-r--r--core/extension/SCsub7
-rw-r--r--core/extension/extension_api_dump.cpp805
-rw-r--r--core/extension/extension_api_dump.h45
-rw-r--r--core/extension/gdnative_interface.cpp694
-rw-r--r--core/extension/gdnative_interface.h438
-rw-r--r--core/extension/native_extension.cpp411
-rw-r--r--core/extension/native_extension.h94
-rw-r--r--core/extension/native_extension_manager.cpp130
-rw-r--r--core/extension/native_extension_manager.h (renamed from scene/3d/immediate_geometry_3d.h)59
-rw-r--r--core/input/gamecontrollerdb.txt104
-rw-r--r--core/input/godotcontrollerdb.txt2
-rw-r--r--core/input/input.cpp2
-rw-r--r--core/input/input_event.cpp18
-rw-r--r--core/input/input_map.cpp1
-rw-r--r--core/io/compression.cpp8
-rw-r--r--core/io/http_client_tcp.cpp1
-rw-r--r--core/io/image.cpp9
-rw-r--r--core/io/image.h4
-rw-r--r--core/io/multiplayer_api.cpp96
-rw-r--r--core/io/multiplayer_api.h16
-rw-r--r--core/io/multiplayer_peer.cpp (renamed from core/io/networked_multiplayer_peer.cpp)24
-rw-r--r--core/io/multiplayer_peer.h (renamed from core/io/networked_multiplayer_peer.h)12
-rw-r--r--core/io/tcp_server.cpp1
-rw-r--r--core/io/udp_server.cpp1
-rw-r--r--core/math/geometry_2d.h13
-rw-r--r--core/object/SCsub5
-rw-r--r--core/object/class_db.cpp51
-rw-r--r--core/object/class_db.h59
-rw-r--r--core/object/make_virtuals.py152
-rw-r--r--core/object/method_bind.cpp29
-rw-r--r--core/object/method_bind.h2
-rw-r--r--core/object/object.cpp98
-rw-r--r--core/object/object.h107
-rw-r--r--core/object/ref_counted.cpp19
-rw-r--r--core/object/ref_counted.h4
-rw-r--r--core/object/undo_redo.cpp14
-rw-r--r--core/os/memory.h2
-rw-r--r--core/os/os.h2
-rw-r--r--core/register_core_types.cpp184
-rw-r--r--core/register_core_types.h1
-rw-r--r--core/string/string_name.cpp108
-rw-r--r--core/string/string_name.h36
-rw-r--r--core/string/translation.cpp6
-rw-r--r--core/string/ustring.cpp19
-rw-r--r--core/templates/list.h77
-rw-r--r--core/templates/local_vector.h2
-rw-r--r--core/templates/map.h133
-rw-r--r--core/templates/pair.h40
-rw-r--r--core/templates/rid_owner.h42
-rw-r--r--core/templates/set.h79
-rw-r--r--core/templates/vector.h64
-rw-r--r--core/typedefs.h7
-rw-r--r--core/variant/binder_common.h2
-rw-r--r--core/variant/callable.cpp4
-rw-r--r--core/variant/callable.h1
-rw-r--r--core/variant/dictionary.cpp59
-rw-r--r--core/variant/method_ptrcall.h14
-rw-r--r--core/variant/variant.h6
-rw-r--r--core/variant/variant_call.cpp20
-rw-r--r--core/variant/variant_op.cpp4
-rw-r--r--core/variant/variant_op.h12
-rw-r--r--core/variant/variant_parser.cpp32
-rw-r--r--core/variant/variant_setget.cpp4
-rw-r--r--core/variant/variant_utility.cpp19
-rw-r--r--doc/classes/@GlobalScope.xml18
-rw-r--r--doc/classes/AcceptDialog.xml11
-rw-r--r--doc/classes/ArrayMesh.xml30
-rw-r--r--doc/classes/BaseButton.xml13
-rw-r--r--doc/classes/BaseMaterial3D.xml2
-rw-r--r--doc/classes/Button.xml3
-rw-r--r--doc/classes/CPUParticles2D.xml2
-rw-r--r--doc/classes/CPUParticles3D.xml4
-rw-r--r--doc/classes/Callable.xml7
-rw-r--r--doc/classes/Camera2D.xml18
-rw-r--r--doc/classes/Camera3D.xml4
-rw-r--r--doc/classes/CanvasLayer.xml3
-rw-r--r--doc/classes/CharacterBody2D.xml6
-rw-r--r--doc/classes/CharacterBody3D.xml3
-rw-r--r--doc/classes/CollisionObject2D.xml32
-rw-r--r--doc/classes/CollisionObject3D.xml14
-rw-r--r--doc/classes/Color.xml40
-rw-r--r--doc/classes/Control.xml134
-rw-r--r--doc/classes/CurveTexture.xml6
-rw-r--r--doc/classes/CurveXYZTexture.xml23
-rw-r--r--doc/classes/DirectionalLight3D.xml9
-rw-r--r--doc/classes/DisplayServer.xml69
-rw-r--r--doc/classes/EditorPlugin.xml2
-rw-r--r--doc/classes/EditorSpinSlider.xml3
-rw-r--r--doc/classes/File.xml1
-rw-r--r--doc/classes/HTTPClient.xml8
-rw-r--r--doc/classes/ImageTexture.xml4
-rw-r--r--doc/classes/ImmediateGeometry3D.xml113
-rw-r--r--doc/classes/ImmediateMesh.xml103
-rw-r--r--doc/classes/InputMap.xml9
-rw-r--r--doc/classes/Label.xml36
-rw-r--r--doc/classes/LineEdit.xml34
-rw-r--r--doc/classes/Mesh.xml6
-rw-r--r--doc/classes/MeshDataTool.xml2
-rw-r--r--doc/classes/MeshInstance3D.xml6
-rw-r--r--doc/classes/MultiplayerAPI.xml17
-rw-r--r--doc/classes/MultiplayerPeer.xml (renamed from doc/classes/NetworkedMultiplayerPeer.xml)12
-rw-r--r--doc/classes/NativeExtension.xml57
-rw-r--r--doc/classes/NativeExtensionManager.xml61
-rw-r--r--doc/classes/Node.xml18
-rw-r--r--doc/classes/Node2D.xml8
-rw-r--r--doc/classes/Node3D.xml5
-rw-r--r--doc/classes/NodePath.xml1
-rw-r--r--doc/classes/PacketPeerUDP.xml2
-rw-r--r--doc/classes/ParticlesMaterial.xml2
-rw-r--r--doc/classes/Performance.xml44
-rw-r--r--doc/classes/PhysicalBone3D.xml5
-rw-r--r--doc/classes/PhysicsServer2D.xml6
-rw-r--r--doc/classes/PhysicsServer3D.xml29
-rw-r--r--doc/classes/PhysicsShapeQueryParameters2D.xml2
-rw-r--r--doc/classes/PhysicsShapeQueryParameters3D.xml2
-rw-r--r--doc/classes/PhysicsShapeQueryResult2D.xml58
-rw-r--r--doc/classes/PhysicsShapeQueryResult3D.xml58
-rw-r--r--doc/classes/PhysicsTestMotionResult2D.xml6
-rw-r--r--doc/classes/PhysicsTestMotionResult3D.xml39
-rw-r--r--doc/classes/Plane.xml14
-rw-r--r--doc/classes/PlaneMesh.xml3
-rw-r--r--doc/classes/Polygon2D.xml5
-rw-r--r--doc/classes/Popup.xml1
-rw-r--r--doc/classes/PopupMenu.xml1
-rw-r--r--doc/classes/ProjectSettings.xml18
-rw-r--r--doc/classes/QuadMesh.xml3
-rw-r--r--doc/classes/Quaternion.xml32
-rw-r--r--doc/classes/RDPipelineSpecializationConstant.xml19
-rw-r--r--doc/classes/RandomNumberGenerator.xml12
-rw-r--r--doc/classes/ReflectionProbe.xml4
-rw-r--r--doc/classes/RenderingDevice.xml24
-rw-r--r--doc/classes/RenderingServer.xml2358
-rw-r--r--doc/classes/SceneTree.xml70
-rw-r--r--doc/classes/SoftBody3D.xml10
-rw-r--r--doc/classes/Sprite3D.xml6
-rw-r--r--doc/classes/StaticBody2D.xml3
-rw-r--r--doc/classes/StaticBody3D.xml3
-rw-r--r--doc/classes/SurfaceTool.xml2
-rw-r--r--doc/classes/TextEdit.xml16
-rw-r--r--doc/classes/TextServer.xml28
-rw-r--r--doc/classes/Theme.xml52
-rw-r--r--doc/classes/TileData.xml40
-rw-r--r--doc/classes/TileSet.xml34
-rw-r--r--doc/classes/Tree.xml59
-rw-r--r--doc/classes/TreeItem.xml8
-rw-r--r--doc/classes/Vector2.xml24
-rw-r--r--doc/classes/Vector2i.xml24
-rw-r--r--doc/classes/Vector3.xml24
-rw-r--r--doc/classes/Vector3i.xml24
-rw-r--r--doc/classes/Viewport.xml38
-rw-r--r--doc/classes/VisualShaderNode.xml1
-rw-r--r--doc/classes/VisualShaderNodeCurveTexture.xml3
-rw-r--r--doc/classes/VisualShaderNodeCurveXYZTexture.xml20
-rw-r--r--doc/classes/VisualShaderNodeResizableBase.xml2
-rw-r--r--doc/classes/VoxelGIData.xml6
-rw-r--r--doc/classes/Window.xml9
-rw-r--r--doc/classes/float.xml33
-rw-r--r--doc/classes/int.xml45
-rwxr-xr-xdoc/tools/makerst.py7
-rw-r--r--drivers/unix/ip_unix.cpp12
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp210
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h19
-rw-r--r--drivers/vulkan/vulkan_context.cpp119
-rw-r--r--drivers/vulkan/vulkan_context.h12
-rw-r--r--editor/action_map_editor.cpp62
-rw-r--r--editor/animation_bezier_editor.cpp50
-rw-r--r--editor/animation_track_editor.cpp290
-rw-r--r--editor/animation_track_editor_plugins.cpp130
-rw-r--r--editor/audio_stream_preview.cpp4
-rw-r--r--editor/audio_stream_preview.h9
-rw-r--r--editor/code_editor.cpp128
-rw-r--r--editor/code_editor.h2
-rw-r--r--editor/connections_dialog.cpp26
-rw-r--r--editor/create_dialog.cpp30
-rw-r--r--editor/debugger/editor_debugger_inspector.cpp8
-rw-r--r--editor/debugger/editor_debugger_node.cpp28
-rw-r--r--editor/debugger/editor_debugger_node.h2
-rw-r--r--editor/debugger/editor_debugger_tree.cpp10
-rw-r--r--editor/debugger/editor_network_profiler.cpp37
-rw-r--r--editor/debugger/editor_performance_profiler.cpp12
-rw-r--r--editor/debugger/editor_profiler.cpp31
-rw-r--r--editor/debugger/editor_visual_profiler.cpp33
-rw-r--r--editor/debugger/script_editor_debugger.cpp104
-rw-r--r--editor/dependency_editor.cpp28
-rw-r--r--editor/editor_about.cpp9
-rw-r--r--editor/editor_asset_installer.cpp102
-rw-r--r--editor/editor_asset_installer.h6
-rw-r--r--editor/editor_audio_buses.cpp92
-rw-r--r--editor/editor_autoload_settings.cpp26
-rw-r--r--editor/editor_data.cpp8
-rw-r--r--editor/editor_dir_dialog.cpp4
-rw-r--r--editor/editor_feature_profile.cpp4
-rw-r--r--editor/editor_file_dialog.cpp113
-rw-r--r--editor/editor_file_system.cpp30
-rw-r--r--editor/editor_fonts.cpp186
-rw-r--r--editor/editor_help.cpp82
-rw-r--r--editor/editor_help_search.cpp26
-rw-r--r--editor/editor_inspector.cpp201
-rw-r--r--editor/editor_inspector.h4
-rw-r--r--editor/editor_layouts_dialog.cpp4
-rw-r--r--editor/editor_log.cpp107
-rw-r--r--editor/editor_log.h2
-rw-r--r--editor/editor_node.cpp339
-rw-r--r--editor/editor_node.h8
-rw-r--r--editor/editor_path.cpp4
-rw-r--r--editor/editor_plugin.cpp14
-rw-r--r--editor/editor_plugin_settings.cpp19
-rw-r--r--editor/editor_properties.cpp703
-rw-r--r--editor/editor_properties.h61
-rw-r--r--editor/editor_properties_array_dict.cpp367
-rw-r--r--editor/editor_properties_array_dict.h34
-rw-r--r--editor/editor_resource_picker.cpp65
-rw-r--r--editor/editor_resource_picker.h4
-rw-r--r--editor/editor_resource_preview.cpp4
-rw-r--r--editor/editor_run_native.cpp2
-rw-r--r--editor/editor_sectioned_inspector.cpp4
-rw-r--r--editor/editor_settings.cpp17
-rw-r--r--editor/editor_spin_slider.cpp190
-rw-r--r--editor/editor_spin_slider.h15
-rw-r--r--editor/editor_themes.cpp12
-rw-r--r--editor/editor_vcs_interface.h20
-rw-r--r--editor/editor_zoom_widget.cpp96
-rw-r--r--editor/editor_zoom_widget.h2
-rw-r--r--editor/export_template_manager.cpp33
-rw-r--r--editor/export_template_manager.h2
-rw-r--r--editor/filesystem_dock.cpp199
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/find_in_files.cpp42
-rw-r--r--editor/groups_editor.cpp28
-rw-r--r--editor/icons/CenterView.svg1
-rw-r--r--editor/icons/ImmediateMesh.svg1
-rw-r--r--editor/icons/ORMMaterial3D.svg2
-rw-r--r--editor/icons/RectangleAddRemove.svg1
-rw-r--r--editor/icons/TileChecked.svg1
-rw-r--r--editor/icons/TileUnchecked.svg1
-rw-r--r--editor/icons/TripleBar.svg1
-rw-r--r--editor/import/resource_importer_wav.cpp2
-rw-r--r--editor/import/scene_import_settings.cpp50
-rw-r--r--editor/import/scene_importer_mesh.cpp2
-rw-r--r--editor/import_defaults_editor.cpp2
-rw-r--r--editor/import_dock.cpp8
-rw-r--r--editor/inspector_dock.cpp69
-rw-r--r--editor/localization_editor.cpp34
-rw-r--r--editor/node_3d_editor_gizmos.cpp30
-rw-r--r--editor/node_dock.cpp6
-rw-r--r--editor/plugin_config_dialog.cpp105
-rw-r--r--editor/plugin_config_dialog.h5
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp14
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp34
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp46
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp20
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp86
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp78
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp49
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp32
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp319
-rw-r--r--editor/plugins/collision_polygon_3d_editor_plugin.cpp98
-rw-r--r--editor/plugins/collision_polygon_3d_editor_plugin.h5
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/cpu_particles_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/curve_editor_plugin.cpp39
-rw-r--r--editor/plugins/editor_debugger_plugin.cpp8
-rw-r--r--editor/plugins/font_editor_plugin.cpp20
-rw-r--r--editor/plugins/font_editor_plugin.h2
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp10
-rw-r--r--editor/plugins/input_event_editor_plugin.cpp122
-rw-r--r--editor/plugins/input_event_editor_plugin.h79
-rw-r--r--editor/plugins/item_list_editor_plugin.cpp4
-rw-r--r--editor/plugins/lightmap_gi_editor_plugin.cpp2
-rw-r--r--editor/plugins/material_editor_plugin.cpp18
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp8
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp21
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h1
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp2
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp595
-rw-r--r--editor/plugins/node_3d_editor_plugin.h11
-rw-r--r--editor/plugins/occluder_instance_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/ot_features_plugin.cpp14
-rw-r--r--editor/plugins/ot_features_plugin.h2
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp20
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp18
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp40
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp14
-rw-r--r--editor/plugins/root_motion_editor_plugin.cpp8
-rw-r--r--editor/plugins/root_motion_editor_plugin.h2
-rw-r--r--editor/plugins/script_editor_plugin.cpp56
-rw-r--r--editor/plugins/script_text_editor.cpp79
-rw-r--r--editor/plugins/script_text_editor.h2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp26
-rw-r--r--editor/plugins/shader_editor_plugin.h2
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp12
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp22
-rw-r--r--editor/plugins/skeleton_ik_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp50
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp2
-rw-r--r--editor/plugins/style_box_editor_plugin.h2
-rw-r--r--editor/plugins/sub_viewport_preview_editor_plugin.cpp50
-rw-r--r--editor/plugins/sub_viewport_preview_editor_plugin.h56
-rw-r--r--editor/plugins/text_editor.cpp28
-rw-r--r--editor/plugins/text_editor.h2
-rw-r--r--editor/plugins/texture_3d_editor_plugin.cpp21
-rw-r--r--editor/plugins/texture_editor_plugin.cpp141
-rw-r--r--editor/plugins/texture_editor_plugin.h18
-rw-r--r--editor/plugins/texture_layered_editor_plugin.cpp69
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp16
-rw-r--r--editor/plugins/theme_editor_plugin.cpp539
-rw-r--r--editor/plugins/theme_editor_plugin.h57
-rw-r--r--editor/plugins/theme_editor_preview.cpp55
-rw-r--r--editor/plugins/theme_editor_preview.h8
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp222
-rw-r--r--editor/plugins/tiles/tile_atlas_view.h19
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp2470
-rw-r--r--editor/plugins/tiles/tile_data_editors.h359
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp104
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp1235
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h30
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp108
-rw-r--r--editor/plugins/tiles/tile_set_editor.h12
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp18
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp4
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp39
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp265
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h8
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.cpp13
-rw-r--r--editor/progress_dialog.cpp2
-rw-r--r--editor/project_export.cpp51
-rw-r--r--editor/project_manager.cpp66
-rw-r--r--editor/project_settings_editor.cpp14
-rw-r--r--editor/property_editor.cpp96
-rw-r--r--editor/property_selector.cpp73
-rw-r--r--editor/quick_open.cpp6
-rw-r--r--editor/rename_dialog.cpp18
-rw-r--r--editor/reparent_dialog.cpp2
-rw-r--r--editor/scene_tree_dock.cpp365
-rw-r--r--editor/scene_tree_dock.h10
-rw-r--r--editor/scene_tree_editor.cpp140
-rw-r--r--editor/scene_tree_editor.h3
-rw-r--r--editor/script_create_dialog.cpp90
-rw-r--r--editor/script_create_dialog.h2
-rw-r--r--editor/settings_config_dialog.cpp38
-rw-r--r--editor/shader_globals_editor.cpp13
-rw-r--r--editor/translations/af.po13
-rw-r--r--editor/translations/ar.po32
-rw-r--r--editor/translations/az.po23
-rw-r--r--editor/translations/bg.po13
-rw-r--r--editor/translations/bn.po23
-rw-r--r--editor/translations/br.po25
-rw-r--r--editor/translations/ca.po53
-rw-r--r--editor/translations/cs.po32
-rw-r--r--editor/translations/da.po23
-rw-r--r--editor/translations/de.po45
-rw-r--r--editor/translations/editor.pot13
-rw-r--r--editor/translations/el.po66
-rw-r--r--editor/translations/eo.po33
-rw-r--r--editor/translations/es.po90
-rw-r--r--editor/translations/es_AR.po35
-rw-r--r--editor/translations/et.po22
-rw-r--r--editor/translations/eu.po101
-rw-r--r--editor/translations/fa.po40
-rw-r--r--editor/translations/fi.po32
-rw-r--r--editor/translations/fil.po18
-rw-r--r--editor/translations/fr.po44
-rw-r--r--editor/translations/ga.po13
-rw-r--r--editor/translations/gl.po25
-rw-r--r--editor/translations/he.po21
-rw-r--r--editor/translations/hi.po21
-rw-r--r--editor/translations/hr.po21
-rw-r--r--editor/translations/hu.po25
-rw-r--r--editor/translations/id.po83
-rw-r--r--editor/translations/is.po13
-rw-r--r--editor/translations/it.po22
-rw-r--r--editor/translations/ja.po25
-rw-r--r--editor/translations/ka.po20
-rw-r--r--editor/translations/km.po13
-rw-r--r--editor/translations/ko.po37
-rw-r--r--editor/translations/lt.po16
-rw-r--r--editor/translations/lv.po22
-rw-r--r--editor/translations/mi.po13
-rw-r--r--editor/translations/mk.po13
-rw-r--r--editor/translations/ml.po13
-rw-r--r--editor/translations/mr.po13
-rw-r--r--editor/translations/ms.po23
-rw-r--r--editor/translations/nb.po23
-rw-r--r--editor/translations/nl.po22
-rw-r--r--editor/translations/or.po13
-rw-r--r--editor/translations/pl.po41
-rw-r--r--editor/translations/pr.po13
-rw-r--r--editor/translations/pt.po34
-rw-r--r--editor/translations/pt_BR.po41
-rw-r--r--editor/translations/ro.po25
-rw-r--r--editor/translations/ru.po45
-rw-r--r--editor/translations/si.po13
-rw-r--r--editor/translations/sk.po100
-rw-r--r--editor/translations/sl.po13
-rw-r--r--editor/translations/sq.po18
-rw-r--r--editor/translations/sr_Cyrl.po25
-rw-r--r--editor/translations/sr_Latn.po13
-rw-r--r--editor/translations/sv.po50
-rw-r--r--editor/translations/ta.po13
-rw-r--r--editor/translations/te.po13
-rw-r--r--editor/translations/th.po21
-rw-r--r--editor/translations/tr.po38
-rw-r--r--editor/translations/tt.po13
-rw-r--r--editor/translations/tzm.po13
-rw-r--r--editor/translations/uk.po35
-rw-r--r--editor/translations/ur_PK.po13
-rw-r--r--editor/translations/vi.po24
-rw-r--r--editor/translations/zh_CN.po128
-rw-r--r--editor/translations/zh_HK.po18
-rw-r--r--editor/translations/zh_TW.po30
-rw-r--r--main/main.cpp63
-rw-r--r--main/performance.cpp56
-rw-r--r--main/performance.h12
-rw-r--r--methods.py12
-rw-r--r--misc/dist/linux/godot.66
-rw-r--r--misc/dist/shell/_godot.zsh-completion2
-rw-r--r--misc/dist/shell/godot.bash-completion2
-rw-r--r--misc/dist/shell/godot.fish2
-rw-r--r--modules/basis_universal/register_types.cpp2
-rw-r--r--modules/bullet/godot_result_callbacks.cpp27
-rw-r--r--modules/bullet/godot_result_callbacks.h2
-rw-r--r--modules/bullet/space_bullet.cpp12
-rw-r--r--modules/csg/csg.cpp10
-rw-r--r--modules/csg/csg_shape.cpp36
-rw-r--r--modules/csg/register_types.cpp18
-rw-r--r--modules/enet/config.py2
-rw-r--r--modules/enet/doc_classes/ENetMultiplayerPeer.xml (renamed from modules/enet/doc_classes/NetworkedMultiplayerENet.xml)21
-rw-r--r--modules/enet/enet_multiplayer_peer.cpp (renamed from modules/enet/networked_multiplayer_enet.cpp)180
-rw-r--r--modules/enet/enet_multiplayer_peer.h (renamed from modules/enet/networked_multiplayer_enet.h)16
-rw-r--r--modules/enet/register_types.cpp4
-rw-r--r--modules/fbx/data/fbx_material.cpp4
-rw-r--r--modules/fbx/data/fbx_mesh_data.cpp4
-rw-r--r--modules/fbx/data/import_state.h1
-rw-r--r--modules/fbx/editor_scene_importer_fbx.h1
-rw-r--r--modules/fbx/register_types.cpp2
-rw-r--r--modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml2
-rw-r--r--modules/gdnative/gdnative_library_editor_plugin.cpp28
-rw-r--r--modules/gdnative/include/gdnative/variant.h2
-rw-r--r--modules/gdnative/include/net/godot_net.h2
-rw-r--r--modules/gdnative/include/net/godot_webrtc.h1
-rw-r--r--modules/gdnative/include/text/godot_text.h3
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp2
-rw-r--r--modules/gdnative/nativescript/godot_nativescript.cpp2
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp13
-rw-r--r--modules/gdnative/nativescript/register_types.cpp2
-rw-r--r--modules/gdnative/net/multiplayer_peer_gdnative.cpp6
-rw-r--r--modules/gdnative/net/multiplayer_peer_gdnative.h8
-rw-r--r--modules/gdnative/net/register_types.cpp6
-rw-r--r--modules/gdnative/pluginscript/register_types.cpp2
-rw-r--r--modules/gdnative/register_types.cpp4
-rw-r--r--modules/gdnative/text/text_server_gdnative.cpp11
-rw-r--r--modules/gdnative/text/text_server_gdnative.h4
-rw-r--r--modules/gdnative/videodecoder/register_types.cpp2
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp2
-rw-r--r--modules/gdnative/xr/register_types.cpp2
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp2
-rw-r--r--modules/gdscript/editor/gdscript_translation_parser_plugin.h1
-rw-r--r--modules/gdscript/gdscript.cpp14
-rw-r--r--modules/gdscript/gdscript.h1
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp4
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h2
-rw-r--r--modules/gdscript/gdscript_codegen.h2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp9
-rw-r--r--modules/gdscript/gdscript_editor.cpp6
-rw-r--r--modules/gdscript/gdscript_function.cpp4
-rw-r--r--modules/gdscript/gdscript_function.h4
-rw-r--r--modules/gdscript/gdscript_parser.cpp61
-rw-r--r--modules/gdscript/gdscript_parser.h3
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp4
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h12
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp6
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp10
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h1
-rw-r--r--modules/gdscript/register_types.cpp2
-rw-r--r--modules/gltf/editor_scene_importer_gltf.cpp22
-rw-r--r--modules/gltf/editor_scene_importer_gltf.h21
-rw-r--r--modules/gltf/gltf_document.cpp51
-rw-r--r--modules/gltf/gltf_document.h8
-rw-r--r--modules/gltf/gltf_state.h6
-rw-r--r--modules/gltf/register_types.cpp30
-rw-r--r--modules/gridmap/grid_map.cpp4
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp10
-rw-r--r--modules/gridmap/register_types.cpp2
-rw-r--r--modules/jsonrpc/register_types.cpp2
-rw-r--r--modules/lightmapper_rd/register_types.cpp2
-rw-r--r--modules/mbedtls/crypto_mbedtls.cpp7
-rw-r--r--modules/mbedtls/crypto_mbedtls.h1
-rw-r--r--modules/mbedtls/tests/test_crypto_mbedtls.cpp2
-rw-r--r--modules/minimp3/register_types.cpp2
-rw-r--r--modules/mobile_vr/register_types.cpp2
-rw-r--r--modules/mono/build_scripts/mono_configure.py6
-rw-r--r--modules/mono/csharp_script.cpp25
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs73
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs15
-rw-r--r--modules/mono/glue/base_object_glue.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h3
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp3
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp3
-rw-r--r--modules/mono/register_types.cpp4
-rw-r--r--modules/navigation/SCsub (renamed from modules/gdnavigation/SCsub)0
-rw-r--r--modules/navigation/config.py (renamed from modules/gdnavigation/config.py)0
-rw-r--r--modules/navigation/godot_navigation_server.cpp (renamed from modules/gdnavigation/gd_navigation_server.cpp)217
-rw-r--r--modules/navigation/godot_navigation_server.h (renamed from modules/gdnavigation/gd_navigation_server.h)24
-rw-r--r--modules/navigation/nav_map.cpp (renamed from modules/gdnavigation/nav_map.cpp)6
-rw-r--r--modules/navigation/nav_map.h (renamed from modules/gdnavigation/nav_map.h)0
-rw-r--r--modules/navigation/nav_region.cpp (renamed from modules/gdnavigation/nav_region.cpp)0
-rw-r--r--modules/navigation/nav_region.h (renamed from modules/gdnavigation/nav_region.h)0
-rw-r--r--modules/navigation/nav_rid.h (renamed from modules/gdnavigation/nav_rid.h)0
-rw-r--r--modules/navigation/nav_utils.h (renamed from modules/gdnavigation/nav_utils.h)0
-rw-r--r--modules/navigation/navigation_mesh_editor_plugin.cpp (renamed from modules/gdnavigation/navigation_mesh_editor_plugin.cpp)4
-rw-r--r--modules/navigation/navigation_mesh_editor_plugin.h (renamed from modules/gdnavigation/navigation_mesh_editor_plugin.h)0
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp (renamed from modules/gdnavigation/navigation_mesh_generator.cpp)2
-rw-r--r--modules/navigation/navigation_mesh_generator.h (renamed from modules/gdnavigation/navigation_mesh_generator.h)0
-rw-r--r--modules/navigation/register_types.cpp (renamed from modules/gdnavigation/register_types.cpp)20
-rw-r--r--modules/navigation/register_types.h (renamed from modules/gdnavigation/register_types.h)14
-rw-r--r--modules/navigation/rvo_agent.cpp (renamed from modules/gdnavigation/rvo_agent.cpp)0
-rw-r--r--modules/navigation/rvo_agent.h (renamed from modules/gdnavigation/rvo_agent.h)0
-rw-r--r--modules/opensimplex/noise_texture.cpp4
-rw-r--r--modules/opensimplex/register_types.cpp4
-rw-r--r--modules/pvr/image_compress_pvrtc.cpp4
-rw-r--r--modules/regex/register_types.cpp4
-rw-r--r--modules/stb_vorbis/register_types.cpp2
-rw-r--r--modules/text_server_adv/dynamic_font_adv.h1
-rw-r--r--modules/text_server_adv/text_server_adv.cpp164
-rw-r--r--modules/text_server_adv/text_server_adv.h2
-rw-r--r--modules/text_server_fb/dynamic_font_fb.h1
-rw-r--r--modules/text_server_fb/text_server_fb.cpp164
-rw-r--r--modules/text_server_fb/text_server_fb.h2
-rw-r--r--modules/theora/register_types.cpp2
-rw-r--r--modules/theora/video_stream_theora.cpp2
-rw-r--r--modules/upnp/register_types.cpp4
-rw-r--r--modules/vhacd/register_types.cpp8
-rw-r--r--modules/visual_script/doc_classes/VisualScriptExpression.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionCall.xml22
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionState.xml5
-rw-r--r--modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml3
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptInputAction.xml8
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLists.xml8
-rw-r--r--modules/visual_script/doc_classes/VisualScriptOperator.xml3
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertyGet.xml13
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertySet.xml25
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneTree.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSubCall.xml3
-rw-r--r--modules/visual_script/doc_classes/VisualScriptTypeCast.xml4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYield.xml7
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYieldSignal.xml9
-rw-r--r--modules/visual_script/register_types.cpp98
-rw-r--r--modules/visual_script/visual_script.cpp6
-rw-r--r--modules/visual_script/visual_script_editor.cpp245
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp28
-rw-r--r--modules/visual_script/visual_script_nodes.cpp115
-rw-r--r--modules/visual_script/visual_script_nodes.h2
-rw-r--r--modules/visual_script/visual_script_property_selector.cpp72
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp4
-rw-r--r--modules/webm/register_types.cpp2
-rw-r--r--modules/webrtc/config.py2
-rw-r--r--modules/webrtc/doc_classes/WebRTCDataChannel.xml7
-rw-r--r--modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml (renamed from modules/webrtc/doc_classes/WebRTCMultiplayer.xml)12
-rw-r--r--modules/webrtc/library_godot_webrtc.js13
-rw-r--r--modules/webrtc/register_types.cpp10
-rw-r--r--modules/webrtc/webrtc_data_channel.cpp1
-rw-r--r--modules/webrtc/webrtc_data_channel.h2
-rw-r--r--modules/webrtc/webrtc_data_channel_gdnative.cpp6
-rw-r--r--modules/webrtc/webrtc_data_channel_gdnative.h1
-rw-r--r--modules/webrtc/webrtc_data_channel_js.cpp5
-rw-r--r--modules/webrtc/webrtc_data_channel_js.h1
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp (renamed from modules/webrtc/webrtc_multiplayer.cpp)84
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.h (renamed from modules/webrtc/webrtc_multiplayer.h)14
-rw-r--r--modules/webrtc/webrtc_peer_connection_js.cpp11
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml4
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml10
-rw-r--r--modules/websocket/editor_debugger_server_websocket.cpp6
-rw-r--r--modules/websocket/editor_debugger_server_websocket.h9
-rw-r--r--modules/websocket/emws_client.cpp2
-rw-r--r--modules/websocket/emws_peer.cpp18
-rw-r--r--modules/websocket/register_types.cpp2
-rw-r--r--modules/websocket/remote_debugger_peer_websocket.h6
-rw-r--r--modules/websocket/websocket_client.cpp23
-rw-r--r--modules/websocket/websocket_multiplayer_peer.cpp12
-rw-r--r--modules/websocket/websocket_multiplayer_peer.h8
-rw-r--r--modules/websocket/websocket_server.cpp31
-rw-r--r--modules/websocket/websocket_server.h6
-rw-r--r--modules/websocket/wsl_client.cpp3
-rw-r--r--modules/websocket/wsl_server.cpp27
-rw-r--r--modules/websocket/wsl_server.h6
-rw-r--r--modules/webxr/register_types.cpp2
-rw-r--r--modules/webxr/webxr_interface_js.cpp33
-rw-r--r--modules/webxr/webxr_interface_js.h3
-rw-r--r--platform/android/api/api.cpp6
-rw-r--r--platform/android/display_server_android.cpp25
-rw-r--r--platform/android/display_server_android.h137
-rw-r--r--platform/android/export/export.cpp76
-rw-r--r--platform/android/export/gradle_export_util.h18
-rw-r--r--platform/android/java/app/AndroidManifest.xml5
-rw-r--r--platform/android/java/app/gradle.properties25
-rw-r--r--platform/android/java/build.gradle2
-rw-r--r--platform/android/java/gradle.properties6
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Dictionary.java16
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java163
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java22
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java16
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java16
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java23
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java14
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java117
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java58
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java18
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java6
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java1
-rw-r--r--platform/android/java_godot_lib_jni.cpp8
-rw-r--r--platform/android/plugin/godot_plugin_jni.cpp2
-rw-r--r--platform/android/vulkan/vulkan_context_android.cpp4
-rw-r--r--platform/android/vulkan/vulkan_context_android.h2
-rw-r--r--platform/iphone/display_server_iphone.h7
-rw-r--r--platform/iphone/display_server_iphone.mm24
-rw-r--r--platform/iphone/export/export.cpp9
-rw-r--r--platform/iphone/plugin/godot_plugin_config.h2
-rw-r--r--platform/iphone/vulkan_context_iphone.h2
-rw-r--r--platform/iphone/vulkan_context_iphone.mm4
-rw-r--r--platform/javascript/api/api.cpp4
-rw-r--r--platform/javascript/detect.py5
-rw-r--r--platform/javascript/display_server_javascript.cpp16
-rw-r--r--platform/javascript/display_server_javascript.h112
-rw-r--r--platform/javascript/export/export.cpp2
-rw-r--r--platform/javascript/javascript_main.cpp2
-rw-r--r--platform/javascript/javascript_singleton.cpp2
-rw-r--r--platform/javascript/js/engine/config.js10
-rw-r--r--platform/javascript/js/libs/library_godot_os.js3
-rw-r--r--platform/javascript/os_javascript.cpp5
-rw-r--r--platform/linuxbsd/SCsub1
-rw-r--r--platform/linuxbsd/detect.py9
-rw-r--r--platform/linuxbsd/display_server_x11.cpp64
-rw-r--r--platform/linuxbsd/display_server_x11.h161
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp125
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.h47
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp2
-rw-r--r--platform/linuxbsd/vulkan_context_x11.cpp4
-rw-r--r--platform/linuxbsd/vulkan_context_x11.h2
-rw-r--r--platform/osx/display_server_osx.h11
-rw-r--r--platform/osx/display_server_osx.mm32
-rw-r--r--platform/osx/export/export.cpp31
-rw-r--r--platform/osx/vulkan_context_osx.h2
-rw-r--r--platform/osx/vulkan_context_osx.mm4
-rw-r--r--platform/uwp/export/export.cpp1
-rw-r--r--platform/windows/context_gl_windows.cpp36
-rw-r--r--platform/windows/context_gl_windows.h3
-rw-r--r--platform/windows/display_server_windows.cpp32
-rw-r--r--platform/windows/display_server_windows.h170
-rw-r--r--platform/windows/export/export.cpp12
-rw-r--r--platform/windows/os_windows.cpp12
-rw-r--r--platform/windows/vulkan_context_win.cpp5
-rw-r--r--platform/windows/vulkan_context_win.h2
-rw-r--r--platform/windows/windows_terminal_logger.cpp24
-rw-r--r--scene/2d/area_2d.cpp2
-rw-r--r--scene/2d/audio_stream_player_2d.cpp4
-rw-r--r--scene/2d/camera_2d.cpp67
-rw-r--r--scene/2d/camera_2d.h2
-rw-r--r--scene/2d/collision_object_2d.cpp161
-rw-r--r--scene/2d/collision_object_2d.h28
-rw-r--r--scene/2d/cpu_particles_2d.cpp20
-rw-r--r--scene/2d/gpu_particles_2d.cpp4
-rw-r--r--scene/2d/joints_2d.cpp14
-rw-r--r--scene/2d/navigation_agent_2d.cpp8
-rw-r--r--scene/2d/node_2d.cpp39
-rw-r--r--scene/2d/node_2d.h6
-rw-r--r--scene/2d/physical_bone_2d.cpp62
-rw-r--r--scene/2d/physics_body_2d.cpp416
-rw-r--r--scene/2d/physics_body_2d.h25
-rw-r--r--scene/2d/polygon_2d.cpp14
-rw-r--r--scene/2d/polygon_2d.h3
-rw-r--r--scene/2d/remote_transform_2d.cpp2
-rw-r--r--scene/2d/skeleton_2d.cpp6
-rw-r--r--scene/2d/tile_map.cpp16
-rw-r--r--scene/2d/touch_screen_button.cpp4
-rw-r--r--scene/3d/area_3d.cpp2
-rw-r--r--scene/3d/audio_stream_player_3d.cpp6
-rw-r--r--scene/3d/camera_3d.cpp26
-rw-r--r--scene/3d/collision_object_3d.cpp158
-rw-r--r--scene/3d/collision_object_3d.h28
-rw-r--r--scene/3d/cpu_particles_3d.cpp24
-rw-r--r--scene/3d/decal.cpp27
-rw-r--r--scene/3d/decal.h2
-rw-r--r--scene/3d/gpu_particles_3d.cpp8
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp2
-rw-r--r--scene/3d/immediate_geometry_3d.cpp157
-rw-r--r--scene/3d/light_3d.cpp35
-rw-r--r--scene/3d/light_3d.h10
-rw-r--r--scene/3d/lightmap_gi.cpp8
-rw-r--r--scene/3d/mesh_instance_3d.cpp12
-rw-r--r--scene/3d/mesh_instance_3d.h4
-rw-r--r--scene/3d/navigation_agent_3d.cpp8
-rw-r--r--scene/3d/navigation_region_3d.cpp8
-rw-r--r--scene/3d/node_3d.cpp15
-rw-r--r--scene/3d/node_3d.h2
-rw-r--r--scene/3d/occluder_instance_3d.cpp28
-rw-r--r--scene/3d/occluder_instance_3d.h2
-rw-r--r--scene/3d/path_3d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp358
-rw-r--r--scene/3d/physics_body_3d.h22
-rw-r--r--scene/3d/proximity_group_3d.cpp2
-rw-r--r--scene/3d/reflection_probe.cpp2
-rw-r--r--scene/3d/reflection_probe.h2
-rw-r--r--scene/3d/remote_transform_3d.cpp2
-rw-r--r--scene/3d/soft_body_3d.cpp72
-rw-r--r--scene/3d/soft_body_3d.h12
-rw-r--r--scene/3d/sprite_3d.cpp306
-rw-r--r--scene/3d/sprite_3d.h49
-rw-r--r--scene/3d/vehicle_body_3d.cpp43
-rw-r--r--scene/3d/visual_instance_3d.cpp13
-rw-r--r--scene/3d/voxel_gi.cpp48
-rw-r--r--scene/3d/voxel_gi.h13
-rw-r--r--scene/3d/voxelizer.cpp6
-rw-r--r--scene/3d/xr_nodes.cpp8
-rw-r--r--scene/animation/animation_blend_space_1d.cpp10
-rw-r--r--scene/animation/animation_blend_space_2d.cpp32
-rw-r--r--scene/animation/animation_blend_tree.cpp30
-rw-r--r--scene/animation/animation_node_state_machine.cpp14
-rw-r--r--scene/animation/animation_player.cpp15
-rw-r--r--scene/animation/animation_tree.cpp10
-rw-r--r--scene/animation/root_motion_view.cpp34
-rw-r--r--scene/animation/root_motion_view.h6
-rw-r--r--scene/animation/tween.cpp14
-rw-r--r--scene/audio/audio_stream_player.cpp2
-rw-r--r--scene/debugger/scene_debugger.cpp26
-rw-r--r--scene/gui/base_button.cpp27
-rw-r--r--scene/gui/base_button.h3
-rw-r--r--scene/gui/box_container.cpp5
-rw-r--r--scene/gui/button.cpp243
-rw-r--r--scene/gui/button.h4
-rw-r--r--scene/gui/check_box.cpp20
-rw-r--r--scene/gui/check_button.cpp8
-rw-r--r--scene/gui/code_edit.cpp60
-rw-r--r--scene/gui/color_picker.cpp176
-rw-r--r--scene/gui/color_picker.h1
-rw-r--r--scene/gui/container.cpp6
-rw-r--r--scene/gui/control.cpp130
-rw-r--r--scene/gui/control.h14
-rw-r--r--scene/gui/dialogs.cpp45
-rw-r--r--scene/gui/dialogs.h1
-rw-r--r--scene/gui/file_dialog.cpp44
-rw-r--r--scene/gui/gradient_edit.cpp14
-rw-r--r--scene/gui/graph_edit.cpp108
-rw-r--r--scene/gui/graph_node.cpp78
-rw-r--r--scene/gui/grid_container.cpp8
-rw-r--r--scene/gui/item_list.cpp80
-rw-r--r--scene/gui/label.cpp171
-rw-r--r--scene/gui/label.h27
-rw-r--r--scene/gui/line_edit.cpp270
-rw-r--r--scene/gui/line_edit.h4
-rw-r--r--scene/gui/link_button.cpp24
-rw-r--r--scene/gui/margin_container.cpp16
-rw-r--r--scene/gui/option_button.cpp44
-rw-r--r--scene/gui/panel.cpp2
-rw-r--r--scene/gui/panel_container.cpp18
-rw-r--r--scene/gui/popup.cpp6
-rw-r--r--scene/gui/popup_menu.cpp96
-rw-r--r--scene/gui/progress_bar.cpp22
-rw-r--r--scene/gui/range.cpp4
-rw-r--r--scene/gui/rich_text_label.cpp106
-rw-r--r--scene/gui/scroll_bar.cpp52
-rw-r--r--scene/gui/scroll_container.cpp18
-rw-r--r--scene/gui/separator.cpp6
-rw-r--r--scene/gui/slider.cpp10
-rw-r--r--scene/gui/spin_box.cpp10
-rw-r--r--scene/gui/split_container.cpp30
-rw-r--r--scene/gui/tab_container.cpp120
-rw-r--r--scene/gui/tabs.cpp126
-rw-r--r--scene/gui/text_edit.cpp262
-rw-r--r--scene/gui/text_edit.h19
-rw-r--r--scene/gui/tree.cpp593
-rw-r--r--scene/gui/tree.h40
-rw-r--r--scene/gui/video_player.cpp2
-rw-r--r--scene/main/canvas_item.cpp41
-rw-r--r--scene/main/canvas_item.h2
-rw-r--r--scene/main/canvas_layer.cpp14
-rw-r--r--scene/main/canvas_layer.h3
-rw-r--r--scene/main/http_request.cpp44
-rw-r--r--scene/main/node.cpp88
-rw-r--r--scene/main/node.h12
-rw-r--r--scene/main/scene_tree.cpp121
-rw-r--r--scene/main/scene_tree.h17
-rw-r--r--scene/main/shader_globals_override.cpp14
-rw-r--r--scene/main/timer.cpp8
-rw-r--r--scene/main/viewport.cpp259
-rw-r--r--scene/main/viewport.h44
-rw-r--r--scene/main/window.cpp85
-rw-r--r--scene/main/window.h7
-rw-r--r--scene/register_scene_types.cpp951
-rw-r--r--scene/resources/camera_effects.cpp8
-rw-r--r--scene/resources/curve.cpp4
-rw-r--r--scene/resources/default_theme/default_theme.cpp11
-rw-r--r--scene/resources/default_theme/default_theme.h2
-rw-r--r--scene/resources/environment.cpp2
-rw-r--r--scene/resources/immediate_mesh.cpp416
-rw-r--r--scene/resources/immediate_mesh.h117
-rw-r--r--scene/resources/material.cpp561
-rw-r--r--scene/resources/material.h9
-rw-r--r--scene/resources/mesh.cpp547
-rw-r--r--scene/resources/mesh.h10
-rw-r--r--scene/resources/navigation_mesh.cpp4
-rw-r--r--scene/resources/packed_scene.cpp4
-rw-r--r--scene/resources/particles_material.cpp60
-rw-r--r--scene/resources/primitive_meshes.cpp39
-rw-r--r--scene/resources/primitive_meshes.h8
-rw-r--r--scene/resources/sky_material.cpp336
-rw-r--r--scene/resources/syntax_highlighter.cpp2
-rw-r--r--scene/resources/texture.cpp269
-rw-r--r--scene/resources/texture.h66
-rw-r--r--scene/resources/theme.cpp149
-rw-r--r--scene/resources/theme.h12
-rw-r--r--scene/resources/tile_set.cpp2415
-rw-r--r--scene/resources/tile_set.h86
-rw-r--r--scene/resources/visual_shader.cpp266
-rw-r--r--scene/resources/visual_shader.h5
-rw-r--r--scene/resources/visual_shader_nodes.cpp652
-rw-r--r--scene/resources/visual_shader_nodes.h33
-rw-r--r--scene/resources/visual_shader_particle_nodes.cpp80
-rw-r--r--scene/resources/visual_shader_sdf_nodes.cpp58
-rw-r--r--scene/scene_string_names.cpp6
-rw-r--r--scene/scene_string_names.h4
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp2
-rw-r--r--servers/audio/effects/audio_effect_filter.h6
-rw-r--r--servers/audio_server.cpp10
-rw-r--r--servers/camera_server.cpp4
-rw-r--r--servers/display_server.cpp49
-rw-r--r--servers/display_server.h33
-rw-r--r--servers/display_server_headless.h2
-rw-r--r--servers/navigation_server_2d.cpp2
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp9
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp7
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp11
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h16
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp8
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h2
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.h6
-rw-r--r--servers/physics_2d/space_2d_sw.cpp115
-rw-r--r--servers/physics_2d/space_2d_sw.h2
-rw-r--r--servers/physics_3d/area_pair_3d_sw.cpp9
-rw-r--r--servers/physics_3d/body_pair_3d_sw.cpp14
-rw-r--r--servers/physics_3d/collision_object_3d_sw.cpp42
-rw-r--r--servers/physics_3d/collision_object_3d_sw.h37
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.cpp44
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp8
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h2
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.h1
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp4
-rw-r--r--servers/physics_3d/space_3d_sw.cpp116
-rw-r--r--servers/physics_server_2d.cpp59
-rw-r--r--servers/physics_server_2d.h36
-rw-r--r--servers/physics_server_3d.cpp93
-rw-r--r--servers/physics_server_3d.h58
-rw-r--r--servers/register_server_types.cpp185
-rw-r--r--servers/rendering/rasterizer_dummy.h48
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp27
-rw-r--r--servers/rendering/renderer_canvas_cull.h10
-rw-r--r--servers/rendering/renderer_canvas_render.h2
-rw-r--r--servers/rendering/renderer_compositor.h3
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp76
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h12
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp271
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h121
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp153
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h26
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp298
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h143
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp146
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h20
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp31
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h13
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp99
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h7
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp78
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h3
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp12
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp216
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h268
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp186
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h113
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp381
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h118
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp8
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl27
-rw-r--r--servers/rendering/renderer_rd/shaders/resolve.glsl16
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl826
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl34
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl230
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl31
-rw-r--r--servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl15
-rw-r--r--servers/rendering/renderer_scene.h12
-rw-r--r--servers/rendering/renderer_scene_cull.cpp150
-rw-r--r--servers/rendering/renderer_scene_cull.h30
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.cpp2
-rw-r--r--servers/rendering/renderer_scene_render.h8
-rw-r--r--servers/rendering/renderer_storage.h40
-rw-r--r--servers/rendering/renderer_viewport.cpp85
-rw-r--r--servers/rendering/renderer_viewport.h35
-rw-r--r--servers/rendering/rendering_device.cpp51
-rw-r--r--servers/rendering/rendering_device.h46
-rw-r--r--servers/rendering/rendering_device_binds.h35
-rw-r--r--servers/rendering/rendering_server_default.cpp43
-rw-r--r--servers/rendering/rendering_server_default.h67
-rw-r--r--servers/rendering/shader_language.cpp49
-rw-r--r--servers/rendering/shader_language.h5
-rw-r--r--servers/rendering/shader_types.cpp1
-rw-r--r--servers/rendering/shader_warnings.cpp4
-rw-r--r--servers/rendering/shader_warnings.h2
-rw-r--r--servers/rendering_server.cpp1348
-rw-r--r--servers/rendering_server.h214
-rw-r--r--servers/text_server.cpp25
-rw-r--r--servers/text_server.h22
-rw-r--r--servers/xr_server.cpp8
-rw-r--r--tests/test_class_db.h8
-rw-r--r--tests/test_gui.cpp2
-rw-r--r--tests/test_object.h4
-rw-r--r--tests/test_text_server.h10
-rw-r--r--thirdparty/README.md27
-rw-r--r--thirdparty/fonts/NotoNaskhArabicUI_Bold.ttfbin0 -> 148972 bytes
-rw-r--r--thirdparty/fonts/NotoNaskhArabicUI_Regular.ttfbin256116 -> 150460 bytes
-rw-r--r--thirdparty/fonts/NotoSansBengaliUI_Bold.ttfbin0 -> 123308 bytes
-rw-r--r--thirdparty/fonts/NotoSansBengaliUI_Regular.ttf (renamed from thirdparty/fonts/NotoSansBengali_Regular.ttf)bin125440 -> 125436 bytes
-rw-r--r--thirdparty/fonts/NotoSansDevanagariUI_Bold.ttfbin0 -> 146272 bytes
-rw-r--r--thirdparty/fonts/NotoSansDevanagariUI_Regular.ttfbin199888 -> 145348 bytes
-rw-r--r--thirdparty/fonts/NotoSansGeorgian_Bold.ttfbin0 -> 27024 bytes
-rw-r--r--thirdparty/fonts/NotoSansHebrew_Bold.ttfbin0 -> 17592 bytes
-rw-r--r--thirdparty/fonts/NotoSansHebrew_Regular.ttfbin27124 -> 17556 bytes
-rw-r--r--thirdparty/fonts/NotoSansMalayalamUI_Bold.ttfbin0 -> 61084 bytes
-rw-r--r--thirdparty/fonts/NotoSansOriyaUI_Bold.ttfbin0 -> 96424 bytes
-rw-r--r--thirdparty/fonts/NotoSansSinhalaUI_Bold.ttfbin0 -> 183444 bytes
-rw-r--r--thirdparty/fonts/NotoSansTamilUI_Bold.ttfbin0 -> 44588 bytes
-rw-r--r--thirdparty/fonts/NotoSansTeluguUI_Bold.ttfbin0 -> 127720 bytes
-rw-r--r--thirdparty/fonts/NotoSansThaiUI_Bold.ttfbin0 -> 21820 bytes
-rw-r--r--thirdparty/fonts/NotoSansThaiUI_Regular.ttfbin34852 -> 22044 bytes
-rw-r--r--thirdparty/fonts/NotoSansUI_Bold.ttfbin311496 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansUI_Regular.ttfbin305888 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSans_Bold.ttfbin0 -> 313792 bytes
-rw-r--r--thirdparty/fonts/NotoSans_Regular.ttfbin0 -> 313144 bytes
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aria.h8
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bn_mul.h40
-rw-r--r--thirdparty/mbedtls/include/mbedtls/config.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecp.h42
-rw-r--r--thirdparty/mbedtls/include/mbedtls/padlock.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_ticket.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/version.h8
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_crt.h11
-rw-r--r--thirdparty/mbedtls/library/aria.c11
-rw-r--r--thirdparty/mbedtls/library/bignum.c280
-rw-r--r--thirdparty/mbedtls/library/camellia.c20
-rw-r--r--thirdparty/mbedtls/library/debug.c70
-rw-r--r--thirdparty/mbedtls/library/dhm.c165
-rw-r--r--thirdparty/mbedtls/library/ecp.c151
-rw-r--r--thirdparty/mbedtls/library/ecp_curves.c667
-rw-r--r--thirdparty/mbedtls/library/entropy.c18
-rw-r--r--thirdparty/mbedtls/library/net_sockets.c63
-rw-r--r--thirdparty/mbedtls/library/nist_kw.c8
-rw-r--r--thirdparty/mbedtls/library/pk.c5
-rw-r--r--thirdparty/mbedtls/library/pkparse.c2
-rw-r--r--thirdparty/mbedtls/library/ssl_ciphersuites.c4
-rw-r--r--thirdparty/mbedtls/library/ssl_cli.c18
-rw-r--r--thirdparty/mbedtls/library/ssl_tls.c28
-rw-r--r--thirdparty/mbedtls/library/x509_crt.c5
-rw-r--r--thirdparty/spirv-reflect/patches/specialization-constants.patch293
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.c139
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.h53
998 files changed, 34261 insertions, 18737 deletions
diff --git a/.github/workflows/javascript_builds.disabled b/.github/workflows/javascript_builds.yml
index 006981f3d4..ced2c36a91 100644
--- a/.github/workflows/javascript_builds.disabled
+++ b/.github/workflows/javascript_builds.yml
@@ -4,9 +4,9 @@ on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=javascript verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2
+ SCONSFLAGS: platform=javascript verbose=yes warnings=extra debug_symbols=no --jobs=2
SCONS_CACHE_LIMIT: 4096
- EM_VERSION: 1.39.20
+ EM_VERSION: 2.0.25
EM_CACHE_FOLDER: 'emsdk-cache'
jobs:
@@ -62,7 +62,7 @@ jobs:
scons --version
- name: Set up Emscripten latest
- uses: mymindstorm/setup-emsdk@v6
+ uses: mymindstorm/setup-emsdk@v10
with:
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index b4bbaaacb1..1b68f66956 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -26,7 +26,7 @@ jobs:
- name: Configure dependencies
run: |
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
- libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm
+ libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm
# Upload cache on completion and check it out now
- name: Load .scons_cache directory
@@ -85,7 +85,7 @@ jobs:
echo "Running --doctool to see if this changes the public API without updating the documentation."
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run bin/godot.linuxbsd.opt.tools.64 --doctool . 2>&1 > /dev/null || true
- git diff --color --exit-code
+ git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
- uses: actions/upload-artifact@v2
with:
@@ -111,7 +111,7 @@ jobs:
- name: Configure dependencies
run: |
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
- libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm \
+ libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm \
xvfb wget unzip
# Upload cache on completion and check it out now
@@ -204,7 +204,7 @@ jobs:
- name: Configure dependencies
run: |
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
- libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm
+ libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm
# Upload cache on completion and check it out now
- name: Load .scons_cache directory
diff --git a/AUTHORS.md b/AUTHORS.md
index 0aacde20e8..c5a971b345 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -28,6 +28,7 @@ name is available.
(in alphabetical order, with over 10 commits excluding merges)
Aaron Franke (aaronfranke)
+ Aaron Record (LightningAA)
Alexander Holland (AlexHolly)
Alexey Khoroshavin (allkhor)
Alket Rexhepi (alketii)
@@ -182,6 +183,7 @@ name is available.
Stijn Hinlopen (hinlopen)
Swarnim Arun (minraws)
Thakee Nathees (ThakeeNathees)
+ thebestnom
Theo Hallenius (TheoXD)
Thomas Herzog (karroffel)
Timo Schwarzer (timoschwarzer)
diff --git a/DONORS.md b/DONORS.md
index 6f359d4b6c..d31b15fa5a 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -40,13 +40,11 @@ generous deed immortalized in the next stable release of Godot Engine.
## Mini sponsors
AD Ford
- Alejandro Saucedo
alex brown
Andrew Dunai
Angry Skull
anti666
blurp
- CD
Christian Baune
Christoffer Sundbom
Christopher Montesano
@@ -85,6 +83,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Slobodan Milnovic
Stephan Lanfermann
Steve
+ Stonesoft io
Thomas Krampl
Tristan Pemble
Violin Iliev
@@ -101,12 +100,10 @@ generous deed immortalized in the next stable release of Godot Engine.
Barugon
Carlo Cabanilla
Chris Goddard
- Christopher Case
Daniel James
David Gehrig
David Snopek
Don B
- Ealthy Studio
Ed Morley
Ellen Poe
Florian Rämisch
@@ -120,7 +117,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Klavdij Voncina
kuku
Lex Steers
- Luke
Maciej Pendolski
Manuele Finocchiaro
Markus Wiesner
@@ -176,7 +172,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Chris Petrich
Chris Serino
Christian Leth Jeppesen
- Container7
+ Cow
Craig Ostrin
Craig Smith
Cristopher
@@ -187,7 +183,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Darrian Little
Dennis Belfrage
Dev To be curious
- Dietrich Schuetz
Digital Denizen
Dimitri Nüscheler
Donn Eddy
@@ -200,15 +195,16 @@ generous deed immortalized in the next stable release of Godot Engine.
flesk
foxydevloper
Fransiska
- F S
Gabrielius Vaiškūnas
Gary Hulst
gavlig
General Chicken
Geoffroy Warin
GGGames.org
+ GrayDwarf
Guilherme Felipe de C. G. da Silva
Harvey Fong
+ Hayden Whitehead
Heath Hayes
Horváth Péter
Hu Hund
@@ -241,12 +237,12 @@ generous deed immortalized in the next stable release of Godot Engine.
kinfox
Kis Levente Lorand
Kos
- Lachie
Lain Ballard
Laszlo Kiss
leetNightshade
Leo Fidel R Liban
Liam Smyth
+ LoparPanda
Luca Vazzano
Luc-Frédéric Langis
MadScientistCarl
@@ -259,6 +255,7 @@ generous deed immortalized in the next stable release of Godot Engine.
matt
Matt Greene
Matthias Toepp
+ Mecha Kaiju X
medecau
Michael
Michael Bordießer-Krauth
@@ -266,6 +263,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Michael Policastro
MightyPossum
MikadoSC
+ minz1
MuffinManKen
nate etan
Nick Abousselam
@@ -288,7 +286,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Rhodochrone
Ricardo Alcantara
Rob
- Robert Larnach
Robert McDermott
Robert Willes
Rob McInroy
@@ -299,6 +296,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Ronny Mühle
Ryan Scott
Samuel Judd
+ Samuel Smart
Sean Morgan
Sebastian Hutter
Sébastien
@@ -325,9 +323,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Turntsnaco
tweaklab
Valryia
+ VikFro
Vincent Cloutier
Vlad Ceru Opran
VoidPointer
+ Vramexon
Winston
Wojciech Chojnacki
xzibiting
@@ -366,7 +366,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Alexander Walter (SilvanuZ)
Alexandre Beaudoin
Alex Chan
- alex clavelle
+ Alex Clavelle
alex raeside
Alex (Well Done Games)
Allan Davis
@@ -376,7 +376,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Anders Marstein Kruke
Andre Stackhouse
andrew james morris
- Andrew Mansuetti
Andrew Thomas
Ano Nim
Anthony Avina
@@ -416,6 +415,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Burney Waring
bwhirt
Caleb Gartner
+ Caleb Makela
Cameron Meyer
Carlos Cejudo
Carl van der Geest
@@ -433,15 +433,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Christoffer Dahlblom
Christophe Gagnier
Christopher Chin
- Christopher Schmitt
Chris Truebe
- Clay Heaton
Cody Parker
Conall O
Conner Lane
Corchari
Craig Maloney
Craig Post
+ damucz
Daniel Cheney
Daniel Johnson
Daren Scot Wilson
@@ -450,7 +449,6 @@ generous deed immortalized in the next stable release of Godot Engine.
David Bôle
David May
David Maziarka
- David Woodard
deadwithbread
Devin Carraway
Diego Pereira
@@ -487,10 +485,10 @@ generous deed immortalized in the next stable release of Godot Engine.
Francois Holland
Frank
Game Endeavor
- Gareth Knowles
Gary Thomas
George Marques
- georgios katsanakis
+ Georgi Petkov
+ Graham Overby
Greg Lincoln
Greg Olson
Greyson Richey
@@ -500,10 +498,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Guillaume Pham Ngoc
Guldoman
Hal A
+ Hayden Foley
Heribert Hirth
- Hoojib
Houdini Blueprints
Hunter Jones
+ Ian ORourke
Ian Williams
Iiari
IndustrialRobot
@@ -512,7 +511,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Jackson Harmer
Jacob D
Jaguar
- Jaime Ruiz-Borau Vizárraga
Jake D
Jake Huxell
Jako Danar
@@ -529,15 +527,19 @@ generous deed immortalized in the next stable release of Godot Engine.
Jason Bolton
Jason Malcolm-Herzmark
Jason Uechi
+ Jeferson R. P. Belmiro
Jeff Hungerford
+ Jeff Messer
Jeffrey Berube
Jennifer Graves
+ JernauGurgeh
Jesse Dubay
Jim Engstrand
Joe Klemmer
Joel Höglund
John Bruce
John Gabriel
+ John Szevin
Jonah Branch
Jonas
Jonas Bernemann
@@ -546,8 +548,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Jonatan R
Jonathan Bieber
Jonathan G
+ Jonathan Wright
Jon Bonazza
- Jon Oakes
Jon Sully
Jordan West
Jordy Goodridge
@@ -555,11 +557,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Jorge Araya Navarro
Jose C. Rubio
Joseph Catrambone
- Josep Sanchez
Josh Taylor
Joshua Heidrich
jromkjrom
Juanfran
+ Juan Maggi
Juan Uys
Jueast
Julian Murgia
@@ -569,7 +571,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Justin Spedding
Justin W. Flory
KaDokta
- Kalin
Keedong Park
Keinan Powers
Keith Bradner
@@ -581,9 +582,12 @@ generous deed immortalized in the next stable release of Godot Engine.
Kevin van Rooijen
Kiri Jolly
Kjetil Haugland
+ Kolandrious
Konstantin Goncharov
+ kormai
Krishna Nadoor
Kristian Nygaard Jensen
+ KR McGinley
Kronarq
KsyTek Games
kycho
@@ -595,16 +599,17 @@ generous deed immortalized in the next stable release of Godot Engine.
Laurent CHEA
Laurent Tréguier
Laxman Pradhan
+ LE BOURHIS
LEMMiNO
Leonardo Dimano
Lin Chear
Linus Lind Lundgren
+ Ludovic DELVAL
Luigi Renna
Luis Gaemperle
Luis M
LunaticInAHat
Major Haul
- makoto asano
Malcolm
Marco Lardelli
Mark Jad
@@ -613,20 +618,21 @@ generous deed immortalized in the next stable release of Godot Engine.
Markus Michael Egger
Martin FIbik
Martin Holas
+ Martin Liška
Martin Trbola
Marvin
Mathieu
Matt Edwards
Matthew Booe
Matt Sylvia
- Maverick C.
Max Fiedler
Maxime Blade
Maxwell
- Mecha Kaiju X
+ MC
Melissa Mears
Merlyn Morgan-Graham
mewin
+ mhilbrunner
Michael
Michael Bruce-Lockhart
Michael Haney
@@ -665,12 +671,12 @@ generous deed immortalized in the next stable release of Godot Engine.
Nicolas Rosset
Nicolas SAN AGUSTIN
Nima Farid
+ Noel Billig
+ Nuno Dionísio
NZ
oceoh
Okatima
- OKV
Oleg Reva
- Oleksandr Kryvonos
Olle Soprani
Omar Delarosa
Oriol Muñoz Princep
@@ -690,23 +696,26 @@ generous deed immortalized in the next stable release of Godot Engine.
Point08
Preethi Vaidyanathan
pwab
+ RabidTunes
Rackat
Rad Cat
Rafa Laguna
Raffaele Aramo
Rainer Amler
Rami Hanano
+ Rammeow
RAMupgrade
Remi Rampin
Rémi Verschelde
Reneator
Riccardo Marini
+ Richard Hayes
Richard Ivánek
Richard Néveri
Riley
Robert Farr (Larington)
Rob Ruana
- Roger Smith
+ Rodrigo Loli
Roland RzÄ…sa
Roman Tinkov
Ronald Ho Hip (CrimsonZA)
@@ -719,13 +728,10 @@ generous deed immortalized in the next stable release of Godot Engine.
Sean Lynch
Sebastian Michailidis
SeongWan Kim
- Sergey
SeungJong k
Shaidak
Shane
- Shane Sicienski
Shane Spoor
- Siim Raidma
simdee
Simon Jonas Larsen
Simon Schoenenberger
@@ -763,7 +769,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Toadile
Tobias Bradtke
Tom Coxon
- Toni Duran
Torgeir Lilleskog
Torsten Crass
toupeira
@@ -778,16 +783,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Tyler Stafos
UltyX
Uther
+ v01tech
Vaughan Ling
Victor
- Viktor Ismagilov
+ Vincent Foulon
Vi Watch
Vladimir Savin
Vladislav Smirnov
- Vojtěch
Vytenis Narušis
- waka nya
- Wayne Haak
werner mendizabal
Wiley Thompson
William Edwards
diff --git a/SConstruct b/SConstruct
index e5646a7d0a..5dec3f2020 100644
--- a/SConstruct
+++ b/SConstruct
@@ -4,10 +4,12 @@ EnsureSConsVersion(3, 0, 0)
EnsurePythonVersion(3, 5)
# System
+import atexit
import glob
import os
import pickle
import sys
+import time
from collections import OrderedDict
# Local
@@ -25,6 +27,8 @@ active_platform_ids = []
platform_exporters = []
platform_apis = []
+time_at_start = time.time()
+
for x in sorted(glob.glob("platform/*")):
if not os.path.isdir(x) or not os.path.exists(x + "/detect.py"):
continue
@@ -138,6 +142,7 @@ opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all
opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False))
opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False))
opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False))
+opts.Add("disable_classes", "Disable given classes (comma separated)", "")
opts.Add(BoolVariable("modules_enabled_by_default", "If no, disable all modules except ones explicitly enabled", True))
opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", False))
opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "")
@@ -638,6 +643,7 @@ if selected_platform in platform_list:
if env["tools"]:
env.Append(CPPDEFINES=["TOOLS_ENABLED"])
+ methods.write_disabled_classes(env["disable_classes"].split(","))
if env["disable_3d"]:
if env["tools"]:
print(
@@ -748,3 +754,12 @@ if "env" in locals():
# TODO: replace this with `env.Dump(format="json")`
# once we start requiring SCons 4.0 as min version.
methods.dump(env)
+
+
+def print_elapsed_time():
+ elapsed_time_sec = round(time.time() - time_at_start, 3)
+ time_ms = round((elapsed_time_sec % 1) * 1000)
+ print("[Time elapsed: {}.{:03}]".format(time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)), time_ms))
+
+
+atexit.register(print_elapsed_time)
diff --git a/core/SCsub b/core/SCsub
index e3ba46be02..d9167b8f83 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -186,6 +186,7 @@ SConscript("io/SCsub")
SConscript("debugger/SCsub")
SConscript("input/SCsub")
SConscript("variant/SCsub")
+SConscript("extension/SCsub")
SConscript("object/SCsub")
SConscript("templates/SCsub")
SConscript("string/SCsub")
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 13cfd51570..ad31966a65 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -236,9 +236,10 @@ Engine::Engine() {
singleton = this;
}
-Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr) :
+Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) :
name(p_name),
- ptr(p_ptr) {
+ ptr(p_ptr),
+ class_name(p_class_name) {
#ifdef DEBUG_ENABLED
RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
if (rc && !rc->is_referenced()) {
diff --git a/core/config/engine.h b/core/config/engine.h
index ecf07952ab..970cfb03e8 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -41,7 +41,8 @@ public:
struct Singleton {
StringName name;
Object *ptr;
- Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr);
+ StringName class_name; //used for binding generation hinting
+ Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr, const StringName &p_class_name = StringName());
};
private:
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 74ef05b797..84860b648d 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -30,7 +30,7 @@
#include "project_settings.h"
-#include "core/core_bind.h"
+#include "core/core_bind.h" // For Compression enum.
#include "core/core_string_names.h"
#include "core/input/input_map.h"
#include "core/io/dir_access.h"
@@ -42,8 +42,6 @@
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
-#include <zlib.h>
-
ProjectSettings *ProjectSettings::singleton = nullptr;
ProjectSettings *ProjectSettings::get_singleton() {
@@ -248,7 +246,7 @@ struct _VCSort {
String name;
Variant::Type type;
int order;
- int flags;
+ uint32_t flags;
bool operator<(const _VCSort &p_vcs) const { return order == p_vcs.order ? name < p_vcs.name : order < p_vcs.order; }
};
@@ -1114,6 +1112,8 @@ ProjectSettings::ProjectSettings() {
// Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum.
custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::INT, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor");
+ // Keep the enum values in sync with the `DisplayServer::VSyncMode` enum.
+ custom_prop_info["display/window/vsync/vsync_mode"] = PropertyInfo(Variant::INT, "display/window/vsync/vsync_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Adaptive,Mailbox");
custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
GLOBAL_DEF("physics/2d/run_on_thread", false);
GLOBAL_DEF("physics/3d/run_on_thread", false);
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index a3349444c4..9a58528bd7 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1729,10 +1729,11 @@ void _Thread::_start_func(void *ud) {
memdelete(tud);
Callable::CallError ce;
const Variant *arg[1] = { &t->userdata };
+ int argc = (int)(arg[0]->get_type() != Variant::NIL);
Thread::set_name(t->target_method);
- t->ret = t->target_instance->call(t->target_method, arg, 1, ce);
+ t->ret = t->target_instance->call(t->target_method, arg, argc, ce);
if (ce.error != Callable::CallError::CALL_OK) {
String reason;
switch (ce.error) {
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 9f5f8f733f..de15cfd14a 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -508,8 +508,8 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NONE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_RANGE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_RANGE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM_SUGGESTION);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LENGTH);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_KEY_ACCEL);
diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h
index a2ccbba58a..a46f42949d 100644
--- a/core/crypto/crypto.h
+++ b/core/crypto/crypto.h
@@ -82,6 +82,7 @@ public:
virtual PackedByteArray finish() = 0;
HMACContext() {}
+ virtual ~HMACContext() {}
};
class Crypto : public RefCounted {
diff --git a/core/extension/SCsub b/core/extension/SCsub
new file mode 100644
index 0000000000..a3a54250c1
--- /dev/null
+++ b/core/extension/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env_extension = env.Clone()
+
+env_extension.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
new file mode 100644
index 0000000000..3c132a619d
--- /dev/null
+++ b/core/extension/extension_api_dump.cpp
@@ -0,0 +1,805 @@
+/*************************************************************************/
+/* extension_api_dump.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "extension_api_dump.h"
+#include "core/config/engine.h"
+#include "core/core_constants.h"
+#include "core/io/file_access.h"
+#include "core/io/json.h"
+#include "core/templates/pair.h"
+#include "core/version.h"
+
+#ifdef TOOLS_ENABLED
+
+Dictionary NativeExtensionAPIDump::generate_extension_api() {
+ Dictionary api_dump;
+
+ {
+ //header
+ Dictionary header;
+ header["version_major"] = VERSION_MAJOR;
+ header["version_minor"] = VERSION_MINOR;
+#if VERSION_PATCH
+ header["version_patch"] = VERSION_PATCH;
+#else
+ header["version_patch"] = 0;
+#endif
+ header["version_status"] = VERSION_STATUS;
+ header["version_build"] = VERSION_BUILD;
+ header["version_full_name"] = VERSION_FULL_NAME;
+
+ api_dump["header"] = header;
+ }
+
+ const uint32_t vec3_elems = 3;
+ const uint32_t ptrsize_32 = 4;
+ const uint32_t ptrsize_64 = 4;
+ static const char *build_config_name[4] = { "float_32", "float_64", "double_32", "double_64" };
+
+ {
+ //type sizes
+ struct {
+ Variant::Type type;
+ uint32_t size_32_bits_real_float;
+ uint32_t size_64_bits_real_float;
+ uint32_t size_32_bits_real_double;
+ uint32_t size_64_bits_real_double;
+ } type_size_array[Variant::VARIANT_MAX + 1] = {
+ { Variant::NIL, 0, 0, 0, 0 },
+ { Variant::BOOL, sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t) },
+ { Variant::INT, sizeof(int64_t), sizeof(int64_t), sizeof(int64_t), sizeof(int64_t) },
+ { Variant::FLOAT, sizeof(double), sizeof(double), sizeof(double), sizeof(double) },
+ { Variant::STRING, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::VECTOR2, 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
+ { Variant::VECTOR2I, 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
+ { Variant::RECT2, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::RECT2I, 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t) },
+ { Variant::VECTOR3, vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
+ { Variant::VECTOR3I, 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) },
+ { Variant::TRANSFORM2D, 6 * sizeof(float), 6 * sizeof(float), 6 * sizeof(double), 6 * sizeof(double) },
+ { Variant::PLANE, (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(double), (vec3_elems + 1) * sizeof(double) },
+ { Variant::QUATERNION, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::AABB, (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(double), (vec3_elems * 2) * sizeof(double) },
+ { Variant::BASIS, (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
+ { Variant::TRANSFORM3D, (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(double), (vec3_elems * 4) * sizeof(double) },
+ { Variant::COLOR, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float) },
+ { Variant::STRING_NAME, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::NODE_PATH, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::RID, sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t) },
+ { Variant::OBJECT, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::CALLABLE, sizeof(Callable), sizeof(Callable), sizeof(Callable), sizeof(Callable) }, //harcoded align
+ { Variant::SIGNAL, sizeof(Signal), sizeof(Signal), sizeof(Signal), sizeof(Signal) }, //harcoded align
+ { Variant::DICTIONARY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_BYTE_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_INT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_INT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_FLOAT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_FLOAT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_STRING_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_VECTOR2_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_VECTOR3_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_COLOR_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::VARIANT_MAX, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(double) * 4, sizeof(uint64_t) + sizeof(double) * 4 },
+ };
+
+ Array core_type_sizes;
+
+ for (int i = 0; i < 4; i++) {
+ Dictionary d;
+ d["build_configuration"] = build_config_name[i];
+ Array sizes;
+ for (int j = 0; j < Variant::VARIANT_MAX; j++) {
+ Variant::Type t = type_size_array[j].type;
+ String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
+ Dictionary d2;
+ d2["name"] = name;
+ uint32_t size;
+ switch (i) {
+ case 0:
+ size = type_size_array[j].size_32_bits_real_float;
+ break;
+ case 1:
+ size = type_size_array[j].size_64_bits_real_float;
+ break;
+ case 2:
+ size = type_size_array[j].size_32_bits_real_double;
+ break;
+ case 3:
+ size = type_size_array[j].size_64_bits_real_double;
+ break;
+ }
+ d2["size"] = size;
+ sizes.push_back(d2);
+ }
+ d["sizes"] = sizes;
+ core_type_sizes.push_back(d);
+ }
+ api_dump["builtin_class_sizes"] = core_type_sizes;
+ }
+
+ {
+ //member offsets sizes
+ struct {
+ Variant::Type type;
+ const char *member;
+ uint32_t offset_32_bits_real_float;
+ uint32_t offset_64_bits_real_float;
+ uint32_t offset_32_bits_real_double;
+ uint32_t offset_64_bits_real_double;
+ } member_offset_array[] = {
+ { Variant::VECTOR2, "x", 0, 0, 0, 0 },
+ { Variant::VECTOR2, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
+ { Variant::VECTOR2I, "x", 0, 0, 0, 0 },
+ { Variant::VECTOR2I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
+ { Variant::RECT2, "position", 0, 0, 0, 0 },
+ { Variant::RECT2, "size", 2 * sizeof(Vector2), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
+ { Variant::RECT2I, "position", 0, 0, 0, 0 },
+ { Variant::RECT2I, "size", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
+ { Variant::VECTOR3, "x", 0, 0, 0, 0 },
+ { Variant::VECTOR3, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
+ { Variant::VECTOR3, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
+ { Variant::VECTOR3I, "x", 0, 0, 0, 0 },
+ { Variant::VECTOR3I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
+ { Variant::VECTOR3I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
+ { Variant::TRANSFORM2D, "x", 0, 0, 0, 0 },
+ { Variant::TRANSFORM2D, "y", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
+ { Variant::TRANSFORM2D, "origin", 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::PLANE, "normal", 0, 0, 0, 0 },
+ { Variant::PLANE, "d", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
+ { Variant::QUATERNION, "x", 0, 0, 0, 0 },
+ { Variant::QUATERNION, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
+ { Variant::QUATERNION, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
+ { Variant::QUATERNION, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) },
+ { Variant::AABB, "position", 0, 0, 0, 0 },
+ { Variant::AABB, "size", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
+ //rememer that basis vectors are flipped!
+ { Variant::BASIS, "x", 0, 0, 0, 0 },
+ { Variant::BASIS, "y", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
+ { Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) },
+ { Variant::TRANSFORM3D, "basis", 0, 0, 0, 0 },
+ { Variant::TRANSFORM3D, "origin", (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
+ { Variant::COLOR, "x", 0, 0, 0, 0 },
+ { Variant::COLOR, "y", sizeof(float), sizeof(float), sizeof(float), sizeof(float) },
+ { Variant::COLOR, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) },
+ { Variant::COLOR, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) },
+ { Variant::NIL, nullptr, 0, 0, 0, 0 },
+ };
+
+ Array core_type_member_offsets;
+
+ for (int i = 0; i < 4; i++) {
+ Dictionary d;
+ d["build_configuration"] = build_config_name[i];
+ Array type_offsets;
+ uint32_t idx = 0;
+
+ Variant::Type last_type = Variant::NIL;
+
+ Dictionary d2;
+ Array members;
+
+ while (true) {
+ Variant::Type t = member_offset_array[idx].type;
+ if (t != last_type) {
+ if (last_type != Variant::NIL) {
+ d2["members"] = members;
+ type_offsets.push_back(d2);
+ }
+ if (t == Variant::NIL) {
+ break;
+ }
+
+ String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
+ d2 = Dictionary();
+ members = Array();
+ d2["name"] = name;
+ last_type = t;
+ }
+ Dictionary d3;
+ uint32_t offset;
+ switch (i) {
+ case 0:
+ offset = member_offset_array[idx].offset_32_bits_real_float;
+ break;
+ case 1:
+ offset = member_offset_array[idx].offset_64_bits_real_float;
+ break;
+ case 2:
+ offset = member_offset_array[idx].offset_32_bits_real_double;
+ break;
+ case 3:
+ offset = member_offset_array[idx].offset_64_bits_real_double;
+ break;
+ }
+ d3["member"] = member_offset_array[idx].member;
+ d3["offset"] = offset;
+ members.push_back(d3);
+ idx++;
+ }
+ d["classes"] = type_offsets;
+ core_type_member_offsets.push_back(d);
+ }
+ api_dump["builtin_class_member_offsets"] = core_type_member_offsets;
+ }
+
+ {
+ // global enums and constants
+ Array constants;
+ Map<String, List<Pair<String, int>>> enum_list;
+
+ for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
+ int value = CoreConstants::get_global_constant_value(i);
+ String enum_name = CoreConstants::get_global_constant_enum(i);
+ String name = CoreConstants::get_global_constant_name(i);
+ if (enum_name != String()) {
+ enum_list[enum_name].push_back(Pair<String, int>(name, value));
+ } else {
+ Dictionary d;
+ d["name"] = name;
+ d["value"] = value;
+ constants.push_back(d);
+ }
+ }
+
+ api_dump["global_constants"] = constants;
+
+ Array enums;
+ for (Map<String, List<Pair<String, int>>>::Element *E = enum_list.front(); E; E = E->next()) {
+ Dictionary d1;
+ d1["name"] = E->key();
+ Array values;
+ for (List<Pair<String, int>>::Element *F = E->get().front(); F; F = F->next()) {
+ Dictionary d2;
+ d2["name"] = F->get().first;
+ d2["value"] = F->get().second;
+ values.push_back(d2);
+ }
+ d1["values"] = values;
+ enums.push_back(d1);
+ }
+
+ api_dump["global_enums"] = enums;
+ }
+ {
+ Array utility_funcs;
+
+ List<StringName> utility_func_names;
+ Variant::get_utility_function_list(&utility_func_names);
+
+ for (List<StringName>::Element *E = utility_func_names.front(); E; E = E->next()) {
+ StringName name = E->get();
+ Dictionary func;
+ func["name"] = String(name);
+ if (Variant::has_utility_function_return_value(name)) {
+ Variant::Type rt = Variant::get_utility_function_return_type(name);
+ func["return_type"] = rt == Variant::NIL ? String("Variant") : Variant::get_type_name(rt);
+ }
+ switch (Variant::get_utility_function_type(name)) {
+ case Variant::UTILITY_FUNC_TYPE_MATH:
+ func["category"] = "math";
+ break;
+ case Variant::UTILITY_FUNC_TYPE_RANDOM:
+ func["category"] = "random";
+ break;
+ case Variant::UTILITY_FUNC_TYPE_GENERAL:
+ func["category"] = "general";
+ break;
+ }
+ bool vararg = Variant::is_utility_function_vararg(name);
+ func["is_vararg"] = Variant::is_utility_function_vararg(name);
+ func["hash"] = Variant::get_utility_function_hash(name);
+ Array arguments;
+ int argcount = Variant::get_utility_function_argument_count(name);
+ for (int i = 0; i < argcount; i++) {
+ Dictionary arg;
+ String argname = vararg ? "arg" + itos(i + 1) : Variant::get_utility_function_argument_name(name, i);
+ arg["name"] = argname;
+ Variant::Type argtype = Variant::get_utility_function_argument_type(name, i);
+ arg["type"] = argtype == Variant::NIL ? String("Variant") : Variant::get_type_name(argtype);
+ //no default value support in utility functions
+ arguments.push_back(arg);
+ }
+
+ if (arguments.size()) {
+ func["arguments"] = arguments;
+ }
+
+ utility_funcs.push_back(func);
+ }
+
+ api_dump["utility_functions"] = utility_funcs;
+ }
+
+ {
+ // builtin types
+
+ Array builtins;
+
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ if (i == Variant::OBJECT) {
+ continue;
+ }
+
+ Variant::Type type = Variant::Type(i);
+
+ Dictionary d;
+ d["name"] = Variant::get_type_name(type);
+ if (Variant::has_indexing(type)) {
+ Variant::Type index_type = Variant::get_indexed_element_type(type);
+ d["indexing_return_type"] = index_type == Variant::NIL ? String("Variant") : Variant::get_type_name(index_type);
+ }
+
+ {
+ //members
+ Array members;
+
+ List<StringName> member_names;
+ Variant::get_member_list(type, &member_names);
+ for (List<StringName>::Element *E = member_names.front(); E; E = E->next()) {
+ StringName member_name = E->get();
+ Dictionary d2;
+ d2["name"] = String(member_name);
+ d2["type"] = Variant::get_type_name(Variant::get_member_type(type, member_name));
+ members.push_back(d2);
+ }
+ if (members.size()) {
+ d["members"] = members;
+ }
+ }
+ {
+ //constants
+ Array constants;
+
+ List<StringName> constant_names;
+ Variant::get_constants_for_type(type, &constant_names);
+ for (List<StringName>::Element *E = constant_names.front(); E; E = E->next()) {
+ StringName constant_name = E->get();
+ Dictionary d2;
+ d2["name"] = String(constant_name);
+ Variant constant = Variant::get_constant_value(type, constant_name);
+ d2["type"] = Variant::get_type_name(constant.get_type());
+ d2["value"] = constant.get_construct_string();
+ constants.push_back(d2);
+ }
+ if (constants.size()) {
+ d["constants"] = constants;
+ }
+ }
+ {
+ //operators
+ Array operators;
+
+ for (int j = 0; j < Variant::VARIANT_MAX; j++) {
+ for (int k = 0; k < Variant::OP_MAX; k++) {
+ Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j));
+ if (rt != Variant::NIL) {
+ Dictionary d2;
+ d2["name"] = Variant::get_operator_name(Variant::Operator(k));
+ if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) {
+ d2["right_type"] = Variant::get_type_name(Variant::Type(j));
+ }
+ operators.push_back(d2);
+ }
+ }
+ }
+ if (operators.size()) {
+ d["operators"] = operators;
+ }
+ }
+ {
+ //methods
+ Array methods;
+
+ List<StringName> method_names;
+ Variant::get_builtin_method_list(type, &method_names);
+ for (List<StringName>::Element *E = method_names.front(); E; E = E->next()) {
+ StringName method_name = E->get();
+ Dictionary d2;
+ d2["name"] = String(method_name);
+ if (Variant::has_builtin_method_return_value(type, method_name)) {
+ Variant::Type ret_type = Variant::get_builtin_method_return_type(type, method_name);
+ d2["return_type"] = ret_type == Variant::NIL ? String("Variant") : Variant::get_type_name(ret_type);
+ }
+ d2["is_vararg"] = Variant::is_builtin_method_vararg(type, method_name);
+ d2["is_const"] = Variant::is_builtin_method_const(type, method_name);
+ d2["is_static"] = Variant::is_builtin_method_static(type, method_name);
+ d2["hash"] = Variant::get_builtin_method_hash(type, method_name);
+
+ Vector<Variant> default_args = Variant::get_builtin_method_default_arguments(type, method_name);
+
+ Array arguments;
+ int argcount = Variant::get_builtin_method_argument_count(type, method_name);
+ for (int j = 0; j < argcount; j++) {
+ Dictionary d3;
+ d3["name"] = Variant::get_builtin_method_argument_name(type, method_name, j);
+ Variant::Type argtype = Variant::get_builtin_method_argument_type(type, method_name, j);
+ d3["type"] = argtype == Variant::NIL ? String("Variant") : Variant::get_type_name(argtype);
+
+ if (j >= (argcount - default_args.size())) {
+ int dargidx = j - (argcount - default_args.size());
+ d3["default_value"] = default_args[dargidx].get_construct_string();
+ }
+ arguments.push_back(d3);
+ }
+
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ methods.push_back(d2);
+ }
+ if (methods.size()) {
+ d["methods"] = methods;
+ }
+ }
+ {
+ //constructors
+ Array constructors;
+
+ for (int j = 0; j < Variant::get_constructor_count(type); j++) {
+ Dictionary d2;
+ d2["index"] = j;
+
+ Array arguments;
+ int argcount = Variant::get_constructor_argument_count(type, j);
+ for (int k = 0; k < argcount; k++) {
+ Dictionary d3;
+ d3["name"] = Variant::get_constructor_argument_name(type, j, k);
+ d3["type"] = Variant::get_type_name(Variant::get_constructor_argument_type(type, j, k));
+ arguments.push_back(d3);
+ }
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+ constructors.push_back(d2);
+ }
+
+ if (constructors.size()) {
+ d["constructors"] = constructors;
+ }
+ }
+
+ builtins.push_back(d);
+ }
+
+ api_dump["builtin_classes"] = builtins;
+ }
+
+ {
+ // classes
+ Array classes;
+
+ List<StringName> class_list;
+
+ ClassDB::get_class_list(&class_list);
+
+ class_list.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *E = class_list.front(); E; E = E->next()) {
+ Dictionary d;
+ StringName class_name = E->get();
+ d["name"] = String(class_name);
+ d["is_refcounted"] = ClassDB::is_parent_class(class_name, "RefCounted");
+ d["is_instantiable"] = ClassDB::can_instantiate(class_name);
+ StringName parent_class = ClassDB::get_parent_class(class_name);
+ if (parent_class != StringName()) {
+ d["inherits"] = String(parent_class);
+ }
+
+ {
+ ClassDB::APIType api = ClassDB::get_api_type(class_name);
+ static const char *api_type[5] = { "core", "editor", "extension", "editor_extension" };
+ d["api_type"] = api_type[api];
+ }
+
+ {
+ //constants
+ Array constants;
+ List<String> constant_list;
+ ClassDB::get_integer_constant_list(class_name, &constant_list, true);
+ for (List<String>::Element *F = constant_list.front(); F; F = F->next()) {
+ StringName enum_name = ClassDB::get_integer_constant_enum(class_name, F->get());
+ if (enum_name != StringName()) {
+ continue; //enums will be handled on their own
+ }
+
+ Dictionary d2;
+ d2["name"] = String(F->get());
+ d2["value"] = ClassDB::get_integer_constant(class_name, F->get());
+
+ constants.push_back(d2);
+ }
+
+ if (constants.size()) {
+ d["constants"] = constants;
+ }
+ }
+ {
+ //enum
+ Array enums;
+ List<StringName> enum_list;
+ ClassDB::get_enum_list(class_name, &enum_list, true);
+ for (List<StringName>::Element *F = enum_list.front(); F; F = F->next()) {
+ Dictionary d2;
+ d2["name"] = String(F->get());
+
+ Array values;
+ List<StringName> enum_constant_list;
+ ClassDB::get_enum_constants(class_name, F->get(), &enum_constant_list, true);
+ for (List<StringName>::Element *G = enum_constant_list.front(); G; G = G->next()) {
+ Dictionary d3;
+ d3["name"] = String(G->get());
+ d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
+ values.push_back(d3);
+ }
+
+ d2["values"] = values;
+
+ enums.push_back(d2);
+ }
+
+ if (enums.size()) {
+ d["enums"] = enums;
+ }
+ }
+ {
+ //methods
+ Array methods;
+ List<MethodInfo> method_list;
+ ClassDB::get_method_list(class_name, &method_list, true);
+ for (List<MethodInfo>::Element *F = method_list.front(); F; F = F->next()) {
+ StringName method_name = F->get().name;
+ if (F->get().flags & METHOD_FLAG_VIRTUAL) {
+ //virtual method
+ const MethodInfo &mi = F->get();
+ Dictionary d2;
+ d2["name"] = String(method_name);
+ d2["is_const"] = (F->get().flags & METHOD_FLAG_CONST) ? true : false;
+ d2["is_vararg"] = false;
+ d2["is_virtual"] = true;
+ // virtual functions have no hash since no MethodBind is involved
+ bool has_return = mi.return_val.type != Variant::NIL || (mi.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT);
+ Array arguments;
+ for (int i = (has_return ? -1 : 0); i < mi.arguments.size(); i++) {
+ PropertyInfo pinfo = i == -1 ? mi.return_val : mi.arguments[i];
+ Dictionary d3;
+
+ if (i >= 0) {
+ d3["name"] = pinfo.name;
+ }
+ if (pinfo.class_name != StringName()) {
+ d3["type"] = String(pinfo.class_name);
+ } else {
+ Variant::Type type = pinfo.type;
+ if (type == Variant::NIL) {
+ d3["type"] = "Variant";
+ } else {
+ d3["type"] = Variant::get_type_name(type);
+ }
+ }
+
+ if (i == -1) {
+ d2["return_value"] = d3;
+ } else {
+ arguments.push_back(d3);
+ }
+ }
+
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ methods.push_back(d2);
+
+ } else if (F->get().name.begins_with("_")) {
+ //hidden method, ignore
+
+ } else {
+ Dictionary d2;
+ d2["name"] = String(method_name);
+
+ MethodBind *method = ClassDB::get_method(class_name, method_name);
+ if (!method) {
+ continue;
+ }
+
+ d2["is_const"] = method->is_const();
+ d2["is_vararg"] = method->is_vararg();
+ d2["is_virtual"] = false;
+ d2["hash"] = method->get_hash();
+
+ Vector<Variant> default_args = method->get_default_arguments();
+
+ Array arguments;
+ for (int i = (method->has_return() ? -1 : 0); i < method->get_argument_count(); i++) {
+ PropertyInfo pinfo = i == -1 ? method->get_return_info() : method->get_argument_info(i);
+ Dictionary d3;
+
+ if (i >= 0) {
+ d3["name"] = pinfo.name;
+ }
+ if (pinfo.class_name != StringName()) {
+ d3["type"] = String(pinfo.class_name);
+ } else {
+ Variant::Type type = pinfo.type;
+ if (type == Variant::NIL) {
+ d3["type"] = "Variant";
+ } else {
+ d3["type"] = Variant::get_type_name(type);
+ }
+ }
+
+ if (method->get_argument_meta(i) > 0) {
+ static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" };
+ d3["meta"] = argmeta[method->get_argument_meta(i)];
+ }
+
+ if (i >= 0 && i >= (method->get_argument_count() - default_args.size())) {
+ int dargidx = i - (method->get_argument_count() - default_args.size());
+ d3["default_value"] = default_args[dargidx].get_construct_string();
+ }
+
+ if (i == -1) {
+ d2["return_value"] = d3;
+ } else {
+ arguments.push_back(d3);
+ }
+ }
+
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ methods.push_back(d2);
+ }
+ }
+
+ if (methods.size()) {
+ d["methods"] = methods;
+ }
+ }
+
+ {
+ //signals
+ Array signals;
+ List<MethodInfo> signal_list;
+ ClassDB::get_signal_list(class_name, &signal_list, true);
+ for (List<MethodInfo>::Element *F = signal_list.front(); F; F = F->next()) {
+ StringName signal_name = F->get().name;
+ Dictionary d2;
+ d2["name"] = String(signal_name);
+
+ Array arguments;
+
+ for (int i = 0; i < F->get().arguments.size(); i++) {
+ Dictionary d3;
+ d3["name"] = F->get().arguments[i].name;
+ Variant::Type type = F->get().arguments[i].type;
+ if (F->get().arguments[i].class_name != StringName()) {
+ d3["type"] = String(F->get().arguments[i].class_name);
+ } else if (type == Variant::NIL) {
+ d3["type"] = "Variant";
+ } else {
+ d3["type"] = Variant::get_type_name(type);
+ }
+ arguments.push_back(d3);
+ }
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ signals.push_back(d2);
+ }
+
+ if (signals.size()) {
+ d["signals"] = signals;
+ }
+ }
+ {
+ //properties
+ Array properties;
+ List<PropertyInfo> property_list;
+ ClassDB::get_property_list(class_name, &property_list, true);
+ for (List<PropertyInfo>::Element *F = property_list.front(); F; F = F->next()) {
+ if (F->get().usage & PROPERTY_USAGE_CATEGORY || F->get().usage & PROPERTY_USAGE_GROUP || F->get().usage & PROPERTY_USAGE_SUBGROUP) {
+ continue; //not real properties
+ }
+ if (F->get().name.begins_with("_")) {
+ continue; //hidden property
+ }
+ StringName property_name = F->get().name;
+ Dictionary d2;
+ d2["name"] = String(property_name);
+
+ if (F->get().class_name != StringName()) {
+ d2["type"] = String(F->get().class_name);
+ } else if (F->get().type == Variant::NIL && F->get().usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
+ d2["type"] = "Variant";
+ } else {
+ d2["type"] = Variant::get_type_name(F->get().type);
+ }
+
+ d2["setter"] = ClassDB::get_property_setter(class_name, F->get().name);
+ d2["getter"] = ClassDB::get_property_getter(class_name, F->get().name);
+ d2["index"] = ClassDB::get_property_index(class_name, F->get().name);
+ properties.push_back(d2);
+ }
+
+ if (properties.size()) {
+ d["properties"] = properties;
+ }
+ }
+
+ classes.push_back(d);
+ }
+
+ api_dump["classes"] = classes;
+ }
+
+ {
+ // singletons
+
+ Array singletons;
+ List<Engine::Singleton> singleton_list;
+ Engine::get_singleton()->get_singletons(&singleton_list);
+
+ for (List<Engine::Singleton>::Element *E = singleton_list.front(); E; E = E->next()) {
+ const Engine::Singleton &s = E->get();
+ Dictionary d;
+ d["name"] = s.name;
+ if (s.class_name != StringName()) {
+ d["type"] = String(s.class_name);
+ } else {
+ d["type"] = String(s.ptr->get_class());
+ }
+ singletons.push_back(d);
+ }
+
+ if (singletons.size()) {
+ api_dump["singletons"] = singletons;
+ }
+ }
+
+ return api_dump;
+}
+
+void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path) {
+ Dictionary api = generate_extension_api();
+ Ref<JSON> json;
+ json.instantiate();
+
+ String text = json->stringify(api, "\t", false);
+ FileAccessRef 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/extension_api_dump.h b/core/extension/extension_api_dump.h
new file mode 100644
index 0000000000..a7825c10a9
--- /dev/null
+++ b/core/extension/extension_api_dump.h
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* extension_api_dump.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef API_DUMP_H
+#define API_DUMP_H
+
+#include "core/extension/native_extension.h"
+
+#ifdef TOOLS_ENABLED
+
+class NativeExtensionAPIDump {
+public:
+ static Dictionary generate_extension_api();
+ static void generate_extension_json_file(const String &p_path);
+};
+#endif
+
+#endif // API_DUMP_H
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
new file mode 100644
index 0000000000..8f68b8d848
--- /dev/null
+++ b/core/extension/gdnative_interface.cpp
@@ -0,0 +1,694 @@
+/*************************************************************************/
+/* gdnative_interface.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gdnative_interface.h"
+
+#include "core/config/engine.h"
+#include "core/object/class_db.h"
+#include "core/os/memory.h"
+#include "core/variant/variant.h"
+#include "core/version.h"
+
+// Memory Functions
+static void *gdnative_alloc(size_t p_size) {
+ return memalloc(p_size);
+}
+
+static void *gdnative_realloc(void *p_mem, size_t p_size) {
+ return memrealloc(p_mem, p_size);
+}
+
+static void gdnative_free(void *p_mem) {
+ memfree(p_mem);
+}
+
+// Helper print functions.
+static void gdnative_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_ERROR);
+}
+static void gdnative_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_WARNING);
+}
+static void gdnative_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_SCRIPT);
+}
+
+// Variant functions
+
+static void gdnative_variant_new_copy(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src) {
+ memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<Variant *>(p_src)));
+}
+static void gdnative_variant_new_nil(GDNativeVariantPtr r_dest) {
+ memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant);
+}
+static void gdnative_variant_destroy(GDNativeVariantPtr p_self) {
+ reinterpret_cast<Variant *>(p_self)->~Variant();
+}
+
+// variant type
+
+#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr)
+
+static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
+ Variant *self = (Variant *)p_self;
+ const StringName *method = (const StringName *)p_method;
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ self->call(*method, args, p_argcount, ret, error);
+ memnew_placement_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (GDNativeCallErrorType)(error.error);
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+
+static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
+ Variant::Type type = (Variant::Type)p_type;
+ const StringName *method = (const StringName *)p_method;
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ Variant::call_static(type, *method, args, p_argcount, ret, error);
+ memnew_placement_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (GDNativeCallErrorType)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+
+static void gdnative_variant_evaluate(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid) {
+ Variant::Operator op = (Variant::Operator)p_op;
+ const Variant *a = (const Variant *)p_a;
+ const Variant *b = (const Variant *)p_b;
+ Variant *ret = (Variant *)r_return;
+ bool valid;
+ Variant::evaluate(op, *a, *b, *ret, valid);
+ *r_valid = valid;
+}
+
+static void gdnative_variant_set(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ self->set(*key, *value, &valid);
+ *r_valid = valid;
+}
+
+static void gdnative_variant_set_named(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const StringName *key = (const StringName *)p_key;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ self->set_named(*key, *value, valid);
+ *r_valid = valid;
+}
+
+static void gdnative_variant_set_keyed(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ self->set_keyed(*key, *value, valid);
+ *r_valid = valid;
+}
+
+static void gdnative_variant_set_indexed(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob) {
+ Variant *self = (Variant *)p_self;
+ const Variant *value = (const Variant *)p_value;
+
+ bool valid;
+ bool oob;
+ self->set_indexed(p_index, value, valid, oob);
+ *r_valid = valid;
+ *r_oob = oob;
+}
+
+static void gdnative_variant_get(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+
+ bool valid;
+ memnew_placement_custom(r_ret, Variant, Variant(self->get(*key, &valid)));
+ *r_valid = valid;
+}
+
+static void gdnative_variant_get_named(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const StringName *key = (const StringName *)p_key;
+
+ bool valid;
+ memnew_placement_custom(r_ret, Variant, Variant(self->get_named(*key, valid)));
+ *r_valid = valid;
+}
+
+static void gdnative_variant_get_keyed(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+
+ bool valid;
+ memnew_placement_custom(r_ret, Variant, Variant(self->get_keyed(*key, valid)));
+ *r_valid = valid;
+}
+
+static void gdnative_variant_get_indexed(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob) {
+ const Variant *self = (const Variant *)p_self;
+
+ bool valid;
+ bool oob;
+ memnew_placement_custom(r_ret, Variant, Variant(self->get_indexed(p_index, valid, oob)));
+ *r_valid = valid;
+ *r_oob = oob;
+}
+
+/// Iteration.
+static GDNativeBool gdnative_variant_iter_init(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ Variant *iter = (Variant *)r_iter;
+
+ bool valid;
+ bool ret = self->iter_init(*iter, valid);
+ *r_valid = valid;
+ return ret;
+}
+
+static GDNativeBool gdnative_variant_iter_next(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ Variant *iter = (Variant *)r_iter;
+
+ bool valid;
+ bool ret = self->iter_next(*iter, valid);
+ *r_valid = valid;
+ return ret;
+}
+
+static void gdnative_variant_iter_get(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ Variant *iter = (Variant *)r_iter;
+
+ bool valid;
+ memnew_placement_custom(r_ret, Variant, Variant(self->iter_next(*iter, valid)));
+ *r_valid = valid;
+}
+
+/// Variant functions.
+static GDNativeBool gdnative_variant_hash_compare(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *other = (const Variant *)p_other;
+ return self->hash_compare(*other);
+}
+
+static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self) {
+ const Variant *self = (const Variant *)p_self;
+ return self->booleanize();
+}
+
+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;
+ memnew_placement(r_dst, Variant);
+ Variant::blend(*a, *b, p_c, *(Variant *)r_dst);
+}
+
+static void gdnative_variant_interpolate(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;
+ memnew_placement(r_dst, Variant);
+ Variant::interpolate(*a, *b, p_c, *(Variant *)r_dst);
+}
+
+static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) {
+ const Variant *self = (const Variant *)p_self;
+ memnew_placement_custom(r_ret, Variant, Variant(self->duplicate(p_deep)));
+}
+
+static void gdnative_variant_stringify(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret) {
+ const Variant *self = (const Variant *)p_self;
+ memnew_placement_custom(r_ret, String, String(*self));
+}
+
+static GDNativeVariantType gdnative_variant_get_type(const GDNativeVariantPtr p_self) {
+ const Variant *self = (const Variant *)p_self;
+ return (GDNativeVariantType)self->get_type();
+}
+
+static GDNativeBool gdnative_variant_has_method(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method) {
+ const Variant *self = (const Variant *)p_self;
+ const StringName *method = (const StringName *)p_method;
+ return self->has_method(*method);
+}
+
+static GDNativeBool gdnative_variant_has_member(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) {
+ return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member));
+}
+
+static GDNativeBool gdnative_variant_has_key(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const Variant *key = (const Variant *)p_key;
+ bool valid;
+ return self->has_key(*key, valid);
+ *r_valid = valid;
+}
+
+static void gdnative_variant_get_type_name(GDNativeVariantType p_type, GDNativeStringPtr r_ret) {
+ String name = Variant::get_type_name((Variant::Type)p_type);
+ memnew_placement_custom(r_ret, String, String(name));
+}
+
+static GDNativeBool gdnative_variant_can_convert(GDNativeVariantType p_from, GDNativeVariantType p_to) {
+ return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to);
+}
+
+static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_from, GDNativeVariantType p_to) {
+ return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to);
+}
+
+// ptrcalls
+static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) {
+ return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b));
+}
+static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash) {
+ StringName method = p_method;
+ uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method);
+ if (hash != p_hash) {
+ ERR_PRINT_ONCE("Error getting method " + String(method) + ", hash mismatch.");
+ return nullptr;
+ }
+
+ return (GDNativePtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method);
+}
+static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) {
+ return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor);
+}
+static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) {
+ memnew_placement(p_base, Variant);
+
+ Callable::CallError error;
+ Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error);
+
+ if (r_error) {
+ r_error->error = (GDNativeCallErrorType)(error.error);
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const char *p_member) {
+ return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), p_member);
+}
+static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const char *p_member) {
+ return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), p_member);
+}
+static GDNativePtrIndexedSetter gdnative_variant_get_ptr_indexed_setter(GDNativeVariantType p_type) {
+ return (GDNativePtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type));
+}
+static GDNativePtrIndexedGetter gdnative_variant_get_ptr_indexed_getter(GDNativeVariantType p_type) {
+ return (GDNativePtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type));
+}
+static GDNativePtrKeyedSetter gdnative_variant_get_ptr_keyed_setter(GDNativeVariantType p_type) {
+ return (GDNativePtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type));
+}
+static GDNativePtrKeyedGetter gdnative_variant_get_ptr_keyed_getter(GDNativeVariantType p_type) {
+ return (GDNativePtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type));
+}
+static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVariantType p_type) {
+ return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type));
+}
+static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret) {
+ memnew_placement_custom(r_ret, Variant, Variant(Variant::get_constant_value(Variant::Type(p_type), p_constant)));
+}
+static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const char *p_function, GDNativeInt p_hash) {
+ StringName function = p_function;
+ uint32_t hash = Variant::get_utility_function_hash(function);
+ if (hash != p_hash) {
+ ERR_PRINT_ONCE("Error getting utility function " + String(function) + ", hash mismatch.");
+ return nullptr;
+ }
+ return (GDNativePtrUtilityFunction)Variant::get_ptr_utility_function(function);
+}
+
+//string helpers
+
+static void gdnative_string_new_with_latin1_chars(GDNativeStringPtr r_dest, const char *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String(p_contents);
+}
+
+static void gdnative_string_new_with_utf8_chars(GDNativeStringPtr r_dest, const char *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf8(p_contents);
+}
+
+static void gdnative_string_new_with_utf16_chars(GDNativeStringPtr r_dest, const char16_t *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf16(p_contents);
+}
+
+static void gdnative_string_new_with_utf32_chars(GDNativeStringPtr r_dest, const char32_t *p_contents) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents);
+}
+
+static void gdnative_string_new_with_wide_chars(GDNativeStringPtr r_dest, const wchar_t *p_contents) {
+ String *dest = (String *)r_dest;
+ if (sizeof(wchar_t) == 2) {
+ // wchar_t is 16 bit, parse.
+ memnew_placement(dest, String);
+ dest->parse_utf16((const char16_t *)p_contents);
+ } else {
+ // wchar_t is 32 bit, copy.
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents);
+ }
+}
+
+static void gdnative_string_new_with_latin1_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String(p_contents, p_size);
+}
+
+static void gdnative_string_new_with_utf8_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf8(p_contents, p_size);
+}
+
+static void gdnative_string_new_with_utf16_chars_and_len(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ dest->parse_utf16(p_contents, p_size);
+}
+
+static void gdnative_string_new_with_utf32_chars_and_len(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size) {
+ String *dest = (String *)r_dest;
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents, p_size);
+}
+
+static void gdnative_string_new_with_wide_chars_and_len(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size) {
+ String *dest = (String *)r_dest;
+ if (sizeof(wchar_t) == 2) {
+ // wchar_t is 16 bit, parse.
+ memnew_placement(dest, String);
+ dest->parse_utf16((const char16_t *)p_contents, p_size);
+ } else {
+ // wchar_t is 32 bit, copy.
+ memnew_placement(dest, String);
+ *dest = String((const char32_t *)p_contents, p_size);
+ }
+}
+
+static GDNativeInt gdnative_string_to_latin1_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) {
+ String *self = (String *)p_self;
+ CharString cs = self->ascii(true);
+ GDNativeInt len = cs.length();
+ if (r_text) {
+ const char *s_text = cs.ptr();
+ for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDNativeInt gdnative_string_to_utf8_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) {
+ String *self = (String *)p_self;
+ CharString cs = self->utf8();
+ GDNativeInt len = cs.length();
+ if (r_text) {
+ const char *s_text = cs.ptr();
+ for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDNativeInt gdnative_string_to_utf16_chars(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length) {
+ String *self = (String *)p_self;
+ Char16String cs = self->utf16();
+ GDNativeInt len = cs.length();
+ if (r_text) {
+ const char16_t *s_text = cs.ptr();
+ for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDNativeInt gdnative_string_to_utf32_chars(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length) {
+ String *self = (String *)p_self;
+ GDNativeInt len = self->length();
+ if (r_text) {
+ const char32_t *s_text = self->ptr();
+ for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) {
+ r_text[i] = s_text[i];
+ }
+ }
+ return len;
+}
+static GDNativeInt gdnative_string_to_wide_chars(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length) {
+ if (sizeof(wchar_t) == 4) {
+ return gdnative_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length);
+ } else {
+ return gdnative_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length);
+ }
+}
+
+static char32_t *gdnative_string_operator_index(GDNativeStringPtr p_self, GDNativeInt p_index) {
+ String *self = (String *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
+ return &self->ptrw()[p_index];
+}
+
+static const char32_t *gdnative_string_operator_index_const(const GDNativeStringPtr p_self, GDNativeInt p_index) {
+ const String *self = (const String *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr);
+ return &self->ptr()[p_index];
+}
+
+/* OBJECT API */
+
+static void gdnative_object_method_bind_ptrcall(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) {
+ MethodBind *mb = (MethodBind *)p_method_bind;
+ Object *o = (Object *)p_instance;
+ mb->ptrcall(o, (const void **)p_args, p_ret);
+}
+
+static void gdnative_object_destroy(GDNativeObjectPtr p_o) {
+ memdelete((Object *)p_o);
+}
+
+static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) {
+ return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name));
+}
+
+static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks) {
+ Object *o = (Object *)p_instance;
+ return o->get_instance_binding(p_token, p_callbacks);
+}
+
+static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
+ return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id));
+}
+
+static GDNativeObjectPtr gdnative_object_cast_to(const GDNativeObjectPtr p_object, void *p_class_tag) {
+ if (!p_object) {
+ return nullptr;
+ }
+ Object *o = (Object *)p_object;
+
+ return o->is_class_ptr(p_class_tag) ? (GDNativeObjectPtr)o : (GDNativeObjectPtr) nullptr;
+}
+
+static GDObjectInstanceID gdnative_object_get_instance_id(const GDNativeObjectPtr p_object) {
+ const Object *o = (const Object *)p_object;
+ return (GDObjectInstanceID)o->get_instance_id();
+}
+
+static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_classname, const char *p_methodname, GDNativeInt p_hash) {
+ MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname));
+ ERR_FAIL_COND_V(!mb, nullptr);
+ if (mb->get_hash() != p_hash) {
+ ERR_PRINT_ONCE("Hash mismatch for method '" + String(p_classname) + "." + String(p_methodname) + "'.");
+ return nullptr;
+ }
+ // MethodBind *mb = ClassDB::get_method("Node", "get_name");
+ return (GDNativeMethodBindPtr)mb;
+}
+
+static GDNativeClassConstructor gdnative_classdb_get_constructor(const char *p_classname) {
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname));
+ if (class_info) {
+ return (GDNativeClassConstructor)class_info->creation_func;
+ }
+ return nullptr;
+}
+
+static void *gdnative_classdb_get_class_tag(const char *p_classname) {
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(p_classname);
+ return class_info ? class_info->class_ptr : nullptr;
+}
+
+void gdnative_setup_interface(GDNativeInterface *p_interface) {
+ GDNativeInterface &gdni = *p_interface;
+
+ gdni.version_major = VERSION_MAJOR;
+ gdni.version_minor = VERSION_MINOR;
+#if VERSION_PATCH
+ gdni.version_patch = VERSION_PATCH;
+#else
+ gdni.version_patch = 0;
+#endif
+ gdni.version_string = VERSION_FULL_NAME;
+
+ /* GODOT CORE */
+
+ gdni.mem_alloc = gdnative_alloc;
+ gdni.mem_realloc = gdnative_realloc;
+ gdni.mem_free = gdnative_free;
+
+ gdni.print_error = gdnative_print_error;
+ gdni.print_warning = gdnative_print_warning;
+ gdni.print_script_error = gdnative_print_script_error;
+
+ /* GODOT VARIANT */
+
+ // variant general
+ gdni.variant_new_copy = gdnative_variant_new_copy;
+ gdni.variant_new_nil = gdnative_variant_new_nil;
+ gdni.variant_destroy = gdnative_variant_destroy;
+
+ gdni.variant_call = gdnative_variant_call;
+ gdni.variant_call_static = gdnative_variant_call_static;
+ gdni.variant_evaluate = gdnative_variant_evaluate;
+ gdni.variant_set = gdnative_variant_set;
+ gdni.variant_set_named = gdnative_variant_set_named;
+ gdni.variant_set_keyed = gdnative_variant_set_keyed;
+ gdni.variant_set_indexed = gdnative_variant_set_indexed;
+ gdni.variant_get = gdnative_variant_get;
+ gdni.variant_get_named = gdnative_variant_get_named;
+ gdni.variant_get_keyed = gdnative_variant_get_keyed;
+ gdni.variant_get_indexed = gdnative_variant_get_indexed;
+ gdni.variant_iter_init = gdnative_variant_iter_init;
+ gdni.variant_iter_next = gdnative_variant_iter_next;
+ gdni.variant_iter_get = gdnative_variant_iter_get;
+ gdni.variant_hash_compare = gdnative_variant_hash_compare;
+ gdni.variant_booleanize = gdnative_variant_booleanize;
+ gdni.variant_blend = gdnative_variant_blend;
+ gdni.variant_interpolate = gdnative_variant_interpolate;
+ gdni.variant_duplicate = gdnative_variant_duplicate;
+ gdni.variant_stringify = gdnative_variant_stringify;
+
+ gdni.variant_get_type = gdnative_variant_get_type;
+ gdni.variant_has_method = gdnative_variant_has_method;
+ gdni.variant_has_member = gdnative_variant_has_member;
+ gdni.variant_has_key = gdnative_variant_has_key;
+ gdni.variant_get_type_name = gdnative_variant_get_type_name;
+ gdni.variant_can_convert = gdnative_variant_can_convert;
+ gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict;
+
+ //ptrcalls
+#if 0
+ GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
+ GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
+#endif
+
+ gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator;
+ gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method;
+ gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor;
+ gdni.variant_construct = gdnative_variant_construct;
+ gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter;
+ gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter;
+ gdni.variant_get_ptr_indexed_setter = gdnative_variant_get_ptr_indexed_setter;
+ gdni.variant_get_ptr_indexed_getter = gdnative_variant_get_ptr_indexed_getter;
+ gdni.variant_get_ptr_keyed_setter = gdnative_variant_get_ptr_keyed_setter;
+ gdni.variant_get_ptr_keyed_getter = gdnative_variant_get_ptr_keyed_getter;
+ gdni.variant_get_ptr_keyed_checker = gdnative_variant_get_ptr_keyed_checker;
+ gdni.variant_get_constant_value = gdnative_variant_get_constant_value;
+ gdni.variant_get_ptr_utility_function = gdnative_variant_get_ptr_utility_function;
+
+ // extra utilities
+
+ gdni.string_new_with_latin1_chars = gdnative_string_new_with_latin1_chars;
+ gdni.string_new_with_utf8_chars = gdnative_string_new_with_utf8_chars;
+ gdni.string_new_with_utf16_chars = gdnative_string_new_with_utf16_chars;
+ gdni.string_new_with_utf32_chars = gdnative_string_new_with_utf32_chars;
+ gdni.string_new_with_wide_chars = gdnative_string_new_with_wide_chars;
+ gdni.string_new_with_latin1_chars_and_len = gdnative_string_new_with_latin1_chars_and_len;
+ gdni.string_new_with_utf8_chars_and_len = gdnative_string_new_with_utf8_chars_and_len;
+ gdni.string_new_with_utf16_chars_and_len = gdnative_string_new_with_utf16_chars_and_len;
+ gdni.string_new_with_utf32_chars_and_len = gdnative_string_new_with_utf32_chars_and_len;
+ gdni.string_new_with_wide_chars_and_len = gdnative_string_new_with_wide_chars_and_len;
+ gdni.string_to_latin1_chars = gdnative_string_to_latin1_chars;
+ gdni.string_to_utf8_chars = gdnative_string_to_utf8_chars;
+ gdni.string_to_utf16_chars = gdnative_string_to_utf16_chars;
+ gdni.string_to_utf32_chars = gdnative_string_to_utf32_chars;
+ gdni.string_to_wide_chars = gdnative_string_to_wide_chars;
+ gdni.string_operator_index = gdnative_string_operator_index;
+ gdni.string_operator_index_const = gdnative_string_operator_index_const;
+
+ /* OBJECT */
+
+ gdni.object_method_bind_ptrcall = gdnative_object_method_bind_ptrcall;
+ gdni.object_destroy = gdnative_object_destroy;
+ gdni.global_get_singleton = gdnative_global_get_singleton;
+ gdni.object_get_instance_binding = gdnative_object_get_instance_binding;
+
+ gdni.object_cast_to = gdnative_object_cast_to;
+ gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id;
+ gdni.object_get_instance_id = gdnative_object_get_instance_id;
+
+ /* CLASSDB */
+
+ gdni.classdb_get_constructor = gdnative_classdb_get_constructor;
+ gdni.classdb_get_method_bind = gdnative_classdb_get_method_bind;
+ gdni.classdb_get_class_tag = gdnative_classdb_get_class_tag;
+
+ /* CLASSDB EXTENSION */
+
+ //these are filled by implementation, since it will want to keep track of registered classes
+ gdni.classdb_register_extension_class = nullptr;
+ gdni.classdb_register_extension_class_method = nullptr;
+ gdni.classdb_register_extension_class_integer_constant = nullptr;
+ gdni.classdb_register_extension_class_property = nullptr;
+ gdni.classdb_register_extension_class_signal = nullptr;
+ gdni.classdb_unregister_extension_class = nullptr;
+}
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
new file mode 100644
index 0000000000..c1ebb3e76a
--- /dev/null
+++ b/core/extension/gdnative_interface.h
@@ -0,0 +1,438 @@
+/*************************************************************************/
+/* gdnative_interface.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GDNATIVE_INTERFACE_H
+#define GDNATIVE_INTERFACE_H
+
+/* This is a C class header, you can copy it and use it directly in your own binders.
+ * Together with the JSON file, you should be able to generate any binder.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* VARIANT TYPES */
+
+typedef enum {
+ GDNATIVE_VARIANT_TYPE_NIL,
+
+ /* atomic types */
+ GDNATIVE_VARIANT_TYPE_BOOL,
+ GDNATIVE_VARIANT_TYPE_INT,
+ GDNATIVE_VARIANT_TYPE_FLOAT,
+ GDNATIVE_VARIANT_TYPE_STRING,
+
+ /* math types */
+ GDNATIVE_VARIANT_TYPE_VECTOR2,
+ GDNATIVE_VARIANT_TYPE_VECTOR2I,
+ GDNATIVE_VARIANT_TYPE_RECT2,
+ GDNATIVE_VARIANT_TYPE_RECT2I,
+ GDNATIVE_VARIANT_TYPE_VECTOR3,
+ GDNATIVE_VARIANT_TYPE_VECTOR3I,
+ GDNATIVE_VARIANT_TYPE_TRANSFORM2D,
+ GDNATIVE_VARIANT_TYPE_PLANE,
+ GDNATIVE_VARIANT_TYPE_QUATERNION,
+ GDNATIVE_VARIANT_TYPE_AABB,
+ GDNATIVE_VARIANT_TYPE_BASIS,
+ GDNATIVE_VARIANT_TYPE_TRANSFORM3D,
+
+ /* misc types */
+ GDNATIVE_VARIANT_TYPE_COLOR,
+ GDNATIVE_VARIANT_TYPE_STRING_NAME,
+ GDNATIVE_VARIANT_TYPE_NODE_PATH,
+ GDNATIVE_VARIANT_TYPE_RID,
+ GDNATIVE_VARIANT_TYPE_OBJECT,
+ GDNATIVE_VARIANT_TYPE_CALLABLE,
+ GDNATIVE_VARIANT_TYPE_SIGNAL,
+ GDNATIVE_VARIANT_TYPE_DICTIONARY,
+ GDNATIVE_VARIANT_TYPE_ARRAY,
+
+ /* typed arrays */
+ GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
+ GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY,
+
+ GDNATIVE_VARIANT_TYPE_VARIANT_MAX
+} GDNativeVariantType;
+
+typedef enum {
+ /* comparison */
+ GDNATIVE_VARIANT_OP_EQUAL,
+ GDNATIVE_VARIANT_OP_NOT_EQUAL,
+ GDNATIVE_VARIANT_OP_LESS,
+ GDNATIVE_VARIANT_OP_LESS_EQUAL,
+ GDNATIVE_VARIANT_OP_GREATER,
+ GDNATIVE_VARIANT_OP_GREATER_EQUAL,
+ /* mathematic */
+ GDNATIVE_VARIANT_OP_ADD,
+ GDNATIVE_VARIANT_OP_SUBTRACT,
+ GDNATIVE_VARIANT_OP_MULTIPLY,
+ GDNATIVE_VARIANT_OP_DIVIDE,
+ GDNATIVE_VARIANT_OP_NEGATE,
+ GDNATIVE_VARIANT_OP_POSITIVE,
+ GDNATIVE_VARIANT_OP_MODULE,
+ /* bitwise */
+ GDNATIVE_VARIANT_OP_SHIFT_LEFT,
+ GDNATIVE_VARIANT_OP_SHIFT_RIGHT,
+ GDNATIVE_VARIANT_OP_BIT_AND,
+ GDNATIVE_VARIANT_OP_BIT_OR,
+ GDNATIVE_VARIANT_OP_BIT_XOR,
+ GDNATIVE_VARIANT_OP_BIT_NEGATE,
+ /* logic */
+ GDNATIVE_VARIANT_OP_AND,
+ GDNATIVE_VARIANT_OP_OR,
+ GDNATIVE_VARIANT_OP_XOR,
+ GDNATIVE_VARIANT_OP_NOT,
+ /* containment */
+ GDNATIVE_VARIANT_OP_IN,
+ GDNATIVE_VARIANT_OP_MAX
+
+} GDNativeVariantOperator;
+
+typedef void *GDNativeVariantPtr;
+typedef void *GDNativeStringNamePtr;
+typedef void *GDNativeStringPtr;
+typedef void *GDNativeObjectPtr;
+typedef void *GDNativeTypePtr;
+typedef void *GDNativeMethodBindPtr;
+typedef int64_t GDNativeInt;
+typedef uint32_t GDNativeBool;
+typedef uint64_t GDObjectInstanceID;
+
+/* VARIANT DATA I/O */
+
+typedef enum {
+ NATIVE_CALL_OK,
+ NATIVE_CALL_ERROR_INVALID_METHOD,
+ NATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */
+ NATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */
+ NATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */
+ NATIVE_CALL_ERROR_INSTANCE_IS_NULL,
+
+} GDNativeCallErrorType;
+
+typedef struct {
+ GDNativeCallErrorType error;
+ int32_t argument;
+ int32_t expected;
+} GDNativeCallError;
+
+typedef void (*GDNativeVariantFromTypeConstructorFunc)(GDNativeVariantPtr, GDNativeTypePtr);
+typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNativeVariantPtr);
+typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result);
+typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count);
+typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args);
+typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value);
+typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value);
+typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value);
+typedef void (*GDNativePtrIndexedGetter)(const GDNativeTypePtr p_base, GDNativeInt p_index, GDNativeTypePtr r_value);
+typedef void (*GDNativePtrKeyedSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_key, const GDNativeTypePtr p_value);
+typedef void (*GDNativePtrKeyedGetter)(const GDNativeTypePtr p_base, const GDNativeTypePtr p_key, GDNativeTypePtr r_value);
+typedef uint32_t (*GDNativePtrKeyedChecker)(const GDNativeVariantPtr p_base, const GDNativeVariantPtr p_key);
+typedef void (*GDNativePtrUtilityFunction)(GDNativeTypePtr r_return, const GDNativeTypePtr *p_arguments, int p_argument_count);
+
+typedef GDNativeObjectPtr (*GDNativeClassConstructor)();
+
+typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_instance);
+typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding);
+typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_instance, GDNativeBool p_reference);
+
+struct GDNativeInstanceBindingCallbacks {
+ GDNativeInstanceBindingCreateCallback create_callback;
+ GDNativeInstanceBindingFreeCallback free_callback;
+ GDNativeInstanceBindingReferenceCallback reference_callback;
+};
+
+/* EXTENSION CLASSES */
+
+typedef void *GDExtensionClassInstancePtr;
+
+typedef GDNativeBool (*GDNativeExtensionClassSet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
+typedef GDNativeBool (*GDNativeExtensionClassGet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
+
+typedef struct {
+ uint32_t type;
+ const char *name;
+ const char *class_name;
+ uint32_t hint;
+ const char *hint_string;
+ uint32_t usage;
+} GDNativePropertyInfo;
+
+typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
+typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list);
+typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
+typedef const char *(*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance);
+typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
+typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
+typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
+typedef GDExtensionClassInstancePtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
+typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
+typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
+
+typedef struct {
+ GDNativeExtensionClassSet set_func;
+ GDNativeExtensionClassGet get_func;
+ GDNativeExtensionClassGetPropertyList get_property_list_func;
+ GDNativeExtensionClassFreePropertyList free_property_list_func;
+ GDNativeExtensionClassNotification notification_func;
+ GDNativeExtensionClassToString to_string_func;
+ GDNativeExtensionClassReference reference_func;
+ GDNativeExtensionClassUnreference unreference_func;
+ GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
+ GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
+ GDNativeExtensionClassGetVirtual get_firtual_func;
+ void *class_userdata;
+} GDNativeExtensionClassCreationInfo;
+
+typedef void *GDNativeExtensionClassLibraryPtr;
+
+typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
+
+/* Method */
+
+typedef enum {
+ GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL = 1,
+ GDNATIVE_EXTENSION_METHOD_FLAG_EDITOR = 2,
+ GDNATIVE_EXTENSION_METHOD_FLAG_NOSCRIPT = 4,
+ GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 8,
+ GDNATIVE_EXTENSION_METHOD_FLAG_REVERSE = 16, /* used for events */
+ GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 32,
+ GDNATIVE_EXTENSION_METHOD_FLAG_FROM_SCRIPT = 64,
+ GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 128,
+ GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 256,
+ GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT = GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL,
+} GDNativeExtensionClassMethodFlags;
+
+typedef enum {
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT,
+ GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
+} GDNativeExtensionClassMethodArgumentMetadata;
+
+typedef void (*GDNativeExtensionClassMethodCall)(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
+typedef void (*GDNativeExtensionClassMethodPtrCall)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
+
+/* passing -1 as argument in the following functions refers to the return type */
+typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument);
+typedef void (*GDNativeExtensionClassMethodGetArgumentInfo)(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info);
+typedef GDNativeExtensionClassMethodArgumentMetadata (*GDNativeExtensionClassMethodGetArgumentMetadata)(void *p_method_userdata, int32_t p_argument);
+
+typedef struct {
+ const char *name;
+ void *method_userdata;
+ GDNativeExtensionClassMethodCall call_func;
+ GDNativeExtensionClassMethodPtrCall ptrcall_func;
+ uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */
+ uint32_t argument_count;
+ GDNativeBool has_return_value;
+ GDNativeExtensionClassMethodGetArgumentType get_argument_type_func;
+ GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
+ GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
+ uint32_t default_argument_count;
+ GDNativeVariantPtr *default_arguments;
+} GDNativeExtensionClassMethodInfo;
+
+/* INTERFACE */
+
+typedef struct {
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t version_patch;
+ const char *version_string;
+
+ /* GODOT CORE */
+ void *(*mem_alloc)(size_t p_bytes);
+ void *(*mem_realloc)(void *p_ptr, size_t p_bytes);
+ void (*mem_free)(void *p_ptr);
+
+ void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
+ void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
+ void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
+
+ /* GODOT VARIANT */
+
+ /* variant general */
+ void (*variant_new_copy)(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src);
+ void (*variant_new_nil)(GDNativeVariantPtr r_dest);
+ void (*variant_destroy)(GDNativeVariantPtr p_self);
+
+ /* variant type */
+ void (*variant_call)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
+ void (*variant_call_static)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
+ void (*variant_evaluate)(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid);
+ void (*variant_set)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
+ void (*variant_set_named)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
+ void (*variant_set_keyed)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid);
+ void (*variant_set_indexed)(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob);
+ void (*variant_get)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
+ void (*variant_get_named)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
+ void (*variant_get_keyed)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
+ void (*variant_get_indexed)(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob);
+ GDNativeBool (*variant_iter_init)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid);
+ GDNativeBool (*variant_iter_next)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid);
+ 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_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);
+ void (*variant_stringify)(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret);
+
+ GDNativeVariantType (*variant_get_type)(const GDNativeVariantPtr p_self);
+ GDNativeBool (*variant_has_method)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method);
+ GDNativeBool (*variant_has_member)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member);
+ GDNativeBool (*variant_has_key)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid);
+ void (*variant_get_type_name)(GDNativeVariantType p_type, GDNativeStringPtr r_name);
+ GDNativeBool (*variant_can_convert)(GDNativeVariantType p_from, GDNativeVariantType p_to);
+ GDNativeBool (*variant_can_convert_strict)(GDNativeVariantType p_from, GDNativeVariantType p_to);
+
+ /* ptrcalls */
+ GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
+ GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
+ GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b);
+ GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash);
+ GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor);
+ void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error);
+ GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member);
+ GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member);
+ GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type);
+ GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type);
+ GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type);
+ GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type);
+ GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type);
+ void (*variant_get_constant_value)(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret);
+ GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const char *p_function, GDNativeInt p_hash);
+
+ /* extra utilities */
+
+ void (*string_new_with_latin1_chars)(GDNativeStringPtr r_dest, const char *p_contents);
+ void (*string_new_with_utf8_chars)(GDNativeStringPtr r_dest, const char *p_contents);
+ void (*string_new_with_utf16_chars)(GDNativeStringPtr r_dest, const char16_t *p_contents);
+ void (*string_new_with_utf32_chars)(GDNativeStringPtr r_dest, const char32_t *p_contents);
+ void (*string_new_with_wide_chars)(GDNativeStringPtr r_dest, const wchar_t *p_contents);
+ void (*string_new_with_latin1_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size);
+ void (*string_new_with_utf8_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size);
+ void (*string_new_with_utf16_chars_and_len)(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size);
+ void (*string_new_with_utf32_chars_and_len)(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size);
+ void (*string_new_with_wide_chars_and_len)(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size);
+ /* Information about the following functions:
+ * - The return value is the resulting encoded string length.
+ * - The length returned is in characters, not in bytes. It also does not include a trailing zero.
+ * - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it).
+ * - Passing NULL in r_text means only the length is computed (again, without including trailing zero).
+ * - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL.
+ * - p_max_write_length argument does not affect the return value, it's only to cap write length.
+ */
+ GDNativeInt (*string_to_latin1_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length);
+ GDNativeInt (*string_to_utf8_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length);
+ GDNativeInt (*string_to_utf16_chars)(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length);
+ GDNativeInt (*string_to_utf32_chars)(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length);
+ GDNativeInt (*string_to_wide_chars)(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length);
+ char32_t *(*string_operator_index)(GDNativeStringPtr p_self, GDNativeInt p_index);
+ const char32_t *(*string_operator_index_const)(const GDNativeStringPtr p_self, GDNativeInt p_index);
+
+ /* OBJECT */
+
+ void (*object_method_bind_ptrcall)(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
+ void (*object_destroy)(GDNativeObjectPtr p_o);
+ GDNativeObjectPtr (*global_get_singleton)(const char *p_name);
+ void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks);
+
+ GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag);
+ GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
+ GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object);
+
+ /* CLASSDB */
+
+ GDNativeClassConstructor (*classdb_get_constructor)(const char *p_classname);
+ GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash);
+ void *(*classdb_get_class_tag)(const char *p_classname);
+
+ /* CLASSDB EXTENSION */
+
+ void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
+ void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
+ void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_enum_name, const char *p_class_name, const char *p_constant_name, uint32_t p_constant_value);
+ void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
+ void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
+ void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
+} GDNativeInterface;
+
+/* INITIALIZATION */
+
+typedef enum {
+ GDNATIVE_INITIALIZATION_CORE,
+ GDNATIVE_INITIALIZATION_SERVERS,
+ GDNATIVE_INITIALIZATION_SCENE,
+ GDNATIVE_INITIALIZATION_EDITOR,
+} GDNativeInitializationLevel;
+
+typedef struct {
+ /* Minimum initialization level required.
+ * If Core or Servers, the extension needs editor or game restart to take effect */
+ GDNativeInitializationLevel minimum_initialization_level;
+ /* Up to the user to supply when initializing */
+ void *userdata;
+ /* This function will be called multiple times for each initialization level. */
+ void (*initialize)(void *userdata, GDNativeInitializationLevel p_level);
+ void (*deinitialize)(void *userdata, GDNativeInitializationLevel p_level);
+} GDNativeInitialization;
+
+/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar).
+ * It will be called on initialization. The name must be an unique one specified in the .gdextension config file.
+ */
+
+typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
new file mode 100644
index 0000000000..65718a7507
--- /dev/null
+++ b/core/extension/native_extension.cpp
@@ -0,0 +1,411 @@
+/*************************************************************************/
+/* native_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "native_extension.h"
+#include "core/io/config_file.h"
+#include "core/object/class_db.h"
+#include "core/object/method_bind.h"
+#include "core/os/os.h"
+
+class NativeExtensionMethodBind : public MethodBind {
+ GDNativeExtensionClassMethodCall call_func;
+ GDNativeExtensionClassMethodPtrCall ptrcall_func;
+ GDNativeExtensionClassMethodGetArgumentType get_argument_type_func;
+ GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func;
+ GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
+ void *method_userdata;
+ bool vararg;
+
+protected:
+ virtual Variant::Type _gen_argument_type(int p_arg) const {
+ return Variant::Type(get_argument_type_func(method_userdata, p_arg));
+ }
+ virtual PropertyInfo _gen_argument_type_info(int p_arg) const {
+ GDNativePropertyInfo pinfo;
+ get_argument_info_func(method_userdata, p_arg, &pinfo);
+ PropertyInfo ret;
+ ret.type = Variant::Type(pinfo.type);
+ ret.name = pinfo.name;
+ ret.class_name = pinfo.class_name;
+ ret.hint = PropertyHint(pinfo.hint);
+ ret.usage = pinfo.usage;
+ ret.class_name = pinfo.class_name;
+ return ret;
+ }
+
+public:
+ virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
+ return GodotTypeInfo::Metadata(get_argument_metadata_func(method_userdata, p_arg));
+ }
+
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ Variant ret;
+ GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
+ GDNativeCallError ce;
+ call_func(extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
+ r_error.error = Callable::CallError::Error(ce.error);
+ r_error.argument = ce.argument;
+ r_error.expected = ce.expected;
+ return ret;
+ }
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
+ ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug.");
+ GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
+ ptrcall_func(extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret);
+ }
+
+ virtual bool is_vararg() const {
+ return false;
+ }
+ NativeExtensionMethodBind(const GDNativeExtensionClassMethodInfo *p_method_info) {
+ method_userdata = p_method_info->method_userdata;
+ call_func = p_method_info->call_func;
+ ptrcall_func = p_method_info->ptrcall_func;
+ get_argument_type_func = p_method_info->get_argument_type_func;
+ get_argument_info_func = p_method_info->get_argument_info_func;
+ get_argument_metadata_func = p_method_info->get_argument_metadata_func;
+
+ vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG;
+
+ _set_returns(p_method_info->has_return_value);
+ _set_const(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_CONST);
+#ifdef DEBUG_METHODS_ENABLED
+ _generate_argument_types(p_method_info->argument_count);
+#endif
+ set_argument_count(p_method_info->argument_count);
+ }
+};
+
+static GDNativeInterface gdnative_interface;
+
+void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(String(class_name).is_valid_identifier(), "Attempt to register extension clas '" + class_name + "', which is not a valid class identifier.");
+ ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
+
+ Extension *parent_extension = nullptr;
+ StringName parent_class_name = p_parent_class_name;
+
+ if (self->extension_classes.has(parent_class_name)) {
+ parent_extension = &self->extension_classes[parent_class_name];
+ } else if (ClassDB::class_exists(parent_class_name)) {
+ if (ClassDB::get_api_type(parent_class_name) == ClassDB::API_EXTENSION || ClassDB::get_api_type(parent_class_name) == ClassDB::API_EDITOR_EXTENSION) {
+ ERR_PRINT("Unimplemented yet");
+ //inheriting from another extension
+ } else {
+ //inheriting from engine class
+ }
+ } else {
+ ERR_FAIL_MSG("Attempt to register an extension class '" + String(class_name) + "' using non-existing parent class '" + String(parent_class_name) + "'");
+ }
+
+ self->extension_classes[class_name] = Extension();
+
+ Extension *extension = &self->extension_classes[class_name];
+
+ if (parent_extension) {
+ extension->native_extension.parent = &parent_extension->native_extension;
+ parent_extension->native_extension.children.push_back(&extension->native_extension);
+ }
+
+ extension->native_extension.parent_class_name = parent_class_name;
+ extension->native_extension.class_name = class_name;
+ extension->native_extension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR;
+ extension->native_extension.set = p_extension_funcs->set_func;
+ extension->native_extension.get = p_extension_funcs->get_func;
+ extension->native_extension.get_property_list = p_extension_funcs->get_property_list_func;
+ extension->native_extension.free_property_list = p_extension_funcs->free_property_list_func;
+ extension->native_extension.notification = p_extension_funcs->notification_func;
+ extension->native_extension.to_string = p_extension_funcs->to_string_func;
+ extension->native_extension.reference = p_extension_funcs->reference_func;
+ extension->native_extension.unreference = p_extension_funcs->unreference_func;
+ extension->native_extension.class_userdata = p_extension_funcs->class_userdata;
+ extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
+ extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
+
+ ClassDB::register_extension_class(&extension->native_extension);
+}
+void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ StringName method_name = p_method_info->name;
+ ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
+
+ //Extension *extension = &self->extension_classes[class_name];
+
+ NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info));
+
+ ClassDB::bind_method_custom(class_name, method);
+}
+void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
+
+ //Extension *extension = &self->extension_classes[class_name];
+
+ ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value);
+}
+void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
+
+ //Extension *extension = &self->extension_classes[class_name];
+ PropertyInfo pinfo;
+ pinfo.type = Variant::Type(p_info->type);
+ pinfo.name = p_info->name;
+ pinfo.class_name = p_info->class_name;
+ pinfo.hint = PropertyHint(p_info->hint);
+ pinfo.hint_string = p_info->hint_string;
+ pinfo.usage = p_info->usage;
+
+ ClassDB::add_property(class_name, pinfo, p_setter, p_getter);
+}
+
+void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
+
+ MethodInfo s;
+ s.name = p_signal_name;
+ for (int i = 0; i < p_argument_count; i++) {
+ PropertyInfo arg;
+ arg.type = Variant::Type(p_argument_info[i].type);
+ arg.name = p_argument_info[i].name;
+ arg.class_name = p_argument_info[i].class_name;
+ arg.hint = PropertyHint(p_argument_info[i].hint);
+ arg.hint_string = p_argument_info[i].hint_string;
+ arg.usage = p_argument_info[i].usage;
+ s.arguments.push_back(arg);
+ }
+ ClassDB::add_signal(class_name, s);
+}
+
+void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
+ Extension *ext = &self->extension_classes[class_name];
+ ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
+
+ ClassDB::unregister_extension_class(class_name);
+ if (ext->native_extension.parent != nullptr) {
+ ext->native_extension.parent->children.erase(&ext->native_extension);
+ }
+ self->extension_classes.erase(class_name);
+}
+
+Error NativeExtension::open_library(const String &p_path, const String &p_entry_symbol) {
+ Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true);
+ if (err != OK) {
+ return err;
+ }
+
+ void *entry_funcptr = nullptr;
+
+ err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false);
+
+ if (err != OK) {
+ OS::get_singleton()->close_dynamic_library(library);
+ return err;
+ }
+
+ GDNativeInitializationFunction initialization_function = (GDNativeInitializationFunction)entry_funcptr;
+
+ initialization_function(&gdnative_interface, this, &initialization);
+ level_initialized = -1;
+ return OK;
+}
+
+void NativeExtension::close_library() {
+ ERR_FAIL_COND(library == nullptr);
+ OS::get_singleton()->close_dynamic_library(library);
+
+ library = nullptr;
+}
+
+bool NativeExtension::is_library_open() const {
+ return library != nullptr;
+}
+
+NativeExtension::InitializationLevel NativeExtension::get_minimum_library_initialization_level() const {
+ ERR_FAIL_COND_V(library == nullptr, INITIALIZATION_LEVEL_CORE);
+ return InitializationLevel(initialization.minimum_initialization_level);
+}
+void NativeExtension::initialize_library(InitializationLevel p_level) {
+ ERR_FAIL_COND(library == nullptr);
+ ERR_FAIL_COND(p_level <= int32_t(level_initialized));
+
+ level_initialized = int32_t(p_level);
+
+ ERR_FAIL_COND(initialization.initialize == nullptr);
+
+ initialization.initialize(initialization.userdata, GDNativeInitializationLevel(p_level));
+}
+void NativeExtension::deinitialize_library(InitializationLevel p_level) {
+ ERR_FAIL_COND(library == nullptr);
+ ERR_FAIL_COND(p_level > int32_t(level_initialized));
+
+ level_initialized = int32_t(p_level) - 1;
+ initialization.deinitialize(initialization.userdata, GDNativeInitializationLevel(p_level));
+}
+
+void NativeExtension::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &NativeExtension::open_library);
+ ClassDB::bind_method(D_METHOD("close_library"), &NativeExtension::close_library);
+ ClassDB::bind_method(D_METHOD("is_library_open"), &NativeExtension::is_library_open);
+
+ ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &NativeExtension::get_minimum_library_initialization_level);
+ ClassDB::bind_method(D_METHOD("initialize_library", "level"), &NativeExtension::initialize_library);
+
+ BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_CORE);
+ BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SERVERS);
+ BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SCENE);
+ BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_EDITOR);
+}
+
+NativeExtension::NativeExtension() {
+}
+
+NativeExtension::~NativeExtension() {
+ if (library != nullptr) {
+ close_library();
+ }
+}
+
+extern void gdnative_setup_interface(GDNativeInterface *p_interface);
+
+void NativeExtension::initialize_native_extensions() {
+ gdnative_setup_interface(&gdnative_interface);
+
+ gdnative_interface.classdb_register_extension_class = _register_extension_class;
+ gdnative_interface.classdb_register_extension_class_method = _register_extension_class_method;
+ gdnative_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant;
+ gdnative_interface.classdb_register_extension_class_property = _register_extension_class_property;
+ gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
+ gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class;
+}
+
+RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+ Ref<ConfigFile> config;
+ config.instantiate();
+
+ Error err = config->load(p_path);
+
+ if (r_error) {
+ *r_error = err;
+ }
+
+ if (err != OK) {
+ return RES();
+ }
+
+ if (!config->has_section_key("configuration", "entry_symbol")) {
+ if (r_error) {
+ *r_error = ERR_INVALID_DATA;
+ }
+ return RES();
+ }
+
+ String entry_symbol = config->get_value("configuration", "entry_symbol");
+
+ List<String> libraries;
+
+ config->get_section_keys("libraries", &libraries);
+
+ String library_path;
+
+ for (List<String>::Element *E = libraries.front(); E; E = E->next()) {
+ Vector<String> tags = E->get().split(".");
+ bool all_tags_met = true;
+ for (int i = 0; i < tags.size(); i++) {
+ String tag = tags[i].strip_edges();
+ if (!OS::get_singleton()->has_feature(tag)) {
+ all_tags_met = false;
+ break;
+ }
+ }
+
+ if (all_tags_met) {
+ library_path = config->get_value("libraries", E->get());
+ break;
+ }
+ }
+
+ if (library_path != String()) {
+ if (r_error) {
+ *r_error = ERR_FILE_NOT_FOUND;
+ }
+ return RES();
+ }
+
+ if (!library_path.is_resource_file()) {
+ library_path = p_path.get_base_dir().plus_file(library_path);
+ }
+
+ Ref<NativeExtension> lib;
+ lib.instantiate();
+ err = lib->open_library(library_path, entry_symbol);
+
+ if (r_error) {
+ *r_error = err;
+ }
+
+ if (err != OK) {
+ return RES();
+ }
+
+ return lib;
+}
+
+void NativeExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("gdextension");
+}
+
+bool NativeExtensionResourceLoader::handles_type(const String &p_type) const {
+ return p_type == "NativeExtension";
+}
+
+String NativeExtensionResourceLoader::get_resource_type(const String &p_path) const {
+ String el = p_path.get_extension().to_lower();
+ if (el == "gdextension") {
+ return "NativeExtension";
+ }
+ return "";
+}
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
new file mode 100644
index 0000000000..0a23848eb2
--- /dev/null
+++ b/core/extension/native_extension.h
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* native_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef NATIVE_EXTENSION_H
+#define NATIVE_EXTENSION_H
+
+#include "core/extension/gdnative_interface.h"
+#include "core/io/resource_loader.h"
+#include "core/object/ref_counted.h"
+
+class NativeExtension : public RefCounted {
+ GDCLASS(NativeExtension, RefCounted)
+
+ void *library = nullptr; // pointer if valid,
+
+ struct Extension {
+ ObjectNativeExtension native_extension;
+ };
+
+ Map<StringName, Extension> extension_classes;
+
+ static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
+ static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
+ static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value);
+ static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
+ static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
+ static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
+
+ GDNativeInitialization initialization;
+ int32_t level_initialized = -1;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Error open_library(const String &p_path, const String &p_entry_symbol);
+ void close_library();
+
+ enum InitializationLevel {
+ INITIALIZATION_LEVEL_CORE,
+ INITIALIZATION_LEVEL_SERVERS,
+ INITIALIZATION_LEVEL_SCENE,
+ INITIALIZATION_LEVEL_EDITOR,
+ };
+
+ bool is_library_open() const;
+
+ InitializationLevel get_minimum_library_initialization_level() const;
+ void initialize_library(InitializationLevel p_level);
+ void deinitialize_library(InitializationLevel p_level);
+
+ static void initialize_native_extensions();
+ NativeExtension();
+ ~NativeExtension();
+};
+
+VARIANT_ENUM_CAST(NativeExtension::InitializationLevel)
+
+class NativeExtensionResourceLoader : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path, const String &p_original_path, Error *r_error, 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;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+#endif // NATIVEEXTENSION_H
diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp
new file mode 100644
index 0000000000..7be2593845
--- /dev/null
+++ b/core/extension/native_extension_manager.cpp
@@ -0,0 +1,130 @@
+/*************************************************************************/
+/* native_extension_manager.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "native_extension_manager.h"
+
+NativeExtensionManager::LoadStatus NativeExtensionManager::load_extension(const String &p_path) {
+ if (native_extension_map.has(p_path)) {
+ return LOAD_STATUS_ALREADY_LOADED;
+ }
+ Ref<NativeExtension> extension = ResourceLoader::load(p_path);
+ if (extension.is_null()) {
+ return LOAD_STATUS_FAILED;
+ }
+
+ if (level >= 0) { //already initialized up to some level
+ int32_t minimum_level = extension->get_minimum_library_initialization_level();
+ if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) {
+ return LOAD_STATUS_NEEDS_RESTART;
+ }
+ //initialize up to current level
+ for (int32_t i = minimum_level; i < level; i++) {
+ extension->initialize_library(NativeExtension::InitializationLevel(level));
+ }
+ }
+ native_extension_map[p_path] = extension;
+ return LOAD_STATUS_OK;
+}
+
+NativeExtensionManager::LoadStatus NativeExtensionManager::reload_extension(const String &p_path) {
+ return LOAD_STATUS_OK; //TODO
+}
+NativeExtensionManager::LoadStatus NativeExtensionManager::unload_extension(const String &p_path) {
+ if (!native_extension_map.has(p_path)) {
+ return LOAD_STATUS_NOT_LOADED;
+ }
+
+ Ref<NativeExtension> extension = native_extension_map[p_path];
+
+ if (level >= 0) { //already initialized up to some level
+ int32_t minimum_level = extension->get_minimum_library_initialization_level();
+ if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) {
+ return LOAD_STATUS_NEEDS_RESTART;
+ }
+ //initialize up to current level
+ for (int32_t i = level; i >= minimum_level; i--) {
+ extension->deinitialize_library(NativeExtension::InitializationLevel(level));
+ }
+ }
+ native_extension_map.erase(p_path);
+ return LOAD_STATUS_OK;
+}
+Vector<String> NativeExtensionManager::get_loaded_extensions() const {
+ Vector<String> ret;
+ for (const Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
+ ret.push_back(E->key());
+ }
+ return ret;
+}
+Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path) {
+ Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.find(p_path);
+ ERR_FAIL_COND_V(!E, Ref<NativeExtension>());
+ return E->get();
+}
+
+void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) {
+ ERR_FAIL_COND(int32_t(p_level) - 1 != level);
+ for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
+ E->get()->initialize_library(p_level);
+ }
+ level = p_level;
+}
+
+void NativeExtensionManager::deinitialize_extensions(NativeExtension::InitializationLevel p_level) {
+ ERR_FAIL_COND(int32_t(p_level) != level);
+ for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
+ E->get()->deinitialize_library(p_level);
+ }
+ level = int32_t(p_level) - 1;
+}
+
+NativeExtensionManager *NativeExtensionManager::get_singleton() {
+ return singleton;
+}
+void NativeExtensionManager::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("load_extension", "path"), &NativeExtensionManager::load_extension);
+ ClassDB::bind_method(D_METHOD("reload_extension", "path"), &NativeExtensionManager::reload_extension);
+ ClassDB::bind_method(D_METHOD("unload_extension", "path"), &NativeExtensionManager::unload_extension);
+ ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &NativeExtensionManager::get_loaded_extensions);
+ ClassDB::bind_method(D_METHOD("get_extension", "path"), &NativeExtensionManager::get_extension);
+
+ BIND_ENUM_CONSTANT(LOAD_STATUS_OK);
+ BIND_ENUM_CONSTANT(LOAD_STATUS_FAILED);
+ BIND_ENUM_CONSTANT(LOAD_STATUS_ALREADY_LOADED);
+ BIND_ENUM_CONSTANT(LOAD_STATUS_NOT_LOADED);
+ BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART);
+}
+
+NativeExtensionManager *NativeExtensionManager::singleton = nullptr;
+
+NativeExtensionManager::NativeExtensionManager() {
+ ERR_FAIL_COND(singleton != nullptr);
+ singleton = this;
+}
diff --git a/scene/3d/immediate_geometry_3d.h b/core/extension/native_extension_manager.h
index ee4938d9f7..78465bd5cf 100644
--- a/scene/3d/immediate_geometry_3d.h
+++ b/core/extension/native_extension_manager.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* immediate_geometry_3d.h */
+/* native_extension_manager.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,45 +28,44 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef IMMEDIATE_GEOMETRY_3D_H
-#define IMMEDIATE_GEOMETRY_3D_H
+#ifndef NATIVE_EXTENSION_MANAGER_H
+#define NATIVE_EXTENSION_MANAGER_H
-#include "scene/3d/visual_instance_3d.h"
-#include "scene/resources/mesh.h"
+#include "core/extension/native_extension.h"
-class ImmediateGeometry3D : public GeometryInstance3D {
- GDCLASS(ImmediateGeometry3D, GeometryInstance3D);
+class NativeExtensionManager : public Object {
+ GDCLASS(NativeExtensionManager, Object);
- RID im;
- //a list of textures drawn need to be kept, to avoid references
- // in RenderingServer from becoming invalid if the texture is no longer used
- List<Ref<Texture2D>> cached_textures;
- bool empty = true;
- AABB aabb;
+ int32_t level = -1;
+ Map<String, Ref<NativeExtension>> native_extension_map;
-protected:
static void _bind_methods();
-public:
- void begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture = Ref<Texture2D>());
- void set_normal(const Vector3 &p_normal);
- void set_tangent(const Plane &p_tangent);
- void set_color(const Color &p_color);
- void set_uv(const Vector2 &p_uv);
- void set_uv2(const Vector2 &p_uv2);
+ static NativeExtensionManager *singleton;
- void add_vertex(const Vector3 &p_vertex);
+public:
+ enum LoadStatus {
+ LOAD_STATUS_OK,
+ LOAD_STATUS_FAILED,
+ LOAD_STATUS_ALREADY_LOADED,
+ LOAD_STATUS_NOT_LOADED,
+ LOAD_STATUS_NEEDS_RESTART,
+ };
- void end();
- void clear();
+ LoadStatus load_extension(const String &p_path);
+ LoadStatus reload_extension(const String &p_path);
+ LoadStatus unload_extension(const String &p_path);
+ Vector<String> get_loaded_extensions() const;
+ Ref<NativeExtension> get_extension(const String &p_path);
- void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true);
+ void initialize_extensions(NativeExtension::InitializationLevel p_level);
+ void deinitialize_extensions(NativeExtension::InitializationLevel p_level);
- virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
+ static NativeExtensionManager *get_singleton();
- ImmediateGeometry3D();
- ~ImmediateGeometry3D();
+ NativeExtensionManager();
};
-#endif // IMMEDIATE_GEOMETRY_H
+VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus)
+
+#endif // NATIVEEXTENSIONMANAGER_H
diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt
index 884fb9550c..f136d83496 100644
--- a/core/input/gamecontrollerdb.txt
+++ b/core/input/gamecontrollerdb.txt
@@ -4,19 +4,24 @@
# Windows
03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
03000000c82d000011ab000000000000,8BitDo F30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000151000000000000,8BitDo M30 ModKit,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows,
03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000061000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
@@ -24,19 +29,22 @@
03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003028000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
030000008f0e00001200000000000000,Acme GA-02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000c01100000355000011010000,ACRUX USB GAME PAD,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000fa190000f0ff000000000000,Acteck AGJ-3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -49,7 +57,9 @@
030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d62000001d57000000000000,Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000869800002400000000007801,Astro C40 TR,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows,
+03000000ef0500000300000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
03000000d6200000e557000000000000,Batarang,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,
030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -65,7 +75,7 @@
03000000808300000300000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
-03000000120c0000210e000000000000,Brook Mars,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+03000000120c0000210e000000000000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -106,7 +116,6 @@
03000000ac0500004d04000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000006f0e00000102000000007801,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000009b2800003200000000000000,GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800006000000000000000,GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
@@ -157,6 +166,7 @@
030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,
030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
+03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000bd12000003c0000000000000,JY-P70UR,a:b1,b:b0,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b4,x:b3,y:b2,platform:Windows,
03000000242f00002d00000000000000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000242f00008a00000000000000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
@@ -184,6 +194,7 @@
03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
+030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
@@ -202,6 +213,8 @@
03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
030000006b140000010c000000000000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000921200004b46000000000000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
+03000000790000004518000000000000,NEXILUX GAMECUBE Controller Adapter,platform:Windows,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,
030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,
03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
@@ -217,6 +230,7 @@
030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -241,6 +255,7 @@
030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000ff000000cb01000000000000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,
03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,
@@ -292,7 +307,6 @@
030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
03000000a30c00002500000000000000,Sega Genesis Mini 3B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
03000000a30c00002400000000000000,Sega Mega Drive Mini 6B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
-030000005e0400008e02000000007801,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000908000000000000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000008f0e00000800000000000000,SpeedLink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -337,8 +351,7 @@
030000006f0e00000702000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows,
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000005e040000ff02000000007801,Xbox One Elite Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000ac0500005b05000000000000,Xiaoji Gamesir-G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -362,6 +375,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00004028000000010000,8Bitdo SN30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Mac OS X,
03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
@@ -371,21 +385,28 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000a00500003232000009010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000ef0500000300000000020000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,
+03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,
+03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
-03000000120c0000200e000000010000,Brook Mars,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,
-03000000120c0000210e000000010000,Brook Mars,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
+03000000120c0000200e000000010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000120c0000210e000000010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000006f0e00000102000000000000,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000008f0e00000300000007010000,GreenAsia Inc. USB Joystick,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,
+03000000280400000140000000020000,Gravis Gamepad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000008f0e00000300000007010000,GreenAsia Inc. USB Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,
030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -416,11 +437,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000380700008433000000010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X,
0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,
+03000000790000000018000000010000,Mayflash Wii U Pro Controller Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
@@ -428,15 +451,19 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c62400002b89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000d620000011a7000010050000,Nintendo Switch PowerA Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,
030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
030000004c050000da0c000000010000,Playstation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -487,9 +514,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,
050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,
030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000006f0e00000104000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000050b000003090000,Xbox Elite Wireless Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c62400003a54000000000000,Xbox One PowerA Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
@@ -545,18 +574,28 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000007c1800000006000010010000,Alienware Dual Compatible Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
+05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
+03000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
+05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
+03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
+05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
+03000000ef0500000300000000010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000c21100000791000011010000,Be1 GC101 Controller 1.03 mode,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03 mode,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000005e0400008e02000003030000,Be1 GC101 Xbox 360 Controller mode,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
-03000000120c0000200e000011010000,Brook Mars,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
-03000000120c0000210e000011010000,Brook Mars,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,
+03000000120c0000200e000011010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000210e000011010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000ffff0000ffff000000010000,Chinese-made Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,
@@ -621,6 +660,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,
030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,
050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,
+03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000242f00002d00000011010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000242f00008a00000011010000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -650,8 +690,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000242f0000f700000001010000,Magic-S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
-03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004318000010010000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -681,15 +722,18 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
030000006b140000010c000010010000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000004518000010010000,NEXILUX GAMECUBE Controller Adapter,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,platform:Linux,
030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,
+060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,
-03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b0,y:b3,platform:Linux,
-050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b9,b:b8,x:b7,y:b10,back:b5,start:b0,leftstick:b6,leftshoulder:b2,rightshoulder:b4,leftx:a1,lefty:a0~,platform:Linux,
-050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,x:b0,y:b3,back:b9,start:b8,leftstick:b10,leftshoulder:b4,rightshoulder:b6,leftx:a1~,lefty:a0~,platform:Linux,
+03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
+050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b9,b:b8,back:b5,leftshoulder:b2,leftstick:b6,leftx:a1,lefty:a0~,rightshoulder:b4,start:b0,x:b7,y:b10,platform:Linux,
+030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
-030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0~,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
+050000007e0500001720000001000000,Nintendo Switch SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,
050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
@@ -717,8 +761,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
0500000049190000030400001b010000,PG-9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-05000000491900000204000000000000,PG-9118,a:b73,b:b74,back:b83,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b79,leftstick:b86,lefttrigger:b81,leftx:a0,lefty:a1,rightshoulder:b80,rightstick:b87,righttrigger:b82,rightx:a2,righty:a3,start:b84,x:b76,y:b77,platform:Linux,
+05000000491900000204000000000000,PG-9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -734,6 +779,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+050000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
@@ -755,7 +801,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000ff000000cb01000010010000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,
+030000009b2800004200000001010000,Raphnet Technologies Dual NES to USB v2.0,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux,
030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
030000009b2800006000000001010000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
@@ -792,7 +840,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000a306000020f6000011010000,Saitek PS2700 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux,
-03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,
03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000632500007505000010010000,SHANWAN PS3/PC Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000bc2000000055000010010000,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -800,17 +847,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000632500002305000010010000,ShanWan USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000341a00000908000010010000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000004c050000e60c000011810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
-030000004c050000e60c000000006800,Sony DualSense,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,
050000004c050000e60c000000810000,Sony DualSense ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
-030000004c050000e60c000000016800,Sony DualSense ,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,
03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
-03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
+03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
@@ -874,6 +919,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000005e040000120b000005050000,XBox Series pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000000010000,xbox360 Wireless EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000ac0500005b05000010010000,Xiaoji Gamesir-G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
@@ -900,7 +946,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android,
05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
-38383337343564366131323064613561,Brook Mars,a:b1,b:b19,x:b0,y:b2,leftshoulder:b3,rightshoulder:b20,lefttrigger:b9,righttrigger:b10,back:b17,start:b18,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b15,rightstick:b6,platform:Android,
+38383337343564366131323064613561,Brook Mars,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -916,9 +962,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005509000014720000df7f3f00,NVIDIA Controller v01.04,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
030000004c050000cc09000000006800,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
-050000004c050000cc090000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
@@ -933,9 +980,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000004f0400000ed00000fffe3f00,ThrustMaster eSwap PRO Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,
30306539356238653637313730656134,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000005e040000e00200000ffe3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android,
050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000005e04000091020000ff073f00,Xbox Wireless Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
@@ -953,13 +1005,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,
4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,
050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS,
050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,platform:iOS,
+050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS,
05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,
05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,
05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,
+050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
diff --git a/core/input/godotcontrollerdb.txt b/core/input/godotcontrollerdb.txt
index db612f04d2..5985b121c9 100644
--- a/core/input/godotcontrollerdb.txt
+++ b/core/input/godotcontrollerdb.txt
@@ -29,6 +29,8 @@ Linux0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshould
Windows0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,platform:Javascript
MacOSX0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a4,dpleft:-a3,dpdown:+a4,dpright:+a3,platform:Javascript
Linux046dc216,046d-c216-Logitech Logitech Dual Action,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:-a5,dpleft:-a4,dpdown:+a5,dpright:+a4,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Javascript
+Linux20d6a713,Bensussen Deutsch & Associates Inc.(BDA) NSW Wired controller,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:-a5,dpleft:-a4,dpdown:+a5,dpright:+a4,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Javascript
+Linux054c05c4,Sony Computer Entertainment Wireless Controller,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:-a7,dpleft:-a6,dpdown:+a7,dpright:+a6,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Javascript
# UWP
__UWP_GAMEPAD__,Xbox Controller,a:b2,b:b3,x:b4,y:b5,start:b0,back:b1,leftstick:b12,rightstick:b13,leftshoulder:b10,rightshoulder:b11,dpup:b6,dpdown:b7,dpleft:b8,dpright:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:UWP,
diff --git a/core/input/input.cpp b/core/input/input.cpp
index a712394b35..f57985831a 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -438,7 +438,7 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
}
joy_names[p_idx] = js;
- emit_signal("joy_connection_changed", p_idx, p_connected);
+ emit_signal(SNAME("joy_connection_changed"), p_idx, p_connected);
}
Vector3 Input::get_gravity() const {
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 52a6c5d64f..4a2abffae8 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -38,6 +38,7 @@ const int InputEvent::DEVICE_ID_INTERNAL = -2;
void InputEvent::set_device(int p_device) {
device = p_device;
+ emit_changed();
}
int InputEvent::get_device() const {
@@ -131,6 +132,7 @@ void InputEventFromWindow::_bind_methods() {
void InputEventFromWindow::set_window_id(int64_t p_id) {
window_id = p_id;
+ emit_changed();
}
int64_t InputEventFromWindow::get_window_id() const {
@@ -141,6 +143,7 @@ int64_t InputEventFromWindow::get_window_id() const {
void InputEventWithModifiers::set_store_command(bool p_enabled) {
store_command = p_enabled;
+ emit_changed();
}
bool InputEventWithModifiers::is_storing_command() const {
@@ -149,6 +152,7 @@ bool InputEventWithModifiers::is_storing_command() const {
void InputEventWithModifiers::set_shift_pressed(bool p_enabled) {
shift_pressed = p_enabled;
+ emit_changed();
}
bool InputEventWithModifiers::is_shift_pressed() const {
@@ -157,6 +161,7 @@ bool InputEventWithModifiers::is_shift_pressed() const {
void InputEventWithModifiers::set_alt_pressed(bool p_enabled) {
alt_pressed = p_enabled;
+ emit_changed();
}
bool InputEventWithModifiers::is_alt_pressed() const {
@@ -165,6 +170,7 @@ bool InputEventWithModifiers::is_alt_pressed() const {
void InputEventWithModifiers::set_ctrl_pressed(bool p_enabled) {
ctrl_pressed = p_enabled;
+ emit_changed();
}
bool InputEventWithModifiers::is_ctrl_pressed() const {
@@ -173,6 +179,7 @@ bool InputEventWithModifiers::is_ctrl_pressed() const {
void InputEventWithModifiers::set_meta_pressed(bool p_enabled) {
meta_pressed = p_enabled;
+ emit_changed();
}
bool InputEventWithModifiers::is_meta_pressed() const {
@@ -181,6 +188,7 @@ bool InputEventWithModifiers::is_meta_pressed() const {
void InputEventWithModifiers::set_command_pressed(bool p_enabled) {
command_pressed = p_enabled;
+ emit_changed();
}
bool InputEventWithModifiers::is_command_pressed() const {
@@ -291,6 +299,7 @@ void InputEventWithModifiers::_validate_property(PropertyInfo &property) const {
void InputEventKey::set_pressed(bool p_pressed) {
pressed = p_pressed;
+ emit_changed();
}
bool InputEventKey::is_pressed() const {
@@ -299,6 +308,7 @@ bool InputEventKey::is_pressed() const {
void InputEventKey::set_keycode(uint32_t p_keycode) {
keycode = p_keycode;
+ emit_changed();
}
uint32_t InputEventKey::get_keycode() const {
@@ -307,6 +317,7 @@ uint32_t InputEventKey::get_keycode() const {
void InputEventKey::set_physical_keycode(uint32_t p_keycode) {
physical_keycode = p_keycode;
+ emit_changed();
}
uint32_t InputEventKey::get_physical_keycode() const {
@@ -315,6 +326,7 @@ uint32_t InputEventKey::get_physical_keycode() const {
void InputEventKey::set_unicode(uint32_t p_unicode) {
unicode = p_unicode;
+ emit_changed();
}
uint32_t InputEventKey::get_unicode() const {
@@ -323,6 +335,7 @@ uint32_t InputEventKey::get_unicode() const {
void InputEventKey::set_echo(bool p_enable) {
echo = p_enable;
+ emit_changed();
}
bool InputEventKey::is_echo() const {
@@ -469,6 +482,7 @@ void InputEventKey::_bind_methods() {
void InputEventMouse::set_button_mask(int p_mask) {
button_mask = p_mask;
+ emit_changed();
}
int InputEventMouse::get_button_mask() const {
@@ -518,6 +532,7 @@ float InputEventMouseButton::get_factor() const {
void InputEventMouseButton::set_button_index(MouseButton p_index) {
button_index = p_index;
+ emit_changed();
}
MouseButton InputEventMouseButton::get_button_index() const {
@@ -847,6 +862,7 @@ void InputEventMouseMotion::_bind_methods() {
void InputEventJoypadMotion::set_axis(JoyAxis p_axis) {
axis = p_axis;
+ emit_changed();
}
JoyAxis InputEventJoypadMotion::get_axis() const {
@@ -855,6 +871,7 @@ JoyAxis InputEventJoypadMotion::get_axis() const {
void InputEventJoypadMotion::set_axis_value(float p_value) {
axis_value = p_value;
+ emit_changed();
}
float InputEventJoypadMotion::get_axis_value() const {
@@ -949,6 +966,7 @@ void InputEventJoypadMotion::_bind_methods() {
void InputEventJoypadButton::set_button_index(JoyButton p_index) {
button_index = p_index;
+ emit_changed();
}
JoyButton InputEventJoypadButton::get_button_index() const {
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index 52dc561546..b5f067d499 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -45,6 +45,7 @@ void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
ClassDB::bind_method(D_METHOD("action_set_deadzone", "action", "deadzone"), &InputMap::action_set_deadzone);
+ ClassDB::bind_method(D_METHOD("action_get_deadzone", "action"), &InputMap::action_get_deadzone);
ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event);
ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event);
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 6de626db99..790b6febc0 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -134,8 +134,9 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
if (p_dst_max_size < 16) {
uint8_t dst[16];
- ret_size = fastlz_decompress(p_src, p_src_size, dst, 16);
+ fastlz_decompress(p_src, p_src_size, dst, 16);
memcpy(p_dst, dst, p_dst_max_size);
+ ret_size = p_dst_max_size;
} else {
ret_size = fastlz_decompress(p_src, p_src_size, p_dst, p_dst_max_size);
}
@@ -238,7 +239,10 @@ int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_s
case Z_DATA_ERROR:
case Z_MEM_ERROR:
case Z_STREAM_ERROR:
- WARN_PRINT(strm.msg);
+ case Z_BUF_ERROR:
+ if (strm.msg) {
+ WARN_PRINT(strm.msg);
+ }
(void)inflateEnd(&strm);
p_dst_vect->resize(0);
return ret;
diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp
index f9b3165a07..f291086808 100644
--- a/core/io/http_client_tcp.cpp
+++ b/core/io/http_client_tcp.cpp
@@ -590,6 +590,7 @@ PackedByteArray HTTPClientTCP::read_response_body_chunk() {
}
}
if (err != OK) {
+ ret.resize(_offset);
break;
}
}
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 25d9eab3fe..3112dd217f 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -1985,6 +1985,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
+ ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum.");
int mm = 0;
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
@@ -2007,6 +2008,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
+ ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum.");
int mm;
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
@@ -2378,6 +2380,8 @@ Error Image::decompress() {
}
Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) {
+ ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
+ ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality);
}
@@ -2403,6 +2407,9 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
_image_compress_bptc_func(this, p_lossy_quality, p_channels);
} break;
+ case COMPRESS_MAX: {
+ ERR_FAIL_V(ERR_INVALID_PARAMETER);
+ } break;
}
return OK;
@@ -2997,6 +3004,8 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
}
void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation) {
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot adjust_bcs in compressed or custom image formats.");
+
uint8_t *w = data.ptrw();
uint32_t pixel_size = get_format_pixel_size(format);
uint32_t pixel_count = data.size() / pixel_size;
diff --git a/core/io/image.h b/core/io/image.h
index 060e54a308..8f1b251ac3 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -336,11 +336,13 @@ public:
COMPRESS_ETC,
COMPRESS_ETC2,
COMPRESS_BPTC,
+ COMPRESS_MAX,
};
enum CompressSource {
COMPRESS_SOURCE_GENERIC,
COMPRESS_SOURCE_SRGB,
- COMPRESS_SOURCE_NORMAL
+ COMPRESS_SOURCE_NORMAL,
+ COMPRESS_SOURCE_MAX,
};
Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 51ba8800e4..e99c60613a 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -85,7 +85,7 @@ const MultiplayerAPI::RPCConfig _get_rpc_config_by_id(Node *p_node, uint16_t p_i
if (id & (1 << 15)) {
id = id & ~(1 << 15);
config = p_node->get_node_rpc_methods();
- } else {
+ } else if (p_node->get_script_instance()) {
config = p_node->get_script_instance()->get_rpc_methods();
}
if (id < config.size()) {
@@ -94,52 +94,17 @@ const MultiplayerAPI::RPCConfig _get_rpc_config_by_id(Node *p_node, uint16_t p_i
return MultiplayerAPI::RPCConfig();
}
-_FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_master, bool &r_skip_rpc) {
- switch (mode) {
- case MultiplayerAPI::RPC_MODE_DISABLED: {
- // Do nothing.
- } break;
- case MultiplayerAPI::RPC_MODE_REMOTE: {
- // Do nothing. Remote cannot produce a local call.
- } break;
- case MultiplayerAPI::RPC_MODE_MASTERSYNC: {
- if (is_master) {
- r_skip_rpc = true; // I am the master, so skip remote call.
- }
- [[fallthrough]];
- }
- case MultiplayerAPI::RPC_MODE_REMOTESYNC:
- case MultiplayerAPI::RPC_MODE_PUPPETSYNC: {
- // Call it, sync always results in a local call.
- return true;
- } break;
- case MultiplayerAPI::RPC_MODE_MASTER: {
- if (is_master) {
- r_skip_rpc = true; // I am the master, so skip remote call.
- }
- return is_master;
- } break;
- case MultiplayerAPI::RPC_MODE_PUPPET: {
- return !is_master;
- } break;
- }
- return false;
-}
-
_FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, int p_remote_id) {
switch (mode) {
case MultiplayerAPI::RPC_MODE_DISABLED: {
return false;
} break;
- case MultiplayerAPI::RPC_MODE_REMOTE:
- case MultiplayerAPI::RPC_MODE_REMOTESYNC: {
+ case MultiplayerAPI::RPC_MODE_REMOTE: {
return true;
} break;
- case MultiplayerAPI::RPC_MODE_MASTERSYNC:
case MultiplayerAPI::RPC_MODE_MASTER: {
return p_node->is_network_master();
} break;
- case MultiplayerAPI::RPC_MODE_PUPPETSYNC:
case MultiplayerAPI::RPC_MODE_PUPPET: {
return !p_node->is_network_master() && p_remote_id == p_node->get_network_master();
} break;
@@ -149,7 +114,7 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, i
}
void MultiplayerAPI::poll() {
- if (!network_peer.is_valid() || network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) {
+ if (!network_peer.is_valid() || network_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED) {
return;
}
@@ -196,13 +161,13 @@ Node *MultiplayerAPI::get_root_node() {
return root_node;
}
-void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer) {
+void MultiplayerAPI::set_network_peer(const Ref<MultiplayerPeer> &p_peer) {
if (p_peer == network_peer) {
return; // Nothing to do
}
- ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED,
- "Supplied NetworkedMultiplayerPeer must be connecting or connected.");
+ ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED,
+ "Supplied MultiplayerPeer must be connecting or connected.");
if (network_peer.is_valid()) {
network_peer->disconnect("peer_connected", callable_mp(this, &MultiplayerAPI::_add_peer));
@@ -224,7 +189,7 @@ void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_pee
}
}
-Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const {
+Ref<MultiplayerPeer> MultiplayerAPI::get_network_peer() const {
return network_peer;
}
@@ -513,7 +478,7 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
packet.write[1] = valid_rpc_checksum;
encode_cstring(pname.get_data(), &packet.write[2]);
- network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
network_peer->set_target_peer(p_from);
network_peer->put_packet(packet.ptr(), packet.size());
}
@@ -592,7 +557,7 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC
for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) {
network_peer->set_target_peer(E->get()); // To all of you.
- network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
network_peer->put_packet(packet.ptr(), packet.size());
psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed.
@@ -760,9 +725,9 @@ Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const u
void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND_MSG(network_peer.is_null(), "Attempt to remote call/set when networking is not active in SceneTree.");
- ERR_FAIL_COND_MSG(network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING, "Attempt to remote call/set when networking is not connected yet in SceneTree.");
+ ERR_FAIL_COND_MSG(network_peer->get_connection_status() == MultiplayerPeer::CONNECTION_CONNECTING, "Attempt to remote call/set when networking is not connected yet in SceneTree.");
- ERR_FAIL_COND_MSG(network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED, "Attempt to remote call/set when networking is disconnected.");
+ ERR_FAIL_COND_MSG(network_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED, "Attempt to remote call/set when networking is disconnected.");
ERR_FAIL_COND_MSG(p_argcount > 255, "Too many arguments >255.");
@@ -941,7 +906,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const
void MultiplayerAPI::_add_peer(int p_id) {
connected_peers.insert(p_id);
path_get_cache.insert(p_id, PathGetCache());
- emit_signal("network_peer_connected", p_id);
+ emit_signal(SNAME("network_peer_connected"), p_id);
}
void MultiplayerAPI::_del_peer(int p_id) {
@@ -956,44 +921,42 @@ void MultiplayerAPI::_del_peer(int p_id) {
PathSentCache *psc = path_send_cache.getptr(E->get());
psc->confirmed_peers.erase(p_id);
}
- emit_signal("network_peer_disconnected", p_id);
+ emit_signal(SNAME("network_peer_disconnected"), p_id);
}
void MultiplayerAPI::_connected_to_server() {
- emit_signal("connected_to_server");
+ emit_signal(SNAME("connected_to_server"));
}
void MultiplayerAPI::_connection_failed() {
- emit_signal("connection_failed");
+ emit_signal(SNAME("connection_failed"));
}
void MultiplayerAPI::_server_disconnected() {
- emit_signal("server_disconnected");
+ emit_signal(SNAME("server_disconnected"));
}
void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND_MSG(!network_peer.is_valid(), "Trying to call an RPC while no network peer is active.");
ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "Trying to call an RPC on a node which is not inside SceneTree.");
- ERR_FAIL_COND_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, "Trying to call an RPC via a network peer which is not connected.");
+ ERR_FAIL_COND_MSG(network_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, "Trying to call an RPC via a network peer which is not connected.");
int node_id = network_peer->get_unique_id();
- bool skip_rpc = node_id == p_peer_id;
bool call_local_native = false;
bool call_local_script = false;
- bool is_master = p_node->is_network_master();
uint16_t rpc_id = UINT16_MAX;
const RPCConfig config = _get_rpc_config(p_node, p_method, rpc_id);
ERR_FAIL_COND_MSG(config.name == StringName(),
vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is not marked for RPCs.", p_method, p_node->get_path()));
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
if (rpc_id & (1 << 15)) {
- call_local_native = _should_call_local(config.rpc_mode, is_master, skip_rpc);
+ call_local_native = config.sync;
} else {
- call_local_script = _should_call_local(config.rpc_mode, is_master, skip_rpc);
+ call_local_script = config.sync;
}
}
- if (!skip_rpc) {
+ if (p_peer_id != node_id) {
#ifdef DEBUG_ENABLED
_profile_node_data("out_rpc", p_node->get_instance_id());
#endif
@@ -1030,13 +993,13 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
}
}
- ERR_FAIL_COND_MSG(skip_rpc && !(call_local_native || call_local_script), "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
+ ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.sync, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
}
-Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) {
+Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, MultiplayerPeer::TransferMode p_mode) {
ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no network peer is active.");
- ERR_FAIL_COND_V_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a network peer which is not connected.");
+ ERR_FAIL_COND_V_MSG(network_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a network peer which is not connected.");
MAKE_ROOM(p_data.size() + 1);
const uint8_t *r = p_data.ptr();
@@ -1059,7 +1022,7 @@ void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_pac
uint8_t *w = out.ptrw();
memcpy(&w[0], &p_packet[1], len);
}
- emit_signal("network_peer_packet", p_from, out);
+ emit_signal(SNAME("network_peer_packet"), p_from, out);
}
int MultiplayerAPI::get_network_unique_id() const {
@@ -1068,9 +1031,7 @@ int MultiplayerAPI::get_network_unique_id() const {
}
bool MultiplayerAPI::is_network_server() const {
- // XXX Maybe fail silently? Maybe should actually return true to make development of both local and online multiplayer easier?
- ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), false, "No network peer is assigned. I can't be a server.");
- return network_peer->is_server();
+ return network_peer.is_valid() && network_peer->is_server();
}
void MultiplayerAPI::set_refuse_new_network_connections(bool p_refuse) {
@@ -1105,7 +1066,7 @@ bool MultiplayerAPI::is_object_decoding_allowed() const {
void MultiplayerAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node);
ClassDB::bind_method(D_METHOD("get_root_node"), &MultiplayerAPI::get_root_node);
- ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode"), &MultiplayerAPI::send_bytes, DEFVAL(NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE));
+ ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode"), &MultiplayerAPI::send_bytes, DEFVAL(MultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE));
ClassDB::bind_method(D_METHOD("has_network_peer"), &MultiplayerAPI::has_network_peer);
ClassDB::bind_method(D_METHOD("get_network_peer"), &MultiplayerAPI::get_network_peer);
ClassDB::bind_method(D_METHOD("get_network_unique_id"), &MultiplayerAPI::get_network_unique_id);
@@ -1123,7 +1084,7 @@ void MultiplayerAPI::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", PROPERTY_USAGE_NONE), "set_network_peer", "get_network_peer");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_network_peer", "get_network_peer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_node", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_root_node", "get_root_node");
ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false);
@@ -1138,9 +1099,6 @@ void MultiplayerAPI::_bind_methods() {
BIND_ENUM_CONSTANT(RPC_MODE_REMOTE);
BIND_ENUM_CONSTANT(RPC_MODE_MASTER);
BIND_ENUM_CONSTANT(RPC_MODE_PUPPET);
- BIND_ENUM_CONSTANT(RPC_MODE_REMOTESYNC);
- BIND_ENUM_CONSTANT(RPC_MODE_MASTERSYNC);
- BIND_ENUM_CONSTANT(RPC_MODE_PUPPETSYNC);
}
MultiplayerAPI::MultiplayerAPI() {
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index 43804a20ec..cc994a9852 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -31,7 +31,7 @@
#ifndef MULTIPLAYER_API_H
#define MULTIPLAYER_API_H
-#include "core/io/networked_multiplayer_peer.h"
+#include "core/io/multiplayer_peer.h"
#include "core/object/ref_counted.h"
class MultiplayerAPI : public RefCounted {
@@ -43,15 +43,13 @@ public:
RPC_MODE_REMOTE, // Using rpc() on it will call method in all remote peers
RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
- RPC_MODE_REMOTESYNC, // Using rpc() on it will call method in all remote peers and locally
- RPC_MODE_MASTERSYNC, // Using rpc() on it will call method in the master peer and locally
- RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method in all puppets peers and locally
};
struct RPCConfig {
StringName name;
RPCMode rpc_mode = RPC_MODE_DISABLED;
- NetworkedMultiplayerPeer::TransferMode transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ bool sync = false;
+ MultiplayerPeer::TransferMode transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
int channel = 0;
bool operator==(RPCConfig const &p_other) const {
@@ -83,7 +81,7 @@ private:
Map<int, NodeInfo> nodes;
};
- Ref<NetworkedMultiplayerPeer> network_peer;
+ Ref<MultiplayerPeer> network_peer;
int rpc_sender_id = 0;
Set<int> connected_peers;
HashMap<NodePath, PathSentCache> path_send_cache;
@@ -132,9 +130,9 @@ public:
void clear();
void set_root_node(Node *p_node);
Node *get_root_node();
- void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer);
- Ref<NetworkedMultiplayerPeer> get_network_peer() const;
- Error send_bytes(Vector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST, NetworkedMultiplayerPeer::TransferMode p_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ void set_network_peer(const Ref<MultiplayerPeer> &p_peer);
+ Ref<MultiplayerPeer> get_network_peer() const;
+ Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, MultiplayerPeer::TransferMode p_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE);
// Called by Node.rpc
void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
diff --git a/core/io/networked_multiplayer_peer.cpp b/core/io/multiplayer_peer.cpp
index b6af046e77..8126b4cea3 100644
--- a/core/io/networked_multiplayer_peer.cpp
+++ b/core/io/multiplayer_peer.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* networked_multiplayer_peer.cpp */
+/* multiplayer_peer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,22 +28,22 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "networked_multiplayer_peer.h"
+#include "multiplayer_peer.h"
-void NetworkedMultiplayerPeer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_transfer_mode", "mode"), &NetworkedMultiplayerPeer::set_transfer_mode);
- ClassDB::bind_method(D_METHOD("get_transfer_mode"), &NetworkedMultiplayerPeer::get_transfer_mode);
- ClassDB::bind_method(D_METHOD("set_target_peer", "id"), &NetworkedMultiplayerPeer::set_target_peer);
+void MultiplayerPeer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_transfer_mode", "mode"), &MultiplayerPeer::set_transfer_mode);
+ ClassDB::bind_method(D_METHOD("get_transfer_mode"), &MultiplayerPeer::get_transfer_mode);
+ ClassDB::bind_method(D_METHOD("set_target_peer", "id"), &MultiplayerPeer::set_target_peer);
- ClassDB::bind_method(D_METHOD("get_packet_peer"), &NetworkedMultiplayerPeer::get_packet_peer);
+ ClassDB::bind_method(D_METHOD("get_packet_peer"), &MultiplayerPeer::get_packet_peer);
- ClassDB::bind_method(D_METHOD("poll"), &NetworkedMultiplayerPeer::poll);
+ ClassDB::bind_method(D_METHOD("poll"), &MultiplayerPeer::poll);
- ClassDB::bind_method(D_METHOD("get_connection_status"), &NetworkedMultiplayerPeer::get_connection_status);
- ClassDB::bind_method(D_METHOD("get_unique_id"), &NetworkedMultiplayerPeer::get_unique_id);
+ ClassDB::bind_method(D_METHOD("get_connection_status"), &MultiplayerPeer::get_connection_status);
+ ClassDB::bind_method(D_METHOD("get_unique_id"), &MultiplayerPeer::get_unique_id);
- ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "enable"), &NetworkedMultiplayerPeer::set_refuse_new_connections);
- ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &NetworkedMultiplayerPeer::is_refusing_new_connections);
+ ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "enable"), &MultiplayerPeer::set_refuse_new_connections);
+ ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &MultiplayerPeer::is_refusing_new_connections);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_mode", PROPERTY_HINT_ENUM, "Unreliable,Unreliable Ordered,Reliable"), "set_transfer_mode", "get_transfer_mode");
diff --git a/core/io/networked_multiplayer_peer.h b/core/io/multiplayer_peer.h
index 7c90f97d88..432f47280f 100644
--- a/core/io/networked_multiplayer_peer.h
+++ b/core/io/multiplayer_peer.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* networked_multiplayer_peer.h */
+/* multiplayer_peer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -33,8 +33,8 @@
#include "core/io/packet_peer.h"
-class NetworkedMultiplayerPeer : public PacketPeer {
- GDCLASS(NetworkedMultiplayerPeer, PacketPeer);
+class MultiplayerPeer : public PacketPeer {
+ GDCLASS(MultiplayerPeer, PacketPeer);
protected:
static void _bind_methods();
@@ -73,10 +73,10 @@ public:
virtual ConnectionStatus get_connection_status() const = 0;
- NetworkedMultiplayerPeer() {}
+ MultiplayerPeer() {}
};
-VARIANT_ENUM_CAST(NetworkedMultiplayerPeer::TransferMode)
-VARIANT_ENUM_CAST(NetworkedMultiplayerPeer::ConnectionStatus)
+VARIANT_ENUM_CAST(MultiplayerPeer::TransferMode)
+VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus)
#endif // NETWORKED_MULTIPLAYER_PEER_H
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp
index b760a9ef80..5e0c0390f9 100644
--- a/core/io/tcp_server.cpp
+++ b/core/io/tcp_server.cpp
@@ -43,7 +43,6 @@ Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");
Error err;
IP::Type ip_type = IP::TYPE_ANY;
diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp
index 6a1af0c2a9..27a1cab721 100644
--- a/core/io/udp_server.cpp
+++ b/core/io/udp_server.cpp
@@ -91,7 +91,6 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");
Error err;
IP::Type ip_type = IP::TYPE_ANY;
diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h
index 4958b5ac6a..a2894bc1d3 100644
--- a/core/math/geometry_2d.h
+++ b/core/math/geometry_2d.h
@@ -362,6 +362,19 @@ public:
return (intersections & 1);
}
+ static bool is_segment_intersecting_polygon(const Vector2 &p_from, const Vector2 &p_to, const Vector<Vector2> &p_polygon) {
+ int c = p_polygon.size();
+ const Vector2 *p = p_polygon.ptr();
+ for (int i = 0; i < c; i++) {
+ const Vector2 &v1 = p[i];
+ const Vector2 &v2 = p[(i + 1) % c];
+ if (segment_intersects_segment(p_from, p_to, v1, v2, nullptr)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
static real_t vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B) {
return (real_t)(A.x - O.x) * (B.y - O.y) - (real_t)(A.y - O.y) * (B.x - O.x);
}
diff --git a/core/object/SCsub b/core/object/SCsub
index 5d429960e5..dc116aeb19 100644
--- a/core/object/SCsub
+++ b/core/object/SCsub
@@ -2,6 +2,11 @@
Import("env")
+import make_virtuals
+from platform_methods import run_in_subprocess
+
+env.CommandNoCache(["gdvirtual.gen.inc"], "make_virtuals.py", run_in_subprocess(make_virtuals.run))
+
env_object = env.Clone()
env_object.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index df36587662..e2db5918e3 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -503,9 +503,9 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam
thread_local bool initializing_with_extension = false;
thread_local ObjectNativeExtension *initializing_extension = nullptr;
-thread_local void *initializing_extension_instance = nullptr;
+thread_local GDExtensionClassInstancePtr initializing_extension_instance = nullptr;
-void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance) {
+void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance) {
if (initializing_with_extension) {
*r_extension = initializing_extension;
*r_extension_instance = initializing_extension_instance;
@@ -539,7 +539,7 @@ Object *ClassDB::instantiate(const StringName &p_class) {
if (ti->native_extension) {
initializing_with_extension = true;
initializing_extension = ti->native_extension;
- initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->create_instance_userdata);
+ initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->class_userdata);
}
return ti->creation_func();
}
@@ -602,7 +602,7 @@ static MethodInfo info_from_bind(MethodBind *p_method) {
}
#endif
-void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
+void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
OBJTYPE_RLOCK;
ClassInfo *type = classes.getptr(p_class);
@@ -655,7 +655,7 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b
}
}
-bool ClassDB::get_method_info(StringName p_class, StringName p_method, MethodInfo *r_info, bool p_no_inheritance, bool p_exclude_from_properties) {
+bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_method, MethodInfo *r_info, bool p_no_inheritance, bool p_exclude_from_properties) {
OBJTYPE_RLOCK;
ClassInfo *type = classes.getptr(p_class);
@@ -706,7 +706,7 @@ bool ClassDB::get_method_info(StringName p_class, StringName p_method, MethodInf
return false;
}
-MethodBind *ClassDB::get_method(StringName p_class, StringName p_name) {
+MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_name) {
OBJTYPE_RLOCK;
ClassInfo *type = classes.getptr(p_class);
@@ -910,7 +910,7 @@ bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool
return false;
}
-void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) {
+void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
OBJTYPE_WLOCK;
ClassInfo *type = classes.getptr(p_class);
@@ -929,7 +929,7 @@ void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) {
type->signal_map[sname] = p_signal;
}
-void ClassDB::get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance) {
+void ClassDB::get_signal_list(const StringName &p_class, List<MethodInfo> *p_signals, bool p_no_inheritance) {
OBJTYPE_RLOCK;
ClassInfo *type = classes.getptr(p_class);
@@ -951,7 +951,7 @@ void ClassDB::get_signal_list(StringName p_class, List<MethodInfo> *p_signals, b
}
}
-bool ClassDB::has_signal(StringName p_class, StringName p_signal, bool p_no_inheritance) {
+bool ClassDB::has_signal(const StringName &p_class, const StringName &p_signal, bool p_no_inheritance) {
OBJTYPE_RLOCK;
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
@@ -968,7 +968,7 @@ bool ClassDB::has_signal(StringName p_class, StringName p_signal, bool p_no_inhe
return false;
}
-bool ClassDB::get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal) {
+bool ClassDB::get_signal(const StringName &p_class, const StringName &p_signal, MethodInfo *r_signal) {
OBJTYPE_RLOCK;
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
@@ -985,7 +985,7 @@ bool ClassDB::get_signal(StringName p_class, StringName p_signal, MethodInfo *r_
return false;
}
-void ClassDB::add_property_group(StringName p_class, const String &p_name, const String &p_prefix) {
+void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix) {
OBJTYPE_WLOCK;
ClassInfo *type = classes.getptr(p_class);
ERR_FAIL_COND(!type);
@@ -993,7 +993,7 @@ void ClassDB::add_property_group(StringName p_class, const String &p_name, const
type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_GROUP));
}
-void ClassDB::add_property_subgroup(StringName p_class, const String &p_name, const String &p_prefix) {
+void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix) {
OBJTYPE_WLOCK;
ClassInfo *type = classes.getptr(p_class);
ERR_FAIL_COND(!type);
@@ -1002,7 +1002,7 @@ void ClassDB::add_property_subgroup(StringName p_class, const String &p_name, co
}
// NOTE: For implementation simplicity reasons, this method doesn't allow setters to have optional arguments at the end.
-void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
+void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
lock.read_lock();
ClassInfo *type = classes.getptr(p_class);
lock.read_unlock();
@@ -1060,14 +1060,14 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
type->property_setget[p_pinfo.name] = psg;
}
-void ClassDB::set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default) {
+void ClassDB::set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default) {
if (!default_values.has(p_class)) {
default_values[p_class] = HashMap<StringName, Variant>();
}
default_values[p_class][p_name] = p_default;
}
-void ClassDB::get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
+void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
OBJTYPE_RLOCK;
ClassInfo *type = classes.getptr(p_class);
@@ -1090,7 +1090,7 @@ void ClassDB::get_property_list(StringName p_class, List<PropertyInfo> *p_list,
}
}
-bool ClassDB::get_property_info(StringName p_class, StringName p_property, PropertyInfo *r_info, bool p_no_inheritance, const Object *p_validator) {
+bool ClassDB::get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance, const Object *p_validator) {
OBJTYPE_RLOCK;
ClassInfo *check = classes.getptr(p_class);
@@ -1258,7 +1258,7 @@ Variant::Type ClassDB::get_property_type(const StringName &p_class, const String
return Variant::NIL;
}
-StringName ClassDB::get_property_setter(StringName p_class, const StringName &p_property) {
+StringName ClassDB::get_property_setter(const StringName &p_class, const StringName &p_property) {
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
while (check) {
@@ -1273,7 +1273,7 @@ StringName ClassDB::get_property_setter(StringName p_class, const StringName &p_
return StringName();
}
-StringName ClassDB::get_property_getter(StringName p_class, const StringName &p_property) {
+StringName ClassDB::get_property_getter(const StringName &p_class, const StringName &p_property) {
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
while (check) {
@@ -1305,7 +1305,7 @@ bool ClassDB::has_property(const StringName &p_class, const StringName &p_proper
return false;
}
-void ClassDB::set_method_flags(StringName p_class, StringName p_method, int p_flags) {
+void ClassDB::set_method_flags(const StringName &p_class, const StringName &p_method, int p_flags) {
OBJTYPE_WLOCK;
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
@@ -1314,7 +1314,7 @@ void ClassDB::set_method_flags(StringName p_class, StringName p_method, int p_fl
check->method_map[p_method]->set_hint_flags(p_flags);
}
-bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inheritance) {
+bool ClassDB::has_method(const StringName &p_class, const StringName &p_method, bool p_no_inheritance) {
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
while (check) {
@@ -1442,14 +1442,14 @@ void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p
#endif
}
-void ClassDB::set_class_enabled(StringName p_class, bool p_enable) {
+void ClassDB::set_class_enabled(const StringName &p_class, bool p_enable) {
OBJTYPE_WLOCK;
ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
classes[p_class].disabled = !p_enable;
}
-bool ClassDB::is_class_enabled(StringName p_class) {
+bool ClassDB::is_class_enabled(const StringName &p_class) {
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
@@ -1463,7 +1463,7 @@ bool ClassDB::is_class_enabled(StringName p_class) {
return !ti->disabled;
}
-bool ClassDB::is_class_exposed(StringName p_class) {
+bool ClassDB::is_class_exposed(const StringName &p_class) {
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
@@ -1603,6 +1603,11 @@ void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
classes[p_extension->class_name] = c;
}
+void ClassDB::unregister_extension_class(const StringName &p_class) {
+ ERR_FAIL_COND(!classes.has(p_class));
+ classes.erase(p_class);
+}
+
RWLock ClassDB::lock;
void ClassDB::cleanup_defaults() {
diff --git a/core/object/class_db.h b/core/object/class_db.h
index a4af535149..fd574fd2d8 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -204,6 +204,7 @@ public:
}
static void register_extension_class(ObjectNativeExtension *p_extension);
+ static void unregister_extension_class(const StringName &p_class);
template <class T>
static Object *_create_ptr_func() {
@@ -232,7 +233,8 @@ public:
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instantiate(const StringName &p_class);
static Object *instantiate(const StringName &p_class);
- static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance);
+ static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance);
+
static APIType get_api_type(const StringName &p_class);
static uint64_t get_api_hash(APIType p_api);
@@ -309,7 +311,7 @@ public:
}
template <class M>
- static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
+ static MethodBind *bind_vararg_method(uint32_t p_flags, const StringName &p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
GLOBAL_LOCK_FUNCTION;
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
@@ -343,31 +345,31 @@ public:
static void bind_method_custom(const StringName &p_class, MethodBind *p_method);
- static void add_signal(StringName p_class, const MethodInfo &p_signal);
- static bool has_signal(StringName p_class, StringName p_signal, bool p_no_inheritance = false);
- static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
- static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
-
- static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
- static void add_property_subgroup(StringName p_class, const String &p_name, const String &p_prefix = "");
- static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
- static void set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default);
- static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);
- static bool get_property_info(StringName p_class, StringName p_property, PropertyInfo *r_info, bool p_no_inheritance = false, const Object *p_validator = nullptr);
+ static void add_signal(const StringName &p_class, const MethodInfo &p_signal);
+ static bool has_signal(const StringName &p_class, const StringName &p_signal, bool p_no_inheritance = false);
+ static bool get_signal(const StringName &p_class, const StringName &p_signal, MethodInfo *r_signal);
+ static void get_signal_list(const StringName &p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
+
+ static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix = "");
+ static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = "");
+ static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
+ static void set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default);
+ static void get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);
+ static bool get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance = false, const Object *p_validator = nullptr);
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = nullptr);
static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
static int get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid = nullptr);
static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = nullptr);
- static StringName get_property_setter(StringName p_class, const StringName &p_property);
- static StringName get_property_getter(StringName p_class, const StringName &p_property);
+ static StringName get_property_setter(const StringName &p_class, const StringName &p_property);
+ static StringName get_property_getter(const StringName &p_class, const StringName &p_property);
- static bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false);
- static void set_method_flags(StringName p_class, StringName p_method, int p_flags);
+ static bool has_method(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false);
+ static void set_method_flags(const StringName &p_class, const StringName &p_method, int p_flags);
- static void get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
- static bool get_method_info(StringName p_class, StringName p_method, MethodInfo *r_info, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
- static MethodBind *get_method(StringName p_class, StringName p_name);
+ static void get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
+ static bool get_method_info(const StringName &p_class, const StringName &p_method, MethodInfo *r_info, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
+ static MethodBind *get_method(const StringName &p_class, const StringName &p_name);
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true);
static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
@@ -386,10 +388,10 @@ public:
static StringName get_category(const StringName &p_node);
- static void set_class_enabled(StringName p_class, bool p_enable);
- static bool is_class_enabled(StringName p_class);
+ static void set_class_enabled(const StringName &p_class, bool p_enable);
+ static bool is_class_enabled(const StringName &p_class);
- static bool is_class_exposed(StringName p_class);
+ static bool is_class_exposed(const StringName &p_class);
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
static void get_resource_base_extensions(List<String> *p_extensions);
@@ -432,4 +434,15 @@ public:
#endif
+#define GDREGISTER_CLASS(m_class) \
+ if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ ClassDB::register_class<m_class>(); \
+ }
+#define GDREGISTER_VIRTUAL_CLASS(m_class) \
+ if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ ClassDB::register_virtual_class<m_class>(); \
+ }
+
+#include "core/disabled_classes.gen.h"
+
#endif // CLASS_DB_H
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
new file mode 100644
index 0000000000..2c6b8cddc9
--- /dev/null
+++ b/core/object/make_virtuals.py
@@ -0,0 +1,152 @@
+proto = """
+#define GDVIRTUAL$VER($RET m_name $ARG) \\
+GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+StringName _gdvirtual_##m_name##_sn = #m_name;\\
+bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
+ ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
+ if (script_instance) {\\
+ Callable::CallError ce; \\
+ $CALLSIARGS\\
+ $CALLSIBEGINscript_instance->call(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
+ if (ce.error == Callable::CallError::CALL_OK) {\\
+ $CALLSIRET\\
+ return true;\\
+ } \\
+ }\\
+ if (_gdvirtual_##m_name) {\\
+ $CALLPTRARGS\\
+ $CALLPTRRETDEF\\
+ _gdvirtual_##m_name(_get_extension_instance(),$CALLPTRARGPASS,$CALLPTRRETPASS);\\
+ $CALLPTRRET\\
+ return true;\\
+ }\\
+\\
+ return false;\\
+}\\
+\\
+_FORCE_INLINE_ static MethodInfo _gdvirtual_##m_name##_get_method_info() { \\
+ MethodInfo method_info;\\
+ method_info.name = #m_name;\\
+ method_info.flags = METHOD_FLAG_VIRTUAL;\\
+ $FILL_METHOD_INFO\\
+ return method_info;\\
+}
+
+
+"""
+
+
+def generate_version(argcount, const=False, returns=False):
+ s = proto
+ sproto = str(argcount)
+ method_info = ""
+ if returns:
+ sproto += "R"
+ s = s.replace("$RET", "m_ret, ")
+ s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;")
+ method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
+ else:
+ s = s.replace("$RET", "")
+ s = s.replace("$CALLPTRRETDEF", "")
+
+ if const:
+ sproto += "C"
+ s = s.replace("$CONST", "const")
+ method_info += "\tmethod_info.flags|=METHOD_FLAG_CONST;\\\n"
+ else:
+ s = s.replace("$CONST", "")
+
+ s = s.replace("$VER", sproto)
+ argtext = ""
+ callargtext = ""
+ callsiargs = ""
+ callsiargptrs = ""
+ callptrargsptr = ""
+ if argcount > 0:
+ argtext += ", "
+ callsiargs = "Variant vargs[" + str(argcount) + "]={"
+ callsiargptrs = "\t\tconst Variant *vargptrs[" + str(argcount) + "]={"
+ callptrargsptr = "\t\tconst GDNativeTypePtr argptrs[" + str(argcount) + "]={"
+ callptrargs = ""
+ for i in range(argcount):
+ if i > 0:
+ argtext += ", "
+ callargtext += ", "
+ callsiargs += ", "
+ callsiargptrs += ", "
+ callptrargs += "\t\t"
+ callptrargsptr += ", "
+ argtext += "m_type" + str(i + 1)
+ callargtext += "const m_type" + str(i + 1) + "& arg" + str(i + 1)
+ callsiargs += "Variant(arg" + str(i + 1) + ")"
+ callsiargptrs += "&vargs[" + str(i) + "]"
+ callptrargs += (
+ "PtrToArg<m_type" + str(i + 1) + ">::EncodeT argval" + str(i + 1) + " = arg" + str(i + 1) + ";\\\n"
+ )
+ callptrargsptr += "&argval" + str(i + 1)
+ method_info += "\tmethod_info.arguments.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::get_class_info());\\\n"
+
+ if argcount:
+ callsiargs += "};\\\n"
+ callsiargptrs += "};\\\n"
+ s = s.replace("$CALLSIARGS", callsiargs + callsiargptrs)
+ s = s.replace("$CALLSIARGPASS", "(const Variant **)vargptrs," + str(argcount))
+ callptrargsptr += "};\\\n"
+ s = s.replace("$CALLPTRARGS", callptrargs + callptrargsptr)
+ s = s.replace("$CALLPTRARGPASS", "(const GDNativeTypePtr*)argptrs")
+ else:
+ s = s.replace("$CALLSIARGS", "")
+ s = s.replace("$CALLSIARGPASS", "nullptr, 0")
+ s = s.replace("$CALLPTRARGS", "")
+ s = s.replace("$CALLPTRARGPASS", "nullptr")
+
+ if returns:
+ if argcount > 0:
+ callargtext += ","
+ callargtext += " m_ret& r_ret"
+ s = s.replace("$CALLSIBEGIN", "Variant ret = ")
+ s = s.replace("$CALLSIRET", "r_ret = ret;")
+ s = s.replace("$CALLPTRRETPASS", "&ret")
+ s = s.replace("$CALLPTRRET", "r_ret = ret;")
+ else:
+ s = s.replace("$CALLSIBEGIN", "")
+ s = s.replace("$CALLSIRET", "")
+ s = s.replace("$CALLPTRRETPASS", "nullptr")
+ s = s.replace("$CALLPTRRET", "")
+
+ s = s.replace("$ARG", argtext)
+ s = s.replace("$CALLARGS", callargtext)
+ s = s.replace("$FILL_METHOD_INFO", method_info)
+
+ return s
+
+
+def run(target, source, env):
+
+ max_versions = 12
+
+ txt = """
+#ifndef GDVIRTUAL_GEN_H
+#define GDVIRTUAL_GEN_H
+
+
+"""
+
+ for i in range(max_versions + 1):
+
+ txt += "/* " + str(i) + " Arguments */\n\n"
+ txt += generate_version(i, False, False)
+ txt += generate_version(i, False, True)
+ txt += generate_version(i, True, False)
+ txt += generate_version(i, True, True)
+
+ txt += "#endif"
+
+ with open(target[0], "w") as f:
+ f.write(txt)
+
+
+if __name__ == "__main__":
+ from platform_methods import subprocess_main
+
+ subprocess_main(globals())
diff --git a/core/object/method_bind.cpp b/core/object/method_bind.cpp
index 9c5ed60708..c53104fe3f 100644
--- a/core/object/method_bind.cpp
+++ b/core/object/method_bind.cpp
@@ -34,6 +34,35 @@
#include "method_bind.h"
+uint32_t MethodBind::get_hash() const {
+ uint32_t hash = hash_djb2_one_32(has_return() ? 1 : 0);
+ hash = hash_djb2_one_32(get_argument_count(), hash);
+
+#ifndef _MSC_VER
+#warning This needs proper class name and argument type for hashing
+#endif
+#if 0
+
+ for (int i = (has_return() ? -1 : 0); i < get_argument_count(); i++) {
+ PropertyInfo pi = i == -1 ? get_return_info() : get_argument_info(i);
+ hash = hash_djb2_one_32(get_argument_type(i), hash);
+ if (pi.class_name != StringName()) {
+ hash = hash_djb2_one_32(pi.class_name.operator String().hash(), hash);
+ }
+ }
+#endif
+ hash = hash_djb2_one_32(get_default_argument_count(), hash);
+ for (int i = 0; i < get_default_argument_count(); i++) {
+ Variant v = get_default_argument(i);
+ hash = hash_djb2_one_32(v.hash(), hash);
+ }
+
+ hash = hash_djb2_one_32(is_const(), hash);
+ hash = hash_djb2_one_32(is_vararg(), hash);
+
+ return hash;
+}
+
#ifdef DEBUG_METHODS_ENABLED
PropertyInfo MethodBind::get_argument_info(int p_argument) const {
ERR_FAIL_INDEX_V(p_argument, get_argument_count(), PropertyInfo());
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 7030ae201b..92b964772a 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -135,6 +135,8 @@ public:
void set_default_arguments(const Vector<Variant> &p_defargs);
+ uint32_t get_hash() const;
+
MethodBind();
virtual ~MethodBind();
};
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 00b89ab398..0644012318 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -386,12 +386,20 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
}
if (_extension && _extension->set) {
- if (_extension->set(_extension_instance, &p_name, &p_value)) {
+// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+ if (_extension->set(_extension_instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value)) {
if (r_valid) {
*r_valid = true;
}
return;
}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
}
//try built-in setgetter
@@ -459,14 +467,22 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
return ret;
}
}
-
if (_extension && _extension->get) {
- if (_extension->get(_extension_instance, &p_name, &ret)) {
+// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+
+ if (_extension->get(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) {
if (r_valid) {
*r_valid = true;
}
return ret;
}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
}
//try built-in setgetter
@@ -616,7 +632,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
if (_extension && _extension->get_property_list) {
uint32_t pcount;
- const ObjectNativeExtension::PInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
+ const GDNativePropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
for (uint32_t i = 0; i < pcount; i++) {
p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
}
@@ -1753,42 +1769,52 @@ uint32_t Object::get_edited_version() const {
}
#endif
-void *Object::get_script_instance_binding(int p_script_language_index) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_INDEX_V(p_script_language_index, MAX_SCRIPT_INSTANCE_BINDINGS, nullptr);
-#endif
-
- //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of sync
- //just return the same pointer.
- //if you want to put a big lock in the entire function and keep allocated pointers in a map or something, feel free to do it
- //as it should not really affect performance much (won't be called too often), as in far most cases the condition below will be false afterwards
-
- if (!_script_instance_bindings[p_script_language_index]) {
- void *script_data = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this);
- if (script_data) {
- instance_binding_count.increment();
- _script_instance_bindings[p_script_language_index] = script_data;
+void Object::set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ // This is only meant to be used on creation by the binder.
+ ERR_FAIL_COND(_instance_bindings != nullptr);
+ _instance_bindings = (InstanceBinding *)memalloc(sizeof(InstanceBinding));
+ _instance_bindings[0].binding = p_binding;
+ _instance_bindings[0].free_callback = p_callbacks->free_callback;
+ _instance_bindings[0].reference_callback = p_callbacks->reference_callback;
+ _instance_bindings[0].token = p_token;
+ _instance_binding_count = 1;
+}
+
+void *Object::get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ void *binding = nullptr;
+ _instance_binding_mutex.lock();
+ for (uint32_t i = 0; i < _instance_binding_count; i++) {
+ if (_instance_bindings[i].token == p_token) {
+ binding = _instance_bindings[i].binding;
+ break;
}
}
+ if (unlikely(!binding)) {
+ uint32_t current_size = next_power_of_2(_instance_binding_count);
+ uint32_t new_size = next_power_of_2(_instance_binding_count + 1);
- return _script_instance_bindings[p_script_language_index];
-}
+ if (current_size == 0 || new_size > current_size) {
+ _instance_bindings = (InstanceBinding *)memrealloc(_instance_bindings, new_size * sizeof(InstanceBinding));
+ }
-bool Object::has_script_instance_binding(int p_script_language_index) {
- return _script_instance_bindings[p_script_language_index] != nullptr;
-}
+ _instance_bindings[_instance_binding_count].free_callback = p_callbacks->free_callback;
+ _instance_bindings[_instance_binding_count].reference_callback = p_callbacks->reference_callback;
+ _instance_bindings[_instance_binding_count].token = p_token;
-void Object::set_script_instance_binding(int p_script_language_index, void *p_data) {
-#ifdef DEBUG_ENABLED
- CRASH_COND(_script_instance_bindings[p_script_language_index] != nullptr);
-#endif
- _script_instance_bindings[p_script_language_index] = p_data;
+ binding = p_callbacks->create_callback(p_token, this);
+ _instance_bindings[_instance_binding_count].binding = binding;
+
+ _instance_binding_count++;
+ }
+
+ _instance_binding_mutex.unlock();
+
+ return binding;
}
void Object::_construct_object(bool p_reference) {
type_is_reference = p_reference;
_instance_id = ObjectDB::add_instance(this);
- memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance);
@@ -1812,7 +1838,7 @@ Object::~Object() {
script_instance = nullptr;
if (_extension && _extension->free_instance) {
- _extension->free_instance(_extension->create_instance_userdata, _extension_instance);
+ _extension->free_instance(_extension->class_userdata, _extension_instance);
_extension = nullptr;
_extension_instance = nullptr;
}
@@ -1848,12 +1874,13 @@ Object::~Object() {
_instance_id = ObjectID();
_predelete_ok = 2;
- if (!ScriptServer::are_languages_finished()) {
- for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
- if (_script_instance_bindings[i]) {
- ScriptServer::get_language(i)->free_instance_binding_data(_script_instance_bindings[i]);
+ if (_instance_bindings != nullptr) {
+ for (uint32_t i = 0; i < _instance_binding_count; i++) {
+ if (_instance_bindings[i].free_callback) {
+ _instance_bindings[i].free_callback(_instance_bindings[i].token, _instance_bindings[i].binding, this);
}
}
+ memfree(_instance_bindings);
}
}
@@ -1871,7 +1898,6 @@ void ObjectDB::debug_objects(DebugFunc p_func) {
for (uint32_t i = 0, count = slot_count; i < slot_max && count != 0; i++) {
if (object_slots[i].validator) {
p_func(object_slots[i].object);
-
count--;
}
}
diff --git a/core/object/object.h b/core/object/object.h
index 65621a47ca..296e07983d 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -31,6 +31,7 @@
#ifndef OBJECT_H
#define OBJECT_H
+#include "core/extension/gdnative_interface.h"
#include "core/object/object_id.h"
#include "core/os/rw_lock.h"
#include "core/os/spin_lock.h"
@@ -43,13 +44,13 @@
#include "core/variant/callable_bind.h"
#include "core/variant/variant.h"
-#define VARIANT_ARG_LIST const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant()
-#define VARIANT_ARG_PASS p_arg1, p_arg2, p_arg3, p_arg4, p_arg5
-#define VARIANT_ARG_DECLARE const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5
-#define VARIANT_ARG_MAX 5
-#define VARIANT_ARGPTRS const Variant *argptr[5] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4, &p_arg5 };
-#define VARIANT_ARGPTRS_PASS *argptr[0], *argptr[1], *argptr[2], *argptr[3], *argptr[4]
-#define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0], m_arr[1], m_arr[2], m_arr[3], m_arr[4]
+#define VARIANT_ARG_LIST const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant()
+#define VARIANT_ARG_PASS p_arg1, p_arg2, p_arg3, p_arg4, p_arg5, p_arg6, p_arg7, p_arg8
+#define VARIANT_ARG_DECLARE const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5, const Variant &p_arg6, const Variant &p_arg7, const Variant &p_arg8
+#define VARIANT_ARG_MAX 8
+#define VARIANT_ARGPTRS const Variant *argptr[8] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4, &p_arg5, &p_arg6, &p_arg7, &p_arg8 };
+#define VARIANT_ARGPTRS_PASS *argptr[0], *argptr[1], *argptr[2], *argptr[3], *argptr[4], *argptr[5], *argptr[6]], *argptr[7]
+#define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0], m_arr[1], m_arr[2], m_arr[3], m_arr[4], m_arr[5], m_arr[6], m_arr[7]
/**
@author Juan Linietsky <reduzio@gmail.com>
@@ -57,9 +58,9 @@
enum PropertyHint {
PROPERTY_HINT_NONE, ///< no hint provided.
- PROPERTY_HINT_RANGE, ///< hint_text = "min,max,step,slider; //slider is optional"
- PROPERTY_HINT_EXP_RANGE, ///< hint_text = "min,max,step", exponential edit
+ PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,noslider][,radians][,degrees][,exp][,suffix:<keyword>] range.
PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
+ PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc"
PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation,inout")
PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer)
PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer)
@@ -151,7 +152,7 @@ struct PropertyInfo {
String hint_string;
uint32_t usage = PROPERTY_USAGE_DEFAULT;
- _FORCE_INLINE_ PropertyInfo added_usage(int p_fl) const {
+ _FORCE_INLINE_ PropertyInfo added_usage(uint32_t p_fl) const {
PropertyInfo pi = *this;
pi.usage |= p_fl;
return pi;
@@ -163,7 +164,7 @@ struct PropertyInfo {
PropertyInfo() {}
- PropertyInfo(Variant::Type p_type, const String p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = StringName()) :
+ PropertyInfo(const Variant::Type p_type, const String p_name, const PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", const uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = StringName()) :
type(p_type),
name(p_name),
hint(p_hint),
@@ -244,29 +245,18 @@ class MethodBind;
struct ObjectNativeExtension {
ObjectNativeExtension *parent = nullptr;
+ List<ObjectNativeExtension *> children;
StringName parent_class_name;
StringName class_name;
bool editor_class = false;
- bool (*set)(void *instance, const void *name, const void *value) = nullptr;
- bool (*get)(void *instance, const void *name, void *ret_variant) = nullptr;
- struct PInfo {
- uint32_t type;
- const char *name;
- const char *class_name;
- uint32_t hint;
- const char *hint_string;
- uint32_t usage;
- };
- const PInfo *(*get_property_list)(void *instance, uint32_t *count) = nullptr;
- void (*free_property_list)(void *instance, const PInfo *) = nullptr;
-
- //call is not used, as all methods registered in ClassDB
-
- void (*notification)(void *instance, int32_t what) = nullptr;
- const char *(*to_string)(void *instance) = nullptr;
-
- void (*reference)(void *instance) = nullptr;
- void (*unreference)(void *instance) = nullptr;
+ GDNativeExtensionClassSet set;
+ GDNativeExtensionClassGet get;
+ GDNativeExtensionClassGetPropertyList get_property_list;
+ GDNativeExtensionClassFreePropertyList free_property_list;
+ GDNativeExtensionClassNotification notification;
+ GDNativeExtensionClassToString to_string;
+ GDNativeExtensionClassReference reference;
+ GDNativeExtensionClassReference unreference;
_FORCE_INLINE_ bool is_class(const String &p_class) const {
const ObjectNativeExtension *e = this;
@@ -278,11 +268,16 @@ struct ObjectNativeExtension {
}
return false;
}
- void *create_instance_userdata = nullptr;
- void *(*create_instance)(void *create_instance_userdata) = nullptr;
- void (*free_instance)(void *create_instance_userdata, void *instance) = nullptr;
+ void *class_userdata = nullptr;
+
+ GDNativeExtensionClassCreateInstance create_instance;
+ GDNativeExtensionClassFreeInstance free_instance;
+ GDNativeExtensionClassGetVirtual get_virtual;
};
+#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
+#define GDVIRTUAL_BIND(m_name) ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info());
+
/*
the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
*/
@@ -486,10 +481,6 @@ public:
};
private:
- enum {
- MAX_SCRIPT_INSTANCE_BINDINGS = 8
- };
-
#ifdef DEBUG_ENABLED
friend struct _ObjectDebugLock;
#endif
@@ -497,7 +488,7 @@ private:
friend void postinitialize_handler(Object *);
ObjectNativeExtension *_extension = nullptr;
- void *_extension_instance = nullptr;
+ GDExtensionClassInstancePtr _extension_instance = nullptr;
struct SignalData {
struct Slot {
@@ -548,14 +539,38 @@ private:
friend class RefCounted;
bool type_is_reference = false;
- SafeNumeric<uint32_t> instance_binding_count;
- void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
+
+ std::mutex _instance_binding_mutex;
+ struct InstanceBinding {
+ void *binding;
+ void *token;
+ GDNativeInstanceBindingFreeCallback free_callback = nullptr;
+ GDNativeInstanceBindingReferenceCallback reference_callback = nullptr;
+ };
+ InstanceBinding *_instance_bindings = nullptr;
+ uint32_t _instance_binding_count = 0;
Object(bool p_reference);
protected:
+ _FORCE_INLINE_ bool _instance_binding_reference(bool p_reference) {
+ bool can_die = true;
+ if (_instance_bindings) {
+ _instance_binding_mutex.lock();
+ for (uint32_t i = 0; i < _instance_binding_count; i++) {
+ if (_instance_bindings[i].reference_callback) {
+ if (!_instance_bindings[i].reference_callback(_instance_bindings[i].token, _instance_bindings[i].binding, p_reference)) {
+ can_die = false;
+ }
+ }
+ }
+ _instance_binding_mutex.unlock();
+ }
+ return can_die;
+ }
+ friend class NativeExtensionMethodBind;
_ALWAYS_INLINE_ const ObjectNativeExtension *_get_extension() const { return _extension; }
- _ALWAYS_INLINE_ void *_get_extension_instance() const { return _extension_instance; }
+ _ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance() const { return _extension_instance; }
virtual void _initialize_classv() { initialize_class(); }
virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; };
@@ -789,10 +804,10 @@ public:
#endif
- //used by script languages to store binding data
- void *get_script_instance_binding(int p_script_language_index);
- bool has_script_instance_binding(int p_script_language_index);
- void set_script_instance_binding(int p_script_language_index, void *p_data);
+ // Used by script languages to store binding data.
+ void *get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
+ // Used on creation by binding only.
+ void set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
void clear_internal_resource_paths();
diff --git a/core/object/ref_counted.cpp b/core/object/ref_counted.cpp
index 9862624972..2833f774dc 100644
--- a/core/object/ref_counted.cpp
+++ b/core/object/ref_counted.cpp
@@ -65,13 +65,8 @@ bool RefCounted::reference() {
if (_get_extension() && _get_extension()->reference) {
_get_extension()->reference(_get_extension_instance());
}
- if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
- for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
- if (_script_instance_bindings[i]) {
- ScriptServer::get_language(i)->refcount_incremented_instance_binding(this);
- }
- }
- }
+
+ _instance_binding_reference(true);
}
return success;
@@ -89,14 +84,8 @@ bool RefCounted::unreference() {
if (_get_extension() && _get_extension()->unreference) {
_get_extension()->unreference(_get_extension_instance());
}
- if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
- for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
- if (_script_instance_bindings[i]) {
- bool script_ret = ScriptServer::get_language(i)->refcount_decremented_instance_binding(this);
- die = die && script_ret;
- }
- }
- }
+
+ die = die && _instance_binding_reference(false);
}
return die;
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index 61780eb061..e0af2c18bb 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -258,6 +258,8 @@ struct PtrToArg<Ref<T>> {
return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr)));
}
+ typedef Ref<T> EncodeT;
+
_FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) {
*(Ref<RefCounted> *)p_ptr = p_val;
}
@@ -265,6 +267,8 @@ struct PtrToArg<Ref<T>> {
template <class T>
struct PtrToArg<const Ref<T> &> {
+ typedef Ref<T> EncodeT;
+
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
return Ref<T>((T *)p_ptr);
}
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index 96c96c1efb..0532b2ae40 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -65,7 +65,7 @@ bool UndoRedo::_redo(bool p_execute) {
_process_operation_list(actions.write[current_action].do_ops.front());
}
version++;
- emit_signal("version_changed");
+ emit_signal(SNAME("version_changed"));
return true;
}
@@ -352,7 +352,7 @@ bool UndoRedo::undo() {
_process_operation_list(actions.write[current_action].undo_ops.front());
current_action--;
version--;
- emit_signal("version_changed");
+ emit_signal(SNAME("version_changed"));
return true;
}
@@ -385,7 +385,7 @@ void UndoRedo::clear_history(bool p_increase_version) {
if (p_increase_version) {
version++;
- emit_signal("version_changed");
+ emit_signal(SNAME("version_changed"));
}
}
@@ -460,8 +460,8 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl
v[i] = *p_args[i + 2];
}
- static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5");
- add_do_method(object, method, v[0], v[1], v[2], v[3], v[4]);
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
+ add_do_method(object, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
return Variant();
}
@@ -497,8 +497,8 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla
v[i] = *p_args[i + 2];
}
- static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5");
- add_undo_method(object, method, v[0], v[1], v[2], v[3], v[4]);
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
+ add_undo_method(object, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
return Variant();
}
diff --git a/core/os/memory.h b/core/os/memory.h
index 10e678103d..9d09626b8c 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -80,7 +80,7 @@ void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_d
#define memalloc(m_size) Memory::alloc_static(m_size)
#define memrealloc(m_mem, m_size) Memory::realloc_static(m_mem, m_size)
-#define memfree(m_size) Memory::free_static(m_size)
+#define memfree(m_mem) Memory::free_static(m_mem)
_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
diff --git a/core/os/os.h b/core/os/os.h
index 444f67431f..301718a8b3 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -58,8 +58,6 @@ class OS {
int _orientation;
bool _allow_hidpi = false;
bool _allow_layered = false;
- bool _use_vsync;
- bool _vsync_via_compositor;
bool _stdout_enabled = true;
bool _stderr_enabled = true;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 6ce230b77b..eb37267546 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -37,6 +37,8 @@
#include "core/crypto/aes_context.h"
#include "core/crypto/crypto.h"
#include "core/crypto/hashing_context.h"
+#include "core/extension/native_extension.h"
+#include "core/extension/native_extension_manager.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
#include "core/io/config_file.h"
@@ -46,7 +48,7 @@
#include "core/io/json.h"
#include "core/io/marshalls.h"
#include "core/io/multiplayer_api.h"
-#include "core/io/networked_multiplayer_peer.h"
+#include "core/io/multiplayer_peer.h"
#include "core/io/packed_data_container.h"
#include "core/io/packet_peer.h"
#include "core/io/packet_peer_dtls.h"
@@ -95,6 +97,8 @@ static _Geometry3D *_geometry_3d = nullptr;
extern Mutex _global_mutex;
+static NativeExtensionManager *native_extension_manager = nullptr;
+
extern void register_global_constants();
extern void unregister_global_constants();
@@ -127,50 +131,50 @@ void register_core_types() {
resource_format_image.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_image);
- ClassDB::register_class<Object>();
-
- ClassDB::register_virtual_class<Script>();
-
- ClassDB::register_class<RefCounted>();
- ClassDB::register_class<WeakRef>();
- ClassDB::register_class<Resource>();
- ClassDB::register_class<Image>();
-
- ClassDB::register_virtual_class<InputEvent>();
- ClassDB::register_virtual_class<InputEventWithModifiers>();
- ClassDB::register_virtual_class<InputEventFromWindow>();
- ClassDB::register_class<InputEventKey>();
- ClassDB::register_virtual_class<InputEventMouse>();
- ClassDB::register_class<InputEventMouseButton>();
- ClassDB::register_class<InputEventMouseMotion>();
- ClassDB::register_class<InputEventJoypadButton>();
- ClassDB::register_class<InputEventJoypadMotion>();
- ClassDB::register_class<InputEventScreenDrag>();
- ClassDB::register_class<InputEventScreenTouch>();
- ClassDB::register_class<InputEventAction>();
- ClassDB::register_virtual_class<InputEventGesture>();
- ClassDB::register_class<InputEventMagnifyGesture>();
- ClassDB::register_class<InputEventPanGesture>();
- ClassDB::register_class<InputEventMIDI>();
+ GDREGISTER_CLASS(Object);
+
+ GDREGISTER_VIRTUAL_CLASS(Script);
+
+ GDREGISTER_CLASS(RefCounted);
+ GDREGISTER_CLASS(WeakRef);
+ GDREGISTER_CLASS(Resource);
+ GDREGISTER_CLASS(Image);
+
+ GDREGISTER_VIRTUAL_CLASS(InputEvent);
+ GDREGISTER_VIRTUAL_CLASS(InputEventWithModifiers);
+ GDREGISTER_VIRTUAL_CLASS(InputEventFromWindow);
+ GDREGISTER_CLASS(InputEventKey);
+ GDREGISTER_VIRTUAL_CLASS(InputEventMouse);
+ GDREGISTER_CLASS(InputEventMouseButton);
+ GDREGISTER_CLASS(InputEventMouseMotion);
+ GDREGISTER_CLASS(InputEventJoypadButton);
+ GDREGISTER_CLASS(InputEventJoypadMotion);
+ GDREGISTER_CLASS(InputEventScreenDrag);
+ GDREGISTER_CLASS(InputEventScreenTouch);
+ GDREGISTER_CLASS(InputEventAction);
+ GDREGISTER_VIRTUAL_CLASS(InputEventGesture);
+ GDREGISTER_CLASS(InputEventMagnifyGesture);
+ GDREGISTER_CLASS(InputEventPanGesture);
+ GDREGISTER_CLASS(InputEventMIDI);
// Network
- ClassDB::register_virtual_class<IP>();
+ GDREGISTER_VIRTUAL_CLASS(IP);
- ClassDB::register_virtual_class<StreamPeer>();
- ClassDB::register_class<StreamPeerBuffer>();
- ClassDB::register_class<StreamPeerTCP>();
- ClassDB::register_class<TCPServer>();
+ GDREGISTER_VIRTUAL_CLASS(StreamPeer);
+ GDREGISTER_CLASS(StreamPeerBuffer);
+ GDREGISTER_CLASS(StreamPeerTCP);
+ GDREGISTER_CLASS(TCPServer);
- ClassDB::register_virtual_class<PacketPeer>();
- ClassDB::register_class<PacketPeerStream>();
- ClassDB::register_class<PacketPeerUDP>();
- ClassDB::register_class<UDPServer>();
+ GDREGISTER_VIRTUAL_CLASS(PacketPeer);
+ GDREGISTER_CLASS(PacketPeerStream);
+ GDREGISTER_CLASS(PacketPeerUDP);
+ GDREGISTER_CLASS(UDPServer);
ClassDB::register_custom_instance_class<HTTPClient>();
// Crypto
- ClassDB::register_class<HashingContext>();
- ClassDB::register_class<AESContext>();
+ GDREGISTER_CLASS(HashingContext);
+ GDREGISTER_CLASS(AESContext);
ClassDB::register_custom_instance_class<X509Certificate>();
ClassDB::register_custom_instance_class<CryptoKey>();
ClassDB::register_custom_instance_class<HMACContext>();
@@ -184,38 +188,44 @@ void register_core_types() {
resource_format_loader_crypto.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
- ClassDB::register_virtual_class<NetworkedMultiplayerPeer>();
- ClassDB::register_class<MultiplayerAPI>();
- ClassDB::register_class<MainLoop>();
- ClassDB::register_class<Translation>();
- ClassDB::register_class<OptimizedTranslation>();
- ClassDB::register_class<UndoRedo>();
- ClassDB::register_class<TriangleMesh>();
+ GDREGISTER_VIRTUAL_CLASS(MultiplayerPeer);
+ GDREGISTER_CLASS(MultiplayerAPI);
+ GDREGISTER_CLASS(MainLoop);
+ GDREGISTER_CLASS(Translation);
+ GDREGISTER_CLASS(OptimizedTranslation);
+ GDREGISTER_CLASS(UndoRedo);
+ GDREGISTER_CLASS(TriangleMesh);
+
+ GDREGISTER_CLASS(ResourceFormatLoader);
+ GDREGISTER_CLASS(ResourceFormatSaver);
+
+ GDREGISTER_CLASS(_File);
+ GDREGISTER_CLASS(_Directory);
+ GDREGISTER_CLASS(_Thread);
+ GDREGISTER_CLASS(_Mutex);
+ GDREGISTER_CLASS(_Semaphore);
+
+ GDREGISTER_CLASS(XMLParser);
+ GDREGISTER_CLASS(JSON);
- ClassDB::register_class<ResourceFormatLoader>();
- ClassDB::register_class<ResourceFormatSaver>();
+ GDREGISTER_CLASS(ConfigFile);
- ClassDB::register_class<_File>();
- ClassDB::register_class<_Directory>();
- ClassDB::register_class<_Thread>();
- ClassDB::register_class<_Mutex>();
- ClassDB::register_class<_Semaphore>();
+ GDREGISTER_CLASS(PCKPacker);
- ClassDB::register_class<XMLParser>();
- ClassDB::register_class<JSON>();
+ GDREGISTER_CLASS(PackedDataContainer);
+ GDREGISTER_VIRTUAL_CLASS(PackedDataContainerRef);
+ GDREGISTER_CLASS(AStar);
+ GDREGISTER_CLASS(AStar2D);
+ GDREGISTER_CLASS(EncodedObjectAsID);
+ GDREGISTER_CLASS(RandomNumberGenerator);
- ClassDB::register_class<ConfigFile>();
+ GDREGISTER_VIRTUAL_CLASS(ResourceImporter);
- ClassDB::register_class<PCKPacker>();
+ GDREGISTER_CLASS(NativeExtension);
- ClassDB::register_class<PackedDataContainer>();
- ClassDB::register_virtual_class<PackedDataContainerRef>();
- ClassDB::register_class<AStar>();
- ClassDB::register_class<AStar2D>();
- ClassDB::register_class<EncodedObjectAsID>();
- ClassDB::register_class<RandomNumberGenerator>();
+ GDREGISTER_VIRTUAL_CLASS(NativeExtensionManager);
- ClassDB::register_virtual_class<ResourceImporter>();
+ native_extension_manager = memnew(NativeExtensionManager);
ip = IP::create();
@@ -243,25 +253,25 @@ void register_core_settings() {
}
void register_core_singletons() {
- ClassDB::register_class<ProjectSettings>();
- ClassDB::register_virtual_class<IP>();
- ClassDB::register_class<_Geometry2D>();
- ClassDB::register_class<_Geometry3D>();
- ClassDB::register_class<_ResourceLoader>();
- ClassDB::register_class<_ResourceSaver>();
- ClassDB::register_class<_OS>();
- ClassDB::register_class<_Engine>();
- ClassDB::register_class<_ClassDB>();
- ClassDB::register_class<_Marshalls>();
- ClassDB::register_class<TranslationServer>();
- ClassDB::register_virtual_class<Input>();
- ClassDB::register_class<InputMap>();
- ClassDB::register_class<Expression>();
- ClassDB::register_class<_EngineDebugger>();
- ClassDB::register_class<Time>();
+ GDREGISTER_CLASS(ProjectSettings);
+ GDREGISTER_VIRTUAL_CLASS(IP);
+ GDREGISTER_CLASS(_Geometry2D);
+ GDREGISTER_CLASS(_Geometry3D);
+ GDREGISTER_CLASS(_ResourceLoader);
+ GDREGISTER_CLASS(_ResourceSaver);
+ GDREGISTER_CLASS(_OS);
+ GDREGISTER_CLASS(_Engine);
+ GDREGISTER_CLASS(_ClassDB);
+ GDREGISTER_CLASS(_Marshalls);
+ GDREGISTER_CLASS(TranslationServer);
+ GDREGISTER_VIRTUAL_CLASS(Input);
+ GDREGISTER_CLASS(InputMap);
+ GDREGISTER_CLASS(Expression);
+ GDREGISTER_CLASS(_EngineDebugger);
+ GDREGISTER_CLASS(Time);
Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton(), "IP"));
Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry2D", _Geometry2D::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry3D", _Geometry3D::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", _ResourceLoader::get_singleton()));
@@ -275,9 +285,25 @@ void register_core_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", _EngineDebugger::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("NativeExtensionManager", NativeExtensionManager::get_singleton()));
+}
+
+void register_core_extensions() {
+ //harcoded for now
+ if (ProjectSettings::get_singleton()->has_setting("native_extensions/paths")) {
+ Vector<String> paths = ProjectSettings::get_singleton()->get("native_extensions/paths");
+ for (int i = 0; i < paths.size(); i++) {
+ NativeExtensionManager::LoadStatus status = native_extension_manager->load_extension(paths[i]);
+ ERR_CONTINUE_MSG(status != NativeExtensionManager::LOAD_STATUS_OK, "Error loading extension: " + paths[i]);
+ }
+ }
+ native_extension_manager->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
}
void unregister_core_types() {
+ native_extension_manager->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
+
+ memdelete(native_extension_manager);
memdelete(_resource_loader);
memdelete(_resource_saver);
memdelete(_os);
diff --git a/core/register_core_types.h b/core/register_core_types.h
index baf7ddbe65..830f05607d 100644
--- a/core/register_core_types.h
+++ b/core/register_core_types.h
@@ -33,6 +33,7 @@
void register_core_types();
void register_core_settings();
+void register_core_extensions();
void register_core_singletons();
void unregister_core_types();
diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp
index 14b87072bb..9024f60dae 100644
--- a/core/string/string_name.cpp
+++ b/core/string/string_name.cpp
@@ -41,13 +41,17 @@ StaticCString StaticCString::create(const char *p_ptr) {
StringName::_Data *StringName::_table[STRING_TABLE_LEN];
-StringName _scs_create(const char *p_chr) {
- return (p_chr[0] ? StringName(StaticCString::create(p_chr)) : StringName());
+StringName _scs_create(const char *p_chr, bool p_static) {
+ return (p_chr[0] ? StringName(StaticCString::create(p_chr), p_static) : StringName());
}
bool StringName::configured = false;
Mutex StringName::mutex;
+#ifdef DEBUG_ENABLED
+bool StringName::debug_stringname = false;
+#endif
+
void StringName::setup() {
ERR_FAIL_COND(configured);
for (int i = 0; i < STRING_TABLE_LEN; i++) {
@@ -59,12 +63,29 @@ void StringName::setup() {
void StringName::cleanup() {
MutexLock lock(mutex);
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ Vector<_Data *> data;
+ for (int i = 0; i < STRING_TABLE_LEN; i++) {
+ _Data *d = _table[i];
+ while (d) {
+ data.push_back(d);
+ d = d->next;
+ }
+ }
+ print_line("\nStringName Reference Ranking:\n");
+ data.sort_custom<DebugSortReferences>();
+ for (int i = 0; i < MIN(100, data.size()); i++) {
+ print_line(itos(i + 1) + ": " + data[i]->get_name() + " - " + itos(data[i]->debug_references));
+ }
+ }
+#endif
int lost_strings = 0;
for (int i = 0; i < STRING_TABLE_LEN; i++) {
while (_table[i]) {
_Data *d = _table[i];
lost_strings++;
- if (OS::get_singleton()->is_stdout_verbose()) {
+ if (d->static_count.get() != d->refcount.get() && OS::get_singleton()->is_stdout_verbose()) {
if (d->cname) {
print_line("Orphan StringName: " + String(d->cname));
} else {
@@ -79,6 +100,7 @@ void StringName::cleanup() {
if (lost_strings) {
print_verbose("StringName: " + itos(lost_strings) + " unclaimed string names at exit.");
}
+ configured = false;
}
void StringName::unref() {
@@ -87,6 +109,13 @@ void StringName::unref() {
if (_data && _data->refcount.unref()) {
MutexLock lock(mutex);
+ if (_data->static_count.get() > 0) {
+ if (_data->cname) {
+ ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->cname));
+ } else {
+ ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->name));
+ }
+ }
if (_data->prev) {
_data->prev->next = _data->next;
} else {
@@ -153,7 +182,7 @@ StringName::StringName(const StringName &p_name) {
}
}
-StringName::StringName(const char *p_name) {
+StringName::StringName(const char *p_name, bool p_static) {
_data = nullptr;
ERR_FAIL_COND(!configured);
@@ -181,25 +210,42 @@ StringName::StringName(const char *p_name) {
if (_data) {
if (_data->refcount.ref()) {
// exists
- return;
+ if (p_static) {
+ _data->static_count.increment();
+ }
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ _data->debug_references++;
+ }
+#endif
}
+
+ return;
}
_data = memnew(_Data);
_data->name = p_name;
_data->refcount.init();
+ _data->static_count.set(p_static ? 1 : 0);
_data->hash = hash;
_data->idx = idx;
_data->cname = nullptr;
_data->next = _table[idx];
_data->prev = nullptr;
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ // Keep in memory, force static.
+ _data->refcount.ref();
+ _data->static_count.increment();
+ }
+#endif
if (_table[idx]) {
_table[idx]->prev = _data;
}
_table[idx] = _data;
}
-StringName::StringName(const StaticCString &p_static_string) {
+StringName::StringName(const StaticCString &p_static_string, bool p_static) {
_data = nullptr;
ERR_FAIL_COND(!configured);
@@ -225,6 +271,14 @@ StringName::StringName(const StaticCString &p_static_string) {
if (_data) {
if (_data->refcount.ref()) {
// exists
+ if (p_static) {
+ _data->static_count.increment();
+ }
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ _data->debug_references++;
+ }
+#endif
return;
}
}
@@ -232,18 +286,26 @@ StringName::StringName(const StaticCString &p_static_string) {
_data = memnew(_Data);
_data->refcount.init();
+ _data->static_count.set(p_static ? 1 : 0);
_data->hash = hash;
_data->idx = idx;
_data->cname = p_static_string.ptr;
_data->next = _table[idx];
_data->prev = nullptr;
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ // Keep in memory, force static.
+ _data->refcount.ref();
+ _data->static_count.increment();
+ }
+#endif
if (_table[idx]) {
_table[idx]->prev = _data;
}
_table[idx] = _data;
}
-StringName::StringName(const String &p_name) {
+StringName::StringName(const String &p_name, bool p_static) {
_data = nullptr;
ERR_FAIL_COND(!configured);
@@ -269,6 +331,14 @@ StringName::StringName(const String &p_name) {
if (_data) {
if (_data->refcount.ref()) {
// exists
+ if (p_static) {
+ _data->static_count.increment();
+ }
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ _data->debug_references++;
+ }
+#endif
return;
}
}
@@ -276,11 +346,20 @@ StringName::StringName(const String &p_name) {
_data = memnew(_Data);
_data->name = p_name;
_data->refcount.init();
+ _data->static_count.set(p_static ? 1 : 0);
_data->hash = hash;
_data->idx = idx;
_data->cname = nullptr;
_data->next = _table[idx];
_data->prev = nullptr;
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ // Keep in memory, force static.
+ _data->refcount.ref();
+ _data->static_count.increment();
+ }
+#endif
+
if (_table[idx]) {
_table[idx]->prev = _data;
}
@@ -311,6 +390,12 @@ StringName StringName::search(const char *p_name) {
}
if (_data && _data->refcount.ref()) {
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ _data->debug_references++;
+ }
+#endif
+
return StringName(_data);
}
@@ -368,16 +453,17 @@ StringName StringName::search(const String &p_name) {
}
if (_data && _data->refcount.ref()) {
+#ifdef DEBUG_ENABLED
+ if (unlikely(debug_stringname)) {
+ _data->debug_references++;
+ }
+#endif
return StringName(_data);
}
return StringName(); //does not exist
}
-StringName::~StringName() {
- unref();
-}
-
bool operator==(const String &p_name, const StringName &p_string_name) {
return p_name == p_string_name.operator String();
}
diff --git a/core/string/string_name.h b/core/string/string_name.h
index 44d0ea14fa..ce7988744b 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -44,16 +44,19 @@ struct StaticCString {
class StringName {
enum {
- STRING_TABLE_BITS = 12,
+ STRING_TABLE_BITS = 16,
STRING_TABLE_LEN = 1 << STRING_TABLE_BITS,
STRING_TABLE_MASK = STRING_TABLE_LEN - 1
};
struct _Data {
SafeRefCount refcount;
+ SafeNumeric<uint32_t> static_count;
const char *cname = nullptr;
String name;
-
+#ifdef DEBUG_ENABLED
+ uint32_t debug_references = 0;
+#endif
String get_name() const { return cname ? String(cname) : name; }
int idx = 0;
uint32_t hash = 0;
@@ -79,6 +82,15 @@ class StringName {
static void setup();
static void cleanup();
static bool configured;
+#ifdef DEBUG_ENABLED
+ struct DebugSortReferences {
+ bool operator()(const _Data *p_left, const _Data *p_right) const {
+ return p_left->debug_references > p_right->debug_references;
+ }
+ };
+
+ static bool debug_stringname;
+#endif
StringName(_Data *p_data) { _data = p_data; }
@@ -146,12 +158,20 @@ public:
};
void operator=(const StringName &p_name);
- StringName(const char *p_name);
+ StringName(const char *p_name, bool p_static = false);
StringName(const StringName &p_name);
- StringName(const String &p_name);
- StringName(const StaticCString &p_static_string);
+ StringName(const String &p_name, bool p_static = false);
+ StringName(const StaticCString &p_static_string, bool p_static = false);
StringName() {}
- ~StringName();
+ _FORCE_INLINE_ ~StringName() {
+ if (likely(configured) && _data) { //only free if configured
+ unref();
+ }
+ }
+
+#ifdef DEBUG_ENABLED
+ static void set_debug_stringnames(bool p_enable) { debug_stringname = p_enable; }
+#endif
};
bool operator==(const String &p_name, const StringName &p_string_name);
@@ -159,6 +179,8 @@ bool operator!=(const String &p_name, const StringName &p_string_name);
bool operator==(const char *p_name, const StringName &p_string_name);
bool operator!=(const char *p_name, const StringName &p_string_name);
-StringName _scs_create(const char *p_chr);
+StringName _scs_create(const char *p_chr, bool p_static = false);
+
+#define SNAME(m_arg) ([]() -> const StringName & { static StringName sname = _scs_create(m_arg, true); return sname; })()
#endif // STRING_NAME_H
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index 153f0190fd..678f8fb207 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -84,6 +84,7 @@ static const char *locale_list[] = {
"ast_ES", // Asturian (Spain)
"ayc_PE", // Southern Aymara (Peru)
"ay_PE", // Aymara (Peru)
+ "az", // Azerbaijani
"az_AZ", // Azerbaijani (Azerbaijan)
"be", // Belarusian
"be_BY", // Belarusian (Belarus)
@@ -240,6 +241,7 @@ static const char *locale_list[] = {
"ka_GE", // Georgian (Georgia)
"kk_KZ", // Kazakh (Kazakhstan)
"kl_GL", // Kalaallisut (Greenland)
+ "km", // Central Khmer
"km_KH", // Central Khmer (Cambodia)
"kn_IN", // Kannada (India)
"kok_IN", // Konkani (India)
@@ -390,6 +392,7 @@ static const char *locale_list[] = {
"tr_CY", // Turkish (Cyprus)
"tr_TR", // Turkish (Turkey)
"ts_ZA", // Tsonga (South Africa)
+ "tt", // Tatar
"tt_RU", // Tatar (Russia)
"tzm", // Central Atlas Tamazight
"tzm_MA", // Central Atlas Tamazight (Marrocos)
@@ -458,6 +461,7 @@ static const char *locale_names[] = {
"Asturian (Spain)",
"Southern Aymara (Peru)",
"Aymara (Peru)",
+ "Azerbaijani",
"Azerbaijani (Azerbaijan)",
"Belarusian",
"Belarusian (Belarus)",
@@ -614,6 +618,7 @@ static const char *locale_names[] = {
"Georgian (Georgia)",
"Kazakh (Kazakhstan)",
"Kalaallisut (Greenland)",
+ "Central Khmer",
"Central Khmer (Cambodia)",
"Kannada (India)",
"Konkani (India)",
@@ -764,6 +769,7 @@ static const char *locale_names[] = {
"Turkish (Cyprus)",
"Turkish (Turkey)",
"Tsonga (South Africa)",
+ "Tatar",
"Tatar (Russia)",
"Central Atlas Tamazight",
"Central Atlas Tamazight (Marrocos)",
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 16ecd2b985..4cd2915ffa 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -3397,17 +3397,10 @@ String String::format(const Variant &values, String placeholder) const {
if (value_arr.size() == 2) {
Variant v_key = value_arr[0];
String key = v_key;
- if (key.left(1) == "\"" && key.right(1) == "\"") {
- key = key.substr(1, key.length() - 2);
- }
Variant v_val = value_arr[1];
String val = v_val;
- if (val.left(1) == "\"" && val.right(1) == "\"") {
- val = val.substr(1, val.length() - 2);
- }
-
new_string = new_string.replace(placeholder.replace("_", key), val);
} else {
ERR_PRINT(String("STRING.format Inner Array size != 2 ").ascii().get_data());
@@ -3416,10 +3409,6 @@ String String::format(const Variant &values, String placeholder) const {
Variant v_val = values_arr[i];
String val = v_val;
- if (val.left(1) == "\"" && val.right(1) == "\"") {
- val = val.substr(1, val.length() - 2);
- }
-
if (placeholder.find("_") > -1) {
new_string = new_string.replace(placeholder.replace("_", i_as_str), val);
} else {
@@ -3436,14 +3425,6 @@ String String::format(const Variant &values, String placeholder) const {
String key = E->get();
String val = d[E->get()];
- if (key.left(1) == "\"" && key.right(1) == "\"") {
- key = key.substr(1, key.length() - 2);
- }
-
- if (val.left(1) == "\"" && val.right(1) == "\"") {
- val = val.substr(1, val.length() - 2);
- }
-
new_string = new_string.replace(placeholder.replace("_", key), val);
}
} else {
diff --git a/core/templates/list.h b/core/templates/list.h
index 010e35eed8..c2e17a2f6f 100644
--- a/core/templates/list.h
+++ b/core/templates/list.h
@@ -135,6 +135,83 @@ public:
_FORCE_INLINE_ Element() {}
};
+ typedef T ValueType;
+
+ struct Iterator {
+ _FORCE_INLINE_ T &operator*() const {
+ return E->get();
+ }
+ _FORCE_INLINE_ T *operator->() const { return &E->get(); }
+ _FORCE_INLINE_ Iterator &operator++() {
+ E = E->next();
+ return *this;
+ }
+ _FORCE_INLINE_ Iterator &operator--() {
+ E = E->prev();
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
+ _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
+
+ Iterator(Element *p_E) { E = p_E; }
+ Iterator() {}
+ Iterator(const Iterator &p_it) { E = p_it.E; }
+
+ private:
+ Element *E = nullptr;
+ };
+
+ struct ConstIterator {
+ _FORCE_INLINE_ const T &operator*() const {
+ return E->get();
+ }
+ _FORCE_INLINE_ const T *operator->() const { return &E->get(); }
+ _FORCE_INLINE_ ConstIterator &operator++() {
+ E = E->next();
+ return *this;
+ }
+ _FORCE_INLINE_ ConstIterator &operator--() {
+ E = E->prev();
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
+ _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
+
+ _FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; }
+ _FORCE_INLINE_ ConstIterator() {}
+ _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
+
+ private:
+ const Element *E = nullptr;
+ };
+
+ _FORCE_INLINE_ Iterator begin() {
+ return Iterator(front());
+ }
+ _FORCE_INLINE_ Iterator end() {
+ return Iterator(nullptr);
+ }
+
+#if 0
+ //to use when replacing find()
+ _FORCE_INLINE_ Iterator find(const K &p_key) {
+ return Iterator(find(p_key));
+ }
+#endif
+ _FORCE_INLINE_ ConstIterator begin() const {
+ return ConstIterator(front());
+ }
+ _FORCE_INLINE_ ConstIterator end() const {
+ return ConstIterator(nullptr);
+ }
+#if 0
+ //to use when replacing find()
+ _FORCE_INLINE_ ConstIterator find(const K &p_key) const {
+ return ConstIterator(find(p_key));
+ }
+#endif
private:
struct _Data {
Element *first = nullptr;
diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h
index 5f22e08eb8..668ec513d6 100644
--- a/core/templates/local_vector.h
+++ b/core/templates/local_vector.h
@@ -178,7 +178,7 @@ public:
}
int64_t find(const T &p_val, U p_from = 0) const {
- for (U i = 0; i < count; i++) {
+ for (U i = p_from; i < count; i++) {
if (data[i] == p_val) {
return int64_t(i);
}
diff --git a/core/templates/map.h b/core/templates/map.h
index 7dfee13d2c..a47547d355 100644
--- a/core/templates/map.h
+++ b/core/templates/map.h
@@ -33,6 +33,7 @@
#include "core/error/error_macros.h"
#include "core/os/memory.h"
+#include "core/templates/pair.h"
// based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
@@ -55,11 +56,12 @@ public:
Element *parent = nullptr;
Element *_next = nullptr;
Element *_prev = nullptr;
- K _key;
- V _value;
- //_Data *data;
+ KeyValue<K, V> _data;
public:
+ KeyValue<K, V> &key_value() { return _data; }
+ const KeyValue<K, V> &key_value() const { return _data; }
+
const Element *next() const {
return _next;
}
@@ -73,23 +75,106 @@ public:
return _prev;
}
const K &key() const {
- return _key;
+ return _data.key;
}
V &value() {
- return _value;
+ return _data.value;
}
const V &value() const {
- return _value;
+ return _data.value;
}
V &get() {
- return _value;
+ return _data.value;
}
const V &get() const {
- return _value;
+ return _data.value;
}
- Element() {}
+ Element(const KeyValue<K, V> &p_data) :
+ _data(p_data) {}
};
+ typedef KeyValue<K, V> ValueType;
+
+ struct Iterator {
+ _FORCE_INLINE_ KeyValue<K, V> &operator*() const {
+ return E->key_value();
+ }
+ _FORCE_INLINE_ KeyValue<K, V> *operator->() const { return &E->key_value(); }
+ _FORCE_INLINE_ Iterator &operator++() {
+ E = E->next();
+ return *this;
+ }
+ _FORCE_INLINE_ Iterator &operator--() {
+ E = E->prev();
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
+ _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
+
+ Iterator(Element *p_E) { E = p_E; }
+ Iterator() {}
+ Iterator(const Iterator &p_it) { E = p_it.E; }
+
+ private:
+ Element *E = nullptr;
+ };
+
+ struct ConstIterator {
+ _FORCE_INLINE_ const KeyValue<K, V> &operator*() const {
+ return E->key_value();
+ }
+ _FORCE_INLINE_ const KeyValue<K, V> *operator->() const { return &E->key_value(); }
+ _FORCE_INLINE_ ConstIterator &operator++() {
+ E = E->next();
+ return *this;
+ }
+ _FORCE_INLINE_ ConstIterator &operator--() {
+ E = E->prev();
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
+ _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
+
+ ConstIterator(const Element *p_E) { E = p_E; }
+ ConstIterator() {}
+ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
+
+ private:
+ const Element *E = nullptr;
+ };
+
+ _FORCE_INLINE_ Iterator begin() {
+ return Iterator(front());
+ }
+ _FORCE_INLINE_ Iterator end() {
+ return Iterator(nullptr);
+ }
+
+#if 0
+ //to use when replacing find()
+ _FORCE_INLINE_ Iterator find(const K &p_key) {
+ return Iterator(find(p_key));
+ }
+#endif
+ _FORCE_INLINE_ void remove(const Iterator &p_iter) {
+ return erase(p_iter.E);
+ }
+
+ _FORCE_INLINE_ ConstIterator begin() const {
+ return ConstIterator(front());
+ }
+ _FORCE_INLINE_ ConstIterator end() const {
+ return ConstIterator(nullptr);
+ }
+
+#if 0
+ //to use when replacing find()
+ _FORCE_INLINE_ ConstIterator find(const K &p_key) const {
+ return ConstIterator(find(p_key));
+ }
+#endif
private:
struct _Data {
Element *_root = nullptr;
@@ -107,7 +192,7 @@ private:
}
void _create_root() {
- _root = memnew_allocator(Element, A);
+ _root = memnew_allocator(Element(KeyValue<K, V>(K(), V())), A);
_root->parent = _root->left = _root->right = _nil;
_root->color = BLACK;
}
@@ -216,9 +301,9 @@ private:
C less;
while (node != _data._nil) {
- if (less(p_key, node->_key)) {
+ if (less(p_key, node->_data.key)) {
node = node->left;
- } else if (less(node->_key, p_key)) {
+ } else if (less(node->_data.key, p_key)) {
node = node->right;
} else {
return node; // found
@@ -236,9 +321,9 @@ private:
while (node != _data._nil) {
prev = node;
- if (less(p_key, node->_key)) {
+ if (less(p_key, node->_data.key)) {
node = node->left;
- } else if (less(node->_key, p_key)) {
+ } else if (less(node->_data.key, p_key)) {
node = node->right;
} else {
return node; // found
@@ -249,7 +334,7 @@ private:
return nullptr; // tree empty
}
- if (less(p_key, prev->_key)) {
+ if (less(p_key, prev->_data.key)) {
prev = prev->_prev;
}
@@ -312,25 +397,25 @@ private:
while (node != _data._nil) {
new_parent = node;
- if (less(p_key, node->_key)) {
+ if (less(p_key, node->_data.key)) {
node = node->left;
- } else if (less(node->_key, p_key)) {
+ } else if (less(node->_data.key, p_key)) {
node = node->right;
} else {
- node->_value = p_value;
+ node->_data.value = p_value;
return node; // Return existing node with new value
}
}
- Element *new_node = memnew_allocator(Element, A);
+ typedef KeyValue<K, V> KV;
+ Element *new_node = memnew_allocator(Element(KV(p_key, p_value)), A);
new_node->parent = new_parent;
new_node->right = _data._nil;
new_node->left = _data._nil;
- new_node->_key = p_key;
- new_node->_value = p_value;
+
//new_node->data=_data;
- if (new_parent == _data._root || less(p_key, new_parent->_key)) {
+ if (new_parent == _data._root || less(p_key, new_parent->_data.key)) {
new_parent->left = new_node;
} else {
new_parent->right = new_node;
@@ -575,7 +660,7 @@ public:
CRASH_COND(!_data._root);
const Element *e = find(p_key);
CRASH_COND(!e);
- return e->_value;
+ return e->_data.value;
}
V &operator[](const K &p_key) {
@@ -588,7 +673,7 @@ public:
e = insert(p_key, V());
}
- return e->_value;
+ return e->_data.value;
}
Element *front() const {
diff --git a/core/templates/pair.h b/core/templates/pair.h
index bc1a764694..e30ee8bc56 100644
--- a/core/templates/pair.h
+++ b/core/templates/pair.h
@@ -31,6 +31,8 @@
#ifndef PAIR_H
#define PAIR_H
+#include "core/typedefs.h"
+
template <class F, class S>
struct Pair {
F first;
@@ -60,7 +62,43 @@ bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) {
template <class F, class S>
struct PairSort {
bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const {
- return A.first < B.first;
+ if (A.first != B.first) {
+ return A.first < B.first;
+ }
+ return A.second < B.second;
+ }
+};
+
+template <class K, class V>
+struct KeyValue {
+ const K key;
+ V value;
+
+ void operator=(const KeyValue &p_kv) = delete;
+ _FORCE_INLINE_ KeyValue(const KeyValue &p_kv) :
+ key(p_kv.key),
+ value(p_kv.value) {
+ }
+ _FORCE_INLINE_ KeyValue(const K &p_key, const V &p_value) :
+ key(p_key),
+ value(p_value) {
+ }
+};
+
+template <class K, class V>
+bool operator==(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
+ return (pair.key == other.key) && (pair.value == other.value);
+}
+
+template <class K, class V>
+bool operator!=(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
+ return (pair.key != other.key) || (pair.value != other.value);
+}
+
+template <class K, class V>
+struct KeyValueSort {
+ bool operator()(const KeyValue<K, V> &A, const KeyValue<K, V> &B) const {
+ return A.key < B.key;
}
};
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index 31278b71bd..4f5c74ca46 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -79,7 +79,7 @@ class RID_Alloc : public RID_AllocBase {
SpinLock spin_lock;
- _FORCE_INLINE_ RID _allocate_rid(const T *p_initializer) {
+ _FORCE_INLINE_ RID _allocate_rid() {
if (THREAD_SAFE) {
spin_lock.lock();
}
@@ -114,11 +114,6 @@ class RID_Alloc : public RID_AllocBase {
uint32_t free_chunk = free_index / elements_in_chunk;
uint32_t free_element = free_index % elements_in_chunk;
- if (p_initializer) {
- T *ptr = &chunks[free_chunk][free_element];
- memnew_placement(ptr, T(*p_initializer));
- }
-
uint32_t validator = (uint32_t)(_gen_id() & 0x7FFFFFFF);
uint64_t id = validator;
id <<= 32;
@@ -126,9 +121,7 @@ class RID_Alloc : public RID_AllocBase {
validator_chunks[free_chunk][free_element] = validator;
- if (!p_initializer) {
- validator_chunks[free_chunk][free_element] |= 0x80000000; //mark uninitialized bit
- }
+ validator_chunks[free_chunk][free_element] |= 0x80000000; //mark uninitialized bit
alloc_count++;
@@ -140,13 +133,20 @@ class RID_Alloc : public RID_AllocBase {
}
public:
+ RID make_rid() {
+ RID rid = _allocate_rid();
+ initialize_rid(rid);
+ return rid;
+ }
RID make_rid(const T &p_value) {
- return _allocate_rid(&p_value);
+ RID rid = _allocate_rid();
+ initialize_rid(rid, p_value);
+ return rid;
}
//allocate but don't initialize, use initialize_rid afterwards
RID allocate_rid() {
- return _allocate_rid(nullptr);
+ return _allocate_rid();
}
_FORCE_INLINE_ T *getornull(const RID &p_rid, bool p_initialize = false) {
@@ -193,7 +193,7 @@ public:
if (THREAD_SAFE) {
spin_lock.unlock();
}
- if (validator_chunks[idx_chunk][idx_element] & 0x80000000) {
+ if ((validator_chunks[idx_chunk][idx_element] & 0x80000000) && validator_chunks[idx_chunk][idx_element] != 0xFFFFFFFF) {
ERR_FAIL_V_MSG(nullptr, "Attempting to use an uninitialized RID");
}
return nullptr;
@@ -207,6 +207,11 @@ public:
return ptr;
}
+ void initialize_rid(RID p_rid) {
+ T *mem = getornull(p_rid, true);
+ ERR_FAIL_COND(!mem);
+ memnew_placement(mem, T);
+ }
void initialize_rid(RID p_rid, const T &p_value) {
T *mem = getornull(p_rid, true);
ERR_FAIL_COND(!mem);
@@ -333,7 +338,7 @@ public:
description = p_descrption;
}
- RID_Alloc(uint32_t p_target_chunk_byte_size = 4096) {
+ RID_Alloc(uint32_t p_target_chunk_byte_size = 65536) {
elements_in_chunk = sizeof(T) > p_target_chunk_byte_size ? 1 : (p_target_chunk_byte_size / sizeof(T));
}
@@ -434,7 +439,7 @@ public:
alloc.set_description(p_descrption);
}
- RID_PtrOwner(uint32_t p_target_chunk_byte_size = 4096) :
+ RID_PtrOwner(uint32_t p_target_chunk_byte_size = 65536) :
alloc(p_target_chunk_byte_size) {}
};
@@ -443,6 +448,9 @@ class RID_Owner {
RID_Alloc<T, THREAD_SAFE> alloc;
public:
+ _FORCE_INLINE_ RID make_rid() {
+ return alloc.make_rid();
+ }
_FORCE_INLINE_ RID make_rid(const T &p_ptr) {
return alloc.make_rid(p_ptr);
}
@@ -451,6 +459,10 @@ public:
return alloc.allocate_rid();
}
+ _FORCE_INLINE_ void initialize_rid(RID p_rid) {
+ alloc.initialize_rid(p_rid);
+ }
+
_FORCE_INLINE_ void initialize_rid(RID p_rid, const T &p_ptr) {
alloc.initialize_rid(p_rid, p_ptr);
}
@@ -486,7 +498,7 @@ public:
void set_description(const char *p_descrption) {
alloc.set_description(p_descrption);
}
- RID_Owner(uint32_t p_target_chunk_byte_size = 4096) :
+ RID_Owner(uint32_t p_target_chunk_byte_size = 65536) :
alloc(p_target_chunk_byte_size) {}
};
diff --git a/core/templates/set.h b/core/templates/set.h
index 3036ecf27d..245c174862 100644
--- a/core/templates/set.h
+++ b/core/templates/set.h
@@ -77,6 +77,85 @@ public:
Element() {}
};
+ typedef T ValueType;
+
+ struct Iterator {
+ _FORCE_INLINE_ T &operator*() const {
+ return E->get();
+ }
+ _FORCE_INLINE_ T *operator->() const { return &E->get(); }
+ _FORCE_INLINE_ Iterator &operator++() {
+ E = E->next();
+ return *this;
+ }
+ _FORCE_INLINE_ Iterator &operator--() {
+ E = E->prev();
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
+ _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
+
+ Iterator(Element *p_E) { E = p_E; }
+ Iterator() {}
+ Iterator(const Iterator &p_it) { E = p_it.E; }
+
+ private:
+ Element *E = nullptr;
+ };
+
+ struct ConstIterator {
+ _FORCE_INLINE_ const T &operator*() const {
+ return E->get();
+ }
+ _FORCE_INLINE_ const T *operator->() const { return &E->get(); }
+ _FORCE_INLINE_ ConstIterator &operator++() {
+ E = E->next();
+ return *this;
+ }
+ _FORCE_INLINE_ ConstIterator &operator--() {
+ E = E->prev();
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
+ _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
+
+ _FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; }
+ _FORCE_INLINE_ ConstIterator() {}
+ _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
+
+ private:
+ const Element *E = nullptr;
+ };
+
+ _FORCE_INLINE_ Iterator begin() {
+ return Iterator(front());
+ }
+ _FORCE_INLINE_ Iterator end() {
+ return Iterator(nullptr);
+ }
+
+#if 0
+ //to use when replacing find()
+ _FORCE_INLINE_ Iterator find(const K &p_key) {
+ return Iterator(find(p_key));
+ }
+#endif
+
+ _FORCE_INLINE_ ConstIterator begin() const {
+ return ConstIterator(front());
+ }
+ _FORCE_INLINE_ ConstIterator end() const {
+ return ConstIterator(nullptr);
+ }
+
+#if 0
+ //to use when replacing find()
+ _FORCE_INLINE_ ConstIterator find(const K &p_key) const {
+ return ConstIterator(find(p_key));
+ }
+#endif
private:
struct _Data {
Element *_root = nullptr;
diff --git a/core/templates/vector.h b/core/templates/vector.h
index dae8874a87..08cbef6ba4 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -187,6 +187,70 @@ public:
return false;
}
+ struct Iterator {
+ _FORCE_INLINE_ T &operator*() const {
+ return *elem_ptr;
+ }
+ _FORCE_INLINE_ T *operator->() const { return elem_ptr; }
+ _FORCE_INLINE_ Iterator &operator++() {
+ elem_ptr++;
+ return *this;
+ }
+ _FORCE_INLINE_ Iterator &operator--() {
+ elem_ptr--;
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const Iterator &b) const { return elem_ptr == b.elem_ptr; }
+ _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return elem_ptr != b.elem_ptr; }
+
+ Iterator(T *p_ptr) { elem_ptr = p_ptr; }
+ Iterator() {}
+ Iterator(const Iterator &p_it) { elem_ptr = p_it.elem_ptr; }
+
+ private:
+ T *elem_ptr = nullptr;
+ };
+
+ struct ConstIterator {
+ _FORCE_INLINE_ const T &operator*() const {
+ return *elem_ptr;
+ }
+ _FORCE_INLINE_ const T *operator->() const { return elem_ptr; }
+ _FORCE_INLINE_ ConstIterator &operator++() {
+ elem_ptr++;
+ return *this;
+ }
+ _FORCE_INLINE_ ConstIterator &operator--() {
+ elem_ptr--;
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return elem_ptr == b.elem_ptr; }
+ _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return elem_ptr != b.elem_ptr; }
+
+ ConstIterator(T *p_ptr) { elem_ptr = p_ptr; }
+ ConstIterator() {}
+ ConstIterator(const ConstIterator &p_it) { elem_ptr = p_it.elem_ptr; }
+
+ private:
+ const T *elem_ptr = nullptr;
+ };
+
+ _FORCE_INLINE_ Iterator begin() {
+ return Iterator(ptrw());
+ }
+ _FORCE_INLINE_ Iterator end() {
+ return Iterator(ptrw() + size());
+ }
+
+ _FORCE_INLINE_ ConstIterator begin() const {
+ return ConstIterator(ptr());
+ }
+ _FORCE_INLINE_ ConstIterator end() const {
+ return ConstIterator(ptr() + size());
+ }
+
_FORCE_INLINE_ Vector() {}
_FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); }
diff --git a/core/typedefs.h b/core/typedefs.h
index cdbfb34e56..dde254af23 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -281,4 +281,11 @@ struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
#define DEBUG_METHODS_ENABLED
#endif
+// Macro GD_IS_DEFINED() allows to check if a macro is defined. It needs to be defined to anything (say 1) to work.
+#define __GDARG_PLACEHOLDER_1 0,
+#define __gd_take_second_arg(__ignored, val, ...) val
+#define ____gd_is_defined(arg1_or_junk) __gd_take_second_arg(arg1_or_junk 1, 0)
+#define ___gd_is_defined(val) ____gd_is_defined(__GDARG_PLACEHOLDER_##val)
+#define GD_IS_DEFINED(x) ___gd_is_defined(x)
+
#endif // TYPEDEFS_H
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 0885777429..ef5867c685 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -77,6 +77,7 @@ struct VariantCaster<const T &> {
_FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \
return m_enum(*reinterpret_cast<const int *>(p_ptr)); \
} \
+ typedef int64_t EncodeT; \
_FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \
*(int *)p_ptr = p_val; \
} \
@@ -117,6 +118,7 @@ struct PtrToArg<char32_t> {
_FORCE_INLINE_ static char32_t convert(const void *p_ptr) {
return char32_t(*reinterpret_cast<const int *>(p_ptr));
}
+ typedef int64_t EncodeT;
_FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) {
*(int *)p_ptr = p_val;
}
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 34b3e3ea35..ca6f3d615e 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -89,6 +89,10 @@ Callable Callable::unbind(int p_argcount) const {
return Callable(memnew(CallableCustomUnbind(*this, p_argcount)));
}
+bool Callable::is_valid() const {
+ return get_object() && (is_custom() || get_object()->has_method(get_method()));
+}
+
Object *Callable::get_object() const {
if (is_null()) {
return nullptr;
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 20d0804292..52094af3aa 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -81,6 +81,7 @@ public:
_FORCE_INLINE_ bool is_standard() const {
return method != StringName();
}
+ bool is_valid() const;
Callable bind(const Variant **p_arguments, int p_argcount) const;
Callable unbind(int p_argcount) const;
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index b2f7c6aa0a..07b3a9a675 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -33,6 +33,11 @@
#include "core/templates/ordered_hash_map.h"
#include "core/templates/safe_refcount.h"
#include "core/variant/variant.h"
+// required in this order by VariantInternal, do not remove this comment.
+#include "core/object/class_db.h"
+#include "core/object/object.h"
+#include "core/variant/type_info.h"
+#include "core/variant/variant_internal.h"
struct DictionaryPrivate {
SafeRefCount refcount;
@@ -74,15 +79,32 @@ Variant Dictionary::get_value_at_index(int p_index) const {
}
Variant &Dictionary::operator[](const Variant &p_key) {
- return _p->variant_map[p_key];
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ return _p->variant_map[sn->operator String()];
+ } else {
+ return _p->variant_map[p_key];
+ }
}
const Variant &Dictionary::operator[](const Variant &p_key) const {
- return _p->variant_map[p_key];
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ return _p->variant_map[sn->operator String()];
+ } else {
+ return _p->variant_map[p_key];
+ }
}
const Variant *Dictionary::getptr(const Variant &p_key) const {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ } else {
+ E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ }
if (!E) {
return nullptr;
@@ -91,8 +113,14 @@ const Variant *Dictionary::getptr(const Variant &p_key) const {
}
Variant *Dictionary::getptr(const Variant &p_key) {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(p_key);
+ OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E;
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ } else {
+ E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ }
if (!E) {
return nullptr;
}
@@ -100,7 +128,14 @@ Variant *Dictionary::getptr(const Variant &p_key) {
}
Variant Dictionary::get_valid(const Variant &p_key) const {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ } else {
+ E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ }
if (!E) {
return Variant();
@@ -126,7 +161,12 @@ bool Dictionary::is_empty() const {
}
bool Dictionary::has(const Variant &p_key) const {
- return _p->variant_map.has(p_key);
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ return _p->variant_map.has(sn->operator String());
+ } else {
+ return _p->variant_map.has(p_key);
+ }
}
bool Dictionary::has_all(const Array &p_keys) const {
@@ -139,7 +179,12 @@ bool Dictionary::has_all(const Array &p_keys) const {
}
bool Dictionary::erase(const Variant &p_key) {
- return _p->variant_map.erase(p_key);
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ return _p->variant_map.erase(sn->operator String());
+ } else {
+ return _p->variant_map.erase(p_key);
+ }
}
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h
index d4ec5e570c..7852187b77 100644
--- a/core/variant/method_ptrcall.h
+++ b/core/variant/method_ptrcall.h
@@ -45,6 +45,7 @@ struct PtrToArg {};
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
+ typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
@@ -54,6 +55,7 @@ struct PtrToArg {};
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
+ typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
@@ -65,6 +67,7 @@ struct PtrToArg {};
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
} \
+ typedef m_conv EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
} \
@@ -74,6 +77,7 @@ struct PtrToArg {};
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
} \
+ typedef m_conv EncodeT; \
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
} \
@@ -85,6 +89,7 @@ struct PtrToArg {};
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
+ typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
@@ -94,12 +99,13 @@ struct PtrToArg {};
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
return *reinterpret_cast<const m_type *>(p_ptr); \
} \
+ typedef m_type EncodeT; \
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
*((m_type *)p_ptr) = p_val; \
} \
}
-MAKE_PTRARG(bool);
+MAKE_PTRARGCONV(bool, uint32_t);
// Integer types.
MAKE_PTRARGCONV(uint8_t, int64_t);
MAKE_PTRARGCONV(int8_t, int64_t);
@@ -153,7 +159,7 @@ struct PtrToArg<T *> {
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return const_cast<T *>(reinterpret_cast<const T *>(p_ptr));
}
-
+ typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*((T **)p_ptr) = p_var;
}
@@ -164,7 +170,7 @@ struct PtrToArg<const T *> {
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(p_ptr);
}
-
+ typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*((T **)p_ptr) = p_var;
}
@@ -177,7 +183,7 @@ struct PtrToArg<ObjectID> {
_FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) {
return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr));
}
-
+ typedef uint64_t EncodeT;
_FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) {
*((uint64_t *)p_ptr) = p_val;
}
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 125173ea5c..6d1b4da9e8 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -499,9 +499,10 @@ public:
static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method);
static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list);
static int get_builtin_method_count(Variant::Type p_type);
+ static uint32_t get_builtin_method_hash(Variant::Type p_type, const StringName &p_method);
void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
- Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant());
+ Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant());
static void call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
@@ -586,7 +587,7 @@ public:
typedef void (*PTRKeyedSetter)(void *base, const void *key, const void *value);
typedef void (*PTRKeyedGetter)(const void *base, const void *key, void *value);
- typedef bool (*PTRKeyedChecker)(const void *base, const void *key);
+ typedef uint32_t (*PTRKeyedChecker)(const void *base, const void *key);
static PTRKeyedSetter get_member_ptr_keyed_setter(Variant::Type p_type);
static PTRKeyedGetter get_member_ptr_keyed_getter(Variant::Type p_type);
@@ -631,6 +632,7 @@ public:
static bool has_utility_function_return_value(const StringName &p_name);
static Variant::Type get_utility_function_return_type(const StringName &p_name);
static bool is_utility_function_vararg(const StringName &p_name);
+ static uint32_t get_utility_function_hash(const StringName &p_name);
static void get_utility_function_list(List<StringName> *r_functions);
static int get_utility_function_count();
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 9c7cd23d72..733361fe58 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1126,6 +1126,25 @@ bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p
return method->is_vararg;
}
+uint32_t Variant::get_builtin_method_hash(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, 0);
+ uint32_t hash = hash_djb2_one_32(method->is_const);
+ hash = hash_djb2_one_32(method->is_static, hash);
+ hash = hash_djb2_one_32(method->is_vararg, hash);
+ hash = hash_djb2_one_32(method->has_return_type, hash);
+ if (method->has_return_type) {
+ hash = hash_djb2_one_32(method->return_type, hash);
+ }
+ hash = hash_djb2_one_32(method->argument_count, hash);
+ for (int i = 0; i < method->argument_count; i++) {
+ hash = method->get_argument_type(i);
+ }
+
+ return hash;
+}
+
void Variant::get_method_list(List<MethodInfo> *p_list) const {
if (type == OBJECT) {
Object *obj = get_validated_object();
@@ -1611,6 +1630,7 @@ static void _register_variant_builtin_methods() {
bind_method(Callable, is_null, sarray(), varray());
bind_method(Callable, is_custom, sarray(), varray());
bind_method(Callable, is_standard, sarray(), varray());
+ bind_method(Callable, is_valid, sarray(), varray());
bind_method(Callable, get_object, sarray(), varray());
bind_method(Callable, get_object_id, sarray(), varray());
bind_method(Callable, get_method, sarray(), varray());
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index 4a1950c9bf..16c7428781 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -661,8 +661,8 @@ static const char *_op_names[Variant::OP_MAX] = {
"-",
"*",
"/",
- "-",
- "+",
+ "unary-",
+ "unary+",
"%",
"<<",
">>",
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index e744e76ea3..cbdd60f404 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -1261,8 +1261,10 @@ public:
const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
- b->get(a, &r_valid);
- *r_ret = r_valid;
+ bool exist;
+ b->get(a, &exist);
+ *r_ret = exist;
+ r_valid = true;
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
Object *l = right->get_validated_object();
@@ -1293,8 +1295,10 @@ public:
const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(&p_left);
- b->get(a, &r_valid);
- *r_ret = r_valid;
+ bool exist;
+ b->get(a, &exist);
+ *r_ret = exist;
+ r_valid = true;
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
Object *l = right->get_validated_object();
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index e61ce1eeaa..86d5ae7f38 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -1204,16 +1204,32 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin
r_tag.name = "";
r_tag.fields.clear();
- while (true) {
- char32_t c = p_stream->get_char();
- if (p_stream->is_eof()) {
- r_err_str = "Unexpected EOF while parsing simple tag";
- return ERR_PARSE_ERROR;
+ if (p_stream->is_utf8()) {
+ CharString cs;
+ while (true) {
+ char c = p_stream->get_char();
+ if (p_stream->is_eof()) {
+ r_err_str = "Unexpected EOF while parsing simple tag";
+ return ERR_PARSE_ERROR;
+ }
+ if (c == ']') {
+ break;
+ }
+ cs += c;
}
- if (c == ']') {
- break;
+ r_tag.name.parse_utf8(cs.get_data(), cs.length());
+ } else {
+ while (true) {
+ char32_t c = p_stream->get_char();
+ if (p_stream->is_eof()) {
+ r_err_str = "Unexpected EOF while parsing simple tag";
+ return ERR_PARSE_ERROR;
+ }
+ if (c == ']') {
+ break;
+ }
+ r_tag.name += String::chr(c);
}
- r_tag.name += String::chr(c);
}
r_tag.name = r_tag.name.strip_edges();
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 5cb329e69a..de1deace63 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -871,7 +871,7 @@ struct VariantKeyedSetGetDictionary {
*r_valid = true;
return VariantGetInternalPtr<Dictionary>::get_ptr(base)->has(*key);
}
- static bool ptr_has(const void *base, const void *key) {
+ static uint32_t ptr_has(const void *base, const void *key) {
/* avoid ptrconvert for performance*/
const Dictionary &v = *reinterpret_cast<const Dictionary *>(base);
return v.has(PtrToArg<Variant>::convert(key));
@@ -921,7 +921,7 @@ struct VariantKeyedSetGetObject {
obj->getvar(*key, &exists);
return exists;
}
- static bool ptr_has(const void *base, const void *key) {
+ static uint32_t ptr_has(const void *base, const void *key) {
const Object *obj = PtrToArg<Object *>::convert(base);
ERR_FAIL_COND_V(!obj, false);
bool valid;
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 5d1efb4166..1f69e81d99 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -1348,8 +1348,8 @@ String Variant::get_utility_function_argument_name(const StringName &p_name, int
if (!bfi) {
return String();
}
- ERR_FAIL_COND_V(bfi->is_vararg, String());
ERR_FAIL_INDEX_V(p_arg, bfi->argnames.size(), String());
+ ERR_FAIL_COND_V(bfi->is_vararg, String());
return bfi->argnames[p_arg];
}
@@ -1379,6 +1379,23 @@ bool Variant::is_utility_function_vararg(const StringName &p_name) {
return bfi->is_vararg;
}
+uint32_t Variant::get_utility_function_hash(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ ERR_FAIL_COND_V(!bfi, 0);
+
+ uint32_t hash = hash_djb2_one_32(bfi->is_vararg);
+ hash = hash_djb2_one_32(bfi->returns_value, hash);
+ if (bfi->returns_value) {
+ hash = hash_djb2_one_32(bfi->return_type, hash);
+ }
+ hash = hash_djb2_one_32(bfi->argcount, hash);
+ for (int i = 0; i < bfi->argcount; i++) {
+ hash = hash_djb2_one_32(bfi->get_arg_type(i), hash);
+ }
+
+ return hash;
+}
+
void Variant::get_utility_function_list(List<StringName> *r_functions) {
for (List<StringName>::Element *E = utility_function_name_table.front(); E; E = E->next()) {
r_functions->push_back(E->get());
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index fa118bec54..d0bd517050 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -778,7 +778,7 @@
<return type="float">
</return>
<description>
- Returns a random floating point value on the interval [code][0, 1][/code].
+ Returns a random floating point value between [code]0.0[/code] and [code]1.0[/code] (inclusive).
[codeblock]
randf() # Returns e.g. 0.375671
[/codeblock]
@@ -792,7 +792,7 @@
<argument index="1" name="to" type="float">
</argument>
<description>
- Random range, any floating point value between [code]from[/code] and [code]to[/code].
+ Returns a random floating point value on the interval between [code]from[/code] and [code]to[/code] (inclusive).
[codeblock]
prints(randf_range(-10, 10), randf_range(-10, 10)) # Prints e.g. -3.844535 7.45315
[/codeblock]
@@ -819,7 +819,7 @@
<argument index="1" name="to" type="int">
</argument>
<description>
- Random range, any 32-bit integer value between [code]from[/code] and [code]to[/code] (inclusive). If [code]to[/code] is lesser than [code]from[/code] they are swapped.
+ Returns a random signed 32-bit integer between [code]from[/code] and [code]to[/code] (inclusive). If [code]to[/code] is lesser than [code]from[/code], they are swapped.
[codeblock]
print(randi_range(0, 1)) # Prints 0 or 1
print(randi_range(-10, 1000)) # Prints any number from -10 to 1000
@@ -1224,6 +1224,8 @@
<member name="Marshalls" type="Marshalls" setter="" getter="">
The [Marshalls] singleton.
</member>
+ <member name="NativeExtensionManager" type="NativeExtensionManager" setter="" getter="">
+ </member>
<member name="NavigationMeshGenerator" type="NavigationMeshGenerator" setter="" getter="">
The [NavigationMeshGenerator] singleton.
</member>
@@ -2408,13 +2410,15 @@
</constant>
<constant name="PROPERTY_HINT_RANGE" value="1" enum="PropertyHint">
Hints that an integer or float property should be within a range specified via the hint string [code]"min,max"[/code] or [code]"min,max,step"[/code]. The hint string can optionally include [code]"or_greater"[/code] and/or [code]"or_lesser"[/code] to allow manual input going respectively above the max or below the min values. Example: [code]"-360,360,1,or_greater,or_lesser"[/code].
+ Additionally, other keywords can be included: "exp" for exponential range editing, "radians" for editing radian angles in degrees, "degrees" to hint at an angle and "noslider" to hide the slider.
</constant>
- <constant name="PROPERTY_HINT_EXP_RANGE" value="2" enum="PropertyHint">
- Hints that an integer or float property should be within an exponential range specified via the hint string [code]"min,max"[/code] or [code]"min,max,step"[/code]. The hint string can optionally include [code]"or_greater"[/code] and/or [code]"or_lesser"[/code] to allow manual input going respectively above the max or below the min values. Example: [code]"0.01,100,0.01,or_greater"[/code].
- </constant>
- <constant name="PROPERTY_HINT_ENUM" value="3" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_ENUM" value="2" enum="PropertyHint">
Hints that an integer, float or string property is an enumerated value to pick in a list specified via a hint string such as [code]"Hello,Something,Else"[/code].
</constant>
+ <constant name="PROPERTY_HINT_ENUM_SUGGESTION" value="3" enum="PropertyHint">
+ Hints that a string property is can be an enumerated value to pick in a list specified via a hint string such as [code]"Hello,Something,Else"[/code].
+ Unlike [constant PROPERTY_HINT_ENUM] a property with this hint still accepts arbitrary values and can be empty. The list of values serves to suggest possible values.
+ </constant>
<constant name="PROPERTY_HINT_EXP_EASING" value="4" enum="PropertyHint">
Hints that a float property should be edited via an exponential easing function. The hint string can include [code]"attenuation"[/code] to flip the curve horizontally and/or [code]"inout"[/code] to also include in/out easing.
</constant>
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index f644606040..fd1e2ba104 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -21,6 +21,7 @@
<description>
Adds a button with label [code]text[/code] and a custom [code]action[/code] to the dialog and returns the created button. [code]action[/code] will be passed to the [signal custom_action] signal when pressed.
If [code]true[/code], [code]right[/code] will place the button to the right of any sibling buttons.
+ You can use [method remove_button] method to remove a button created with this method from the dialog.
</description>
</method>
<method name="add_cancel_button">
@@ -30,6 +31,7 @@
</argument>
<description>
Adds a button with label [code]name[/code] and a cancel action to the dialog and returns the created button.
+ You can use [method remove_button] method to remove a button created with this method from the dialog.
</description>
</method>
<method name="get_label">
@@ -55,6 +57,15 @@
Registers a [LineEdit] in the dialog. When the enter key is pressed, the dialog will be accepted.
</description>
</method>
+ <method name="remove_button">
+ <return type="void">
+ </return>
+ <argument index="0" name="button" type="Control">
+ </argument>
+ <description>
+ Removes the [code]button[/code] from the dialog. Does NOT free the [code]button[/code]. The [code]button[/code] must be a [Button] added with [method add_button] or [method add_cancel_button] method. After removal, pressing the [code]button[/code] will no longer emit this dialog's [signal custom_action] or [signal cancelled] signals.
+ </description>
+ </method>
</methods>
<members>
<member name="dialog_autowrap" type="bool" setter="set_autowrap" getter="has_autowrap" default="false">
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 1bbf9bcd93..7fbf53c7d1 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -43,7 +43,7 @@
[/csharp]
[/codeblocks]
The [MeshInstance3D] is ready to be added to the [SceneTree] to be shown.
- See also [ImmediateGeometry3D], [MeshDataTool] and [SurfaceTool] for procedural geometry generation.
+ See also [ImmediateMesh], [MeshDataTool] and [SurfaceTool] for procedural geometry generation.
[b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes.
</description>
<tutorials>
@@ -202,7 +202,31 @@
Sets a name for a given surface.
</description>
</method>
- <method name="surface_update_region">
+ <method name="surface_update_attribute_region">
+ <return type="void">
+ </return>
+ <argument index="0" name="surf_idx" type="int">
+ </argument>
+ <argument index="1" name="offset" type="int">
+ </argument>
+ <argument index="2" name="data" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="surface_update_skin_region">
+ <return type="void">
+ </return>
+ <argument index="0" name="surf_idx" type="int">
+ </argument>
+ <argument index="1" name="offset" type="int">
+ </argument>
+ <argument index="2" name="data" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="surface_update_vertex_region">
<return type="void">
</return>
<argument index="0" name="surf_idx" type="int">
@@ -212,8 +236,6 @@
<argument index="2" name="data" type="PackedByteArray">
</argument>
<description>
- Updates a specified region of mesh arrays on the GPU.
- [b]Warning:[/b] Only use if you know what you are doing. You can easily cause crashes by calling this function with improper arguments.
</description>
</method>
</methods>
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index f7e31f5f9c..d842bac54a 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -39,6 +39,16 @@
Returns [code]true[/code] if the mouse has entered the button and has not left it yet.
</description>
</method>
+ <method name="set_pressed_no_signal">
+ <return type="void">
+ </return>
+ <argument index="0" name="pressed" type="bool">
+ </argument>
+ <description>
+ Changes the [member pressed] state of the button, without emitting [signal toggled]. Use when you just want to change the state of the button without sending the pressed event (e.g. when initializing scene). Only works if [member toggle_mode] is [code]true[/code].
+ [b]Note:[/b] This method doesn't unpress other buttons in [member button_group].
+ </description>
+ </method>
</methods>
<members>
<member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="BaseButton.ActionMode" default="1">
@@ -60,7 +70,8 @@
[b]Note:[/b] This property only affects the button's visual appearance. Signals will be emitted at the same moment regardless of this property's value.
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false">
- If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active).
+ If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). Only works if [member toggle_mode] is [code]true[/code].
+ [b]Note:[/b] Setting [member pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal].
</member>
<member name="shortcut" type="Shortcut" setter="set_shortcut" getter="get_shortcut">
[Shortcut] associated to the button.
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index abe06bc7e1..2a378ed03e 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -347,8 +347,6 @@
</member>
<member name="subsurf_scatter_transmittance_color" type="Color" setter="set_transmittance_color" getter="get_transmittance_color" default="Color(1, 1, 1, 1)">
</member>
- <member name="subsurf_scatter_transmittance_curve" type="float" setter="set_transmittance_curve" getter="get_transmittance_curve" default="1.0">
- </member>
<member name="subsurf_scatter_transmittance_depth" type="float" setter="set_transmittance_depth" getter="get_transmittance_depth" default="0.1">
</member>
<member name="subsurf_scatter_transmittance_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml
index c9078a4de5..239e0bb2d9 100644
--- a/doc/classes/Button.xml
+++ b/doc/classes/Button.xml
@@ -85,6 +85,9 @@
<member name="icon" type="Texture2D" setter="set_button_icon" getter="get_button_icon">
Button's icon, if text is present the icon will be placed before the text.
</member>
+ <member name="icon_align" type="int" setter="set_icon_align" getter="get_icon_align" enum="Button.TextAlign" default="0">
+ Specifies if the icon should be aligned to the left, right, or center of a button. Uses the same [enum TextAlign] constants as the text alignment. If centered, text will draw on top of the icon.
+ </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>
diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml
index 9620e9abd1..22f070b73b 100644
--- a/doc/classes/CPUParticles2D.xml
+++ b/doc/classes/CPUParticles2D.xml
@@ -152,7 +152,7 @@
Each particle's initial color. If [member texture] is defined, it will be multiplied by this color.
</member>
<member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp">
- Each particle's color will vary along this [Gradient].
+ Each particle's color will vary along this [Gradient] (multiplied with [member color]).
</member>
<member name="damping" type="float" setter="set_param" getter="get_param" default="0.0">
The rate at which particles lose velocity.
diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml
index 7509775d20..d7a89eef11 100644
--- a/doc/classes/CPUParticles3D.xml
+++ b/doc/classes/CPUParticles3D.xml
@@ -148,10 +148,10 @@
Animation speed randomness ratio.
</member>
<member name="color" type="Color" setter="set_color" getter="get_color" default="Color(1, 1, 1, 1)">
- Unused for 3D particles.
+ Each particle's initial color. To have particle display color in a [BaseMaterial3D] make sure to set [member BaseMaterial3D.vertex_color_use_as_albedo] to [code]true[/code].
</member>
<member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp">
- Unused for 3D particles.
+ Each particle's color will vary along this [GradientTexture] over its lifetime (multiplied with [member color]).
</member>
<member name="damping" type="float" setter="set_param" getter="get_param" default="0.0">
The rate at which particles lose velocity.
diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml
index cbab1a8f50..3c61e8278f 100644
--- a/doc/classes/Callable.xml
+++ b/doc/classes/Callable.xml
@@ -133,6 +133,13 @@
Returns [code]true[/code] if this [Callable] is a standard callable, referencing an object and a method using a [StringName].
</description>
</method>
+ <method name="is_valid" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the object exists and has a valid function assigned, or is a custom callable.
+ </description>
+ </method>
<method name="operator !=" qualifiers="operator">
<return type="bool">
</return>
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index bf1a9cc929..e8f4cb49b6 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -21,13 +21,6 @@
Aligns the camera to the tracked node.
</description>
</method>
- <method name="clear_current">
- <return type="void">
- </return>
- <description>
- Removes any [Camera2D] from the ancestor [Viewport]'s internal currently-assigned camera.
- </description>
- </method>
<method name="force_update_scroll">
<return type="void">
</return>
@@ -67,13 +60,6 @@
Returns the camera limit for the specified [enum Side]. See also [member limit_bottom], [member limit_top], [member limit_left], and [member limit_right].
</description>
</method>
- <method name="make_current">
- <return type="void">
- </return>
- <description>
- Make this the current 2D camera for the scene (viewport and layer), in case there are many cameras in the scene.
- </description>
- </method>
<method name="reset_smoothing">
<return type="void">
</return>
@@ -109,7 +95,7 @@
<member name="anchor_mode" type="int" setter="set_anchor_mode" getter="get_anchor_mode" enum="Camera2D.AnchorMode" default="1">
The Camera2D's anchor point. See [enum AnchorMode] constants.
</member>
- <member name="current" type="bool" setter="_set_current" getter="is_current" default="false">
+ <member name="current" type="bool" setter="set_current" getter="is_current" default="false">
If [code]true[/code], the camera is the active camera for the current scene. Only one camera can be current, so setting a different camera [code]current[/code] will disable this one.
</member>
<member name="custom_viewport" type="Node" setter="set_custom_viewport" getter="get_custom_viewport">
@@ -161,6 +147,8 @@
</member>
<member name="limit_smoothed" type="bool" setter="set_limit_smoothing_enabled" getter="is_limit_smoothing_enabled" default="false">
If [code]true[/code], the camera smoothly stops when reaches its limits.
+ This has no effect if smoothing is disabled.
+ [b]Note:[/b] To immediately update the camera's position to be within limits without smoothing, even with this setting enabled, invoke [method reset_smoothing].
</member>
<member name="limit_top" type="int" setter="set_limit" getter="get_limit" default="-10000000">
Top scroll limit in pixels. The camera stops moving when reaching this value.
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml
index afba478a20..0f0bfdc654 100644
--- a/doc/classes/Camera3D.xml
+++ b/doc/classes/Camera3D.xml
@@ -176,8 +176,8 @@
[codeblock]
# This code block is part of a script that inherits from Node3D.
# `control` is a reference to a node inheriting from Control.
- control.visible = not get_viewport().get_camera().is_position_behind(global_transform.origin)
- control.rect_position = get_viewport().get_camera().unproject_position(global_transform.origin)
+ control.visible = not get_viewport().get_camera_3d().is_position_behind(global_transform.origin)
+ control.rect_position = get_viewport().get_camera_3d().unproject_position(global_transform.origin)
[/codeblock]
</description>
</method>
diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml
index f4c04d7bca..eb99368079 100644
--- a/doc/classes/CanvasLayer.xml
+++ b/doc/classes/CanvasLayer.xml
@@ -39,9 +39,6 @@
<member name="rotation" type="float" setter="set_rotation" getter="get_rotation" default="0.0">
The layer's rotation in radians.
</member>
- <member name="rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees" default="0.0">
- The layer's rotation in degrees.
- </member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The layer's scale.
</member>
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
index fbe5c34d7d..e184e7dc82 100644
--- a/doc/classes/CharacterBody2D.xml
+++ b/doc/classes/CharacterBody2D.xml
@@ -101,9 +101,6 @@
<member name="floor_max_angle" type="float" setter="set_floor_max_angle" getter="get_floor_max_angle" default="0.785398">
Maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. The default value equals 45 degrees.
</member>
- <member name="floor_max_angle_degrees" type="float" setter="set_floor_max_angle_degrees" getter="get_floor_max_angle_degrees" default="45.0">
- Maximum angle (in degrees) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide].
- </member>
<member name="infinite_inertia" type="bool" setter="set_infinite_inertia_enabled" getter="is_infinite_inertia_enabled" default="true">
If [code]true[/code], the body will be able to push [RigidBody2D] nodes when calling [method move_and_slide], but it also won't detect any collisions with them. If [code]false[/code], it will interact with [RigidBody2D] nodes like with [StaticBody2D].
</member>
@@ -113,9 +110,6 @@
<member name="max_slides" type="int" setter="set_max_slides" getter="get_max_slides" default="4">
Maximum number of times the body can change direction before it stops when calling [method move_and_slide].
</member>
- <member name="motion/sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
- If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method move_and_slide] or [method PhysicsBody2D.move_and_collide] functions.
- </member>
<member name="snap" type="Vector2" setter="set_snap" getter="get_snap" default="Vector2(0, 0)">
When set to a value different from [code]Vector2(0, 0)[/code], the body is kept attached to slopes when calling [method move_and_slide].
As long as the [code]snap[/code] vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting [code]snap[/code] to [code]Vector2(0, 0)[/code].
diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml
index f6c3d68b3c..c76e02fac0 100644
--- a/doc/classes/CharacterBody3D.xml
+++ b/doc/classes/CharacterBody3D.xml
@@ -87,9 +87,6 @@
<member name="floor_max_angle" type="float" setter="set_floor_max_angle" getter="get_floor_max_angle" default="0.785398">
Maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. The default value equals 45 degrees.
</member>
- <member name="floor_max_angle_degrees" type="float" setter="set_floor_max_angle_degrees" getter="get_floor_max_angle_degrees" default="45.0">
- Maximum angle (in degrees) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide].
- </member>
<member name="infinite_inertia" type="bool" setter="set_infinite_inertia_enabled" getter="is_infinite_inertia_enabled" default="true">
If [code]true[/code], the body will be able to push [RigidBody3D] nodes when calling [method move_and_slide], but it also won't detect any collisions with them. If [code]false[/code], it will interact with [RigidBody3D] nodes like with [StaticBody3D].
</member>
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index 7c4c75bf0f..b0afbb201c 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -266,6 +266,9 @@
The physics layers this CollisionObject2D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer].
[b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
</member>
+ <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject2D.DisableMode" default="0">
+ Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
+ </member>
<member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable" default="true">
If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [code]collision_layer[/code] bit to be set.
</member>
@@ -284,15 +287,40 @@
</signal>
<signal name="mouse_entered">
<description>
- Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set.
+ Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted.
</description>
</signal>
<signal name="mouse_exited">
<description>
- Emitted when the mouse pointer exits all this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set.
+ Emitted when the mouse pointer exits all this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted.
+ </description>
+ </signal>
+ <signal name="mouse_shape_entered">
+ <argument index="0" name="shape_idx" type="int">
+ </argument>
+ <description>
+ Emitted when the mouse pointer enters any of this object's shapes or moves from one shape to another. [code]shape_idx[/code] is the child index of the newly entered [Shape2D]. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
+ </description>
+ </signal>
+ <signal name="mouse_shape_exited">
+ <argument index="0" name="shape_idx" type="int">
+ </argument>
+ <description>
+ Emitted when the mouse pointer exits any of this object's shapes. [code]shape_idx[/code] is the child index of the exited [Shape2D]. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
</description>
</signal>
</signals>
<constants>
+ <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [CollisionObject2D].
+ Automatically re-added to the physics simulation when the [Node] is processed again.
+ </constant>
+ <constant name="DISABLE_MODE_MAKE_STATIC" value="1" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], make the body static. Doesn't affect [Area2D]. [PhysicsBody2D] can't be affected by forces or other bodies while static.
+ Automatically set [PhysicsBody2D] back to its original mode when the [Node] is processed again.
+ </constant>
+ <constant name="DISABLE_MODE_KEEP_ACTIVE" value="2" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml
index 4ab37f5c7b..dfd1e85e56 100644
--- a/doc/classes/CollisionObject3D.xml
+++ b/doc/classes/CollisionObject3D.xml
@@ -230,6 +230,9 @@
The physics layers this CollisionObject3D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer].
[b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
</member>
+ <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject3D.DisableMode" default="0">
+ Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
+ </member>
<member name="input_capture_on_drag" type="bool" setter="set_capture_input_on_drag" getter="get_capture_input_on_drag" default="false">
If [code]true[/code], the [CollisionObject3D] will continue to receive input events as the mouse is dragged across its shapes.
</member>
@@ -265,5 +268,16 @@
</signal>
</signals>
<constants>
+ <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [CollisionObject3D].
+ Automatically re-added to the physics simulation when the [Node] is processed again.
+ </constant>
+ <constant name="DISABLE_MODE_MAKE_STATIC" value="1" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], make the body static. Doesn't affect [Area2D]. [PhysicsBody3D] can't be affected by forces or other bodies while static.
+ Automatically set [PhysicsBody3D] back to its original mode when the [Node] is processed again.
+ </constant>
+ <constant name="DISABLE_MODE_KEEP_ACTIVE" value="2" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 29c21b3213..7b1415e40d 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -80,14 +80,16 @@
</argument>
<argument index="2" name="b" type="float">
</argument>
+ <argument index="3" name="a" type="float">
+ </argument>
<description>
- Constructs a [Color] from RGB values, typically between 0 and 1. Alpha will be 1.
+ Constructs a [Color] from RGBA values, typically between 0 and 1.
[codeblocks]
[gdscript]
- var color = Color(0.2, 1.0, 0.7) # Similar to `Color8(51, 255, 178, 255)`
+ var color = Color(0.2, 1.0, 0.7, 0.8) # Similar to `Color8(51, 255, 178, 204)`
[/gdscript]
[csharp]
- var color = new Color(0.2f, 1.0f, 0.7f); // Similar to `Color.Color8(51, 255, 178, 255)`
+ var color = new Color(0.2f, 1.0f, 0.7f, 0.8f); // Similar to `Color.Color8(51, 255, 178, 255, 204)`
[/csharp]
[/codeblocks]
</description>
@@ -101,16 +103,14 @@
</argument>
<argument index="2" name="b" type="float">
</argument>
- <argument index="3" name="a" type="float">
- </argument>
<description>
- Constructs a [Color] from RGBA values, typically between 0 and 1.
+ Constructs a [Color] from RGB values, typically between 0 and 1. Alpha will be 1.
[codeblocks]
[gdscript]
- var color = Color(0.2, 1.0, 0.7, 0.8) # Similar to `Color8(51, 255, 178, 204)`
+ var color = Color(0.2, 1.0, 0.7) # Similar to `Color8(51, 255, 178, 255)`
[/gdscript]
[csharp]
- var color = new Color(0.2f, 1.0f, 0.7f, 0.8f); // Similar to `Color.Color8(51, 255, 178, 255, 204)`
+ var color = new Color(0.2f, 1.0f, 0.7f); // Similar to `Color.Color8(51, 255, 178, 255)`
[/csharp]
[/codeblocks]
</description>
@@ -349,12 +349,6 @@
<method name="operator +" qualifiers="operator">
<return type="Color">
</return>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Color">
- </return>
<argument index="0" name="right" type="Color">
</argument>
<description>
@@ -363,12 +357,6 @@
<method name="operator -" qualifiers="operator">
<return type="Color">
</return>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Color">
- </return>
<argument index="0" name="right" type="Color">
</argument>
<description>
@@ -414,6 +402,18 @@
<description>
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="to_abgr32" qualifiers="const">
<return type="int">
</return>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index d7e70fad32..23cbdd8cab 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -150,10 +150,10 @@
* it happens outside parent's rectangle and the parent has either [member rect_clip_content] enabled.
</description>
</method>
- <method name="_has_point" qualifiers="virtual">
+ <method name="_has_point" qualifiers="virtual const">
<return type="bool">
</return>
- <argument index="0" name="point" type="Vector2">
+ <argument index="0" name="" type="Vector2">
</argument>
<description>
Virtual method to be implemented by the user. Returns whether the given [code]point[/code] is inside this control.
@@ -235,22 +235,25 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
- Overrides the [Color] with given [code]name[/code] in the [member theme] resource the control uses.
+ Creates a local override for a theme [Color] with the specified [code]name[/code]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_color_override].
+ See also [method get_theme_color].
[b]Example of overriding a label's color and resetting it later:[/b]
[codeblocks]
[gdscript]
- # Override the child node "MyLabel"'s font color to orange.
+ # Given the child Label node "MyLabel", override its font color with a custom value.
$MyLabel.add_theme_color_override("font_color", Color(1, 0.5, 0))
- # Reset the color by creating a new node to get the default value:
- var default_label_color = Label.new().get_theme_color("font_color")
- $MyLabel.add_theme_color_override("font_color", default_label_color)
+ # Reset the font color of the child label.
+ $MyLabel.remove_theme_color_override("font_color")
+ # Alternatively it can be overridden with the default value from the Label type.
+ $MyLabel.add_theme_color_override("font_color", get_theme_color("font_color", "Label"))
[/gdscript]
[csharp]
- // Override the child node "MyLabel"'s font color to orange.
- GetNode&lt;Label&gt;("MyLabel").AddThemeColorOverride("font_color", new Color(1, 0.5f, 0));
- // Reset the color by creating a new node to get the default value:
- var defaultLabelColor = new Label().GetThemeColor("font_color");
- GetNode&lt;Label&gt;("MyLabel").AddThemeColorOverride("font_color", defaultLabelColor);
+ // Given the child Label node "MyLabel", override its font color with a custom value.
+ GetNode&lt;Label&gt;("MyLabel").AddThemeColorOverride("font_color", new Color(1, 0.5f, 0))
+ // Reset the font color of the child label.
+ GetNode&lt;Label&gt;("MyLabel").RemoveThemeColorOverride("font_color")
+ // Alternatively it can be overridden with the default value from the Label type.
+ GetNode&lt;Label&gt;("MyLabel").AddThemeColorOverride("font_color", GetThemeColor("font_color", "Label"))
[/csharp]
[/codeblocks]
</description>
@@ -263,7 +266,8 @@
<argument index="1" name="constant" type="int">
</argument>
<description>
- Overrides an integer constant with given [code]name[/code] in the [member theme] resource the control uses.
+ Creates a local override for a theme constant with the specified [code]name[/code]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_constant_override].
+ See also [method get_theme_constant].
</description>
</method>
<method name="add_theme_font_override">
@@ -274,7 +278,8 @@
<argument index="1" name="font" type="Font">
</argument>
<description>
- Overrides the font with given [code]name[/code] in the [member theme] resource the control uses.
+ Creates a local override for a theme [Font] with the specified [code]name[/code]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_font_override].
+ See also [method get_theme_font].
</description>
</method>
<method name="add_theme_font_size_override">
@@ -285,7 +290,8 @@
<argument index="1" name="font_size" type="int">
</argument>
<description>
- Overrides the font size with given [code]name[/code] in the [member theme] resource the control uses.
+ Creates a local override for a theme font size with the specified [code]name[/code]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_font_size_override].
+ See also [method get_theme_font_size].
</description>
</method>
<method name="add_theme_icon_override">
@@ -296,7 +302,8 @@
<argument index="1" name="texture" type="Texture2D">
</argument>
<description>
- Overrides the icon with given [code]name[/code] in the [member theme] resource the control uses.
+ Creates a local override for a theme icon with the specified [code]name[/code]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_icon_override].
+ See also [method get_theme_icon].
</description>
</method>
<method name="add_theme_stylebox_override">
@@ -307,7 +314,8 @@
<argument index="1" name="stylebox" type="StyleBox">
</argument>
<description>
- Overrides the [StyleBox] with given [code]name[/code] in the [member theme] resource the control uses.
+ Creates a local override for a theme [StyleBox] with the specified [code]name[/code]. Local overrides always take precedence when fetching theme items for the control. An override can be removed with [method remove_theme_stylebox_override].
+ See also [method get_theme_stylebox].
[b]Example of modifying a property in a StyleBox by duplicating it:[/b]
[codeblocks]
[gdscript]
@@ -318,8 +326,8 @@
new_stylebox_normal.border_width_top = 3
new_stylebox_normal.border_color = Color(0, 1, 0.5)
$MyButton.add_theme_stylebox_override("normal", new_stylebox_normal)
- # Remove the stylebox override:
- $MyButton.add_theme_stylebox_override("normal", null)
+ # Remove the stylebox override.
+ $MyButton.remove_theme_stylebox_override("normal")
[/gdscript]
[csharp]
// The snippet below assumes the child node MyButton has a StyleBoxFlat assigned.
@@ -329,8 +337,8 @@
newStyleboxNormal.BorderWidthTop = 3;
newStyleboxNormal.BorderColor = new Color(0, 1, 0.5f);
GetNode&lt;Button&gt;("MyButton").AddThemeStyleboxOverride("normal", newStyleboxNormal);
- // Remove the stylebox override:
- GetNode&lt;Button&gt;("MyButton").AddThemeStyleboxOverride("normal", null);
+ // Remove the stylebox override.
+ GetNode&lt;Button&gt;("MyButton").RemoveThemeStyleboxOverride("normal");
[/csharp]
[/codeblocks]
</description>
@@ -468,16 +476,23 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a color from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
+ Returns a [Color] from the first matching [Theme] in the tree if that [Theme] has a color item with the specified [code]name[/code] and [code]theme_type[/code]. If [code]theme_type[/code] is omitted the class name of the current control is used as the type, or [member theme_type_variation] if it is defined. If the type is a class name its parent classes are also checked, in order of inheritance. If the type is a variation its base types are checked, in order of dependency, then the control's class name and its parent classes are checked.
+ For the current control its local overrides are considered first (see [method add_theme_color_override]), then its assigned [member theme]. After the current control, each parent control and its assigned [member theme] are considered; controls without a [member theme] assigned are skipped. If no matching [Theme] is found in the tree, a custom project [Theme] (see [member ProjectSettings.gui/theme/custom]) and the default [Theme] are used.
[codeblocks]
[gdscript]
func _ready():
- modulate = get_theme_color("font_color", "Button") #get the color defined for button fonts
+ # Get the font color defined for the current Control's class, if it exists.
+ modulate = get_theme_color("font_color")
+ # Get the font color defined for the Button class.
+ modulate = get_theme_color("font_color", "Button")
[/gdscript]
[csharp]
public override void _Ready()
{
- Modulate = GetThemeColor("font_color", "Button"); //get the color defined for button fonts
+ // Get the font color defined for the current Control's class, if it exists.
+ Modulate = GetThemeColor("font_color");
+ // Get the font color defined for the Button class.
+ Modulate = GetThemeColor("font_color", "Button");
}
[/csharp]
[/codeblocks]
@@ -491,7 +506,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a constant from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
+ Returns a constant from the first matching [Theme] in the tree if that [Theme] has a constant item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="get_theme_font" qualifiers="const">
@@ -502,7 +518,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a font from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
+ Returns a [Font] from the first matching [Theme] in the tree if that [Theme] has a font item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="get_theme_font_size" qualifiers="const">
@@ -513,7 +530,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a font size from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
+ Returns a font size from the first matching [Theme] in the tree if that [Theme] has a font size item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="get_theme_icon" qualifiers="const">
@@ -524,7 +542,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns an icon from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
+ Returns an icon from the first matching [Theme] in the tree if that [Theme] has an icon item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="get_theme_stylebox" qualifiers="const">
@@ -535,7 +554,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns a [StyleBox] from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code].
+ Returns a [StyleBox] from the first matching [Theme] in the tree if that [Theme] has a stylebox item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="get_tooltip" qualifiers="const">
@@ -588,7 +608,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if [Color] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a color item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="has_theme_color_override" qualifiers="const">
@@ -597,7 +618,8 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if [Color] with given [code]name[/code] has a valid override in this [Control] node.
+ Returns [code]true[/code] if there is a local override for a theme [Color] with the specified [code]name[/code] in this [Control] node.
+ See [method add_theme_color_override].
</description>
</method>
<method name="has_theme_constant" qualifiers="const">
@@ -608,7 +630,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if constant with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a constant item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="has_theme_constant_override" qualifiers="const">
@@ -617,7 +640,8 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if constant with given [code]name[/code] has a valid override in this [Control] node.
+ Returns [code]true[/code] if there is a local override for a theme constant with the specified [code]name[/code] in this [Control] node.
+ See [method add_theme_constant_override].
</description>
</method>
<method name="has_theme_font" qualifiers="const">
@@ -628,7 +652,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if font with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a font item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="has_theme_font_override" qualifiers="const">
@@ -637,7 +662,8 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if font with given [code]name[/code] has a valid override in this [Control] node.
+ Returns [code]true[/code] if there is a local override for a theme [Font] with the specified [code]name[/code] in this [Control] node.
+ See [method add_theme_font_override].
</description>
</method>
<method name="has_theme_font_size" qualifiers="const">
@@ -648,7 +674,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if font size with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a font size item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="has_theme_font_size_override" qualifiers="const">
@@ -657,7 +684,8 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if font size with given [code]name[/code] has a valid override in this [Control] node.
+ Returns [code]true[/code] if there is a local override for a theme font size with the specified [code]name[/code] in this [Control] node.
+ See [method add_theme_font_size_override].
</description>
</method>
<method name="has_theme_icon" qualifiers="const">
@@ -668,7 +696,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if icon with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has an icon item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="has_theme_icon_override" qualifiers="const">
@@ -677,7 +706,8 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if icon with given [code]name[/code] has a valid override in this [Control] node.
+ Returns [code]true[/code] if there is a local override for a theme icon with the specified [code]name[/code] in this [Control] node.
+ See [method add_theme_icon_override].
</description>
</method>
<method name="has_theme_stylebox" qualifiers="const">
@@ -688,7 +718,8 @@
<argument index="1" name="theme_type" type="StringName" default="&quot;&quot;">
</argument>
<description>
- Returns [code]true[/code] if [StyleBox] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme].
+ Returns [code]true[/code] if there is a matching [Theme] in the tree that has a stylebox item with the specified [code]name[/code] and [code]theme_type[/code].
+ See [method get_theme_color] for details.
</description>
</method>
<method name="has_theme_stylebox_override" qualifiers="const">
@@ -697,7 +728,8 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Returns [code]true[/code] if [StyleBox] with given [code]name[/code] has a valid override in this [Control] node.
+ Returns [code]true[/code] if there is a local override for a theme [StyleBox] with the specified [code]name[/code] in this [Control] node.
+ See [method add_theme_stylebox_override].
</description>
</method>
<method name="is_layout_rtl" qualifiers="const">
@@ -727,7 +759,7 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Removes a theme override for a [Color] with the given [code]name[/code].
+ Removes a local override for a theme [Color] with the specified [code]name[/code] previously added by [method add_theme_color_override] or via the Inspector dock.
</description>
</method>
<method name="remove_theme_constant_override">
@@ -736,7 +768,7 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Removes a theme override for a constant with the given [code]name[/code].
+ Removes a local override for a theme constant with the specified [code]name[/code] previously added by [method add_theme_constant_override] or via the Inspector dock.
</description>
</method>
<method name="remove_theme_font_override">
@@ -745,7 +777,7 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Removes a theme override for a [Font] with the given [code]name[/code].
+ Removes a local override for a theme [Font] with the specified [code]name[/code] previously added by [method add_theme_font_override] or via the Inspector dock.
</description>
</method>
<method name="remove_theme_font_size_override">
@@ -754,7 +786,7 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Removes a theme override for a font size with the given [code]name[/code].
+ Removes a local override for a theme font size with the specified [code]name[/code] previously added by [method add_theme_font_size_override] or via the Inspector dock.
</description>
</method>
<method name="remove_theme_icon_override">
@@ -763,7 +795,7 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Removes a theme override for an icon with the given [code]name[/code].
+ Removes a local override for a theme icon with the specified [code]name[/code] previously added by [method add_theme_icon_override] or via the Inspector dock.
</description>
</method>
<method name="remove_theme_stylebox_override">
@@ -772,7 +804,7 @@
<argument index="0" name="name" type="StringName">
</argument>
<description>
- Removes a theme override for a [StyleBox] with the given [code]name[/code].
+ Removes a local override for a theme [StyleBox] with the specified [code]name[/code] previously added by [method add_theme_stylebox_override] or via the Inspector dock.
</description>
</method>
<method name="set_anchor">
@@ -1144,9 +1176,6 @@
<member name="rect_rotation" type="float" setter="set_rotation" getter="get_rotation" default="0.0">
The node's rotation around its pivot, in radians. See [member rect_pivot_offset] to change the pivot's position.
</member>
- <member name="rect_rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees" default="0.0">
- The node's rotation around its pivot, in degrees. See [member rect_pivot_offset] to change the pivot's position.
- </member>
<member name="rect_scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale, relative to its [member rect_size]. Change this property to scale the node around its [member rect_pivot_offset]. The Control's [member hint_tooltip] will also scale according to this value.
[b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=https://docs.godotengine.org/en/latest/tutorials/viewports/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually.
@@ -1167,8 +1196,9 @@
<member name="theme" type="Theme" setter="set_theme" getter="get_theme">
The [Theme] resource this node and all its [Control] children use. If a child node has its own [Theme] resource set, theme items are merged with child's definitions having higher priority.
</member>
- <member name="theme_custom_type" type="StringName" setter="set_theme_custom_type" getter="get_theme_custom_type" default="&amp;&quot;&quot;">
- The type name used by this [Control] to look up its own theme items. By default, the class name of the node is used (e.g. [code]Button[/code] for the [Button] control), as well as the class names of all parent classes (in order of inheritance). Setting this property gives the highest priority to the type of the specified name, then falls back on the class names.
+ <member name="theme_type_variation" type="StringName" setter="set_theme_type_variation" getter="get_theme_type_variation" default="&amp;&quot;&quot;">
+ The name of a theme type variation used by this [Control] to look up its own theme items. When empty, the class name of the node is used (e.g. [code]Button[/code] for the [Button] control), as well as the class names of all parent classes (in order of inheritance).
+ When set, this property gives the highest priority to the type of the specified name. This type can in turn extend another type, forming a dependency chain. See [method Theme.set_type_variation]. If the theme item cannot be found using this type or its base types, lookup falls back on the class names.
[b]Note:[/b] To look up [Control]'s own items use various [code]get_theme_*[/code] methods without specifying [code]theme_type[/code].
[b]Note:[/b] Theme items are looked for in the tree order, from branch to root, where each [Control] node is checked for its [member theme] property. The earliest match against any type/class name is returned. The project-level Theme and the default Theme are checked last.
</member>
diff --git a/doc/classes/CurveTexture.xml b/doc/classes/CurveTexture.xml
index bc6b69d2d1..54065fe0f9 100644
--- a/doc/classes/CurveTexture.xml
+++ b/doc/classes/CurveTexture.xml
@@ -14,10 +14,16 @@
<member name="curve" type="Curve" setter="set_curve" getter="get_curve">
The [code]curve[/code] rendered onto the texture.
</member>
+ <member name="texture_mode" type="int" setter="set_texture_mode" getter="get_texture_mode" enum="CurveTexture.TextureMode" default="0">
+ </member>
<member name="width" type="int" setter="set_width" getter="get_width" default="2048">
The width of the texture.
</member>
</members>
<constants>
+ <constant name="TEXTURE_MODE_RGB" value="0" enum="TextureMode">
+ </constant>
+ <constant name="TEXTURE_MODE_RED" value="1" enum="TextureMode">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/CurveXYZTexture.xml b/doc/classes/CurveXYZTexture.xml
new file mode 100644
index 0000000000..9afeb58060
--- /dev/null
+++ b/doc/classes/CurveXYZTexture.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="CurveXYZTexture" inherits="Texture2D" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="curve_x" type="Curve" setter="set_curve_x" getter="get_curve_x">
+ </member>
+ <member name="curve_y" type="Curve" setter="set_curve_y" getter="get_curve_y">
+ </member>
+ <member name="curve_z" type="Curve" setter="set_curve_z" getter="get_curve_z">
+ </member>
+ <member name="width" type="int" setter="set_width" getter="get_width" default="2048">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/DirectionalLight3D.xml b/doc/classes/DirectionalLight3D.xml
index 233b1f0c16..4f51adb8fc 100644
--- a/doc/classes/DirectionalLight3D.xml
+++ b/doc/classes/DirectionalLight3D.xml
@@ -15,9 +15,6 @@
<member name="directional_shadow_blend_splits" type="bool" setter="set_blend_splits" getter="is_blend_splits_enabled" default="false">
If [code]true[/code], shadow detail is sacrificed in exchange for smoother transitions between splits.
</member>
- <member name="directional_shadow_depth_range" type="int" setter="set_shadow_depth_range" getter="get_shadow_depth_range" enum="DirectionalLight3D.ShadowDepthRange" default="0">
- Optimizes shadow rendering for detail versus movement. See [enum ShadowDepthRange].
- </member>
<member name="directional_shadow_fade_start" type="float" setter="set_param" getter="get_param" default="0.8">
Proportion of [member directional_shadow_max_distance] at which point the shadow starts to fade. At [member directional_shadow_max_distance] the shadow will disappear.
</member>
@@ -55,11 +52,5 @@
<constant name="SHADOW_PARALLEL_4_SPLITS" value="2" enum="ShadowMode">
Splits the view frustum in 4 areas, each with its own shadow map. This is the slowest directional shadow mode.
</constant>
- <constant name="SHADOW_DEPTH_RANGE_STABLE" value="0" enum="ShadowDepthRange">
- Keeps the shadow stable when the camera moves, at the cost of lower effective shadow resolution.
- </constant>
- <constant name="SHADOW_DEPTH_RANGE_OPTIMIZED" value="1" enum="ShadowDepthRange">
- Tries to achieve maximum shadow resolution. May result in saw effect on shadow edges. This mode typically works best in games where the camera will often move at high speeds, such as most racing games.
- </constant>
</constants>
</class>
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index ef20174ee6..17b51d5cbe 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -44,9 +44,11 @@
</return>
<argument index="0" name="mode" type="int" enum="DisplayServer.WindowMode">
</argument>
- <argument index="1" name="flags" type="int">
+ <argument index="1" name="vsync_mode" type="int" enum="DisplayServer.VSyncMode">
</argument>
- <argument index="2" name="rect" type="Rect2i" default="Rect2i(0, 0, 0, 0)">
+ <argument index="2" name="flags" type="int">
+ </argument>
+ <argument index="3" name="rect" type="Rect2i" default="Rect2i(0, 0, 0, 0)">
</argument>
<description>
</description>
@@ -671,34 +673,6 @@
[b]Note:[/b] This method is implemented on Android, iOS and UWP.
</description>
</method>
- <method name="vsync_is_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="vsync_is_using_via_compositor" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="vsync_set_enabled">
- <return type="void">
- </return>
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="vsync_set_use_via_compositor">
- <return type="void">
- </return>
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
<method name="window_attach_instance_id">
<return type="void">
</return>
@@ -791,6 +765,15 @@
<description>
</description>
</method>
+ <method name="window_get_vsync_mode" qualifiers="const">
+ <return type="int" enum="DisplayServer.VSyncMode">
+ </return>
+ <argument index="0" name="window_id" type="int" default="0">
+ </argument>
+ <description>
+ Returns the VSync mode of the given window.
+ </description>
+ </method>
<method name="window_move_to_foreground">
<return type="void">
</return>
@@ -995,6 +978,19 @@
<description>
</description>
</method>
+ <method name="window_set_vsync_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="vsync_mode" type="int" enum="DisplayServer.VSyncMode">
+ </argument>
+ <argument index="1" name="window_id" type="int" default="0">
+ </argument>
+ <description>
+ Sets the VSync mode of the given window.
+ See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application.
+ Depending on the platform and used renderer, the engine will fall back to [constant VSYNC_ENABLED], if the desired mode is not supported.
+ </description>
+ </method>
<method name="window_set_window_event_callback">
<return type="void">
</return>
@@ -1151,5 +1147,18 @@
</constant>
<constant name="WINDOW_EVENT_DPI_CHANGE" value="6" enum="WindowEvent">
</constant>
+ <constant name="VSYNC_DISABLED" value="0" enum="VSyncMode">
+ No vertical synchronization, which means the engine will display frames as fast as possible (tearing may be visible).
+ </constant>
+ <constant name="VSYNC_ENABLED" value="1" enum="VSyncMode">
+ Default vertical synchronization mode, the image is displayed only on vertical blanking intervals (no tearing is visible).
+ </constant>
+ <constant name="VSYNC_ADAPTIVE" value="2" enum="VSyncMode">
+ Behaves like [constant VSYNC_DISABLED] when the framerate drops below the screen's refresh rate to reduce stuttering (tearing may be visible), otherwise vertical synchronization is enabled to avoid tearing.
+ </constant>
+ <constant name="VSYNC_MAILBOX" value="3" enum="VSyncMode">
+ Displays the most recent image in the queue on vertical blanking intervals, while rendering to the other images (no tearing is visible).
+ Although not guaranteed, the images can be rendered as fast as possible, which may reduce input lag.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index a02d318f70..753227513b 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -547,6 +547,7 @@
<return type="void">
</return>
<description>
+ Minimizes the bottom panel.
</description>
</method>
<method name="make_bottom_panel_item_visible">
@@ -555,6 +556,7 @@
<argument index="0" name="item" type="Control">
</argument>
<description>
+ Makes a specific item in the bottom panel visible.
</description>
</method>
<method name="queue_save_layout">
diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml
index 935335943f..b86e5e5c6e 100644
--- a/doc/classes/EditorSpinSlider.xml
+++ b/doc/classes/EditorSpinSlider.xml
@@ -18,6 +18,9 @@
</member>
<member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false">
</member>
+ <member name="suffix" type="String" setter="set_suffix" getter="get_suffix" default="&quot;&quot;">
+ The suffix to display after the value (in a faded color). This should generally be a plural word. You may have to use an abbreviation if the suffix is too long to be displayed.
+ </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index 7feaaa2040..f98c31dc7f 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -486,6 +486,7 @@
</argument>
<description>
Stores any Variant value in the file. If [code]full_objects[/code] is [code]true[/code], encoding objects is allowed (and can potentially include code).
+ [b]Note:[/b] Not all properties are included. Only properties that are configured with the [constant PROPERTY_USAGE_STORAGE] flag set will be serialized. You can add a new usage flag to a property by overriding the [method Object._get_property_list] method in your class. You can also check how property usage is configured by calling [method Object._get_property_list]. See [enum PropertyUsageFlags] for the possible usage flags.
</description>
</method>
</methods>
diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml
index a549994a69..a08bed751f 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -158,7 +158,8 @@
<argument index="3" name="body" type="String" default="&quot;&quot;">
</argument>
<description>
- Sends a request to the connected host. The URL parameter is just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]index.php[/code].
+ Sends a request to the connected host.
+ The URL parameter is usually just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]/index.php[/code]. When sending requests to an HTTP proxy server, it should be an absolute URL. For [constant HTTPClient.METHOD_OPTIONS] requests, [code]*[/code] is also allowed. For [constant HTTPClient.METHOD_CONNECT] requests, it should be the authority component ([code]host:port[/code]).
Headers are HTTP request headers. For available HTTP methods, see [enum Method].
To create a POST request with query strings to push to the server, do:
[codeblocks]
@@ -166,7 +167,7 @@
var fields = {"username" : "user", "password" : "pass"}
var query_string = http_client.query_string_from_dict(fields)
var headers = ["Content-Type: application/x-www-form-urlencoded", "Content-Length: " + str(query_string.length())]
- var result = http_client.request(http_client.METHOD_POST, "index.php", headers, query_string)
+ var result = http_client.request(http_client.METHOD_POST, "/index.php", headers, query_string)
[/gdscript]
[csharp]
var fields = new Godot.Collections.Dictionary { { "username", "user" }, { "password", "pass" } };
@@ -190,7 +191,8 @@
<argument index="3" name="body" type="PackedByteArray">
</argument>
<description>
- Sends a raw request to the connected host. The URL parameter is just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]index.php[/code].
+ Sends a raw request to the connected host.
+ The URL parameter is usually just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]/index.php[/code]. When sending requests to an HTTP proxy server, it should be an absolute URL. For [constant HTTPClient.METHOD_OPTIONS] requests, [code]*[/code] is also allowed. For [constant HTTPClient.METHOD_CONNECT] requests, it should be the authority component ([code]host:port[/code]).
Headers are HTTP request headers. For available HTTP methods, see [enum Method].
Sends the body data raw, as a byte array and does not encode it in any way.
</description>
diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml
index 5fef56e354..f89b6ad57b 100644
--- a/doc/classes/ImageTexture.xml
+++ b/doc/classes/ImageTexture.xml
@@ -61,10 +61,8 @@
</return>
<argument index="0" name="image" type="Image">
</argument>
- <argument index="1" name="immediate" type="bool" default="false">
- </argument>
<description>
- Replaces the texture's data with a new [Image]. If [code]immediate[/code] is [code]true[/code], it will take effect immediately after the call.
+ Replaces the texture's data with a new [Image].
[b]Note:[/b] The texture has to be initialized first with the [method create_from_image] method before it can be updated. The new image dimensions, format, and mipmaps configuration should match the existing texture's image configuration, otherwise it has to be re-created with the [method create_from_image] method.
Use this method over [method create_from_image] if you need to update the texture frequently, which is faster than allocating additional memory for a new texture each time.
</description>
diff --git a/doc/classes/ImmediateGeometry3D.xml b/doc/classes/ImmediateGeometry3D.xml
deleted file mode 100644
index d2d663847f..0000000000
--- a/doc/classes/ImmediateGeometry3D.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ImmediateGeometry3D" inherits="GeometryInstance3D" version="4.0">
- <brief_description>
- Draws simple geometry from code.
- </brief_description>
- <description>
- Draws simple geometry from code. Uses a drawing mode similar to OpenGL 1.x.
- See also [ArrayMesh], [MeshDataTool] and [SurfaceTool] for procedural geometry generation.
- [b]Note:[/b] ImmediateGeometry3D is best suited to small amounts of mesh data that change every frame. It will be slow when handling large amounts of mesh data. If mesh data doesn't change often, use [ArrayMesh], [MeshDataTool] or [SurfaceTool] instead.
- [b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes.
- </description>
- <tutorials>
- </tutorials>
- <methods>
- <method name="add_sphere">
- <return type="void">
- </return>
- <argument index="0" name="lats" type="int">
- </argument>
- <argument index="1" name="lons" type="int">
- </argument>
- <argument index="2" name="radius" type="float">
- </argument>
- <argument index="3" name="add_uv" type="bool" default="true">
- </argument>
- <description>
- Simple helper to draw an UV sphere with given latitude, longitude and radius.
- </description>
- </method>
- <method name="add_vertex">
- <return type="void">
- </return>
- <argument index="0" name="position" type="Vector3">
- </argument>
- <description>
- Adds a vertex in local coordinate space with the currently set color/uv/etc.
- </description>
- </method>
- <method name="begin">
- <return type="void">
- </return>
- <argument index="0" name="primitive" type="int" enum="Mesh.PrimitiveType">
- </argument>
- <argument index="1" name="texture" type="Texture2D" default="null">
- </argument>
- <description>
- Begin drawing (and optionally pass a texture override). When done call [method end]. For more information on how this works, search for [code]glBegin()[/code] and [code]glEnd()[/code] references.
- For the type of primitive, see the [enum Mesh.PrimitiveType] enum.
- </description>
- </method>
- <method name="clear">
- <return type="void">
- </return>
- <description>
- Clears everything that was drawn using begin/end.
- </description>
- </method>
- <method name="end">
- <return type="void">
- </return>
- <description>
- Ends a drawing context and displays the results.
- </description>
- </method>
- <method name="set_color">
- <return type="void">
- </return>
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- The current drawing color.
- </description>
- </method>
- <method name="set_normal">
- <return type="void">
- </return>
- <argument index="0" name="normal" type="Vector3">
- </argument>
- <description>
- The next vertex's normal.
- </description>
- </method>
- <method name="set_tangent">
- <return type="void">
- </return>
- <argument index="0" name="tangent" type="Plane">
- </argument>
- <description>
- The next vertex's tangent (and binormal facing).
- </description>
- </method>
- <method name="set_uv">
- <return type="void">
- </return>
- <argument index="0" name="uv" type="Vector2">
- </argument>
- <description>
- The next vertex's UV.
- </description>
- </method>
- <method name="set_uv2">
- <return type="void">
- </return>
- <argument index="0" name="uv" type="Vector2">
- </argument>
- <description>
- The next vertex's second layer UV.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/ImmediateMesh.xml b/doc/classes/ImmediateMesh.xml
new file mode 100644
index 0000000000..d2ae091cad
--- /dev/null
+++ b/doc/classes/ImmediateMesh.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="ImmediateMesh" inherits="Mesh" version="4.0">
+ <brief_description>
+ Mesh optimized for creating geometry manually.
+ </brief_description>
+ <description>
+ Mesh optimized for creating geometry manually, similar to OpenGL1.x immediate mode.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="clear_surfaces">
+ <return type="void">
+ </return>
+ <description>
+ Clear all surfaces.
+ </description>
+ </method>
+ <method name="surface_add_vertex">
+ <return type="void">
+ </return>
+ <argument index="0" name="vertex" type="Vector3">
+ </argument>
+ <description>
+ Add a 3D vertex using the current attributes previously set.
+ </description>
+ </method>
+ <method name="surface_add_vertex_2d">
+ <return type="void">
+ </return>
+ <argument index="0" name="vertex" type="Vector2">
+ </argument>
+ <description>
+ Add a 2D vertex using the current attributes previously set.
+ </description>
+ </method>
+ <method name="surface_begin">
+ <return type="void">
+ </return>
+ <argument index="0" name="primitive" type="int" enum="Mesh.PrimitiveType">
+ </argument>
+ <argument index="1" name="material" type="Material" default="null">
+ </argument>
+ <description>
+ Begin a new surface.
+ </description>
+ </method>
+ <method name="surface_end">
+ <return type="void">
+ </return>
+ <description>
+ End and commit current surface. Note that surface being created will not be visible until this function is called.
+ </description>
+ </method>
+ <method name="surface_set_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="color" type="Color">
+ </argument>
+ <description>
+ Set the color attribute that will be pushed with the next vertex.
+ </description>
+ </method>
+ <method name="surface_set_normal">
+ <return type="void">
+ </return>
+ <argument index="0" name="normal" type="Vector3">
+ </argument>
+ <description>
+ Set the normal attribute that will be pushed with the next vertex.
+ </description>
+ </method>
+ <method name="surface_set_tangent">
+ <return type="void">
+ </return>
+ <argument index="0" name="tangent" type="Plane">
+ </argument>
+ <description>
+ Set the tangent attribute that will be pushed with the next vertex.
+ </description>
+ </method>
+ <method name="surface_set_uv">
+ <return type="void">
+ </return>
+ <argument index="0" name="uv" type="Vector2">
+ </argument>
+ <description>
+ Set the UV attribute that will be pushed with the next vertex.
+ </description>
+ </method>
+ <method name="surface_set_uv2">
+ <return type="void">
+ </return>
+ <argument index="0" name="uv2" type="Vector2">
+ </argument>
+ <description>
+ Set the UV2 attribute that will be pushed with the next vertex.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/InputMap.xml b/doc/classes/InputMap.xml
index 0fb18d8e81..3948ab0208 100644
--- a/doc/classes/InputMap.xml
+++ b/doc/classes/InputMap.xml
@@ -41,6 +41,15 @@
Removes all events from an action.
</description>
</method>
+ <method name="action_get_deadzone">
+ <return type="float">
+ </return>
+ <argument index="0" name="action" type="StringName">
+ </argument>
+ <description>
+ Returns a deadzone value for the action.
+ </description>
+ </method>
<method name="action_get_events">
<return type="Array">
</return>
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index ee59f0c85a..ca22567ad5 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -75,11 +75,11 @@
<member name="align" type="int" setter="set_align" getter="get_align" enum="Label.Align" default="0">
Controls the text's horizontal align. Supports left, center, right, and fill, or justify. Set it to one of the [enum Align] constants.
</member>
- <member name="autowrap" type="bool" setter="set_autowrap" getter="has_autowrap" default="false">
- If [code]true[/code], wraps the text inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text.
+ <member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="Label.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="clip_text" type="bool" setter="set_clip_text" getter="is_clipping_text" default="false">
- If [code]true[/code], the Label only shows the text that fits inside its bounding rectangle. It also lets you scale the node down freely.
+ If [code]true[/code], the Label only shows the text that fits inside its bounding rectangle and will clip text horizontally.
</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.
@@ -107,6 +107,9 @@
<member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" enum="Control.TextDirection" default="0">
Base text writing direction.
</member>
+ <member name="text_overrun_behavior" type="int" setter="set_text_overrun_behavior" getter="get_text_overrun_behavior" enum="Label.OverrunBehavior" default="0">
+ Sets the clipping behavior when the text exceeds the node's bounding rectangle. See [enum OverrunBehavior] for a description of all modes.
+ </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>
@@ -142,6 +145,33 @@
<constant name="VALIGN_FILL" value="3" enum="VAlign">
Align the whole text by spreading the rows.
</constant>
+ <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="OVERRUN_NO_TRIMMING" value="0" enum="OverrunBehavior">
+ No text trimming is performed.
+ </constant>
+ <constant name="OVERRUN_TRIM_CHAR" value="1" enum="OverrunBehavior">
+ Trims the text per character.
+ </constant>
+ <constant name="OVERRUN_TRIM_WORD" value="2" enum="OverrunBehavior">
+ Trims the text per word.
+ </constant>
+ <constant name="OVERRUN_TRIM_ELLIPSIS" value="3" enum="OverrunBehavior">
+ Trims the text per character and adds an ellipsis to indicate that parts are hidden.
+ </constant>
+ <constant name="OVERRUN_TRIM_WORD_ELLIPSIS" value="4" enum="OverrunBehavior">
+ Trims the text per word and adds an ellipsis to indicate that parts are hidden.
+ </constant>
</constants>
<theme_items>
<theme_item name="font" type="Font">
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index f1e7c5f6e1..af6fc738c7 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -102,6 +102,13 @@
Inserts [code]text[/code] at the caret. If the resulting value is longer than [member max_length], nothing happens.
</description>
</method>
+ <method name="is_menu_visible" qualifiers="const">
+ <return type="bool">
+ </return>
+ <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="menu_option">
<return type="void">
</return>
@@ -169,6 +176,7 @@
The caret's column position inside the [LineEdit]. When set, the text may scroll to accommodate it.
</member>
<member name="caret_force_displayed" type="bool" setter="set_caret_force_displayed" getter="is_caret_force_displayed" default="false">
+ If [code]true[/code], the [LineEdit] will always show the caret, even if focus is lost.
</member>
<member name="caret_mid_grapheme" type="bool" setter="set_caret_mid_grapheme_enabled" getter="is_caret_mid_grapheme_enabled" default="false">
Allow moving caret, selecting and removing the individual composite character components.
@@ -195,6 +203,28 @@
</member>
<member name="max_length" type="int" setter="set_max_length" getter="get_max_length" default="0">
Maximum amount of characters that can be entered inside the [LineEdit]. If [code]0[/code], there is no limit.
+ When a limit is defined, characters that would exceed [member max_length] are truncated. This happens both for existing [member text] contents when setting the max length, or for new text inserted in the [LineEdit], including pasting. If any input text is truncated, the [signal text_change_rejected] signal is emitted with the truncated substring as parameter.
+ [b]Example:[/b]
+ [codeblocks]
+ [gdscript]
+ text = "Hello world"
+ max_length = 5
+ # `text` becomes "Hello".
+ max_length = 10
+ text += " goodbye"
+ # `text` becomes "Hello good".
+ # `text_change_rejected` is emitted with "bye" as parameter.
+ [/gdscript]
+ [csharp]
+ Text = "Hello world";
+ MaxLength = 5;
+ // `Text` becomes "Hello".
+ MaxLength = 10;
+ Text += " goodbye";
+ // `Text` becomes "Hello good".
+ // `text_change_rejected` is emitted with "bye" as parameter.
+ [/csharp]
+ [/codeblocks]
</member>
<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" override="true" enum="Control.CursorShape" default="1" />
<member name="placeholder_alpha" type="float" setter="set_placeholder_alpha" getter="get_placeholder_alpha" default="0.6">
@@ -237,8 +267,10 @@
</members>
<signals>
<signal name="text_change_rejected">
+ <argument index="0" name="rejected_substring" type="String">
+ </argument>
<description>
- Emitted when trying to append text that would overflow the [member max_length].
+ Emitted when appending text that overflows the [member max_length]. The appended text is truncated to fit [member max_length], and the part that couldn't fit is passed as the [code]rejected_substring[/code] argument.
</description>
</signal>
<signal name="text_changed">
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index 3bbdfbe62e..2cc0bd2ef9 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -16,8 +16,14 @@
<method name="create_convex_shape" qualifiers="const">
<return type="Shape3D">
</return>
+ <argument index="0" name="clean" type="bool" default="true">
+ </argument>
+ <argument index="1" name="simplify" type="bool" default="false">
+ </argument>
<description>
Calculate a [ConvexPolygonShape3D] from the mesh.
+ If [code]clean[/code] is [code]true[/code] (default), duplicate and interior vertices are removed automatically. You can set it to [code]false[/code] to make the process faster if not needed.
+ If [code]simplify[/code] is [code]true[/code], the geometry can be further simplified to reduce the amount of vertices. Disabled by default.
</description>
</method>
<method name="create_outline" qualifiers="const">
diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml
index da02511dc0..c0ee1e1956 100644
--- a/doc/classes/MeshDataTool.xml
+++ b/doc/classes/MeshDataTool.xml
@@ -45,7 +45,7 @@
AddChild(mi);
[/csharp]
[/codeblocks]
- See also [ArrayMesh], [ImmediateGeometry3D] and [SurfaceTool] for procedural geometry generation.
+ See also [ArrayMesh], [ImmediateMesh] and [SurfaceTool] for procedural geometry generation.
[b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes.
</description>
<tutorials>
diff --git a/doc/classes/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml
index 7c4e75793e..930301a742 100644
--- a/doc/classes/MeshInstance3D.xml
+++ b/doc/classes/MeshInstance3D.xml
@@ -16,8 +16,14 @@
<method name="create_convex_collision">
<return type="void">
</return>
+ <argument index="0" name="clean" type="bool" default="true">
+ </argument>
+ <argument index="1" name="simplify" type="bool" default="false">
+ </argument>
<description>
This helper creates a [StaticBody3D] child node with a [ConvexPolygonShape3D] collision shape calculated from the mesh geometry. It's mainly used for testing.
+ If [code]clean[/code] is [code]true[/code] (default), duplicate and interior vertices are removed automatically. You can set it to [code]false[/code] to make the process faster if not needed.
+ If [code]simplify[/code] is [code]true[/code], the geometry can be further simplified to reduce the amount of vertices. Disabled by default.
</description>
</method>
<method name="create_debug_tangents">
diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml
index 5de5703d95..82b929c1f7 100644
--- a/doc/classes/MultiplayerAPI.xml
+++ b/doc/classes/MultiplayerAPI.xml
@@ -4,7 +4,7 @@
High-level multiplayer API.
</brief_description>
<description>
- This class implements most of the logic behind the high-level multiplayer API. See also [NetworkedMultiplayerPeer].
+ This class implements most of the logic behind the high-level multiplayer API. See also [MultiplayerPeer].
By default, [SceneTree] has a reference to this class that is used to provide multiplayer capabilities (i.e. RPC/RSET) across the whole scene.
It is possible to override the MultiplayerAPI instance used by specific Nodes by setting the [member Node.custom_multiplayer] property, effectively allowing to run both client and server in the same scene.
[b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice.
@@ -70,10 +70,10 @@
</argument>
<argument index="1" name="id" type="int" default="0">
</argument>
- <argument index="2" name="mode" type="int" enum="NetworkedMultiplayerPeer.TransferMode" default="2">
+ <argument index="2" name="mode" type="int" enum="MultiplayerPeer.TransferMode" default="2">
</argument>
<description>
- Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
+ Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
</description>
</method>
</methods>
@@ -82,7 +82,7 @@
If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs/RSETs.
[b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threats such as remote code execution.
</member>
- <member name="network_peer" type="NetworkedMultiplayerPeer" setter="set_network_peer" getter="get_network_peer">
+ <member name="network_peer" type="MultiplayerPeer" setter="set_network_peer" getter="get_network_peer">
The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the MultiplayerAPI will become a network server (check with [method is_network_server]) and will set root node's network mode to master, or it will become a regular peer with root node set to puppet. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to MultiplayerAPI's signals.
</member>
<member name="refuse_new_network_connections" type="bool" setter="set_refuse_new_network_connections" getter="is_refusing_new_network_connections" default="false">
@@ -146,14 +146,5 @@
<constant name="RPC_MODE_PUPPET" value="3" enum="RPCMode">
Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on puppets for this node. Analogous to the [code]puppet[/code] keyword. Only accepts calls or property changes from the node's network master, see [method Node.set_network_master].
</constant>
- <constant name="RPC_MODE_REMOTESYNC" value="4" enum="RPCMode">
- Behave like [constant RPC_MODE_REMOTE] but also make the call or property change locally. Analogous to the [code]remotesync[/code] keyword.
- </constant>
- <constant name="RPC_MODE_MASTERSYNC" value="5" enum="RPCMode">
- Behave like [constant RPC_MODE_MASTER] but also make the call or property change locally. Analogous to the [code]mastersync[/code] keyword.
- </constant>
- <constant name="RPC_MODE_PUPPETSYNC" value="6" enum="RPCMode">
- Behave like [constant RPC_MODE_PUPPET] but also make the call or property change locally. Analogous to the [code]puppetsync[/code] keyword.
- </constant>
</constants>
</class>
diff --git a/doc/classes/NetworkedMultiplayerPeer.xml b/doc/classes/MultiplayerPeer.xml
index 06ea46f023..713cd64b82 100644
--- a/doc/classes/NetworkedMultiplayerPeer.xml
+++ b/doc/classes/MultiplayerPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NetworkedMultiplayerPeer" inherits="PacketPeer" version="4.0">
+<class name="MultiplayerPeer" inherits="PacketPeer" version="4.0">
<brief_description>
A high-level network interface to simplify multiplayer interactions.
</brief_description>
@@ -13,7 +13,7 @@
</tutorials>
<methods>
<method name="get_connection_status" qualifiers="const">
- <return type="int" enum="NetworkedMultiplayerPeer.ConnectionStatus">
+ <return type="int" enum="MultiplayerPeer.ConnectionStatus">
</return>
<description>
Returns the current state of the connection. See [enum ConnectionStatus].
@@ -23,14 +23,14 @@
<return type="int">
</return>
<description>
- Returns the ID of the [NetworkedMultiplayerPeer] who sent the most recent packet.
+ Returns the ID of the [MultiplayerPeer] who sent the most recent packet.
</description>
</method>
<method name="get_unique_id" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the ID of this [NetworkedMultiplayerPeer].
+ Returns the ID of this [MultiplayerPeer].
</description>
</method>
<method name="poll">
@@ -53,9 +53,9 @@
</methods>
<members>
<member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="true">
- If [code]true[/code], this [NetworkedMultiplayerPeer] refuses new connections.
+ If [code]true[/code], this [MultiplayerPeer] refuses new connections.
</member>
- <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="NetworkedMultiplayerPeer.TransferMode" default="0">
+ <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="MultiplayerPeer.TransferMode" default="0">
The manner in which to send packets to the [code]target_peer[/code]. See [enum TransferMode].
</member>
</members>
diff --git a/doc/classes/NativeExtension.xml b/doc/classes/NativeExtension.xml
new file mode 100644
index 0000000000..c48af7df7b
--- /dev/null
+++ b/doc/classes/NativeExtension.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="NativeExtension" inherits="RefCounted" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="close_library">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_minimum_library_initialization_level" qualifiers="const">
+ <return type="int" enum="NativeExtension.InitializationLevel">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="initialize_library">
+ <return type="void">
+ </return>
+ <argument index="0" name="level" type="int" enum="NativeExtension.InitializationLevel">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="is_library_open" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="open_library">
+ <return type="int" enum="Error">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <argument index="1" name="entry_symbol" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ <constant name="INITIALIZATION_LEVEL_CORE" value="0" enum="InitializationLevel">
+ </constant>
+ <constant name="INITIALIZATION_LEVEL_SERVERS" value="1" enum="InitializationLevel">
+ </constant>
+ <constant name="INITIALIZATION_LEVEL_SCENE" value="2" enum="InitializationLevel">
+ </constant>
+ <constant name="INITIALIZATION_LEVEL_EDITOR" value="3" enum="InitializationLevel">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/NativeExtensionManager.xml b/doc/classes/NativeExtensionManager.xml
new file mode 100644
index 0000000000..ba9018ff4c
--- /dev/null
+++ b/doc/classes/NativeExtensionManager.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="NativeExtensionManager" inherits="Object" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_extension">
+ <return type="NativeExtension">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_loaded_extensions" qualifiers="const">
+ <return type="PackedStringArray">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="load_extension">
+ <return type="int" enum="NativeExtensionManager.LoadStatus">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="reload_extension">
+ <return type="int" enum="NativeExtensionManager.LoadStatus">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="unload_extension">
+ <return type="int" enum="NativeExtensionManager.LoadStatus">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ <constant name="LOAD_STATUS_OK" value="0" enum="LoadStatus">
+ </constant>
+ <constant name="LOAD_STATUS_FAILED" value="1" enum="LoadStatus">
+ </constant>
+ <constant name="LOAD_STATUS_ALREADY_LOADED" value="2" enum="LoadStatus">
+ </constant>
+ <constant name="LOAD_STATUS_NOT_LOADED" value="3" enum="LoadStatus">
+ </constant>
+ <constant name="LOAD_STATUS_NEEDS_RESTART" value="4" enum="LoadStatus">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 21f3f1fcc0..fc971effd7 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -14,7 +14,7 @@
To keep track of the scene hierarchy (especially when instancing scenes into other scenes), an "owner" can be set for the node with the [member owner] property. This keeps track of who instantiated what. This is mostly useful when writing editors and tools, though.
Finally, when a node is freed with [method Object.free] or [method queue_free], it will also free all its children.
[b]Groups:[/b] Nodes can be added to as many groups as you want to be easy to manage, you could create groups like "enemies" or "collectables" for example, depending on your game. See [method add_to_group], [method is_in_group] and [method remove_from_group]. You can then retrieve all nodes in these groups, iterate them and even call methods on groups via the methods on [SceneTree].
- [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]), it is possible to use the built-in RPC (remote procedure call) system to communicate over the network. By calling [method rpc] with a method name, it will be called locally and in all connected peers (peers = clients and the server that accepts connections). To identify which node receives the RPC call, Godot will use its [NodePath] (make sure node names are the same on all peers). Also, take a look at the high-level networking tutorial and corresponding demos.
+ [b]Networking with nodes:[/b] After connecting to a server (or making one, see [ENetMultiplayerPeer]), it is possible to use the built-in RPC (remote procedure call) system to communicate over the network. By calling [method rpc] with a method name, it will be called locally and in all connected peers (peers = clients and the server that accepts connections). To identify which node receives the RPC call, Godot will use its [NodePath] (make sure node names are the same on all peers). Also, take a look at the high-level networking tutorial and corresponding demos.
</description>
<tutorials>
<link title="Scenes and nodes">https://docs.godotengine.org/en/latest/getting_started/step_by_step/scenes_and_nodes.html</link>
@@ -426,7 +426,7 @@
Returns [code]true[/code] if the [NodePath] points to a valid node and its subname points to a valid resource, e.g. [code]Area2D/CollisionShape2D:shape[/code]. Properties with a non-[Resource] type (e.g. nodes or primitive math types) are not considered resources.
</description>
</method>
- <method name="is_a_parent_of" qualifiers="const">
+ <method name="is_ancestor_of" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="node" type="Node">
@@ -660,7 +660,7 @@
</argument>
<description>
Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. Returns an empty [Variant].
- [b]Note:[/b] You can only safely use RPCs on clients after you received the [code]connected_to_server[/code] signal from the [SceneTree]. You also need to keep track of the connection state, either by the [SceneTree] signals like [code]server_disconnected[/code] or by checking [code]SceneTree.network_peer.get_connection_status() == CONNECTION_CONNECTED[/code].
+ [b]Note:[/b] You can only safely use RPCs on clients after you received the [code]connected_to_server[/code] signal from the [MultiplayerAPI]. You also need to keep track of the connection state, either by the [MultiplayerAPI] signals like [code]server_disconnected[/code] or by checking [code]get_multiplayer().network_peer.get_connection_status() == CONNECTION_CONNECTED[/code].
</description>
</method>
<method name="rpc_config">
@@ -670,12 +670,12 @@
</argument>
<argument index="1" name="rpc_mode" type="int" enum="MultiplayerAPI.RPCMode">
</argument>
- <argument index="2" name="transfer_mode" type="int" enum="NetworkedMultiplayerPeer.TransferMode" default="2">
+ <argument index="2" name="transfer_mode" type="int" enum="MultiplayerPeer.TransferMode" default="2">
</argument>
<argument index="3" name="channel" type="int" default="0">
</argument>
<description>
- Changes the RPC mode for the given [code]method[/code] to the given [code]rpc_mode[/code], optionally specifying the [code]transfer_mode[/code] and [code]channel[/code] (on supported peers). See [enum MultiplayerAPI.RPCMode] and [enum NetworkedMultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, methods are not exposed to networking (and RPCs).
+ Changes the RPC mode for the given [code]method[/code] to the given [code]rpc_mode[/code], optionally specifying the [code]transfer_mode[/code] and [code]channel[/code] (on supported peers). See [enum MultiplayerAPI.RPCMode] and [enum MultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, methods are not exposed to networking (and RPCs).
</description>
</method>
<method name="rpc_id" qualifiers="vararg">
@@ -686,7 +686,7 @@
<argument index="1" name="method" type="StringName">
</argument>
<description>
- Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
+ Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method MultiplayerPeer.set_target_peer]). Returns an empty [Variant].
</description>
</method>
<method name="set_display_folded">
@@ -904,6 +904,12 @@
<constant name="NOTIFICATION_POST_ENTER_TREE" value="27">
Notification received when the node is ready, just before [constant NOTIFICATION_READY] is received. Unlike the latter, it's sent every time the node enters tree, instead of only once.
</constant>
+ <constant name="NOTIFICATION_DISABLED" value="28">
+ Notification received when the node is disabled. See [constant PROCESS_MODE_DISABLED].
+ </constant>
+ <constant name="NOTIFICATION_ENABLED" value="29">
+ Notification received when the node is enabled again after being disabled. See [constant PROCESS_MODE_DISABLED].
+ </constant>
<constant name="NOTIFICATION_EDITOR_PRE_SAVE" value="9001">
Notification received right before the scene with the node is saved in the editor. This notification is only sent in the Godot editor and will not occur in exported projects.
</constant>
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index cc99abf9cb..9ffa333f17 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -122,9 +122,6 @@
<member name="global_rotation" type="float" setter="set_global_rotation" getter="get_global_rotation">
Global rotation in radians.
</member>
- <member name="global_rotation_degrees" type="float" setter="set_global_rotation_degrees" getter="get_global_rotation_degrees">
- Global rotation in degrees.
- </member>
<member name="global_scale" type="Vector2" setter="set_global_scale" getter="get_global_scale">
Global scale.
</member>
@@ -137,16 +134,11 @@
<member name="rotation" type="float" setter="set_rotation" getter="get_rotation" default="0.0">
Rotation in radians, relative to the node's parent.
</member>
- <member name="rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees" default="0.0">
- Rotation in degrees, relative to the node's parent.
- </member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale. Unscaled value: [code](1, 1)[/code].
</member>
<member name="skew" type="float" setter="set_skew" getter="get_skew" default="0.0">
</member>
- <member name="skew_degrees" type="float" setter="set_skew_degrees" getter="get_skew_degrees" default="0.0">
- </member>
<member name="transform" type="Transform2D" setter="set_transform" getter="get_transform">
Local [Transform2D].
</member>
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 2dc8659d5d..14e03a2186 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -294,13 +294,10 @@
<member name="position" type="Vector3" setter="set_position" getter="get_position" default="Vector3(0, 0, 0)">
Local position or translation of this node relative to the parent. This is equivalent to [code]transform.origin[/code].
</member>
- <member name="rotation" type="Vector3" setter="set_rotation" getter="get_rotation">
+ <member name="rotation" type="Vector3" setter="set_rotation" getter="get_rotation" default="Vector3(0, 0, 0)">
Rotation part of the local transformation in radians, specified in terms of YXZ-Euler angles in the format (X angle, Y angle, Z angle).
[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three independent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating-point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful.
</member>
- <member name="rotation_degrees" type="Vector3" setter="set_rotation_degrees" getter="get_rotation_degrees" default="Vector3(0, 0, 0)">
- Rotation part of the local transformation in degrees, specified in terms of YXZ-Euler angles in the format (X angle, Y angle, Z angle).
- </member>
<member name="scale" type="Vector3" setter="set_scale" getter="get_scale" default="Vector3(1, 1, 1)">
Scale part of the local transformation.
</member>
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 817ccd5160..0ba2e73ad4 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -20,6 +20,7 @@
@"/root/Main" # If your main scene's root node were named "Main".
@"/root/MyAutoload" # If you have an autoloaded node or scene.
[/codeblock]
+ [b]Note:[/b] In the editor, [NodePath] properties are automatically updated when moving, renaming or deleting a node in the scene tree, but they are never updated at runtime.
</description>
<tutorials>
<link title="2D Role Playing Game Demo">https://godotengine.org/asset-library/asset/520</link>
diff --git a/doc/classes/PacketPeerUDP.xml b/doc/classes/PacketPeerUDP.xml
index 5d059ad3df..2707df612c 100644
--- a/doc/classes/PacketPeerUDP.xml
+++ b/doc/classes/PacketPeerUDP.xml
@@ -148,7 +148,7 @@
var socket = new PacketPeerUDP();
// Server
socket.SetDestAddress("127.0.0.1", 789);
- socket.PutPacket("Time To Stop".ToAscii());
+ socket.PutPacket("Time to stop".ToAscii());
// Client
while (socket.Wait() == OK)
diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml
index e8fde21032..52430b3f45 100644
--- a/doc/classes/ParticlesMaterial.xml
+++ b/doc/classes/ParticlesMaterial.xml
@@ -145,7 +145,7 @@
Each particle's initial color. If the [GPUParticles2D]'s [code]texture[/code] is defined, it will be multiplied by this color. To have particle display color in a [BaseMaterial3D] make sure to set [member BaseMaterial3D.vertex_color_use_as_albedo] to [code]true[/code].
</member>
<member name="color_ramp" type="Texture2D" setter="set_color_ramp" getter="get_color_ramp">
- Each particle's color will vary along this [GradientTexture].
+ Each particle's color will vary along this [GradientTexture] over its lifetime (multiplied with [member color]).
</member>
<member name="damping" type="float" setter="set_param" getter="get_param" default="0.0">
The rate at which particles lose velocity.
diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml
index b6013fa83e..a141961df5 100644
--- a/doc/classes/Performance.xml
+++ b/doc/classes/Performance.xml
@@ -168,58 +168,42 @@
<constant name="OBJECT_ORPHAN_NODE_COUNT" value="9" enum="Monitor">
Number of orphan nodes, i.e. nodes which are not parented to a node of the scene tree.
</constant>
- <constant name="RENDER_OBJECTS_IN_FRAME" value="10" enum="Monitor">
- 3D objects drawn per frame.
+ <constant name="RENDER_TOTAL_OBJECTS_IN_FRAME" value="10" enum="Monitor">
</constant>
- <constant name="RENDER_VERTICES_IN_FRAME" value="11" enum="Monitor">
- Vertices drawn per frame. 3D only.
+ <constant name="RENDER_TOTAL_PRIMITIVES_IN_FRAME" value="11" enum="Monitor">
</constant>
- <constant name="RENDER_MATERIAL_CHANGES_IN_FRAME" value="12" enum="Monitor">
- Material changes per frame. 3D only.
+ <constant name="RENDER_TOTAL_DRAW_CALLS_IN_FRAME" value="12" enum="Monitor">
</constant>
- <constant name="RENDER_SHADER_CHANGES_IN_FRAME" value="13" enum="Monitor">
- Shader changes per frame. 3D only.
- </constant>
- <constant name="RENDER_SURFACE_CHANGES_IN_FRAME" value="14" enum="Monitor">
- Render surface changes per frame. 3D only.
- </constant>
- <constant name="RENDER_DRAW_CALLS_IN_FRAME" value="15" enum="Monitor">
- Draw calls per frame. 3D only.
- </constant>
- <constant name="RENDER_VIDEO_MEM_USED" value="16" enum="Monitor">
+ <constant name="RENDER_VIDEO_MEM_USED" value="13" enum="Monitor">
The amount of video memory used, i.e. texture and vertex memory combined.
</constant>
- <constant name="RENDER_TEXTURE_MEM_USED" value="17" enum="Monitor">
+ <constant name="RENDER_TEXTURE_MEM_USED" value="14" enum="Monitor">
The amount of texture memory used.
</constant>
- <constant name="RENDER_VERTEX_MEM_USED" value="18" enum="Monitor">
- The amount of vertex memory used.
- </constant>
- <constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="19" enum="Monitor">
- Unimplemented in the GLES2 rendering backend, always returns 0.
+ <constant name="RENDER_BUFFER_MEM_USED" value="15" enum="Monitor">
</constant>
- <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="20" enum="Monitor">
+ <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="16" enum="Monitor">
Number of active [RigidBody2D] nodes in the game.
</constant>
- <constant name="PHYSICS_2D_COLLISION_PAIRS" value="21" enum="Monitor">
+ <constant name="PHYSICS_2D_COLLISION_PAIRS" value="17" enum="Monitor">
Number of collision pairs in the 2D physics engine.
</constant>
- <constant name="PHYSICS_2D_ISLAND_COUNT" value="22" enum="Monitor">
+ <constant name="PHYSICS_2D_ISLAND_COUNT" value="18" enum="Monitor">
Number of islands in the 2D physics engine.
</constant>
- <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="23" enum="Monitor">
+ <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="19" enum="Monitor">
Number of active [RigidBody3D] and [VehicleBody3D] nodes in the game.
</constant>
- <constant name="PHYSICS_3D_COLLISION_PAIRS" value="24" enum="Monitor">
+ <constant name="PHYSICS_3D_COLLISION_PAIRS" value="20" enum="Monitor">
Number of collision pairs in the 3D physics engine.
</constant>
- <constant name="PHYSICS_3D_ISLAND_COUNT" value="25" enum="Monitor">
+ <constant name="PHYSICS_3D_ISLAND_COUNT" value="21" enum="Monitor">
Number of islands in the 3D physics engine.
</constant>
- <constant name="AUDIO_OUTPUT_LATENCY" value="26" enum="Monitor">
+ <constant name="AUDIO_OUTPUT_LATENCY" value="22" enum="Monitor">
Output latency of the [AudioServer].
</constant>
- <constant name="MONITOR_MAX" value="27" enum="Monitor">
+ <constant name="MONITOR_MAX" value="23" enum="Monitor">
Represents the size of the [enum Monitor] enum.
</constant>
</constants>
diff --git a/doc/classes/PhysicalBone3D.xml b/doc/classes/PhysicalBone3D.xml
index 736b44ee1c..2ed862e9ce 100644
--- a/doc/classes/PhysicalBone3D.xml
+++ b/doc/classes/PhysicalBone3D.xml
@@ -66,12 +66,9 @@
<member name="joint_offset" type="Transform3D" setter="set_joint_offset" getter="get_joint_offset" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
Sets the joint's transform.
</member>
- <member name="joint_rotation" type="Vector3" setter="set_joint_rotation" getter="get_joint_rotation">
+ <member name="joint_rotation" type="Vector3" setter="set_joint_rotation" getter="get_joint_rotation" default="Vector3(0, 0, 0)">
Sets the joint's rotation in radians.
</member>
- <member name="joint_rotation_degrees" type="Vector3" setter="set_joint_rotation_degrees" getter="get_joint_rotation_degrees" default="Vector3(0, 0, 0)">
- Sets the joint's rotation in degrees.
- </member>
<member name="joint_type" type="int" setter="set_joint_type" getter="get_joint_type" enum="PhysicalBone3D.JointType" default="0">
Sets the joint type. See [enum JointType] for possible values.
</member>
diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml
index 33cd61eb9c..b492ddaa25 100644
--- a/doc/classes/PhysicsServer2D.xml
+++ b/doc/classes/PhysicsServer2D.xml
@@ -820,6 +820,10 @@
</argument>
<argument index="5" name="result" type="PhysicsTestMotionResult2D" default="null">
</argument>
+ <argument index="6" name="exclude_raycast_shapes" type="bool" default="true">
+ </argument>
+ <argument index="7" name="exclude" type="Array" default="[]">
+ </argument>
<description>
Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [PhysicsTestMotionResult2D] can be passed to return additional information in.
</description>
@@ -1024,7 +1028,7 @@
<argument index="0" name="iterations" type="int">
</argument>
<description>
- Sets the amount of iterations for calculating velocities of colliding bodies. The greater the amount, the more accurate the collisions, but with a performance loss.
+ Sets the amount of iterations for calculating velocities of colliding bodies. The greater the amount of iterations, the more accurate the collisions will be. However, a greater amount of iterations requires more CPU power, which can decrease performance. The default value is [code]8[/code].
</description>
</method>
<method name="shape_get_data" qualifiers="const">
diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml
index aa1f7597ea..9db7ff5c12 100644
--- a/doc/classes/PhysicsServer3D.xml
+++ b/doc/classes/PhysicsServer3D.xml
@@ -772,6 +772,25 @@
Sets a body state (see [enum BodyState] constants).
</description>
</method>
+ <method name="body_test_motion">
+ <return type="bool">
+ </return>
+ <argument index="0" name="body" type="RID">
+ </argument>
+ <argument index="1" name="from" type="Transform3D">
+ </argument>
+ <argument index="2" name="motion" type="Vector3">
+ </argument>
+ <argument index="3" name="infinite_inertia" type="bool">
+ </argument>
+ <argument index="4" name="margin" type="float" default="0.001">
+ </argument>
+ <argument index="5" name="result" type="PhysicsTestMotionResult3D" default="null">
+ </argument>
+ <description>
+ Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [PhysicsTestMotionResult3D] can be passed to return additional information in.
+ </description>
+ </method>
<method name="box_shape_create">
<return type="RID">
</return>
@@ -1168,6 +1187,16 @@
Activates or deactivates the 3D physics engine.
</description>
</method>
+ <method name="set_collision_iterations">
+ <return type="void">
+ </return>
+ <argument index="0" name="iterations" type="int">
+ </argument>
+ <description>
+ Sets the amount of iterations for calculating velocities of colliding bodies. The greater the amount of iterations, the more accurate the collisions will be. However, a greater amount of iterations requires more CPU power, which can decrease performance. The default value is [code]8[/code].
+ [b]Note:[/b] Only has an effect when using the default GodotPhysics engine, not the Bullet physics engine.
+ </description>
+ </method>
<method name="shape_get_data" qualifiers="const">
<return type="Variant">
</return>
diff --git a/doc/classes/PhysicsShapeQueryParameters2D.xml b/doc/classes/PhysicsShapeQueryParameters2D.xml
index 321a713e26..229a40638a 100644
--- a/doc/classes/PhysicsShapeQueryParameters2D.xml
+++ b/doc/classes/PhysicsShapeQueryParameters2D.xml
@@ -4,7 +4,7 @@
Parameters to be sent to a 2D shape physics query.
</brief_description>
<description>
- This class contains the shape and other parameters for 2D intersection/collision queries. See also [PhysicsShapeQueryResult2D].
+ This class contains the shape and other parameters for 2D intersection/collision queries.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PhysicsShapeQueryParameters3D.xml b/doc/classes/PhysicsShapeQueryParameters3D.xml
index 52916a8418..9ca892acb3 100644
--- a/doc/classes/PhysicsShapeQueryParameters3D.xml
+++ b/doc/classes/PhysicsShapeQueryParameters3D.xml
@@ -4,7 +4,7 @@
Parameters to be sent to a 3D shape physics query.
</brief_description>
<description>
- This class contains the shape and other parameters for 3D intersection/collision queries. See also [PhysicsShapeQueryResult3D].
+ This class contains the shape and other parameters for 3D intersection/collision queries.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PhysicsShapeQueryResult2D.xml b/doc/classes/PhysicsShapeQueryResult2D.xml
deleted file mode 100644
index 07b7bc90e2..0000000000
--- a/doc/classes/PhysicsShapeQueryResult2D.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryResult2D" inherits="RefCounted" version="4.0">
- <brief_description>
- Result of a 2D shape query in [PhysicsServer2D].
- </brief_description>
- <description>
- The result of a 2D shape query in [PhysicsServer2D]. See also [PhysicsShapeQueryParameters2D].
- </description>
- <tutorials>
- </tutorials>
- <methods>
- <method name="get_result_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the number of objects that intersected with the shape.
- </description>
- </method>
- <method name="get_result_object" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the [Object] that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- <method name="get_result_object_id" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the instance ID of the [Object] that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- <method name="get_result_object_shape" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the child index of the object's [Shape2D] that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- <method name="get_result_rid" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the [RID] of the object that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/PhysicsShapeQueryResult3D.xml b/doc/classes/PhysicsShapeQueryResult3D.xml
deleted file mode 100644
index d0ca227a68..0000000000
--- a/doc/classes/PhysicsShapeQueryResult3D.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryResult3D" inherits="RefCounted" version="4.0">
- <brief_description>
- Result of a 3D shape query in [PhysicsServer3D].
- </brief_description>
- <description>
- The result of a 3D shape query in [PhysicsServer3D]. See also [PhysicsShapeQueryParameters3D].
- </description>
- <tutorials>
- </tutorials>
- <methods>
- <method name="get_result_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the number of objects that intersected with the shape.
- </description>
- </method>
- <method name="get_result_object" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the [Object] that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- <method name="get_result_object_id" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the instance ID of the [Object] that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- <method name="get_result_object_shape" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the child index of the object's [Shape3D] that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- <method name="get_result_rid" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the [RID] of the object that intersected with the shape at index [code]idx[/code].
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/PhysicsTestMotionResult2D.xml b/doc/classes/PhysicsTestMotionResult2D.xml
index da04ffa86a..bf3497386e 100644
--- a/doc/classes/PhysicsTestMotionResult2D.xml
+++ b/doc/classes/PhysicsTestMotionResult2D.xml
@@ -19,10 +19,16 @@
</member>
<member name="collider_velocity" type="Vector2" setter="" getter="get_collider_velocity" default="Vector2(0, 0)">
</member>
+ <member name="collision_depth" type="float" setter="" getter="get_collision_depth" default="0.0">
+ </member>
<member name="collision_normal" type="Vector2" setter="" getter="get_collision_normal" default="Vector2(0, 0)">
</member>
<member name="collision_point" type="Vector2" setter="" getter="get_collision_point" default="Vector2(0, 0)">
</member>
+ <member name="collision_safe_fraction" type="float" setter="" getter="get_collision_safe_fraction" default="0.0">
+ </member>
+ <member name="collision_unsafe_fraction" type="float" setter="" getter="get_collision_unsafe_fraction" default="0.0">
+ </member>
<member name="motion" type="Vector2" setter="" getter="get_motion" default="Vector2(0, 0)">
</member>
<member name="motion_remainder" type="Vector2" setter="" getter="get_motion_remainder" default="Vector2(0, 0)">
diff --git a/doc/classes/PhysicsTestMotionResult3D.xml b/doc/classes/PhysicsTestMotionResult3D.xml
new file mode 100644
index 0000000000..08c72ba965
--- /dev/null
+++ b/doc/classes/PhysicsTestMotionResult3D.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="PhysicsTestMotionResult3D" inherits="RefCounted" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="collider" type="Object" setter="" getter="get_collider">
+ </member>
+ <member name="collider_id" type="int" setter="" getter="get_collider_id" default="0">
+ </member>
+ <member name="collider_rid" type="RID" setter="" getter="get_collider_rid">
+ </member>
+ <member name="collider_shape" type="int" setter="" getter="get_collider_shape" default="0">
+ </member>
+ <member name="collider_velocity" type="Vector3" setter="" getter="get_collider_velocity" default="Vector3(0, 0, 0)">
+ </member>
+ <member name="collision_depth" type="float" setter="" getter="get_collision_depth" default="0.0">
+ </member>
+ <member name="collision_normal" type="Vector3" setter="" getter="get_collision_normal" default="Vector3(0, 0, 0)">
+ </member>
+ <member name="collision_point" type="Vector3" setter="" getter="get_collision_point" default="Vector3(0, 0, 0)">
+ </member>
+ <member name="collision_safe_fraction" type="float" setter="" getter="get_collision_safe_fraction" default="0.0">
+ </member>
+ <member name="collision_unsafe_fraction" type="float" setter="" getter="get_collision_unsafe_fraction" default="0.0">
+ </member>
+ <member name="motion" type="Vector3" setter="" getter="get_motion" default="Vector3(0, 0, 0)">
+ </member>
+ <member name="motion_remainder" type="Vector3" setter="" getter="get_motion_remainder" default="Vector3(0, 0, 0)">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml
index cca5793fc7..12869061c4 100644
--- a/doc/classes/Plane.xml
+++ b/doc/classes/Plane.xml
@@ -169,23 +169,23 @@
<description>
</description>
</method>
- <method name="operator +" qualifiers="operator">
- <return type="Plane">
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
</return>
+ <argument index="0" name="right" type="Plane">
+ </argument>
<description>
</description>
</method>
- <method name="operator -" qualifiers="operator">
+ <method name="operator unary+" qualifiers="operator">
<return type="Plane">
</return>
<description>
</description>
</method>
- <method name="operator ==" qualifiers="operator">
- <return type="bool">
+ <method name="operator unary-" qualifiers="operator">
+ <return type="Plane">
</return>
- <argument index="0" name="right" type="Plane">
- </argument>
<description>
</description>
</method>
diff --git a/doc/classes/PlaneMesh.xml b/doc/classes/PlaneMesh.xml
index c95ba29ea2..56bf98772b 100644
--- a/doc/classes/PlaneMesh.xml
+++ b/doc/classes/PlaneMesh.xml
@@ -12,6 +12,9 @@
<methods>
</methods>
<members>
+ <member name="center_offset" type="Vector3" setter="set_center_offset" getter="get_center_offset" default="Vector3(0, 0, 0)">
+ Offset of the generated plane. Useful for particles.
+ </member>
<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(2, 2)">
Size of the generated plane.
</member>
diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml
index c33a1424a7..5a53063148 100644
--- a/doc/classes/Polygon2D.xml
+++ b/doc/classes/Polygon2D.xml
@@ -118,12 +118,9 @@
<member name="texture_offset" type="Vector2" setter="set_texture_offset" getter="get_texture_offset" default="Vector2(0, 0)">
Amount to offset the polygon's [code]texture[/code]. If [code](0, 0)[/code] the texture's origin (its top-left corner) will be placed at the polygon's [code]position[/code].
</member>
- <member name="texture_rotation" type="float" setter="set_texture_rotation" getter="get_texture_rotation">
+ <member name="texture_rotation" type="float" setter="set_texture_rotation" getter="get_texture_rotation" default="0.0">
The texture's rotation in radians.
</member>
- <member name="texture_rotation_degrees" type="float" setter="set_texture_rotation_degrees" getter="get_texture_rotation_degrees" default="0.0">
- The texture's rotation in degrees.
- </member>
<member name="texture_scale" type="Vector2" setter="set_texture_scale" getter="get_texture_scale" default="Vector2(1, 1)">
Amount to multiply the [code]uv[/code] coordinates when using a [code]texture[/code]. Larger values make the texture smaller, and vice versa.
</member>
diff --git a/doc/classes/Popup.xml b/doc/classes/Popup.xml
index b8d8a55412..89695989c8 100644
--- a/doc/classes/Popup.xml
+++ b/doc/classes/Popup.xml
@@ -13,6 +13,7 @@
<members>
<member name="borderless" type="bool" setter="set_flag" getter="get_flag" override="true" default="true" />
<member name="close_on_parent_focus" type="bool" setter="set_close_on_parent_focus" getter="get_close_on_parent_focus" default="true">
+ If [code]true[/code], the [Popup] will close when its parent is focused.
</member>
<member name="transient" type="bool" setter="set_transient" getter="is_transient" override="true" default="true" />
<member name="unresizable" type="bool" setter="set_flag" getter="get_flag" override="true" default="true" />
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index e448d18d73..3489c5435a 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -260,6 +260,7 @@
<return type="int">
</return>
<description>
+ Returns the index of the currently focused item. Returns [code]-1[/code] if no item is focused.
</description>
</method>
<method name="get_item_accelerator" qualifiers="const">
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 1847a316e1..c3ef9f2425 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -445,7 +445,7 @@
</member>
<member name="debug/settings/fps/force_fps" type="int" setter="" getter="" default="0">
Maximum number of frames per second allowed. The actual number of frames per second may still be below this value if the game is lagging.
- If [member display/window/vsync/use_vsync] is enabled, it takes precedence and the forced FPS number cannot exceed the monitor's refresh rate.
+ If [member display/window/vsync/vsync_mode] is set to [code]Enabled[/code] or [code]Adaptive[/code], it takes precedence and the forced FPS number cannot exceed the monitor's refresh rate.
This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non-real-time rendering of static frames, or test the project under lag conditions.
</member>
<member name="debug/settings/gdscript/max_call_stack" type="int" setter="" getter="" default="1024">
@@ -532,12 +532,10 @@
<member name="display/window/size/width" type="int" setter="" getter="" default="1024">
Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled.
</member>
- <member name="display/window/vsync/use_vsync" type="bool" setter="" getter="" default="true">
- If [code]true[/code], enables vertical synchronization. This eliminates tearing that may appear in moving scenes, at the cost of higher input latency and stuttering at lower framerates. If [code]false[/code], vertical synchronization will be disabled, however, many platforms will enforce it regardless (such as mobile platforms and HTML5).
- </member>
- <member name="display/window/vsync/vsync_via_compositor" type="bool" setter="" getter="" default="false">
- If [code]Use Vsync[/code] is enabled and this setting is [code]true[/code], enables vertical synchronization via the operating system's window compositor when in windowed mode and the compositor is enabled. This will prevent stutter in certain situations. (Windows only.)
- [b]Note:[/b] This option is experimental and meant to alleviate stutter experienced by some users. However, some users have experienced a Vsync framerate halving (e.g. from 60 FPS to 30 FPS) when using it.
+ <member name="display/window/vsync/vsync_mode" type="int" setter="" getter="" default="1">
+ Sets the VSync mode for the main game window.
+ See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application.
+ Depending on the platform and used renderer, the engine will fall back to [code]Enabled[/code], if the desired mode is not supported.
</member>
<member name="editor/node_naming/name_casing" type="int" setter="" getter="" default="0">
When creating node names automatically, set the type of casing in this project. This is mostly an editor setting.
@@ -1430,8 +1428,6 @@
</member>
<member name="rendering/global_illumination/sdfgi/probe_ray_count" type="int" setter="" getter="" default="1">
</member>
- <member name="rendering/global_illumination/voxel_gi/anisotropic" type="bool" setter="" getter="" default="false">
- </member>
<member name="rendering/global_illumination/voxel_gi/quality" type="int" setter="" getter="" default="1">
</member>
<member name="rendering/lightmapping/bake_performance/max_rays_per_pass" type="int" setter="" getter="" default="32">
@@ -1573,12 +1569,16 @@
<member name="rendering/shadows/shadows/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/shadows/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
</member>
+ <member name="rendering/textures/decals/filter" type="int" setter="" getter="" default="3">
+ </member>
<member name="rendering/textures/default_filters/anisotropic_filtering_level" type="int" setter="" getter="" default="2">
Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled.
</member>
<member name="rendering/textures/default_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false">
If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
</member>
+ <member name="rendering/textures/light_projectors/filter" type="int" setter="" getter="" default="3">
+ </member>
<member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
</member>
diff --git a/doc/classes/QuadMesh.xml b/doc/classes/QuadMesh.xml
index 94d638888c..4209e3db14 100644
--- a/doc/classes/QuadMesh.xml
+++ b/doc/classes/QuadMesh.xml
@@ -13,6 +13,9 @@
<methods>
</methods>
<members>
+ <member name="center_offset" type="Vector3" setter="set_center_offset" getter="get_center_offset" default="Vector3(0, 0, 0)">
+ Offset of the generated Quad. Useful for particles.
+ </member>
<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(1, 1)">
Size on the X and Y axes.
</member>
diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml
index 660204ee7d..06434ab268 100644
--- a/doc/classes/Quaternion.xml
+++ b/doc/classes/Quaternion.xml
@@ -177,17 +177,17 @@
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="Quaternion">
+ <return type="Vector3">
</return>
- <argument index="0" name="right" type="Quaternion">
+ <argument index="0" name="right" type="Vector3">
</argument>
<description>
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="Vector3">
+ <return type="Quaternion">
</return>
- <argument index="0" name="right" type="Vector3">
+ <argument index="0" name="right" type="Quaternion">
</argument>
<description>
</description>
@@ -211,12 +211,6 @@
<method name="operator +" qualifiers="operator">
<return type="Quaternion">
</return>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Quaternion">
- </return>
<argument index="0" name="right" type="Quaternion">
</argument>
<description>
@@ -225,12 +219,6 @@
<method name="operator -" qualifiers="operator">
<return type="Quaternion">
</return>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Quaternion">
- </return>
<argument index="0" name="right" type="Quaternion">
</argument>
<description>
@@ -268,6 +256,18 @@
<description>
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="Quaternion">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="slerp" qualifiers="const">
<return type="Quaternion">
</return>
diff --git a/doc/classes/RDPipelineSpecializationConstant.xml b/doc/classes/RDPipelineSpecializationConstant.xml
new file mode 100644
index 0000000000..4d9481b846
--- /dev/null
+++ b/doc/classes/RDPipelineSpecializationConstant.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="RDPipelineSpecializationConstant" inherits="RefCounted" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="constant_id" type="int" setter="set_constant_id" getter="get_constant_id" default="0">
+ </member>
+ <member name="value" type="Variant" setter="set_value" getter="get_value">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml
index 6fcb79b5fe..9c84cdd03e 100644
--- a/doc/classes/RandomNumberGenerator.xml
+++ b/doc/classes/RandomNumberGenerator.xml
@@ -23,7 +23,7 @@
<return type="float">
</return>
<description>
- Generates a pseudo-random float between [code]0.0[/code] and [code]1.0[/code] (inclusive).
+ Returns a pseudo-random float between [code]0.0[/code] and [code]1.0[/code] (inclusive).
</description>
</method>
<method name="randf_range">
@@ -34,7 +34,7 @@
<argument index="1" name="to" type="float">
</argument>
<description>
- Generates a pseudo-random float between [code]from[/code] and [code]to[/code] (inclusive).
+ Returns a pseudo-random float between [code]from[/code] and [code]to[/code] (inclusive).
</description>
</method>
<method name="randfn">
@@ -45,14 +45,14 @@
<argument index="1" name="deviation" type="float" default="1.0">
</argument>
<description>
- Generates a [url=https://en.wikipedia.org/wiki/Normal_distribution]normally-distributed[/url] pseudo-random number, using Box-Muller transform with the specified [code]mean[/code] and a standard [code]deviation[/code]. This is also called Gaussian distribution.
+ Returns a [url=https://en.wikipedia.org/wiki/Normal_distribution]normally-distributed[/url] pseudo-random number, using Box-Muller transform with the specified [code]mean[/code] and a standard [code]deviation[/code]. This is also called Gaussian distribution.
</description>
</method>
<method name="randi">
<return type="int">
</return>
<description>
- Generates a pseudo-random 32-bit unsigned integer between [code]0[/code] and [code]4294967295[/code] (inclusive).
+ Returns a pseudo-random 32-bit unsigned integer between [code]0[/code] and [code]4294967295[/code] (inclusive).
</description>
</method>
<method name="randi_range">
@@ -63,14 +63,14 @@
<argument index="1" name="to" type="int">
</argument>
<description>
- Generates a pseudo-random 32-bit signed integer between [code]from[/code] and [code]to[/code] (inclusive).
+ Returns a pseudo-random 32-bit signed integer between [code]from[/code] and [code]to[/code] (inclusive).
</description>
</method>
<method name="randomize">
<return type="void">
</return>
<description>
- Setups a time-based seed to generator.
+ Setups a time-based seed to for this [RandomNumberGenerator] instance. Unlike the [@GlobalScope] random number generation functions, different [RandomNumberGenerator] instances can use different seeds.
</description>
</method>
</methods>
diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml
index 1d32a8b509..db01faced8 100644
--- a/doc/classes/ReflectionProbe.xml
+++ b/doc/classes/ReflectionProbe.xml
@@ -28,8 +28,8 @@
<member name="enable_shadows" type="bool" setter="set_enable_shadows" getter="are_shadows_enabled" default="false">
If [code]true[/code], computes shadows in the reflection probe. This makes the reflection probe slower to render; you may want to disable this if using the [constant UPDATE_ALWAYS] [member update_mode].
</member>
- <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)">
- The size of the reflection probe. The larger the extents the more space covered by the probe which will lower the perceived resolution. It is best to keep the extents only as large as you need them.
+ <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(10, 10, 10)">
+ The size of the reflection probe. The larger the extents, the more space covered by the probe, which will lower the perceived resolution. It is best to keep the extents only as large as you need them.
</member>
<member name="intensity" type="float" setter="set_intensity" getter="get_intensity" default="1.0">
Defines the reflection intensity. Intensity modulates the strength of the reflection.
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index b66b945025..901a985961 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -140,6 +140,8 @@
</return>
<argument index="0" name="shader" type="RID">
</argument>
+ <argument index="1" name="specialization_constants" type="RDPipelineSpecializationConstant[]" default="[]">
+ </argument>
<description>
</description>
</method>
@@ -515,6 +517,14 @@
<description>
</description>
</method>
+ <method name="get_memory_usage" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="arg0" type="int" enum="RenderingDevice.MemoryType">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="index_array_create">
<return type="RID">
</return>
@@ -572,6 +582,8 @@
</argument>
<argument index="9" name="for_render_pass" type="int" default="0">
</argument>
+ <argument index="10" name="specialization_constants" type="RDPipelineSpecializationConstant[]" default="[]">
+ </argument>
<description>
</description>
</method>
@@ -1701,6 +1713,12 @@
</constant>
<constant name="SHADER_LANGUAGE_HLSL" value="1" enum="ShaderLanguage">
</constant>
+ <constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL" value="0" enum="PipelineSpecializationConstantType">
+ </constant>
+ <constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT" value="1" enum="PipelineSpecializationConstantType">
+ </constant>
+ <constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT" value="2" enum="PipelineSpecializationConstantType">
+ </constant>
<constant name="LIMIT_MAX_BOUND_UNIFORM_SETS" value="0" enum="Limit">
</constant>
<constant name="LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS" value="1" enum="Limit">
@@ -1771,6 +1789,12 @@
</constant>
<constant name="LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z" value="34" enum="Limit">
</constant>
+ <constant name="MEMORY_TEXTURES" value="0" enum="MemoryType">
+ </constant>
+ <constant name="MEMORY_BUFFERS" value="1" enum="MemoryType">
+ </constant>
+ <constant name="MEMORY_TOTAL" value="2" enum="MemoryType">
+ </constant>
<constant name="INVALID_ID" value="-1">
</constant>
<constant name="INVALID_FORMAT_ID" value="-1">
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 44e0202307..31ced67ac4 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -18,42 +18,92 @@
<link title="Optimization using Servers">https://docs.godotengine.org/en/latest/tutorials/optimization/using_servers.html</link>
</tutorials>
<methods>
- <method name="black_bars_set_images">
- <return type="void">
+ <method name="bake_render_uv2">
+ <return type="Image[]">
</return>
- <argument index="0" name="left" type="RID">
+ <argument index="0" name="base" type="RID">
+ </argument>
+ <argument index="1" name="material_overrides" type="Array">
+ </argument>
+ <argument index="2" name="image_size" type="Vector2i">
</argument>
- <argument index="1" name="top" type="RID">
+ <description>
+ </description>
+ </method>
+ <method name="camera_create">
+ <return type="RID">
+ </return>
+ <description>
+ Creates a camera and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]camera_*[/code] RenderingServer functions.
+ Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
+ </description>
+ </method>
+ <method name="camera_effects_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="camera_effects_set_custom_exposure">
+ <return type="void">
+ </return>
+ <argument index="0" name="camera_effects" type="RID">
</argument>
- <argument index="2" name="right" type="RID">
+ <argument index="1" name="enable" type="bool">
</argument>
- <argument index="3" name="bottom" type="RID">
+ <argument index="2" name="exposure" type="float">
</argument>
<description>
- Sets images to be rendered in the window margin.
</description>
</method>
- <method name="black_bars_set_margins">
+ <method name="camera_effects_set_dof_blur">
<return type="void">
</return>
- <argument index="0" name="left" type="int">
+ <argument index="0" name="camera_effects" type="RID">
+ </argument>
+ <argument index="1" name="far_enable" type="bool">
+ </argument>
+ <argument index="2" name="far_distance" type="float">
</argument>
- <argument index="1" name="top" type="int">
+ <argument index="3" name="far_transition" type="float">
</argument>
- <argument index="2" name="right" type="int">
+ <argument index="4" name="near_enable" type="bool">
</argument>
- <argument index="3" name="bottom" type="int">
+ <argument index="5" name="near_distance" type="float">
+ </argument>
+ <argument index="6" name="near_transition" type="float">
+ </argument>
+ <argument index="7" name="amount" type="float">
</argument>
<description>
- Sets margin size, where black bars (or images, if [method black_bars_set_images] was used) are rendered.
</description>
</method>
- <method name="camera_create">
- <return type="RID">
+ <method name="camera_effects_set_dof_blur_bokeh_shape">
+ <return type="void">
</return>
+ <argument index="0" name="shape" type="int" enum="RenderingServer.DOFBokehShape">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="camera_effects_set_dof_blur_quality">
+ <return type="void">
+ </return>
+ <argument index="0" name="quality" type="int" enum="RenderingServer.DOFBlurQuality">
+ </argument>
+ <argument index="1" name="use_jitter" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="camera_set_camera_effects">
+ <return type="void">
+ </return>
+ <argument index="0" name="camera" type="RID">
+ </argument>
+ <argument index="1" name="effects" type="RID">
+ </argument>
<description>
- Creates a camera and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]camera_*[/code] RenderingServer functions.
- Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
<method name="camera_set_cull_mask">
@@ -155,6 +205,246 @@
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
+ <method name="canvas_item_add_circle">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="pos" type="Vector2">
+ </argument>
+ <argument index="2" name="radius" type="float">
+ </argument>
+ <argument index="3" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_clip_ignore">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="ignore" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_line">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="from" type="Vector2">
+ </argument>
+ <argument index="2" name="to" type="Vector2">
+ </argument>
+ <argument index="3" name="color" type="Color">
+ </argument>
+ <argument index="4" name="width" type="float" default="1.0">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_mesh">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="mesh" type="RID">
+ </argument>
+ <argument index="2" name="transform" type="Transform2D" default="Transform2D(1, 0, 0, 1, 0, 0)">
+ </argument>
+ <argument index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
+ </argument>
+ <argument index="4" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_multimesh">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="mesh" type="RID">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_nine_patch">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="source" type="Rect2">
+ </argument>
+ <argument index="3" name="texture" type="RID">
+ </argument>
+ <argument index="4" name="topleft" type="Vector2">
+ </argument>
+ <argument index="5" name="bottomright" type="Vector2">
+ </argument>
+ <argument index="6" name="x_axis_mode" type="int" enum="RenderingServer.NinePatchAxisMode" default="0">
+ </argument>
+ <argument index="7" name="y_axis_mode" type="int" enum="RenderingServer.NinePatchAxisMode" default="0">
+ </argument>
+ <argument index="8" name="draw_center" type="bool" default="true">
+ </argument>
+ <argument index="9" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_particles">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="particles" type="RID">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_polygon">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="points" type="PackedVector2Array">
+ </argument>
+ <argument index="2" name="colors" type="PackedColorArray">
+ </argument>
+ <argument index="3" name="uvs" type="PackedVector2Array" default="PackedVector2Array()">
+ </argument>
+ <argument index="4" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_polyline">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="points" type="PackedVector2Array">
+ </argument>
+ <argument index="2" name="colors" type="PackedColorArray">
+ </argument>
+ <argument index="3" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="4" name="antialiased" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_primitive">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="points" type="PackedVector2Array">
+ </argument>
+ <argument index="2" name="colors" type="PackedColorArray">
+ </argument>
+ <argument index="3" name="uvs" type="PackedVector2Array">
+ </argument>
+ <argument index="4" name="texture" type="RID">
+ </argument>
+ <argument index="5" name="width" type="float" default="1.0">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_rect">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_set_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_texture_rect">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <argument index="3" name="tile" type="bool" default="false">
+ </argument>
+ <argument index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
+ </argument>
+ <argument index="5" name="transpose" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_texture_rect_region">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <argument index="3" name="src_rect" type="Rect2">
+ </argument>
+ <argument index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
+ </argument>
+ <argument index="5" name="transpose" type="bool" default="false">
+ </argument>
+ <argument index="6" name="clip_uv" type="bool" default="true">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_triangle_array">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="indices" type="PackedInt32Array">
+ </argument>
+ <argument index="2" name="points" type="PackedVector2Array">
+ </argument>
+ <argument index="3" name="colors" type="PackedColorArray">
+ </argument>
+ <argument index="4" name="uvs" type="PackedVector2Array" default="PackedVector2Array()">
+ </argument>
+ <argument index="5" name="bones" type="PackedInt32Array" default="PackedInt32Array()">
+ </argument>
+ <argument index="6" name="weights" type="PackedFloat32Array" default="PackedFloat32Array()">
+ </argument>
+ <argument index="7" name="texture" type="RID">
+ </argument>
+ <argument index="8" name="count" type="int" default="-1">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_item_clear">
<return type="void">
</return>
@@ -164,6 +454,40 @@
Clears the [CanvasItem] and removes all commands in it.
</description>
</method>
+ <method name="canvas_item_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_canvas_group_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="mode" type="int" enum="RenderingServer.CanvasGroupMode">
+ </argument>
+ <argument index="2" name="clear_margin" type="float" default="5.0">
+ </argument>
+ <argument index="3" name="fit_empty" type="bool" default="false">
+ </argument>
+ <argument index="4" name="fit_margin" type="float" default="0.0">
+ </argument>
+ <argument index="5" name="blur_mipmaps" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_clip">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="clip" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_item_set_copy_to_backbuffer">
<return type="void">
</return>
@@ -177,6 +501,58 @@
Sets the [CanvasItem] to copy a rect to the backbuffer.
</description>
</method>
+ <method name="canvas_item_set_custom_rect">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="use_custom_rect" type="bool">
+ </argument>
+ <argument index="2" name="rect" type="Rect2" default="Rect2(0, 0, 0, 0)">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_default_texture_filter">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="filter" type="int" enum="RenderingServer.CanvasItemTextureFilter">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_default_texture_repeat">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="repeat" type="int" enum="RenderingServer.CanvasItemTextureRepeat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_distance_field_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_draw_behind_parent">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_item_set_draw_index">
<return type="void">
</return>
@@ -188,6 +564,16 @@
Sets the index for the [CanvasItem].
</description>
</method>
+ <method name="canvas_item_set_light_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_item_set_material">
<return type="void">
</return>
@@ -199,6 +585,56 @@
Sets a new material to the [CanvasItem].
</description>
</method>
+ <method name="canvas_item_set_modulate">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_parent">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="parent" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_self_modulate">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_sort_children_by_y">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_item_set_use_parent_material">
<return type="void">
</return>
@@ -210,6 +646,32 @@
Sets if the [CanvasItem] uses its parent's material.
</description>
</method>
+ <method name="canvas_item_set_visibility_notifier">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <argument index="2" name="area" type="Rect2">
+ </argument>
+ <argument index="3" name="enter_callable" type="Callable">
+ </argument>
+ <argument index="4" name="exit_callable" type="Callable">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_visible">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="visible" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_item_set_z_as_relative_to_parent">
<return type="void">
</return>
@@ -270,6 +732,16 @@
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
+ <method name="canvas_light_occluder_set_as_sdf_collision">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_light_occluder_set_enabled">
<return type="void">
</return>
@@ -537,6 +1009,14 @@
Sets the shape of the occluder polygon.
</description>
</method>
+ <method name="canvas_set_disable_scale">
+ <return type="void">
+ </return>
+ <argument index="0" name="disable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_set_item_mirroring">
<return type="void">
</return>
@@ -561,12 +1041,182 @@
Modulates all colors in the given canvas.
</description>
</method>
+ <method name="canvas_set_shadow_texture_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="size" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_texture_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_texture_set_channel">
+ <return type="void">
+ </return>
+ <argument index="0" name="canvas_texture" type="RID">
+ </argument>
+ <argument index="1" name="channel" type="int" enum="RenderingServer.CanvasTextureChannel">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_texture_set_shading_parameters">
+ <return type="void">
+ </return>
+ <argument index="0" name="canvas_texture" type="RID">
+ </argument>
+ <argument index="1" name="base_color" type="Color">
+ </argument>
+ <argument index="2" name="shininess" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_texture_set_texture_filter">
+ <return type="void">
+ </return>
+ <argument index="0" name="canvas_texture" type="RID">
+ </argument>
+ <argument index="1" name="filter" type="int" enum="RenderingServer.CanvasItemTextureFilter">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_texture_set_texture_repeat">
+ <return type="void">
+ </return>
+ <argument index="0" name="canvas_texture" type="RID">
+ </argument>
+ <argument index="1" name="repeat" type="int" enum="RenderingServer.CanvasItemTextureRepeat">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="create_local_rendering_device" qualifiers="const">
<return type="RenderingDevice">
</return>
<description>
</description>
</method>
+ <method name="decal_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_albedo_mix">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="albedo_mix" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_cull_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_distance_fade">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <argument index="2" name="begin" type="float">
+ </argument>
+ <argument index="3" name="length" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_emission_energy">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="energy" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_extents">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="extents" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_fade">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="above" type="float">
+ </argument>
+ <argument index="2" name="below" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_modulate">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_normal_fade">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="fade" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decal_set_texture">
+ <return type="void">
+ </return>
+ <argument index="0" name="decal" type="RID">
+ </argument>
+ <argument index="1" name="type" type="int" enum="RenderingServer.DecalTexture">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="decals_set_filter">
+ <return type="void">
+ </return>
+ <argument index="0" name="filter" type="int" enum="RenderingServer.DecalFilter">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="directional_light_create">
<return type="RID">
</return>
@@ -576,6 +1226,36 @@
To place in a scene, attach this directional light to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
+ <method name="directional_shadow_atlas_set_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="size" type="int">
+ </argument>
+ <argument index="1" name="is_16bits" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="directional_shadow_quality_set">
+ <return type="void">
+ </return>
+ <argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="environment_bake_panorama">
+ <return type="Image">
+ </return>
+ <argument index="0" name="environment" type="RID">
+ </argument>
+ <argument index="1" name="bake_irradiance" type="bool">
+ </argument>
+ <argument index="2" name="size" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="environment_create">
<return type="RID">
</return>
@@ -584,6 +1264,22 @@
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
+ <method name="environment_glow_set_use_bicubic_upscale">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="environment_glow_set_use_high_quality">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="environment_set_adjustment">
<return type="void">
</return>
@@ -721,6 +1417,58 @@
<description>
</description>
</method>
+ <method name="environment_set_sdfgi">
+ <return type="void">
+ </return>
+ <argument index="0" name="env" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <argument index="2" name="cascades" type="int" enum="RenderingServer.EnvironmentSDFGICascades">
+ </argument>
+ <argument index="3" name="min_cell_size" type="float">
+ </argument>
+ <argument index="4" name="y_scale" type="int" enum="RenderingServer.EnvironmentSDFGIYScale">
+ </argument>
+ <argument index="5" name="use_occlusion" type="bool">
+ </argument>
+ <argument index="6" name="bounce_feedback" type="float">
+ </argument>
+ <argument index="7" name="read_sky" type="bool">
+ </argument>
+ <argument index="8" name="energy" type="float">
+ </argument>
+ <argument index="9" name="normal_bias" type="float">
+ </argument>
+ <argument index="10" name="probe_bias" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="environment_set_sdfgi_frames_to_converge">
+ <return type="void">
+ </return>
+ <argument index="0" name="frames" type="int" enum="RenderingServer.EnvironmentSDFGIFramesToConverge">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="environment_set_sdfgi_frames_to_update_light">
+ <return type="void">
+ </return>
+ <argument index="0" name="frames" type="int" enum="RenderingServer.EnvironmentSDFGIFramesToUpdateLight">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="environment_set_sdfgi_ray_count">
+ <return type="void">
+ </return>
+ <argument index="0" name="ray_count" type="int" enum="RenderingServer.EnvironmentSDFGIRayCount">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="environment_set_sky">
<return type="void">
</return>
@@ -781,6 +1529,24 @@
Sets the variables to be used with the "screen space ambient occlusion" post-process effect. See [Environment] for more details.
</description>
</method>
+ <method name="environment_set_ssao_quality">
+ <return type="void">
+ </return>
+ <argument index="0" name="quality" type="int" enum="RenderingServer.EnvironmentSSAOQuality">
+ </argument>
+ <argument index="1" name="half_size" type="bool">
+ </argument>
+ <argument index="2" name="adaptive_target" type="float">
+ </argument>
+ <argument index="3" name="blur_passes" type="int">
+ </argument>
+ <argument index="4" name="fadeout_from" type="float">
+ </argument>
+ <argument index="5" name="fadeout_to" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="environment_set_ssr">
<return type="void">
</return>
@@ -800,6 +1566,14 @@
Sets the variables to be used with the "screen space reflections" post-process effect. See [Environment] for more details.
</description>
</method>
+ <method name="environment_set_ssr_roughness_quality">
+ <return type="void">
+ </return>
+ <argument index="0" name="quality" type="int" enum="RenderingServer.EnvironmentSSRRoughnessQuality">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="environment_set_tonemap">
<return type="void">
</return>
@@ -825,11 +1599,48 @@
Sets the variables to be used with the "tonemap" post-process effect. See [Environment] for more details.
</description>
</method>
- <method name="finish">
+ <method name="environment_set_volumetric_fog">
+ <return type="void">
+ </return>
+ <argument index="0" name="env" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <argument index="2" name="density" type="float">
+ </argument>
+ <argument index="3" name="light" type="Color">
+ </argument>
+ <argument index="4" name="light_energy" type="float">
+ </argument>
+ <argument index="5" name="length" type="float">
+ </argument>
+ <argument index="6" name="p_detail_spread" type="float">
+ </argument>
+ <argument index="7" name="gi_inject" type="float">
+ </argument>
+ <argument index="8" name="temporal_reprojection" type="bool">
+ </argument>
+ <argument index="9" name="temporal_reprojection_amount" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="environment_set_volumetric_fog_filter_active">
+ <return type="void">
+ </return>
+ <argument index="0" name="active" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="environment_set_volumetric_fog_volume_size">
<return type="void">
</return>
+ <argument index="0" name="size" type="int">
+ </argument>
+ <argument index="1" name="depth" type="int">
+ </argument>
<description>
- Removes buffers and clears testcubes.
</description>
</method>
<method name="force_draw">
@@ -840,14 +1651,12 @@
<argument index="1" name="frame_step" type="float" default="0.0">
</argument>
<description>
- Forces a frame to be drawn when the function is called. Drawing a frame updates all [Viewport]s that are set to update. Use with extreme caution.
</description>
</method>
<method name="force_sync">
<return type="void">
</return>
<description>
- Synchronizes threads.
</description>
</method>
<method name="free_rid">
@@ -865,13 +1674,12 @@
<description>
</description>
</method>
- <method name="get_render_info">
+ <method name="get_rendering_info">
<return type="int">
</return>
- <argument index="0" name="info" type="int" enum="RenderingServer.RenderInfo">
+ <argument index="0" name="info" type="int" enum="RenderingServer.RenderingInfo">
</argument>
<description>
- Returns a certain information, see [enum RenderInfo] for options.
</description>
</method>
<method name="get_test_cube">
@@ -963,6 +1771,16 @@
<description>
</description>
</method>
+ <method name="global_variable_set_override">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="StringName">
+ </argument>
+ <argument index="1" name="value" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="has_changed" qualifiers="const">
<return type="bool">
</return>
@@ -988,226 +1806,146 @@
Returns [code]true[/code] if the OS supports a certain feature. Features might be [code]s3tc[/code], [code]etc[/code], [code]etc2[/code] and [code]pvrtc[/code].
</description>
</method>
- <method name="immediate_begin">
+ <method name="instance_attach_object_instance_id">
<return type="void">
</return>
- <argument index="0" name="immediate" type="RID">
- </argument>
- <argument index="1" name="primitive" type="int" enum="RenderingServer.PrimitiveType">
- </argument>
- <argument index="2" name="texture" type="RID">
+ <argument index="0" name="instance" type="RID">
</argument>
- <description>
- Sets up [ImmediateGeometry3D] internals to prepare for drawing. Equivalent to [method ImmediateGeometry3D.begin].
- </description>
- </method>
- <method name="immediate_clear">
- <return type="void">
- </return>
- <argument index="0" name="immediate" type="RID">
+ <argument index="1" name="id" type="int">
</argument>
<description>
- Clears everything that was set up between [method immediate_begin] and [method immediate_end]. Equivalent to [method ImmediateGeometry3D.clear].
+ Attaches a unique Object ID to instance. Object ID must be attached to instance for proper culling with [method instances_cull_aabb], [method instances_cull_convex], and [method instances_cull_ray].
</description>
</method>
- <method name="immediate_color">
+ <method name="instance_attach_skeleton">
<return type="void">
</return>
- <argument index="0" name="immediate" type="RID">
+ <argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="color" type="Color">
+ <argument index="1" name="skeleton" type="RID">
</argument>
<description>
- Sets the color to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_color].
+ Attaches a skeleton to an instance. Removes the previous skeleton from the instance.
</description>
</method>
- <method name="immediate_create">
+ <method name="instance_create">
<return type="RID">
</return>
<description>
- Creates an immediate geometry and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]immediate_*[/code] RenderingServer functions.
+ Creates a visual instance and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]instance_*[/code] RenderingServer functions.
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
- To place in a scene, attach this immediate geometry to an instance using [method instance_set_base] using the returned RID.
- </description>
- </method>
- <method name="immediate_end">
- <return type="void">
- </return>
- <argument index="0" name="immediate" type="RID">
- </argument>
- <description>
- Ends drawing the [ImmediateGeometry3D] and displays it. Equivalent to [method ImmediateGeometry3D.end].
+ An instance is a way of placing a 3D object in the scenario. Objects like particles, meshes, and reflection probes need to be associated with an instance to be visible in the scenario using [method instance_set_base].
</description>
</method>
- <method name="immediate_get_material" qualifiers="const">
+ <method name="instance_create2">
<return type="RID">
</return>
- <argument index="0" name="immediate" type="RID">
- </argument>
- <description>
- Returns the material assigned to the [ImmediateGeometry3D].
- </description>
- </method>
- <method name="immediate_normal">
- <return type="void">
- </return>
- <argument index="0" name="immediate" type="RID">
- </argument>
- <argument index="1" name="normal" type="Vector3">
- </argument>
- <description>
- Sets the normal to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_normal].
- </description>
- </method>
- <method name="immediate_set_material">
- <return type="void">
- </return>
- <argument index="0" name="immediate" type="RID">
- </argument>
- <argument index="1" name="material" type="RID">
- </argument>
- <description>
- Sets the material to be used to draw the [ImmediateGeometry3D].
- </description>
- </method>
- <method name="immediate_tangent">
- <return type="void">
- </return>
- <argument index="0" name="immediate" type="RID">
+ <argument index="0" name="base" type="RID">
</argument>
- <argument index="1" name="tangent" type="Plane">
+ <argument index="1" name="scenario" type="RID">
</argument>
<description>
- Sets the tangent to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_tangent].
+ Creates a visual instance, adds it to the RenderingServer, and sets both base and scenario. It can be accessed with the RID that is returned. This RID will be used in all [code]instance_*[/code] RenderingServer functions.
+ Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
- <method name="immediate_uv">
- <return type="void">
+ <method name="instance_geometry_get_shader_parameter" qualifiers="const">
+ <return type="Variant">
</return>
- <argument index="0" name="immediate" type="RID">
+ <argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="tex_uv" type="Vector2">
+ <argument index="1" name="parameter" type="StringName">
</argument>
<description>
- Sets the UV to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_uv].
</description>
</method>
- <method name="immediate_uv2">
- <return type="void">
+ <method name="instance_geometry_get_shader_parameter_default_value" qualifiers="const">
+ <return type="Variant">
</return>
- <argument index="0" name="immediate" type="RID">
+ <argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="tex_uv" type="Vector2">
+ <argument index="1" name="parameter" type="StringName">
</argument>
<description>
- Sets the UV2 to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_uv2].
</description>
</method>
- <method name="immediate_vertex">
- <return type="void">
+ <method name="instance_geometry_get_shader_parameter_list" qualifiers="const">
+ <return type="Array">
</return>
- <argument index="0" name="immediate" type="RID">
- </argument>
- <argument index="1" name="vertex" type="Vector3">
+ <argument index="0" name="instance" type="RID">
</argument>
<description>
- Adds the next vertex using the information provided in advance. Equivalent to [method ImmediateGeometry3D.add_vertex].
</description>
</method>
- <method name="immediate_vertex_2d">
+ <method name="instance_geometry_set_cast_shadows_setting">
<return type="void">
</return>
- <argument index="0" name="immediate" type="RID">
+ <argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="vertex" type="Vector2">
+ <argument index="1" name="shadow_casting_setting" type="int" enum="RenderingServer.ShadowCastingSetting">
</argument>
<description>
- Adds the next vertex using the information provided in advance. This is a helper class that calls [method immediate_vertex] under the hood. Equivalent to [method ImmediateGeometry3D.add_vertex].
- </description>
- </method>
- <method name="init">
- <return type="void">
- </return>
- <description>
- Initializes the rendering server. This function is called internally by platform-dependent code during engine initialization. If called from a running game, it will not do anything.
+ Sets the shadow casting setting to one of [enum ShadowCastingSetting]. Equivalent to [member GeometryInstance3D.cast_shadow].
</description>
</method>
- <method name="instance_attach_object_instance_id">
+ <method name="instance_geometry_set_flag">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="id" type="int">
+ <argument index="1" name="flag" type="int" enum="RenderingServer.InstanceFlags">
+ </argument>
+ <argument index="2" name="enabled" type="bool">
</argument>
<description>
- Attaches a unique Object ID to instance. Object ID must be attached to instance for proper culling with [method instances_cull_aabb], [method instances_cull_convex], and [method instances_cull_ray].
+ Sets the flag for a given [enum InstanceFlags]. See [enum InstanceFlags] for more details.
</description>
</method>
- <method name="instance_attach_skeleton">
+ <method name="instance_geometry_set_lightmap">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="skeleton" type="RID">
+ <argument index="1" name="lightmap" type="RID">
</argument>
- <description>
- Attaches a skeleton to an instance. Removes the previous skeleton from the instance.
- </description>
- </method>
- <method name="instance_create">
- <return type="RID">
- </return>
- <description>
- Creates a visual instance and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]instance_*[/code] RenderingServer functions.
- Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
- An instance is a way of placing a 3D object in the scenario. Objects like particles, meshes, and reflection probes need to be associated with an instance to be visible in the scenario using [method instance_set_base].
- </description>
- </method>
- <method name="instance_create2">
- <return type="RID">
- </return>
- <argument index="0" name="base" type="RID">
+ <argument index="2" name="lightmap_uv_scale" type="Rect2">
</argument>
- <argument index="1" name="scenario" type="RID">
+ <argument index="3" name="lightmap_slice" type="int">
</argument>
<description>
- Creates a visual instance, adds it to the RenderingServer, and sets both base and scenario. It can be accessed with the RID that is returned. This RID will be used in all [code]instance_*[/code] RenderingServer functions.
- Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
- <method name="instance_geometry_set_cast_shadows_setting">
+ <method name="instance_geometry_set_lod_bias">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="shadow_casting_setting" type="int" enum="RenderingServer.ShadowCastingSetting">
+ <argument index="1" name="lod_bias" type="float">
</argument>
<description>
- Sets the shadow casting setting to one of [enum ShadowCastingSetting]. Equivalent to [member GeometryInstance3D.cast_shadow].
</description>
</method>
- <method name="instance_geometry_set_flag">
+ <method name="instance_geometry_set_material_override">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="flag" type="int" enum="RenderingServer.InstanceFlags">
- </argument>
- <argument index="2" name="enabled" type="bool">
+ <argument index="1" name="material" type="RID">
</argument>
<description>
- Sets the flag for a given [enum InstanceFlags]. See [enum InstanceFlags] for more details.
+ Sets a material that will override the material for all surfaces on the mesh associated with this instance. Equivalent to [member GeometryInstance3D.material_override].
</description>
</method>
- <method name="instance_geometry_set_material_override">
+ <method name="instance_geometry_set_shader_parameter">
<return type="void">
</return>
<argument index="0" name="instance" type="RID">
</argument>
- <argument index="1" name="material" type="RID">
+ <argument index="1" name="parameter" type="StringName">
+ </argument>
+ <argument index="2" name="value" type="Variant">
</argument>
<description>
- Sets a material that will override the material for all surfaces on the mesh associated with this instance. Equivalent to [member GeometryInstance3D.material_override].
</description>
</method>
<method name="instance_geometry_set_visibility_range">
@@ -1262,17 +2000,6 @@
Sets a custom AABB to use when culling objects from the view frustum. Equivalent to [method GeometryInstance3D.set_custom_aabb].
</description>
</method>
- <method name="instance_set_exterior">
- <return type="void">
- </return>
- <argument index="0" name="instance" type="RID">
- </argument>
- <argument index="1" name="enabled" type="bool">
- </argument>
- <description>
- Function not implemented in Godot 3.x.
- </description>
- </method>
<method name="instance_set_extra_visibility_margin">
<return type="void">
</return>
@@ -1401,17 +2128,6 @@
If [code]true[/code], this directional light will blend between shadow map splits resulting in a smoother transition between them. Equivalent to [member DirectionalLight3D.directional_shadow_blend_splits].
</description>
</method>
- <method name="light_directional_set_shadow_depth_range_mode">
- <return type="void">
- </return>
- <argument index="0" name="light" type="RID">
- </argument>
- <argument index="1" name="range_mode" type="int" enum="RenderingServer.LightDirectionalShadowDepthRangeMode">
- </argument>
- <description>
- Sets the shadow depth range mode for this directional light. Equivalent to [member DirectionalLight3D.directional_shadow_depth_range]. See [enum LightDirectionalShadowDepthRangeMode] for options.
- </description>
- </method>
<method name="light_directional_set_shadow_mode">
<return type="void">
</return>
@@ -1445,6 +2161,14 @@
Sets whether to use a dual paraboloid or a cubemap for the shadow map. Dual paraboloid is faster but may suffer from artifacts. Equivalent to [member OmniLight3D.omni_shadow_mode].
</description>
</method>
+ <method name="light_projectors_set_filter">
+ <return type="void">
+ </return>
+ <argument index="0" name="filter" type="int" enum="RenderingServer.LightProjectorFilter">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="light_set_bake_mode">
<return type="void">
</return>
@@ -1477,6 +2201,16 @@
Sets the cull mask for this Light3D. Lights only affect objects in the selected layers. Equivalent to [member Light3D.light_cull_mask].
</description>
</method>
+ <method name="light_set_max_sdfgi_cascade">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="cascade" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="light_set_negative">
<return type="void">
</return>
@@ -1545,6 +2279,100 @@
Sets the color of the shadow cast by the light. Equivalent to [member Light3D.shadow_color].
</description>
</method>
+ <method name="lightmap_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_get_probe_capture_bsp_tree" qualifiers="const">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_get_probe_capture_points" qualifiers="const">
+ <return type="PackedVector3Array">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_get_probe_capture_sh" qualifiers="const">
+ <return type="PackedColorArray">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_get_probe_capture_tetrahedra" qualifiers="const">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_set_probe_bounds">
+ <return type="void">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <argument index="1" name="bounds" type="AABB">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_set_probe_capture_data">
+ <return type="void">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <argument index="1" name="points" type="PackedVector3Array">
+ </argument>
+ <argument index="2" name="point_sh" type="PackedColorArray">
+ </argument>
+ <argument index="3" name="tetrahedra" type="PackedInt32Array">
+ </argument>
+ <argument index="4" name="bsp_tree" type="PackedInt32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_set_probe_capture_update_speed">
+ <return type="void">
+ </return>
+ <argument index="0" name="speed" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_set_probe_interior">
+ <return type="void">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <argument index="1" name="interior" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="lightmap_set_textures">
+ <return type="void">
+ </return>
+ <argument index="0" name="lightmap" type="RID">
+ </argument>
+ <argument index="1" name="light" type="RID">
+ </argument>
+ <argument index="2" name="uses_sh" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="make_sphere_mesh">
<return type="RID">
</return>
@@ -1623,6 +2451,35 @@
Sets a shader material's shader.
</description>
</method>
+ <method name="mesh_add_surface">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="Dictionary">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_add_surface_from_arrays">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="primitive" type="int" enum="RenderingServer.PrimitiveType">
+ </argument>
+ <argument index="2" name="arrays" type="Array">
+ </argument>
+ <argument index="3" name="blend_shapes" type="Array" default="[]">
+ </argument>
+ <argument index="4" name="lods" type="Dictionary" default="{
+}">
+ </argument>
+ <argument index="5" name="compress_format" type="int" default="0">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="mesh_clear">
<return type="void">
</return>
@@ -1641,6 +2498,16 @@
To place in a scene, attach this mesh to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
+ <method name="mesh_create_from_surfaces">
+ <return type="RID">
+ </return>
+ <argument index="0" name="surfaces" type="Dictionary[]">
+ </argument>
+ <argument index="1" name="blend_shape_count" type="int" default="0">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="mesh_get_blend_shape_count" qualifiers="const">
<return type="int">
</return>
@@ -1668,6 +2535,16 @@
Returns a mesh's custom aabb.
</description>
</method>
+ <method name="mesh_get_surface">
+ <return type="Dictionary">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="mesh_get_surface_count" qualifiers="const">
<return type="int">
</return>
@@ -1699,6 +2576,16 @@
Sets a mesh's custom aabb.
</description>
</method>
+ <method name="mesh_set_shadow_mesh">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="shadow_mesh" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="mesh_surface_get_arrays" qualifiers="const">
<return type="Array">
</return>
@@ -1787,7 +2674,35 @@
Sets a mesh's surface's material.
</description>
</method>
- <method name="mesh_surface_update_region">
+ <method name="mesh_surface_update_attribute_region">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <argument index="2" name="offset" type="int">
+ </argument>
+ <argument index="3" name="data" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_update_skin_region">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <argument index="2" name="offset" type="int">
+ </argument>
+ <argument index="3" name="data" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_update_vertex_region">
<return type="void">
</return>
<argument index="0" name="mesh" type="RID">
@@ -1799,7 +2714,6 @@
<argument index="3" name="data" type="PackedByteArray">
</argument>
<description>
- Updates a specific region of a vertex buffer for the specified surface. Warning: this function alters the vertex buffer directly with no safety mechanisms, you can easily corrupt your mesh.
</description>
</method>
<method name="multimesh_allocate_data">
@@ -2008,11 +2922,11 @@
<method name="occluder_set_mesh">
<return type="void">
</return>
- <argument index="0" name="arg0" type="RID">
+ <argument index="0" name="occluder" type="RID">
</argument>
- <argument index="1" name="arg1" type="PackedVector3Array">
+ <argument index="1" name="vertices" type="PackedVector3Array">
</argument>
- <argument index="2" name="arg2" type="PackedInt32Array">
+ <argument index="2" name="indices" type="PackedInt32Array">
</argument>
<description>
</description>
@@ -2026,6 +2940,110 @@
To place in a scene, attach this omni light to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
+ <method name="particles_collision_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_height_field_update">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_attractor_attenuation">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="curve" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_attractor_directionality">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="amount" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_attractor_strength">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="setrngth" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_box_extents">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="extents" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_collision_type">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="type" type="int" enum="RenderingServer.ParticlesCollisionType">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_cull_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_field_texture">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_height_field_resolution">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="resolution" type="int" enum="RenderingServer.ParticlesCollisionHeightfieldResolution">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_collision_set_sphere_radius">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles_collision" type="RID">
+ </argument>
+ <argument index="1" name="radius" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="particles_create">
<return type="RID">
</return>
@@ -2035,6 +3053,24 @@
To place in a scene, attach these particles to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
+ <method name="particles_emit">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform3D">
+ </argument>
+ <argument index="2" name="velocity" type="Vector3">
+ </argument>
+ <argument index="3" name="color" type="Color">
+ </argument>
+ <argument index="4" name="custom" type="Color">
+ </argument>
+ <argument index="5" name="emit_flags" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="particles_get_current_aabb">
<return type="AABB">
</return>
@@ -2091,6 +3127,16 @@
Sets the number of particles to be drawn and allocates the memory for them. Equivalent to [member GPUParticles3D.amount].
</description>
</method>
+ <method name="particles_set_collision_base_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="size" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="particles_set_custom_aabb">
<return type="void">
</return>
@@ -2192,6 +3238,16 @@
If [code]true[/code], uses fractional delta which smooths the movement of the particles. Equivalent to [member GPUParticles3D.fract_delta].
</description>
</method>
+ <method name="particles_set_interpolate">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="particles_set_lifetime">
<return type="void">
</return>
@@ -2203,6 +3259,16 @@
Sets the lifetime of each particle in the system. Equivalent to [member GPUParticles3D.lifetime].
</description>
</method>
+ <method name="particles_set_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="mode" type="int" enum="RenderingServer.ParticlesMode">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="particles_set_one_shot">
<return type="void">
</return>
@@ -2258,6 +3324,48 @@
Sets the speed scale of the particle system. Equivalent to [member GPUParticles3D.speed_scale].
</description>
</method>
+ <method name="particles_set_subemitter">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="subemitter_particles" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_set_trail_bind_poses">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="bind_poses" type="Transform3D[]">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_set_trails">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <argument index="2" name="length_sec" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="particles_set_transform_align">
+ <return type="void">
+ </return>
+ <argument index="0" name="particles" type="RID">
+ </argument>
+ <argument index="1" name="align" type="int" enum="RenderingServer.ParticlesTransformAlign">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="particles_set_use_local_coordinates">
<return type="void">
</return>
@@ -2374,6 +3482,16 @@
Sets the intensity of the reflection probe. Intensity modulates the strength of the reflection. Equivalent to [member ReflectionProbe.intensity].
</description>
</method>
+ <method name="reflection_probe_set_lod_threshold">
+ <return type="void">
+ </return>
+ <argument index="0" name="probe" type="RID">
+ </argument>
+ <argument index="1" name="pixels" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="reflection_probe_set_max_distance">
<return type="void">
</return>
@@ -2396,6 +3514,16 @@
Sets the origin offset to be used when this reflection probe is in box project mode. Equivalent to [member ReflectionProbe.origin_offset].
</description>
</method>
+ <method name="reflection_probe_set_resolution">
+ <return type="void">
+ </return>
+ <argument index="0" name="probe" type="RID">
+ </argument>
+ <argument index="1" name="resolution" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="reflection_probe_set_update_mode">
<return type="void">
</return>
@@ -2440,18 +3568,18 @@
<description>
</description>
</method>
- <method name="scenario_set_debug">
+ <method name="scenario_set_environment">
<return type="void">
</return>
<argument index="0" name="scenario" type="RID">
</argument>
- <argument index="1" name="debug_mode" type="int" enum="RenderingServer.ScenarioDebugMode">
+ <argument index="1" name="environment" type="RID">
</argument>
<description>
- Sets the [enum ScenarioDebugMode] for this scenario. See [enum ScenarioDebugMode] for options.
+ Sets the environment that will be used with this scenario.
</description>
</method>
- <method name="scenario_set_environment">
+ <method name="scenario_set_fallback_environment">
<return type="void">
</return>
<argument index="0" name="scenario" type="RID">
@@ -2459,18 +3587,19 @@
<argument index="1" name="environment" type="RID">
</argument>
<description>
- Sets the environment that will be used with this scenario.
+ Sets the fallback environment to be used by this scenario. The fallback environment is used if no environment is set. Internally, this is used by the editor to provide a default environment.
</description>
</method>
- <method name="scenario_set_fallback_environment">
+ <method name="screen_space_roughness_limiter_set_active">
<return type="void">
</return>
- <argument index="0" name="scenario" type="RID">
+ <argument index="0" name="enable" type="bool">
</argument>
- <argument index="1" name="environment" type="RID">
+ <argument index="1" name="amount" type="float">
+ </argument>
+ <argument index="2" name="limit" type="float">
</argument>
<description>
- Sets the fallback environment to be used by this scenario. The fallback environment is used if no environment is set. Internally, this is used by the editor to provide a default environment.
</description>
</method>
<method name="set_boot_image">
@@ -2528,7 +3657,7 @@
</return>
<argument index="0" name="shader" type="RID">
</argument>
- <argument index="1" name="name" type="StringName">
+ <argument index="1" name="param" type="StringName">
</argument>
<description>
Returns a default texture from a shader searched by name.
@@ -2537,15 +3666,15 @@
<method name="shader_get_param_default" qualifiers="const">
<return type="Variant">
</return>
- <argument index="0" name="material" type="RID">
+ <argument index="0" name="shader" type="RID">
</argument>
- <argument index="1" name="parameter" type="StringName">
+ <argument index="1" name="param" type="StringName">
</argument>
<description>
</description>
</method>
<method name="shader_get_param_list" qualifiers="const">
- <return type="Array">
+ <return type="Dictionary[]">
</return>
<argument index="0" name="shader" type="RID">
</argument>
@@ -2553,28 +3682,25 @@
Returns the parameters of a shader.
</description>
</method>
- <method name="shader_set_code">
+ <method name="shader_set_default_texture_param">
<return type="void">
</return>
<argument index="0" name="shader" type="RID">
</argument>
- <argument index="1" name="code" type="String">
+ <argument index="1" name="param" type="StringName">
+ </argument>
+ <argument index="2" name="texture" type="RID">
</argument>
<description>
- Sets a shader's code.
+ Sets a shader's default texture. Overwrites the texture given by name.
</description>
</method>
- <method name="shader_set_default_texture_param">
+ <method name="shadows_quality_set">
<return type="void">
</return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="name" type="StringName">
- </argument>
- <argument index="2" name="texture" type="RID">
+ <argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality">
</argument>
<description>
- Sets a shader's default texture. Overwrites the texture given by name.
</description>
</method>
<method name="skeleton_allocate_data">
@@ -2654,6 +3780,30 @@
Returns the number of bones allocated for this skeleton.
</description>
</method>
+ <method name="skeleton_set_base_transform_2d">
+ <return type="void">
+ </return>
+ <argument index="0" name="skeleton" type="RID">
+ </argument>
+ <argument index="1" name="base_transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="sky_bake_panorama">
+ <return type="Image">
+ </return>
+ <argument index="0" name="sky" type="RID">
+ </argument>
+ <argument index="1" name="energy" type="float">
+ </argument>
+ <argument index="2" name="bake_irradiance" type="bool">
+ </argument>
+ <argument index="3" name="size" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="sky_create">
<return type="RID">
</return>
@@ -2673,6 +3823,26 @@
Sets the material that the sky uses to render the background and reflection maps.
</description>
</method>
+ <method name="sky_set_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="sky" type="RID">
+ </argument>
+ <argument index="1" name="mode" type="int" enum="RenderingServer.SkyMode">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="sky_set_radiance_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="sky" type="RID">
+ </argument>
+ <argument index="1" name="radiance_size" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="spot_light_create">
<return type="RID">
</return>
@@ -2682,6 +3852,24 @@
To place in a scene, attach this spot light to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
+ <method name="sub_surface_scattering_set_quality">
+ <return type="void">
+ </return>
+ <argument index="0" name="quality" type="int" enum="RenderingServer.SubSurfaceScatteringQuality">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="sub_surface_scattering_set_scale">
+ <return type="void">
+ </return>
+ <argument index="0" name="scale" type="float">
+ </argument>
+ <argument index="1" name="depth_scale" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="texture_2d_create">
<return type="RID">
</return>
@@ -2698,6 +3886,162 @@
<description>
</description>
</method>
+ <method name="texture_2d_layer_get" qualifiers="const">
+ <return type="Image">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="layer" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_2d_layered_create">
+ <return type="RID">
+ </return>
+ <argument index="0" name="layers" type="Image[]">
+ </argument>
+ <argument index="1" name="layered_type" type="int" enum="RenderingServer.TextureLayeredType">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_2d_layered_placeholder_create">
+ <return type="RID">
+ </return>
+ <argument index="0" name="layered_type" type="int" enum="RenderingServer.TextureLayeredType">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_2d_placeholder_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="texture_2d_update">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="image" type="Image">
+ </argument>
+ <argument index="2" name="layer" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_3d_create">
+ <return type="RID">
+ </return>
+ <argument index="0" name="format" type="int" enum="Image.Format">
+ </argument>
+ <argument index="1" name="width" type="int">
+ </argument>
+ <argument index="2" name="height" type="int">
+ </argument>
+ <argument index="3" name="depth" type="int">
+ </argument>
+ <argument index="4" name="mipmaps" type="bool">
+ </argument>
+ <argument index="5" name="data" type="Image[]">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_3d_get" qualifiers="const">
+ <return type="Image[]">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_3d_placeholder_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="texture_3d_update">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="data" type="Image[]">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_get_path" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_proxy_create">
+ <return type="RID">
+ </return>
+ <argument index="0" name="base" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_proxy_update">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="proxy_to" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_replace">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="by_texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_set_force_redraw_if_visible">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_set_path">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_set_size_override">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="width" type="int">
+ </argument>
+ <argument index="2" name="height" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="viewport_attach_camera">
<return type="void">
</return>
@@ -2772,10 +4116,11 @@
</return>
<argument index="0" name="viewport" type="RID">
</argument>
- <argument index="1" name="info" type="int" enum="RenderingServer.ViewportRenderInfo">
+ <argument index="1" name="type" type="int" enum="RenderingServer.ViewportRenderInfoType">
+ </argument>
+ <argument index="2" name="info" type="int" enum="RenderingServer.ViewportRenderInfo">
</argument>
<description>
- Returns a viewport's render information. For options, see the [enum ViewportRenderInfo] constants.
</description>
</method>
<method name="viewport_get_texture" qualifiers="const">
@@ -2860,48 +4205,67 @@
Sets the debug draw mode of a viewport. See [enum ViewportDebugDraw] for options.
</description>
</method>
- <method name="viewport_set_disable_environment">
+ <method name="viewport_set_default_canvas_item_texture_filter">
<return type="void">
</return>
<argument index="0" name="viewport" type="RID">
</argument>
- <argument index="1" name="disabled" type="bool">
+ <argument index="1" name="filter" type="int" enum="RenderingServer.CanvasItemTextureFilter">
</argument>
<description>
- If [code]true[/code], rendering of a viewport's environment is disabled.
</description>
</method>
- <method name="viewport_set_global_canvas_transform">
+ <method name="viewport_set_default_canvas_item_texture_repeat">
<return type="void">
</return>
<argument index="0" name="viewport" type="RID">
</argument>
- <argument index="1" name="transform" type="Transform2D">
+ <argument index="1" name="repeat" type="int" enum="RenderingServer.CanvasItemTextureRepeat">
</argument>
<description>
- Sets the viewport's global transformation matrix.
</description>
</method>
- <method name="viewport_set_hide_canvas">
+ <method name="viewport_set_disable_2d">
<return type="void">
</return>
<argument index="0" name="viewport" type="RID">
</argument>
- <argument index="1" name="hidden" type="bool">
+ <argument index="1" name="disable" type="bool">
</argument>
<description>
If [code]true[/code], the viewport's canvas is not rendered.
</description>
</method>
- <method name="viewport_set_hide_scenario">
+ <method name="viewport_set_disable_3d">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="disable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_disable_environment">
<return type="void">
</return>
<argument index="0" name="viewport" type="RID">
</argument>
- <argument index="1" name="hidden" type="bool">
+ <argument index="1" name="disabled" type="bool">
</argument>
<description>
- Currently unimplemented in Godot 3.x.
+ If [code]true[/code], rendering of a viewport's environment is disabled.
+ </description>
+ </method>
+ <method name="viewport_set_global_canvas_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ Sets the viewport's global transformation matrix.
</description>
</method>
<method name="viewport_set_measure_render_time">
@@ -2972,7 +4336,29 @@
</argument>
<description>
Sets a viewport's scenario.
- The scenario contains information about the [enum ScenarioDebugMode], environment information, reflection atlas etc.
+ The scenario contains information about environment information, reflection atlas etc.
+ </description>
+ </method>
+ <method name="viewport_set_screen_space_aa">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="mode" type="int" enum="RenderingServer.ViewportScreenSpaceAA">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_sdf_oversize_and_scale">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="oversize" type="int" enum="RenderingServer.ViewportSDFOversize">
+ </argument>
+ <argument index="2" name="scale" type="int" enum="RenderingServer.ViewportSDFScale">
+ </argument>
+ <description>
</description>
</method>
<method name="viewport_set_shadow_atlas_quadrant_subdivision">
@@ -3014,6 +4400,26 @@
Sets the viewport's width and height.
</description>
</method>
+ <method name="viewport_set_snap_2d_transforms_to_pixel">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_snap_2d_vertices_to_pixel">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="viewport_set_transparent_background">
<return type="void">
</return>
@@ -3067,6 +4473,188 @@
If [code]true[/code], the viewport uses augmented or virtual reality technologies. See [XRInterface].
</description>
</method>
+ <method name="visibility_notifier_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="visibility_notifier_set_aabb">
+ <return type="void">
+ </return>
+ <argument index="0" name="notifier" type="RID">
+ </argument>
+ <argument index="1" name="aabb" type="AABB">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="visibility_notifier_set_callbacks">
+ <return type="void">
+ </return>
+ <argument index="0" name="notifier" type="RID">
+ </argument>
+ <argument index="1" name="enter_callable" type="Callable">
+ </argument>
+ <argument index="2" name="exit_callable" type="Callable">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_allocate_data">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="to_cell_xform" type="Transform3D">
+ </argument>
+ <argument index="2" name="aabb" type="AABB">
+ </argument>
+ <argument index="3" name="octree_size" type="Vector3i">
+ </argument>
+ <argument index="4" name="octree_cells" type="PackedByteArray">
+ </argument>
+ <argument index="5" name="data_cells" type="PackedByteArray">
+ </argument>
+ <argument index="6" name="distance_field" type="PackedByteArray">
+ </argument>
+ <argument index="7" name="level_counts" type="PackedInt32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_get_data_cells" qualifiers="const">
+ <return type="PackedByteArray">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_get_distance_field" qualifiers="const">
+ <return type="PackedByteArray">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_get_level_counts" qualifiers="const">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_get_octree_cells" qualifiers="const">
+ <return type="PackedByteArray">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_get_octree_size" qualifiers="const">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_get_to_cell_xform" qualifiers="const">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_bias">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="bias" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_dynamic_range">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="range" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_energy">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="energy" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_interior">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_normal_bias">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="bias" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_propagation">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="amount" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_quality">
+ <return type="void">
+ </return>
+ <argument index="0" name="quality" type="int" enum="RenderingServer.VoxelGIQuality">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="voxel_gi_set_use_two_bounces">
+ <return type="void">
+ </return>
+ <argument index="0" name="voxel_gi" type="RID">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="render_loop_enabled" type="bool" setter="set_render_loop_enabled" getter="is_render_loop_enabled">
@@ -3104,6 +4692,8 @@
<constant name="MAX_CURSORS" value="8">
Unused enum in Godot 3.x.
</constant>
+ <constant name="MAX_2D_DIRECTIONAL_LIGHTS" value="8">
+ </constant>
<constant name="TEXTURE_LAYERED_2D_ARRAY" value="0" enum="TextureLayeredType">
</constant>
<constant name="TEXTURE_LAYERED_CUBEMAP" value="1" enum="TextureLayeredType">
@@ -3181,6 +4771,26 @@
<constant name="ARRAY_MAX" value="13" enum="ArrayType">
Represents the size of the [enum ArrayType] enum.
</constant>
+ <constant name="ARRAY_CUSTOM_COUNT" value="4">
+ </constant>
+ <constant name="ARRAY_CUSTOM_RGBA8_UNORM" value="0" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_RGBA8_SNORM" value="1" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_RG_HALF" value="2" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_RGBA_HALF" value="3" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_R_FLOAT" value="4" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_RG_FLOAT" value="5" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_RGB_FLOAT" value="6" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_RGBA_FLOAT" value="7" enum="ArrayCustomFormat">
+ </constant>
+ <constant name="ARRAY_CUSTOM_MAX" value="8" enum="ArrayCustomFormat">
+ </constant>
<constant name="ARRAY_FORMAT_VERTEX" value="1" enum="ArrayFormat">
Flag used to mark a vertex array.
</constant>
@@ -3220,6 +4830,8 @@
</constant>
<constant name="ARRAY_FORMAT_CUSTOM_BASE" value="13" enum="ArrayFormat">
</constant>
+ <constant name="ARRAY_FORMAT_CUSTOM_BITS" value="3" enum="ArrayFormat">
+ </constant>
<constant name="ARRAY_FORMAT_CUSTOM0_SHIFT" value="13" enum="ArrayFormat">
</constant>
<constant name="ARRAY_FORMAT_CUSTOM1_SHIFT" value="16" enum="ArrayFormat">
@@ -3269,6 +4881,16 @@
<constant name="MULTIMESH_TRANSFORM_3D" value="1" enum="MultimeshTransformFormat">
Use [Transform3D] to store MultiMesh transform.
</constant>
+ <constant name="LIGHT_PROJECTOR_FILTER_NEAREST" value="0" enum="LightProjectorFilter">
+ </constant>
+ <constant name="LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS" value="1" enum="LightProjectorFilter">
+ </constant>
+ <constant name="LIGHT_PROJECTOR_FILTER_LINEAR" value="2" enum="LightProjectorFilter">
+ </constant>
+ <constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS" value="3" enum="LightProjectorFilter">
+ </constant>
+ <constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="4" enum="LightProjectorFilter">
+ </constant>
<constant name="LIGHT_DIRECTIONAL" value="0" enum="LightType">
Is a directional (sun) light.
</constant>
@@ -3328,6 +4950,8 @@
<constant name="LIGHT_PARAM_SHADOW_BLUR" value="16" enum="LightParam">
Blurs the edges of the shadow. Can be used to hide pixel artifacts in low resolution shadow maps. A high value can make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible.
</constant>
+ <constant name="LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="17" enum="LightParam">
+ </constant>
<constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="18" enum="LightParam">
</constant>
<constant name="LIGHT_PARAM_MAX" value="19" enum="LightParam">
@@ -3354,11 +4978,17 @@
<constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS" value="2" enum="LightDirectionalShadowMode">
Use 4 splits for shadow projection when using directional light.
</constant>
- <constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE" value="0" enum="LightDirectionalShadowDepthRangeMode">
- Keeps shadows stable as camera moves but has lower effective resolution.
+ <constant name="SHADOW_QUALITY_HARD" value="0" enum="ShadowQuality">
+ </constant>
+ <constant name="SHADOW_QUALITY_SOFT_LOW" value="1" enum="ShadowQuality">
+ </constant>
+ <constant name="SHADOW_QUALITY_SOFT_MEDIUM" value="2" enum="ShadowQuality">
</constant>
- <constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED" value="1" enum="LightDirectionalShadowDepthRangeMode">
- Optimize use of shadow maps, increasing the effective resolution. But may result in shadows moving or flickering slightly.
+ <constant name="SHADOW_QUALITY_SOFT_HIGH" value="3" enum="ShadowQuality">
+ </constant>
+ <constant name="SHADOW_QUALITY_SOFT_ULTRA" value="4" enum="ShadowQuality">
+ </constant>
+ <constant name="SHADOW_QUALITY_MAX" value="5" enum="ShadowQuality">
</constant>
<constant name="REFLECTION_PROBE_UPDATE_ONCE" value="0" enum="ReflectionProbeUpdateMode">
Reflection probe will update reflections once and then stop.
@@ -3382,15 +5012,81 @@
</constant>
<constant name="DECAL_TEXTURE_MAX" value="4" enum="DecalTexture">
</constant>
+ <constant name="DECAL_FILTER_NEAREST" value="0" enum="DecalFilter">
+ </constant>
+ <constant name="DECAL_FILTER_NEAREST_MIPMAPS" value="1" enum="DecalFilter">
+ </constant>
+ <constant name="DECAL_FILTER_LINEAR" value="2" enum="DecalFilter">
+ </constant>
+ <constant name="DECAL_FILTER_LINEAR_MIPMAPS" value="3" enum="DecalFilter">
+ </constant>
+ <constant name="DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="4" enum="DecalFilter">
+ </constant>
+ <constant name="VOXEL_GI_QUALITY_LOW" value="0" enum="VoxelGIQuality">
+ </constant>
+ <constant name="VOXEL_GI_QUALITY_HIGH" value="1" enum="VoxelGIQuality">
+ </constant>
+ <constant name="PARTICLES_MODE_2D" value="0" enum="ParticlesMode">
+ </constant>
+ <constant name="PARTICLES_MODE_3D" value="1" enum="ParticlesMode">
+ </constant>
+ <constant name="PARTICLES_TRANSFORM_ALIGN_DISABLED" value="0" enum="ParticlesTransformAlign">
+ </constant>
+ <constant name="PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD" value="1" enum="ParticlesTransformAlign">
+ </constant>
+ <constant name="PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY" value="2" enum="ParticlesTransformAlign">
+ </constant>
+ <constant name="PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY" value="3" enum="ParticlesTransformAlign">
+ </constant>
+ <constant name="PARTICLES_EMIT_FLAG_POSITION" value="1">
+ </constant>
+ <constant name="PARTICLES_EMIT_FLAG_ROTATION_SCALE" value="2">
+ </constant>
+ <constant name="PARTICLES_EMIT_FLAG_VELOCITY" value="4">
+ </constant>
+ <constant name="PARTICLES_EMIT_FLAG_COLOR" value="8">
+ </constant>
+ <constant name="PARTICLES_EMIT_FLAG_CUSTOM" value="16">
+ </constant>
<constant name="PARTICLES_DRAW_ORDER_INDEX" value="0" enum="ParticlesDrawOrder">
Draw particles in the order that they appear in the particles array.
</constant>
<constant name="PARTICLES_DRAW_ORDER_LIFETIME" value="1" enum="ParticlesDrawOrder">
Sort particles based on their lifetime.
</constant>
+ <constant name="PARTICLES_DRAW_ORDER_REVERSE_LIFETIME" value="2" enum="ParticlesDrawOrder">
+ </constant>
<constant name="PARTICLES_DRAW_ORDER_VIEW_DEPTH" value="3" enum="ParticlesDrawOrder">
Sort particles based on their distance to the camera.
</constant>
+ <constant name="PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT" value="0" enum="ParticlesCollisionType">
+ </constant>
+ <constant name="PARTICLES_COLLISION_TYPE_BOX_ATTRACT" value="1" enum="ParticlesCollisionType">
+ </constant>
+ <constant name="PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT" value="2" enum="ParticlesCollisionType">
+ </constant>
+ <constant name="PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE" value="3" enum="ParticlesCollisionType">
+ </constant>
+ <constant name="PARTICLES_COLLISION_TYPE_BOX_COLLIDE" value="4" enum="ParticlesCollisionType">
+ </constant>
+ <constant name="PARTICLES_COLLISION_TYPE_SDF_COLLIDE" value="5" enum="ParticlesCollisionType">
+ </constant>
+ <constant name="PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE" value="6" enum="ParticlesCollisionType">
+ </constant>
+ <constant name="PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_256" value="0" enum="ParticlesCollisionHeightfieldResolution">
+ </constant>
+ <constant name="PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_512" value="1" enum="ParticlesCollisionHeightfieldResolution">
+ </constant>
+ <constant name="PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024" value="2" enum="ParticlesCollisionHeightfieldResolution">
+ </constant>
+ <constant name="PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_2048" value="3" enum="ParticlesCollisionHeightfieldResolution">
+ </constant>
+ <constant name="PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_4096" value="4" enum="ParticlesCollisionHeightfieldResolution">
+ </constant>
+ <constant name="PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_8192" value="5" enum="ParticlesCollisionHeightfieldResolution">
+ </constant>
+ <constant name="PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX" value="6" enum="ParticlesCollisionHeightfieldResolution">
+ </constant>
<constant name="VIEWPORT_UPDATE_DISABLED" value="0" enum="ViewportUpdateMode">
Do not update the viewport.
</constant>
@@ -3414,6 +5110,24 @@
<constant name="VIEWPORT_CLEAR_ONLY_NEXT_FRAME" value="2" enum="ViewportClearMode">
The viewport is cleared once, then the clear mode is set to [constant VIEWPORT_CLEAR_NEVER].
</constant>
+ <constant name="VIEWPORT_SDF_OVERSIZE_100_PERCENT" value="0" enum="ViewportSDFOversize">
+ </constant>
+ <constant name="VIEWPORT_SDF_OVERSIZE_120_PERCENT" value="1" enum="ViewportSDFOversize">
+ </constant>
+ <constant name="VIEWPORT_SDF_OVERSIZE_150_PERCENT" value="2" enum="ViewportSDFOversize">
+ </constant>
+ <constant name="VIEWPORT_SDF_OVERSIZE_200_PERCENT" value="3" enum="ViewportSDFOversize">
+ </constant>
+ <constant name="VIEWPORT_SDF_OVERSIZE_MAX" value="4" enum="ViewportSDFOversize">
+ </constant>
+ <constant name="VIEWPORT_SDF_SCALE_100_PERCENT" value="0" enum="ViewportSDFScale">
+ </constant>
+ <constant name="VIEWPORT_SDF_SCALE_50_PERCENT" value="1" enum="ViewportSDFScale">
+ </constant>
+ <constant name="VIEWPORT_SDF_SCALE_25_PERCENT" value="2" enum="ViewportSDFScale">
+ </constant>
+ <constant name="VIEWPORT_SDF_SCALE_MAX" value="3" enum="ViewportSDFScale">
+ </constant>
<constant name="VIEWPORT_MSAA_DISABLED" value="0" enum="ViewportMSAA">
Multisample antialiasing is disabled.
</constant>
@@ -3437,26 +5151,29 @@
</constant>
<constant name="VIEWPORT_SCREEN_SPACE_AA_MAX" value="2" enum="ViewportScreenSpaceAA">
</constant>
+ <constant name="VIEWPORT_OCCLUSION_BUILD_QUALITY_LOW" value="0" enum="ViewportOcclusionCullingBuildQuality">
+ </constant>
+ <constant name="VIEWPORT_OCCLUSION_BUILD_QUALITY_MEDIUM" value="1" enum="ViewportOcclusionCullingBuildQuality">
+ </constant>
+ <constant name="VIEWPORT_OCCLUSION_BUILD_QUALITY_HIGH" value="2" enum="ViewportOcclusionCullingBuildQuality">
+ </constant>
<constant name="VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME" value="0" enum="ViewportRenderInfo">
Number of objects drawn in a single frame.
</constant>
- <constant name="VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME" value="1" enum="ViewportRenderInfo">
+ <constant name="VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME" value="1" enum="ViewportRenderInfo">
Number of vertices drawn in a single frame.
</constant>
- <constant name="VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="ViewportRenderInfo">
- Number of material changes during this frame.
+ <constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="2" enum="ViewportRenderInfo">
+ Number of draw calls during this frame.
</constant>
- <constant name="VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME" value="3" enum="ViewportRenderInfo">
- Number of shader changes during this frame.
+ <constant name="VIEWPORT_RENDER_INFO_MAX" value="3" enum="ViewportRenderInfo">
+ Represents the size of the [enum ViewportRenderInfo] enum.
</constant>
- <constant name="VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME" value="4" enum="ViewportRenderInfo">
- Number of surface changes during this frame.
+ <constant name="VIEWPORT_RENDER_INFO_TYPE_VISIBLE" value="0" enum="ViewportRenderInfoType">
</constant>
- <constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="ViewportRenderInfo">
- Number of draw calls during this frame.
+ <constant name="VIEWPORT_RENDER_INFO_TYPE_SHADOW" value="1" enum="ViewportRenderInfoType">
</constant>
- <constant name="VIEWPORT_RENDER_INFO_MAX" value="6" enum="ViewportRenderInfo">
- Represents the size of the [enum ViewportRenderInfo] enum.
+ <constant name="VIEWPORT_RENDER_INFO_TYPE_MAX" value="2" enum="ViewportRenderInfoType">
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_DISABLED" value="0" enum="ViewportDebugDraw">
Debug draw is disabled. Default setting.
@@ -3508,11 +5225,25 @@
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_GI_BUFFER" value="17" enum="ViewportDebugDraw">
</constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_DISABLE_LOD" value="18" enum="ViewportDebugDraw">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS" value="19" enum="ViewportDebugDraw">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS" value="20" enum="ViewportDebugDraw">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS" value="21" enum="ViewportDebugDraw">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES" value="22" enum="ViewportDebugDraw">
+ </constant>
<constant name="VIEWPORT_DEBUG_DRAW_OCCLUDERS" value="23" enum="ViewportDebugDraw">
</constant>
+ <constant name="SKY_MODE_AUTOMATIC" value="0" enum="SkyMode">
+ </constant>
<constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode">
Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant Sky.PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/reflections/sky_reflections/ggx_samples].
</constant>
+ <constant name="SKY_MODE_INCREMENTAL" value="2" enum="SkyMode">
+ </constant>
<constant name="SKY_MODE_REALTIME" value="3" enum="SkyMode">
Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times.
[b]Note:[/b] The fast filtering algorithm is limited to 256x256 cubemaps, so [member Sky.radiance_size] must be set to [constant Sky.RADIANCE_SIZE_256].
@@ -3609,64 +5340,88 @@
<constant name="ENV_SSAO_QUALITY_ULTRA" value="4" enum="EnvironmentSSAOQuality">
Highest quality screen space ambient occlusion. Uses the adaptive setting which can be dynamically adjusted to smoothly balance performance and visual quality.
</constant>
- <constant name="SUB_SURFACE_SCATTERING_QUALITY_DISABLED" value="0" enum="SubSurfaceScatteringQuality">
+ <constant name="ENV_SDFGI_CASCADES_4" value="0" enum="EnvironmentSDFGICascades">
</constant>
- <constant name="SUB_SURFACE_SCATTERING_QUALITY_LOW" value="1" enum="SubSurfaceScatteringQuality">
+ <constant name="ENV_SDFGI_CASCADES_6" value="1" enum="EnvironmentSDFGICascades">
</constant>
- <constant name="SUB_SURFACE_SCATTERING_QUALITY_MEDIUM" value="2" enum="SubSurfaceScatteringQuality">
+ <constant name="ENV_SDFGI_CASCADES_8" value="2" enum="EnvironmentSDFGICascades">
</constant>
- <constant name="SUB_SURFACE_SCATTERING_QUALITY_HIGH" value="3" enum="SubSurfaceScatteringQuality">
+ <constant name="ENV_SDFGI_Y_SCALE_DISABLED" value="0" enum="EnvironmentSDFGIYScale">
</constant>
- <constant name="DOF_BLUR_QUALITY_VERY_LOW" value="0" enum="DOFBlurQuality">
- Lowest quality DOF blur. This is the fastest setting, but you may be able to see filtering artifacts.
+ <constant name="ENV_SDFGI_Y_SCALE_75_PERCENT" value="1" enum="EnvironmentSDFGIYScale">
</constant>
- <constant name="DOF_BLUR_QUALITY_LOW" value="1" enum="DOFBlurQuality">
- Low quality DOF blur.
+ <constant name="ENV_SDFGI_Y_SCALE_50_PERCENT" value="2" enum="EnvironmentSDFGIYScale">
</constant>
- <constant name="DOF_BLUR_QUALITY_MEDIUM" value="2" enum="DOFBlurQuality">
- Medium quality DOF blur.
+ <constant name="ENV_SDFGI_RAY_COUNT_4" value="0" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="DOF_BLUR_QUALITY_HIGH" value="3" enum="DOFBlurQuality">
- Highest quality DOF blur. Results in the smoothest looking blur by taking the most samples, but is also significantly slower.
+ <constant name="ENV_SDFGI_RAY_COUNT_8" value="1" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="DOF_BOKEH_BOX" value="0" enum="DOFBokehShape">
- Calculate the DOF blur using a box filter. The fastest option, but results in obvious lines in blur pattern.
+ <constant name="ENV_SDFGI_RAY_COUNT_16" value="2" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="DOF_BOKEH_HEXAGON" value="1" enum="DOFBokehShape">
- Calculates DOF blur using a hexagon shaped filter.
+ <constant name="ENV_SDFGI_RAY_COUNT_32" value="3" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="DOF_BOKEH_CIRCLE" value="2" enum="DOFBokehShape">
- Calculates DOF blur using a circle shaped filter. Best quality and most realistic, but slowest. Use only for areas where a lot of performance can be dedicated to post-processing (e.g. cutscenes).
+ <constant name="ENV_SDFGI_RAY_COUNT_64" value="4" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="SHADOW_QUALITY_HARD" value="0" enum="ShadowQuality">
+ <constant name="ENV_SDFGI_RAY_COUNT_96" value="5" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="SHADOW_QUALITY_SOFT_LOW" value="1" enum="ShadowQuality">
+ <constant name="ENV_SDFGI_RAY_COUNT_128" value="6" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="SHADOW_QUALITY_SOFT_MEDIUM" value="2" enum="ShadowQuality">
+ <constant name="ENV_SDFGI_RAY_COUNT_MAX" value="7" enum="EnvironmentSDFGIRayCount">
</constant>
- <constant name="SHADOW_QUALITY_SOFT_HIGH" value="3" enum="ShadowQuality">
+ <constant name="ENV_SDFGI_CONVERGE_IN_5_FRAMES" value="0" enum="EnvironmentSDFGIFramesToConverge">
</constant>
- <constant name="SHADOW_QUALITY_SOFT_ULTRA" value="4" enum="ShadowQuality">
+ <constant name="ENV_SDFGI_CONVERGE_IN_10_FRAMES" value="1" enum="EnvironmentSDFGIFramesToConverge">
</constant>
- <constant name="SHADOW_QUALITY_MAX" value="5" enum="ShadowQuality">
+ <constant name="ENV_SDFGI_CONVERGE_IN_15_FRAMES" value="2" enum="EnvironmentSDFGIFramesToConverge">
</constant>
- <constant name="SCENARIO_DEBUG_DISABLED" value="0" enum="ScenarioDebugMode">
- Do not use a debug mode.
+ <constant name="ENV_SDFGI_CONVERGE_IN_20_FRAMES" value="3" enum="EnvironmentSDFGIFramesToConverge">
</constant>
- <constant name="SCENARIO_DEBUG_WIREFRAME" value="1" enum="ScenarioDebugMode">
- Draw all objects as wireframe models.
+ <constant name="ENV_SDFGI_CONVERGE_IN_25_FRAMES" value="4" enum="EnvironmentSDFGIFramesToConverge">
</constant>
- <constant name="SCENARIO_DEBUG_OVERDRAW" value="2" enum="ScenarioDebugMode">
- Draw all objects in a way that displays how much overdraw is occurring. Overdraw occurs when a section of pixels is drawn and shaded and then another object covers it up. To optimize a scene, you should reduce overdraw.
+ <constant name="ENV_SDFGI_CONVERGE_IN_30_FRAMES" value="5" enum="EnvironmentSDFGIFramesToConverge">
</constant>
- <constant name="SCENARIO_DEBUG_SHADELESS" value="3" enum="ScenarioDebugMode">
- Draw all objects without shading. Equivalent to setting all objects shaders to [code]unshaded[/code].
+ <constant name="ENV_SDFGI_CONVERGE_MAX" value="6" enum="EnvironmentSDFGIFramesToConverge">
</constant>
- <constant name="VIEWPORT_OCCLUSION_BUILD_QUALITY_LOW" value="0" enum="ViewportOcclusionCullingBuildQuality">
+ <constant name="ENV_SDFGI_UPDATE_LIGHT_IN_1_FRAME" value="0" enum="EnvironmentSDFGIFramesToUpdateLight">
</constant>
- <constant name="VIEWPORT_OCCLUSION_BUILD_QUALITY_MEDIUM" value="1" enum="ViewportOcclusionCullingBuildQuality">
+ <constant name="ENV_SDFGI_UPDATE_LIGHT_IN_2_FRAMES" value="1" enum="EnvironmentSDFGIFramesToUpdateLight">
</constant>
- <constant name="VIEWPORT_OCCLUSION_BUILD_QUALITY_HIGH" value="2" enum="ViewportOcclusionCullingBuildQuality">
+ <constant name="ENV_SDFGI_UPDATE_LIGHT_IN_4_FRAMES" value="2" enum="EnvironmentSDFGIFramesToUpdateLight">
+ </constant>
+ <constant name="ENV_SDFGI_UPDATE_LIGHT_IN_8_FRAMES" value="3" enum="EnvironmentSDFGIFramesToUpdateLight">
+ </constant>
+ <constant name="ENV_SDFGI_UPDATE_LIGHT_IN_16_FRAMES" value="4" enum="EnvironmentSDFGIFramesToUpdateLight">
+ </constant>
+ <constant name="ENV_SDFGI_UPDATE_LIGHT_MAX" value="5" enum="EnvironmentSDFGIFramesToUpdateLight">
+ </constant>
+ <constant name="SUB_SURFACE_SCATTERING_QUALITY_DISABLED" value="0" enum="SubSurfaceScatteringQuality">
+ </constant>
+ <constant name="SUB_SURFACE_SCATTERING_QUALITY_LOW" value="1" enum="SubSurfaceScatteringQuality">
+ </constant>
+ <constant name="SUB_SURFACE_SCATTERING_QUALITY_MEDIUM" value="2" enum="SubSurfaceScatteringQuality">
+ </constant>
+ <constant name="SUB_SURFACE_SCATTERING_QUALITY_HIGH" value="3" enum="SubSurfaceScatteringQuality">
+ </constant>
+ <constant name="DOF_BOKEH_BOX" value="0" enum="DOFBokehShape">
+ Calculate the DOF blur using a box filter. The fastest option, but results in obvious lines in blur pattern.
+ </constant>
+ <constant name="DOF_BOKEH_HEXAGON" value="1" enum="DOFBokehShape">
+ Calculates DOF blur using a hexagon shaped filter.
+ </constant>
+ <constant name="DOF_BOKEH_CIRCLE" value="2" enum="DOFBokehShape">
+ Calculates DOF blur using a circle shaped filter. Best quality and most realistic, but slowest. Use only for areas where a lot of performance can be dedicated to post-processing (e.g. cutscenes).
+ </constant>
+ <constant name="DOF_BLUR_QUALITY_VERY_LOW" value="0" enum="DOFBlurQuality">
+ Lowest quality DOF blur. This is the fastest setting, but you may be able to see filtering artifacts.
+ </constant>
+ <constant name="DOF_BLUR_QUALITY_LOW" value="1" enum="DOFBlurQuality">
+ Low quality DOF blur.
+ </constant>
+ <constant name="DOF_BLUR_QUALITY_MEDIUM" value="2" enum="DOFBlurQuality">
+ Medium quality DOF blur.
+ </constant>
+ <constant name="DOF_BLUR_QUALITY_HIGH" value="3" enum="DOFBlurQuality">
+ Highest quality DOF blur. Results in the smoothest looking blur by taking the most samples, but is also significantly slower.
</constant>
<constant name="INSTANCE_NONE" value="0" enum="InstanceType">
The instance does not have a type.
@@ -3677,35 +5432,34 @@
<constant name="INSTANCE_MULTIMESH" value="2" enum="InstanceType">
The instance is a multimesh.
</constant>
- <constant name="INSTANCE_IMMEDIATE" value="3" enum="InstanceType">
- The instance is an immediate geometry.
- </constant>
- <constant name="INSTANCE_PARTICLES" value="4" enum="InstanceType">
+ <constant name="INSTANCE_PARTICLES" value="3" enum="InstanceType">
The instance is a particle emitter.
</constant>
- <constant name="INSTANCE_PARTICLES_COLLISION" value="5" enum="InstanceType">
+ <constant name="INSTANCE_PARTICLES_COLLISION" value="4" enum="InstanceType">
</constant>
- <constant name="INSTANCE_LIGHT" value="6" enum="InstanceType">
+ <constant name="INSTANCE_LIGHT" value="5" enum="InstanceType">
The instance is a light.
</constant>
- <constant name="INSTANCE_REFLECTION_PROBE" value="7" enum="InstanceType">
+ <constant name="INSTANCE_REFLECTION_PROBE" value="6" enum="InstanceType">
The instance is a reflection probe.
</constant>
- <constant name="INSTANCE_DECAL" value="8" enum="InstanceType">
+ <constant name="INSTANCE_DECAL" value="7" enum="InstanceType">
The instance is a decal.
</constant>
- <constant name="INSTANCE_VOXEL_GI" value="9" enum="InstanceType">
+ <constant name="INSTANCE_VOXEL_GI" value="8" enum="InstanceType">
The instance is a VoxelGI.
</constant>
- <constant name="INSTANCE_LIGHTMAP" value="10" enum="InstanceType">
+ <constant name="INSTANCE_LIGHTMAP" value="9" enum="InstanceType">
The instance is a lightmap.
</constant>
- <constant name="INSTANCE_OCCLUDER" value="11" enum="InstanceType">
+ <constant name="INSTANCE_OCCLUDER" value="10" enum="InstanceType">
</constant>
- <constant name="INSTANCE_MAX" value="13" enum="InstanceType">
+ <constant name="INSTANCE_VISIBLITY_NOTIFIER" value="11" enum="InstanceType">
+ </constant>
+ <constant name="INSTANCE_MAX" value="12" enum="InstanceType">
Represents the size of the [enum InstanceType] enum.
</constant>
- <constant name="INSTANCE_GEOMETRY_MASK" value="30" enum="InstanceType">
+ <constant name="INSTANCE_GEOMETRY_MASK" value="14" enum="InstanceType">
A combination of the flags of geometry instances (mesh, multimesh, immediate and particles).
</constant>
<constant name="INSTANCE_FLAG_USE_BAKED_LIGHT" value="0" enum="InstanceFlags">
@@ -3734,6 +5488,20 @@
<constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3" enum="ShadowCastingSetting">
Only render the shadows from the object. The object itself will not be drawn.
</constant>
+ <constant name="BAKE_CHANNEL_ALBEDO_ALPHA" value="0" enum="BakeChannels">
+ </constant>
+ <constant name="BAKE_CHANNEL_NORMAL" value="1" enum="BakeChannels">
+ </constant>
+ <constant name="BAKE_CHANNEL_ORM" value="2" enum="BakeChannels">
+ </constant>
+ <constant name="BAKE_CHANNEL_EMISSION" value="3" enum="BakeChannels">
+ </constant>
+ <constant name="CANVAS_TEXTURE_CHANNEL_DIFFUSE" value="0" enum="CanvasTextureChannel">
+ </constant>
+ <constant name="CANVAS_TEXTURE_CHANNEL_NORMAL" value="1" enum="CanvasTextureChannel">
+ </constant>
+ <constant name="CANVAS_TEXTURE_CHANNEL_SPECULAR" value="2" enum="CanvasTextureChannel">
+ </constant>
<constant name="NINE_PATCH_STRETCH" value="0" enum="NinePatchAxisMode">
The nine patch gets stretched where needed.
</constant>
@@ -3880,35 +5648,17 @@
</constant>
<constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalVariableType">
</constant>
- <constant name="INFO_OBJECTS_IN_FRAME" value="0" enum="RenderInfo">
- The amount of objects in the frame.
- </constant>
- <constant name="INFO_VERTICES_IN_FRAME" value="1" enum="RenderInfo">
- The amount of vertices in the frame.
- </constant>
- <constant name="INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="RenderInfo">
- The amount of modified materials in the frame.
- </constant>
- <constant name="INFO_SHADER_CHANGES_IN_FRAME" value="3" enum="RenderInfo">
- The amount of shader rebinds in the frame.
- </constant>
- <constant name="INFO_SURFACE_CHANGES_IN_FRAME" value="4" enum="RenderInfo">
- The amount of surface changes in the frame.
+ <constant name="RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME" value="0" enum="RenderingInfo">
</constant>
- <constant name="INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo">
- The amount of draw calls in frame.
+ <constant name="RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME" value="1" enum="RenderingInfo">
</constant>
- <constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="6" enum="RenderInfo">
- Unimplemented in the GLES2 rendering backend, always returns 0.
+ <constant name="RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME" value="2" enum="RenderingInfo">
</constant>
- <constant name="INFO_VIDEO_MEM_USED" value="7" enum="RenderInfo">
- The amount of video memory used, i.e. texture and vertex memory combined.
+ <constant name="RENDERING_INFO_TEXTURE_MEM_USED" value="3" enum="RenderingInfo">
</constant>
- <constant name="INFO_TEXTURE_MEM_USED" value="8" enum="RenderInfo">
- The amount of texture memory used.
+ <constant name="RENDERING_INFO_BUFFER_MEM_USED" value="4" enum="RenderingInfo">
</constant>
- <constant name="INFO_VERTEX_MEM_USED" value="9" enum="RenderInfo">
- The amount of vertex memory used.
+ <constant name="RENDERING_INFO_VIDEO_MEM_USED" value="5" enum="RenderingInfo">
</constant>
<constant name="FEATURE_SHADERS" value="0" enum="Features">
Hardware supports shaders. This enum is currently unused in Godot 3.x.
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index d327e8cbca..bf51b4dfa7 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -112,20 +112,6 @@
Returns the current frame number, i.e. the total frame count since the application started.
</description>
</method>
- <method name="get_network_connected_peers" qualifiers="const">
- <return type="PackedInt32Array">
- </return>
- <description>
- Returns the peer IDs of all connected peers of this [SceneTree]'s [member network_peer].
- </description>
- </method>
- <method name="get_network_unique_id" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the unique peer ID of this [SceneTree]'s [member network_peer].
- </description>
- </method>
<method name="get_node_count" qualifiers="const">
<return type="int">
</return>
@@ -149,13 +135,6 @@
Returns an array of currently exising [Tween]s in the [SceneTree] (both running and paused).
</description>
</method>
- <method name="get_rpc_sender_id" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the sender's peer ID for the most recently received RPC call.
- </description>
- </method>
<method name="has_group" qualifiers="const">
<return type="bool">
</return>
@@ -165,20 +144,6 @@
Returns [code]true[/code] if the given group exists.
</description>
</method>
- <method name="has_network_peer" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if there is a [member network_peer] set.
- </description>
- </method>
- <method name="is_network_server" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns [code]true[/code] if this [SceneTree]'s [member network_peer] is in server mode (listening for connections).
- </description>
- </method>
<method name="notify_group">
<return type="void">
</return>
@@ -301,32 +266,16 @@
If [code]true[/code] (default value), enables automatic polling of the [MultiplayerAPI] for this SceneTree during [signal process_frame].
If [code]false[/code], you need to manually call [method MultiplayerAPI.poll] to process network packets and deliver RPCs/RSETs. This allows running RPCs/RSETs in a different loop (e.g. physics, thread, specific time step) and for manual [Mutex] protection when accessing the [MultiplayerAPI] from threads.
</member>
- <member name="network_peer" type="NetworkedMultiplayerPeer" setter="set_network_peer" getter="get_network_peer">
- The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the [SceneTree] will become a network server (check with [method is_network_server]) and will set the root node's network mode to master, or it will become a regular peer with the root node set to puppet. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to [SceneTree]'s signals.
- </member>
<member name="paused" type="bool" setter="set_pause" getter="is_paused" default="false">
If [code]true[/code], the [SceneTree] is paused. Doing so will have the following behavior:
- 2D and 3D physics will be stopped.
- [method Node._process], [method Node._physics_process] and [method Node._input] will not be called anymore in nodes.
</member>
- <member name="refuse_new_network_connections" type="bool" setter="set_refuse_new_network_connections" getter="is_refusing_new_network_connections" default="false">
- If [code]true[/code], the [SceneTree]'s [member network_peer] refuses new incoming connections.
- </member>
<member name="root" type="Window" setter="" getter="get_root">
The [SceneTree]'s root [Window].
</member>
</members>
<signals>
- <signal name="connected_to_server">
- <description>
- Emitted whenever this [SceneTree]'s [member network_peer] successfully connected to a server. Only emitted on clients.
- </description>
- </signal>
- <signal name="connection_failed">
- <description>
- Emitted whenever this [SceneTree]'s [member network_peer] fails to establish a connection to a server. Only emitted on clients.
- </description>
- </signal>
<signal name="files_dropped">
<argument index="0" name="files" type="PackedStringArray">
</argument>
@@ -336,20 +285,6 @@
Emitted when files are dragged from the OS file manager and dropped in the game window. The arguments are a list of file paths and the identifier of the screen where the drag originated.
</description>
</signal>
- <signal name="network_peer_connected">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Emitted whenever this [SceneTree]'s [member network_peer] connects with a new peer. ID is the peer ID of the new peer. Clients get notified when other clients connect to the same server. Upon connecting to a server, a client also receives this signal for the server (with ID being 1).
- </description>
- </signal>
- <signal name="network_peer_disconnected">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Emitted whenever this [SceneTree]'s [member network_peer] disconnects from a peer. Clients get notified when other clients disconnect from the same server.
- </description>
- </signal>
<signal name="node_added">
<argument index="0" name="node" type="Node">
</argument>
@@ -388,11 +323,6 @@
Emitted immediately before [method Node._process] is called on every node in the [SceneTree].
</description>
</signal>
- <signal name="server_disconnected">
- <description>
- Emitted whenever this [SceneTree]'s [member network_peer] disconnected from server. Only emitted on clients.
- </description>
- </signal>
<signal name="tree_changed">
<description>
Emitted whenever the [SceneTree] hierarchy changed (children being moved or renamed, etc.).
diff --git a/doc/classes/SoftBody3D.xml b/doc/classes/SoftBody3D.xml
index 7999ad774d..b143c60d9d 100644
--- a/doc/classes/SoftBody3D.xml
+++ b/doc/classes/SoftBody3D.xml
@@ -93,6 +93,9 @@
</member>
<member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01">
</member>
+ <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftBody3D.DisableMode" default="0">
+ Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
+ </member>
<member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0">
</member>
<member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5">
@@ -113,5 +116,12 @@
</member>
</members>
<constants>
+ <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [SoftBody3D].
+ Automatically re-added to the physics simulation when the [Node] is processed again.
+ </constant>
+ <constant name="DISABLE_MODE_KEEP_ACTIVE" value="1" enum="DisableMode">
+ When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml
index f7f2ff0de1..ddb9d543e8 100644
--- a/doc/classes/Sprite3D.xml
+++ b/doc/classes/Sprite3D.xml
@@ -21,7 +21,6 @@
The number of columns in the sprite sheet.
</member>
<member name="region_enabled" type="bool" setter="set_region_enabled" getter="is_region_enabled" default="false">
- If [code]true[/code], texture will be cut from a larger atlas texture. See [member region_rect].
</member>
<member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2(0, 0, 0, 0)">
The region of the atlas texture to display. [member region_enabled] must be [code]true[/code].
@@ -39,11 +38,6 @@
Emitted when the [member frame] changes.
</description>
</signal>
- <signal name="texture_changed">
- <description>
- Emitted when the [member texture] changes.
- </description>
- </signal>
</signals>
<constants>
</constants>
diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml
index 85915a53fe..326bf58e22 100644
--- a/doc/classes/StaticBody2D.xml
+++ b/doc/classes/StaticBody2D.xml
@@ -29,6 +29,9 @@
The physics material override for the body.
If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
+ <member name="sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
+ If [code]true[/code] and [member kinematic_motion] is enabled, the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody2D.move_and_collide].
+ </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/StaticBody3D.xml b/doc/classes/StaticBody3D.xml
index f83d440f10..69c123002f 100644
--- a/doc/classes/StaticBody3D.xml
+++ b/doc/classes/StaticBody3D.xml
@@ -32,6 +32,9 @@
The physics material override for the body.
If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
+ <member name="sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
+ If [code]true[/code] and [member kinematic_motion] is enabled, the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody3D.move_and_collide].
+ </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml
index 22d1b52479..a8b836ff0c 100644
--- a/doc/classes/SurfaceTool.xml
+++ b/doc/classes/SurfaceTool.xml
@@ -24,7 +24,7 @@
The above [SurfaceTool] now contains one vertex of a triangle which has a UV coordinate and a specified [Color]. If another vertex were added without calling [method set_uv] or [method set_color], then the last values would be used.
Vertex attributes must be passed [b]before[/b] calling [method add_vertex]. Failure to do so will result in an error when committing the vertex information to a mesh.
Additionally, the attributes used before the first vertex is added determine the format of the mesh. For example, if you only add UVs to the first vertex, you cannot add color to any of the subsequent vertices.
- See also [ArrayMesh], [ImmediateGeometry3D] and [MeshDataTool] for procedural geometry generation.
+ See also [ArrayMesh], [ImmediateMesh] and [MeshDataTool] for procedural geometry generation.
[b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes.
</description>
<tutorials>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 6a3c124c60..e51bf42bdb 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -14,6 +14,7 @@
<return type="void">
</return>
<description>
+ A virtual method that is called whenever backspace is triggered.
</description>
</method>
<method name="add_gutter">
@@ -28,6 +29,7 @@
<return type="void">
</return>
<description>
+ Causes the [TextEdit] to perform a backspace.
</description>
</method>
<method name="center_viewport_to_cursor">
@@ -172,6 +174,7 @@
<argument index="0" name="line" type="int">
</argument>
<description>
+ Returns the indent level of a specific line.
</description>
</method>
<method name="get_line" qualifiers="const">
@@ -312,6 +315,7 @@
<return type="int">
</return>
<description>
+ Returns the [TextEdit]'s' tab size.
</description>
</method>
<method name="get_visible_line_count" qualifiers="const">
@@ -378,6 +382,13 @@
<description>
</description>
</method>
+ <method name="is_menu_visible" qualifiers="const">
+ <return type="bool">
+ </return>
+ <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="is_selection_active" qualifiers="const">
<return type="bool">
</return>
@@ -667,6 +678,7 @@
<argument index="0" name="size" type="int">
</argument>
<description>
+ Sets the tab size for the [TextEdit] to use.
</description>
</method>
<method name="undo">
@@ -846,9 +858,9 @@
</constant>
<constant name="GUTTER_TYPE_STRING" value="0" enum="GutterType">
</constant>
- <constant name="GUTTER_TPYE_ICON" value="1" enum="GutterType">
+ <constant name="GUTTER_TYPE_ICON" value="1" enum="GutterType">
</constant>
- <constant name="GUTTER_TPYE_CUSTOM" value="2" enum="GutterType">
+ <constant name="GUTTER_TYPE_CUSTOM" value="2" enum="GutterType">
</constant>
<constant name="MENU_CUT" value="0" enum="MenuItems">
Cuts (copies and clears) the selected text.
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index c943946ab3..0f9318fda1 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -1088,6 +1088,19 @@
Returns composite character end position closest to the [code]pos[/code].
</description>
</method>
+ <method name="shaped_text_overrun_trim_to_width">
+ <return type="void">
+ </return>
+ <argument index="0" name="shaped" type="RID">
+ </argument>
+ <argument index="1" name="width" type="float" default="0">
+ </argument>
+ <argument index="2" name="overrun_trim_flags" type="int" default="0">
+ </argument>
+ <description>
+ Trims text if it exceeds the given width.
+ </description>
+ </method>
<method name="shaped_text_prev_grapheme_pos">
<return type="int">
</return>
@@ -1260,6 +1273,21 @@
<constant name="BREAK_GRAPHEME_BOUND" value="64" enum="LineBreakFlag">
Break the line between any unconnected graphemes.
</constant>
+ <constant name="OVERRUN_NO_TRIMMING" value="0" enum="TextOverrunFlag">
+ No trimming is performed.
+ </constant>
+ <constant name="OVERRUN_TRIM" value="1" enum="TextOverrunFlag">
+ Trims the text when it exceeds the given width.
+ </constant>
+ <constant name="OVERRUN_TRIM_WORD_ONLY" value="2" enum="TextOverrunFlag">
+ Trims the text per word instead of per grapheme.
+ </constant>
+ <constant name="OVERRUN_ADD_ELLIPSIS" value="4" enum="TextOverrunFlag">
+ Determines whether an ellipsis should be added at the end of the text.
+ </constant>
+ <constant name="OVERRUN_ENFORCE_ELLIPSIS" value="8" enum="TextOverrunFlag">
+ Determines whether the ellipsis at the end of the text is enforced and may not be hidden.
+ </constant>
<constant name="GRAPHEME_IS_RTL" value="2" enum="GraphemeFlag">
Grapheme is part of right-to-left or bottom-to-top run.
</constant>
diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index 7448697df3..969d8ab2a4 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -97,6 +97,15 @@
Clears the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]theme_type[/code].
</description>
</method>
+ <method name="clear_type_variation">
+ <return type="void">
+ </return>
+ <argument index="0" name="theme_type" type="StringName">
+ </argument>
+ <description>
+ Unmarks [code]theme_type[/code] as being a variation of any other type.
+ </description>
+ </method>
<method name="copy_default_theme">
<return type="void">
</return>
@@ -319,6 +328,24 @@
Returns all the theme types as a [PackedStringArray] filled with unique type names, for use in other [code]get_*[/code] functions of this theme.
</description>
</method>
+ <method name="get_type_variation_base" qualifiers="const">
+ <return type="StringName">
+ </return>
+ <argument index="0" name="theme_type" type="StringName">
+ </argument>
+ <description>
+ Returns the base theme type if [code]theme_type[/code] is a valid variation type. Returns an empty string otherwise.
+ </description>
+ </method>
+ <method name="get_type_variation_list" qualifiers="const">
+ <return type="PackedStringArray">
+ </return>
+ <argument index="0" name="base_type" type="StringName">
+ </argument>
+ <description>
+ Returns a list of all variation for the given [code]base_type[/code].
+ </description>
+ </method>
<method name="has_color" qualifiers="const">
<return type="bool">
</return>
@@ -405,6 +432,17 @@
Returns [code]false[/code] if the theme does not have [code]theme_type[/code].
</description>
</method>
+ <method name="is_type_variation" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="theme_type" type="StringName">
+ </argument>
+ <argument index="1" name="base_type" type="StringName">
+ </argument>
+ <description>
+ Returns [code]true[/code] if [code]theme_type[/code] is marked as a variation of [code]base_type[/code] in this theme.
+ </description>
+ </method>
<method name="rename_color">
<return type="void">
</return>
@@ -599,6 +637,20 @@
Creates [code]theme_type[/code] if the theme does not have it.
</description>
</method>
+ <method name="set_type_variation">
+ <return type="void">
+ </return>
+ <argument index="0" name="theme_type" type="StringName">
+ </argument>
+ <argument index="1" name="base_type" type="StringName">
+ </argument>
+ <description>
+ Marks [code]theme_type[/code] as being a variation of [code]base_type[/code].
+ This adds [code]theme_type[/code] as a suggested option for [member Control.theme_type_variation] on a [Control] that is of the [code]base_type[/code] class.
+ Variations can also be nested, i.e. [code]base_type[/code] can be another variation. If a chain of variations ends with a [code]base_type[/code] matching a class of a [Control], the whole chain is going to be suggested as options.
+ Note: Suggestions only show up if this [Theme] is set as the project default theme. See [member ProjectSettings.gui/theme/custom].
+ </description>
+ </method>
</methods>
<members>
<member name="default_font" type="Font" setter="set_default_font" getter="get_default_font">
diff --git a/doc/classes/TileData.xml b/doc/classes/TileData.xml
index 1f0f807a08..bb793024eb 100644
--- a/doc/classes/TileData.xml
+++ b/doc/classes/TileData.xml
@@ -7,7 +7,7 @@
<tutorials>
</tutorials>
<methods>
- <method name="add_collision_shape">
+ <method name="add_collision_polygon">
<return type="void">
</return>
<argument index="0" name="layer_id" type="int">
@@ -15,27 +15,27 @@
<description>
</description>
</method>
- <method name="get_collision_shape_one_way_margin" qualifiers="const">
+ <method name="get_collision_polygon_one_way_margin" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shape_index" type="int">
+ <argument index="1" name="polygon_index" type="int">
</argument>
<description>
</description>
</method>
- <method name="get_collision_shape_shape" qualifiers="const">
- <return type="Shape2D">
+ <method name="get_collision_polygon_points" qualifiers="const">
+ <return type="PackedVector2Array">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shape_index" type="int">
+ <argument index="1" name="polygon_index" type="int">
</argument>
<description>
</description>
</method>
- <method name="get_collision_shapes_count" qualifiers="const">
+ <method name="get_collision_polygons_count" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="layer_id" type="int">
@@ -83,68 +83,68 @@
<description>
</description>
</method>
- <method name="is_collision_shape_one_way" qualifiers="const">
+ <method name="is_collision_polygon_one_way" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shape_index" type="int">
+ <argument index="1" name="polygon_index" type="int">
</argument>
<description>
</description>
</method>
- <method name="remove_collision_shape">
+ <method name="remove_collision_polygon">
<return type="void">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shape_index" type="int">
+ <argument index="1" name="polygon_index" type="int">
</argument>
<description>
</description>
</method>
- <method name="set_collision_shape_one_way">
+ <method name="set_collision_polygon_one_way">
<return type="void">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shape_index" type="int">
+ <argument index="1" name="polygon_index" type="int">
</argument>
<argument index="2" name="one_way" type="bool">
</argument>
<description>
</description>
</method>
- <method name="set_collision_shape_one_way_margin">
+ <method name="set_collision_polygon_one_way_margin">
<return type="void">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shape_index" type="int">
+ <argument index="1" name="polygon_index" type="int">
</argument>
<argument index="2" name="one_way_margin" type="float">
</argument>
<description>
</description>
</method>
- <method name="set_collision_shape_shape">
+ <method name="set_collision_polygon_points">
<return type="void">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shape_index" type="int">
+ <argument index="1" name="polygon_index" type="int">
</argument>
- <argument index="2" name="shape" type="Shape2D">
+ <argument index="2" name="polygon" type="PackedVector2Array">
</argument>
<description>
</description>
</method>
- <method name="set_collision_shapes_count">
+ <method name="set_collision_polygons_count">
<return type="void">
</return>
<argument index="0" name="layer_id" type="int">
</argument>
- <argument index="1" name="shapes_count" type="int">
+ <argument index="1" name="polygons_count" type="int">
</argument>
<description>
</description>
diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml
index 7d8b589f78..436e15387d 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -289,8 +289,6 @@
</member>
<member name="tile_size" type="Vector2i" setter="set_tile_size" getter="get_tile_size" default="Vector2i(16, 16)">
</member>
- <member name="tile_skew" type="Vector2" setter="set_tile_skew" getter="get_tile_skew" default="Vector2(0, 0)">
- </member>
<member name="uv_clipping" type="bool" setter="set_uv_clipping" getter="is_uv_clipping" default="false">
</member>
<member name="y_sorting" type="bool" setter="set_y_sorting" getter="is_y_sorting" default="false">
@@ -324,37 +322,37 @@
</constant>
<constant name="TILE_OFFSET_AXIS_VERTICAL" value="1" enum="TileOffsetAxis">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_RIGHT_SIDE" value="0" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_RIGHT_SIDE" value="0" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_RIGHT_CORNER" value="1" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_RIGHT_CORNER" value="1" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE" value="2" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE" value="2" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER" value="3" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER" value="3" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_BOTTOM_SIDE" value="4" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_BOTTOM_SIDE" value="4" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_BOTTOM_CORNER" value="5" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_BOTTOM_CORNER" value="5" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE" value="6" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_BOTTOM_LEFT_SIDE" value="6" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER" value="7" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_BOTTOM_LEFT_CORNER" value="7" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_LEFT_SIDE" value="8" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_LEFT_SIDE" value="8" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_LEFT_CORNER" value="9" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_LEFT_CORNER" value="9" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE" value="10" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_TOP_LEFT_SIDE" value="10" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER" value="11" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_TOP_LEFT_CORNER" value="11" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_TOP_SIDE" value="12" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_TOP_SIDE" value="12" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_TOP_CORNER" value="13" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_TOP_CORNER" value="13" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE" value="14" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_TOP_RIGHT_SIDE" value="14" enum="CellNeighbor">
</constant>
- <constant name="TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER" value="15" enum="CellNeighbor">
+ <constant name="CELL_NEIGHBOR_TOP_RIGHT_CORNER" value="15" enum="CellNeighbor">
</constant>
<constant name="TERRAIN_MODE_MATCH_CORNERS_AND_SIDES" value="0" enum="TerrainMode">
</constant>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 6a65d4ff7d..b498b9bb90 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -96,6 +96,14 @@
Returns the column index at [code]position[/code], or -1 if no item is there.
</description>
</method>
+ <method name="get_column_expand_ratio" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_column_title" qualifiers="const">
<return type="String">
</return>
@@ -232,7 +240,7 @@
Returns the last pressed button's index.
</description>
</method>
- <method name="get_root">
+ <method name="get_root" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -264,12 +272,50 @@
To tell whether a column of an item is selected, use [method TreeItem.is_selected].
</description>
</method>
+ <method name="is_column_clipping_content" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="is_column_expanding" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="scroll_to_item">
<return type="void">
</return>
<argument index="0" name="item" type="Object">
</argument>
<description>
+ Causes the [Tree] to jump to the specified item.
+ </description>
+ </method>
+ <method name="set_column_clip_content">
+ <return type="void">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <argument index="1" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_column_custom_minimum_width">
+ <return type="void">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <argument index="1" name="min_width" type="int">
+ </argument>
+ <description>
+ Overrides the calculated minimum width of a column. It can be set to `0` to restore the default behavior. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
</description>
</method>
<method name="set_column_expand">
@@ -283,15 +329,14 @@
If [code]true[/code], the column will have the "Expand" flag of [Control]. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
</description>
</method>
- <method name="set_column_min_width">
+ <method name="set_column_expand_ratio">
<return type="void">
</return>
<argument index="0" name="column" type="int">
</argument>
- <argument index="1" name="min_width" type="int">
+ <argument index="1" name="ratio" type="int">
</argument>
<description>
- Sets the minimum width of a column. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
</description>
</method>
<method name="set_column_title">
@@ -372,6 +417,12 @@
If [code]true[/code], the tree's root is hidden.
</member>
<member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents" override="true" default="true" />
+ <member name="scroll_horizontal_enabled" type="bool" setter="set_h_scroll_enabled" getter="is_h_scroll_enabled" default="true">
+ If [code]true[/code], enables horizontal scrolling.
+ </member>
+ <member name="scroll_vertical_enabled" type="bool" setter="set_v_scroll_enabled" getter="is_v_scroll_enabled" default="true">
+ If [code]true[/code], enables vertical scrolling.
+ </member>
<member name="select_mode" type="int" setter="set_select_mode" getter="get_select_mode" enum="Tree.SelectMode" default="0">
Allows single or multiple selection. See the [enum SelectMode] constants.
</member>
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index 0256d83fea..85c9caa101 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -192,7 +192,7 @@
Returns [code]true[/code] if [code]expand_right[/code] is set.
</description>
</method>
- <method name="get_first_child">
+ <method name="get_first_child" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -260,7 +260,7 @@
Returns the metadata value that was set for the given column using [method set_metadata].
</description>
</method>
- <method name="get_next">
+ <method name="get_next" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -288,7 +288,7 @@
Returns OpenType feature [code]tag[/code] of the item's text.
</description>
</method>
- <method name="get_parent">
+ <method name="get_parent" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -391,7 +391,7 @@
Returns the given column's tooltip.
</description>
</method>
- <method name="get_tree">
+ <method name="get_tree" qualifiers="const">
<return type="Tree">
</return>
<description>
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index 07d09c31dc..498aefbef0 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -304,12 +304,6 @@
<method name="operator +" qualifiers="operator">
<return type="Vector2">
</return>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Vector2">
- </return>
<argument index="0" name="right" type="Vector2">
</argument>
<description>
@@ -318,12 +312,6 @@
<method name="operator -" qualifiers="operator">
<return type="Vector2">
</return>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Vector2">
- </return>
<argument index="0" name="right" type="Vector2">
</argument>
<description>
@@ -401,6 +389,18 @@
<description>
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="orthogonal" qualifiers="const">
<return type="Vector2">
</return>
diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml
index 930ec944ba..5f190de8ca 100644
--- a/doc/classes/Vector2i.xml
+++ b/doc/classes/Vector2i.xml
@@ -126,12 +126,6 @@
<method name="operator +" qualifiers="operator">
<return type="Vector2i">
</return>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Vector2i">
- </return>
<argument index="0" name="right" type="Vector2i">
</argument>
<description>
@@ -140,12 +134,6 @@
<method name="operator -" qualifiers="operator">
<return type="Vector2i">
</return>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Vector2i">
- </return>
<argument index="0" name="right" type="Vector2i">
</argument>
<description>
@@ -223,6 +211,18 @@
<description>
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="sign" qualifiers="const">
<return type="Vector2i">
</return>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index eb1fd5f098..1361666c18 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -318,12 +318,6 @@
<method name="operator +" qualifiers="operator">
<return type="Vector3">
</return>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Vector3">
- </return>
<argument index="0" name="right" type="Vector3">
</argument>
<description>
@@ -332,12 +326,6 @@
<method name="operator -" qualifiers="operator">
<return type="Vector3">
</return>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Vector3">
- </return>
<argument index="0" name="right" type="Vector3">
</argument>
<description>
@@ -415,6 +403,18 @@
<description>
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="outer" qualifiers="const">
<return type="Basis">
</return>
diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml
index 8b45a62afa..e08bafa665 100644
--- a/doc/classes/Vector3i.xml
+++ b/doc/classes/Vector3i.xml
@@ -134,12 +134,6 @@
<method name="operator +" qualifiers="operator">
<return type="Vector3i">
</return>
- <description>
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="Vector3i">
- </return>
<argument index="0" name="right" type="Vector3i">
</argument>
<description>
@@ -148,12 +142,6 @@
<method name="operator -" qualifiers="operator">
<return type="Vector3i">
</return>
- <description>
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="Vector3i">
- </return>
<argument index="0" name="right" type="Vector3i">
</argument>
<description>
@@ -231,6 +219,18 @@
<description>
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="sign" qualifiers="const">
<return type="Vector3i">
</return>
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 292be34a0d..bf58dc4d8c 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -36,11 +36,18 @@
Returns the 3D world of the viewport, or if none the world of the parent viewport.
</description>
</method>
- <method name="get_camera" qualifiers="const">
+ <method name="get_camera_2d" qualifiers="const">
+ <return type="Camera2D">
+ </return>
+ <description>
+ Returns the currently active 2D camera. Returns null if there are no active cameras.
+ </description>
+ </method>
+ <method name="get_camera_3d" qualifiers="const">
<return type="Camera3D">
</return>
<description>
- Returns the active 3D camera.
+ Returns the currently active 3D camera.
</description>
</method>
<method name="get_final_transform" qualifiers="const">
@@ -60,10 +67,11 @@
<method name="get_render_info">
<return type="int">
</return>
- <argument index="0" name="info" type="int" enum="Viewport.RenderInfo">
+ <argument index="0" name="type" type="int" enum="Viewport.RenderInfoType">
+ </argument>
+ <argument index="1" name="info" type="int" enum="Viewport.RenderInfo">
</argument>
<description>
- Returns information about the viewport from the rendering pipeline.
</description>
</method>
<method name="get_shadow_atlas_quadrant_subdiv" qualifiers="const">
@@ -208,6 +216,9 @@
<member name="debug_draw" type="int" setter="set_debug_draw" getter="get_debug_draw" enum="Viewport.DebugDraw" default="0">
The overlay mode for test rendered geometry in debug purposes.
</member>
+ <member name="disable_3d" type="bool" setter="set_disable_3d" getter="is_3d_disabled" default="false">
+ Disable 3D rendering (but keep 2D rendering).
+ </member>
<member name="global_canvas_transform" type="Transform2D" setter="set_global_canvas_transform" getter="get_global_canvas_transform">
The global canvas transform of the viewport. The canvas transform is relative to this.
</member>
@@ -347,23 +358,20 @@
<constant name="RENDER_INFO_OBJECTS_IN_FRAME" value="0" enum="RenderInfo">
Amount of objects in frame.
</constant>
- <constant name="RENDER_INFO_VERTICES_IN_FRAME" value="1" enum="RenderInfo">
+ <constant name="RENDER_INFO_PRIMITIVES_IN_FRAME" value="1" enum="RenderInfo">
Amount of vertices in frame.
</constant>
- <constant name="RENDER_INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="RenderInfo">
- Amount of material changes in frame.
+ <constant name="RENDER_INFO_DRAW_CALLS_IN_FRAME" value="2" enum="RenderInfo">
+ Amount of draw calls in frame.
</constant>
- <constant name="RENDER_INFO_SHADER_CHANGES_IN_FRAME" value="3" enum="RenderInfo">
- Amount of shader changes in frame.
+ <constant name="RENDER_INFO_MAX" value="3" enum="RenderInfo">
+ Represents the size of the [enum RenderInfo] enum.
</constant>
- <constant name="RENDER_INFO_SURFACE_CHANGES_IN_FRAME" value="4" enum="RenderInfo">
- Amount of surface changes in frame.
+ <constant name="RENDER_INFO_TYPE_VISIBLE" value="0" enum="RenderInfoType">
</constant>
- <constant name="RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo">
- Amount of draw calls in frame.
+ <constant name="RENDER_INFO_TYPE_SHADOW" value="1" enum="RenderInfoType">
</constant>
- <constant name="RENDER_INFO_MAX" value="6" enum="RenderInfo">
- Represents the size of the [enum RenderInfo] enum.
+ <constant name="RENDER_INFO_TYPE_MAX" value="2" enum="RenderInfoType">
</constant>
<constant name="DEBUG_DRAW_DISABLED" value="0" enum="DebugDraw">
Objects are displayed normally.
diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml
index 9a74f2322e..199224b190 100644
--- a/doc/classes/VisualShaderNode.xml
+++ b/doc/classes/VisualShaderNode.xml
@@ -4,6 +4,7 @@
Base class for nodes in a visual shader graph.
</brief_description>
<description>
+ Visual shader graphs consist of various nodes. Each node in the graph is a separate object and they are represented as a rectangular boxes with title and a set of properties. Each node has also connection ports that allow to connect it to another nodes and control the flow of the shader.
</description>
<tutorials>
<link title="VisualShaders">https://docs.godotengine.org/en/latest/tutorials/shading/visual_shaders.html</link>
diff --git a/doc/classes/VisualShaderNodeCurveTexture.xml b/doc/classes/VisualShaderNodeCurveTexture.xml
index 26b7b07df2..4839ceab92 100644
--- a/doc/classes/VisualShaderNodeCurveTexture.xml
+++ b/doc/classes/VisualShaderNodeCurveTexture.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeCurveTexture" inherits="VisualShaderNodeResizableBase" version="4.0">
<brief_description>
+ Performs a [CurveTexture] lookup within the visual shader graph.
</brief_description>
<description>
+ Comes with a built-in editor for texture's curves.
</description>
<tutorials>
</tutorials>
@@ -10,6 +12,7 @@
</methods>
<members>
<member name="texture" type="CurveTexture" setter="set_texture" getter="get_texture">
+ The source texture.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualShaderNodeCurveXYZTexture.xml b/doc/classes/VisualShaderNodeCurveXYZTexture.xml
new file mode 100644
index 0000000000..11cdc541bb
--- /dev/null
+++ b/doc/classes/VisualShaderNodeCurveXYZTexture.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeCurveXYZTexture" inherits="VisualShaderNodeResizableBase" version="4.0">
+ <brief_description>
+ Performs a [CurveXYZTexture] lookup within the visual shader graph.
+ </brief_description>
+ <description>
+ Comes with a built-in editor for texture's curves.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="texture" type="CurveXYZTexture" setter="set_texture" getter="get_texture">
+ The source texture.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeResizableBase.xml b/doc/classes/VisualShaderNodeResizableBase.xml
index 9052f6854b..f42289a10e 100644
--- a/doc/classes/VisualShaderNodeResizableBase.xml
+++ b/doc/classes/VisualShaderNodeResizableBase.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeResizableBase" inherits="VisualShaderNode" version="4.0">
<brief_description>
+ Base class for resizable nodes in a visual shader graph.
</brief_description>
<description>
+ Resizable nodes have a handle that allows the user to adjust their size as needed.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VoxelGIData.xml b/doc/classes/VoxelGIData.xml
index 88a0411e2b..f613002233 100644
--- a/doc/classes/VoxelGIData.xml
+++ b/doc/classes/VoxelGIData.xml
@@ -66,12 +66,6 @@
</method>
</methods>
<members>
- <member name="anisotropy_strength" type="float" setter="set_anisotropy_strength" getter="get_anisotropy_strength" default="0.5">
- </member>
- <member name="ao" type="float" setter="set_ao" getter="get_ao" default="0.0">
- </member>
- <member name="ao_size" type="float" setter="set_ao_size" getter="get_ao_size" default="0.5">
- </member>
<member name="bias" type="float" setter="set_bias" getter="get_bias" default="1.5">
</member>
<member name="dynamic_range" type="float" setter="set_dynamic_range" getter="get_dynamic_range" default="4.0">
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index 6ae5a5f449..c8efaca1fc 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -19,6 +19,13 @@
<description>
</description>
</method>
+ <method name="get_contents_minimum_size" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ Returns the combined minimum size from the child [Control] nodes of the window.
+ </description>
+ </method>
<method name="get_flag" qualifiers="const">
<return type="bool">
</return>
@@ -340,7 +347,7 @@
</member>
<member name="theme" type="Theme" setter="set_theme" getter="get_theme">
</member>
- <member name="theme_custom_type" type="StringName" setter="set_theme_custom_type" getter="get_theme_custom_type" default="&amp;&quot;&quot;">
+ <member name="theme_type_variation" type="StringName" setter="set_theme_type_variation" getter="get_theme_type_variation" default="&amp;&quot;&quot;">
</member>
<member name="title" type="String" setter="set_title" getter="get_title" default="&quot;&quot;">
</member>
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index f75c130039..585c847d22 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -145,16 +145,6 @@
<method name="operator +" qualifiers="operator">
<return type="float">
</return>
- <description>
- Unary plus operator. Doesn't have any effect.
- [codeblock]
- var a = +2.5 # a is 2.5.
- [/codeblock]
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
- <return type="float">
- </return>
<argument index="0" name="right" type="float">
</argument>
<description>
@@ -173,17 +163,6 @@
<method name="operator -" qualifiers="operator">
<return type="float">
</return>
- <description>
- Unary minus operator. Negates the number.
- [codeblock]
- var a = -2.5 # a is -2.5.
- print(-a) # 2.5
- [/codeblock]
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
- <return type="float">
- </return>
<argument index="0" name="right" type="float">
</argument>
<description>
@@ -308,6 +287,18 @@
Returns [code]true[/code] if this [float] is greater than or equal to the given [int].
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index b0ad963998..95918c9007 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -126,21 +126,21 @@
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="float">
+ <return type="int">
</return>
- <argument index="0" name="right" type="float">
+ <argument index="0" name="right" type="int">
</argument>
<description>
- Multiplies an [int] and a [float]. The result is a [float].
+ Multiplies two [int]s.
</description>
</method>
<method name="operator *" qualifiers="operator">
- <return type="int">
+ <return type="float">
</return>
- <argument index="0" name="right" type="int">
+ <argument index="0" name="right" type="float">
</argument>
<description>
- Multiplies two [int]s.
+ Multiplies an [int] and a [float]. The result is a [float].
</description>
</method>
<method name="operator *" qualifiers="operator">
@@ -204,16 +204,6 @@
</description>
</method>
<method name="operator +" qualifiers="operator">
- <return type="int">
- </return>
- <description>
- Unary plus operator. Doesn't have any effect.
- [codeblock]
- var a = +1 # a is 1.
- [/codeblock]
- </description>
- </method>
- <method name="operator +" qualifiers="operator">
<return type="float">
</return>
<argument index="0" name="right" type="float">
@@ -232,17 +222,6 @@
</description>
</method>
<method name="operator -" qualifiers="operator">
- <return type="int">
- </return>
- <description>
- Unary minus operator. Negates the number.
- [codeblock]
- var a = -1 # a is -1.
- print(-a) # 1
- [/codeblock]
- </description>
- </method>
- <method name="operator -" qualifiers="operator">
<return type="float">
</return>
<argument index="0" name="right" type="float">
@@ -414,6 +393,18 @@
[/codeblock]
</description>
</method>
+ <method name="operator unary+" qualifiers="operator">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator unary-" qualifiers="operator">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="operator |" qualifiers="operator">
<return type="int">
</return>
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index 1c6055f8ca..9be7751d3d 100755
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -350,6 +350,9 @@ def main(): # type: () -> None
pattern = re.compile(args.filter)
+ # Create the output folder recursively if it doesn't already exist.
+ os.makedirs(args.output, exist_ok=True)
+
for class_name, class_def in state.classes.items():
if args.filter and not pattern.search(class_def.filepath):
continue
@@ -358,6 +361,8 @@ def main(): # type: () -> None
if not state.errored:
print("No errors found.")
+ 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.")
exit(1)
@@ -837,7 +842,7 @@ def rstize_text(text, state): # type: (str, State) -> str
inside_code = True
elif cmd == "gdscript":
tag_depth += 1
- tag_text = "\n .. code-tab:: gdscript GDScript\n"
+ tag_text = "\n .. code-tab:: gdscript\n"
inside_code = True
elif cmd == "csharp":
tag_depth += 1
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index e8f8ae4717..8a880ab9c8 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -41,19 +41,7 @@
#include <windows.h>
#include <ws2tcpip.h>
#ifndef UWP_ENABLED
-#if defined(__MINGW32__) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 4)
-// MinGW-w64 on Ubuntu 12.04 (our Travis build env) has bugs in this code where
-// some includes are missing in dependencies of iphlpapi.h for WINVER >= 0x0600 (Vista).
-// We don't use this Vista code for now, so working it around by disabling it.
-// MinGW-w64 >= 4.0 seems to be better judging by its headers.
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501 // Windows XP, disable Vista API
#include <iphlpapi.h>
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0600 // Re-enable Vista API
-#else
-#include <iphlpapi.h>
-#endif // MINGW hack
#endif
#else // UNIX
#include <netdb.h>
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 1539962803..5bf3bbf8a4 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -1398,12 +1398,15 @@ Error RenderingDeviceVulkan::_buffer_allocate(Buffer *p_buffer, uint32_t p_size,
p_buffer->buffer_info.range = p_size;
p_buffer->usage = p_usage;
+ buffer_memory += p_size;
+
return OK;
}
Error RenderingDeviceVulkan::_buffer_free(Buffer *p_buffer) {
ERR_FAIL_COND_V(p_buffer->size == 0, ERR_INVALID_PARAMETER);
+ buffer_memory -= p_buffer->size;
vmaDestroyBuffer(allocator, p_buffer->buffer, p_buffer->allocation);
p_buffer->buffer = VK_NULL_HANDLE;
p_buffer->allocation = nullptr;
@@ -1896,7 +1899,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
VkResult err = vmaCreateImage(allocator, &image_create_info, &allocInfo, &texture.image, &texture.allocation, &texture.allocation_info);
ERR_FAIL_COND_V_MSG(err, RID(), "vmaCreateImage failed with error " + itos(err) + ".");
-
+ image_memory += texture.allocation_info.size;
texture.type = p_format.texture_type;
texture.format = p_format.format;
texture.width = image_create_info.extent.width;
@@ -2029,7 +2032,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
if (p_data.size()) {
for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) {
- texture_update(id, i, p_data[i]);
+ _texture_update(id, i, p_data[i], RD::BARRIER_MASK_ALL, true);
}
}
return id;
@@ -2276,10 +2279,14 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
}
Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier) {
+ return _texture_update(p_texture, p_layer, p_data, p_post_barrier, false);
+}
+
+Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier, bool p_use_setup_queue) {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND_V_MSG(draw_list || compute_list, ERR_INVALID_PARAMETER,
- "Updating textures in is forbidden during creation of a draw or compute list");
+ ERR_FAIL_COND_V_MSG((draw_list || compute_list) && !p_use_setup_queue, ERR_INVALID_PARAMETER,
+ "Updating textures is forbidden during creation of a draw or compute list");
Texture *texture = texture_owner.getornull(p_texture);
ERR_FAIL_COND_V(!texture, ERR_INVALID_PARAMETER);
@@ -2320,7 +2327,7 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
const uint8_t *r = p_data.ptr();
- VkCommandBuffer command_buffer = p_post_barrier ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
+ VkCommandBuffer command_buffer = p_use_setup_queue ? frames[frame].setup_command_buffer : frames[frame].draw_command_buffer;
//barrier to transfer
{
@@ -2373,7 +2380,7 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
to_allocate >>= get_compressed_image_format_pixel_rshift(texture->format);
uint32_t alloc_offset, alloc_size;
- Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false, p_post_barrier);
+ Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false, !p_use_setup_queue);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
uint8_t *write_ptr;
@@ -3524,7 +3531,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachment_last_pass[attachment] = i;
- if (!is_multisample_first) {
+ if (is_multisample_first) {
+ texture_samples = p_attachments[attachment].samples;
+ is_multisample_first = false;
+ } else {
ERR_FAIL_COND_V_MSG(texture_samples != p_attachments[attachment].samples, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), if an attachment is marked as multisample, all of them should be multisample and use the same number of samples including the depth.");
}
@@ -4364,6 +4374,8 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
uint32_t stages_processed = 0;
+ Vector<Shader::SpecializationConstant> specialization_constants;
+
bool is_compute = false;
uint32_t compute_local_size[3] = { 0, 0, 0 };
@@ -4550,6 +4562,60 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
}
}
+ {
+ //specialization constants
+
+ uint32_t sc_count = 0;
+ result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, nullptr);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating specialization constants.");
+
+ if (sc_count) {
+ Vector<SpvReflectSpecializationConstant *> spec_constants;
+ spec_constants.resize(sc_count);
+
+ result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, spec_constants.ptrw());
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed obtaining specialization constants.");
+
+ for (uint32_t j = 0; j < sc_count; j++) {
+ int32_t existing = -1;
+ Shader::SpecializationConstant sconst;
+ sconst.constant.constant_id = spec_constants[j]->constant_id;
+ switch (spec_constants[j]->constant_type) {
+ case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: {
+ sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sconst.constant.bool_value = spec_constants[j]->default_value.int_bool_value != 0;
+ } break;
+ case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: {
+ sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+ sconst.constant.int_value = spec_constants[j]->default_value.int_bool_value;
+ } break;
+ case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: {
+ sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
+ sconst.constant.float_value = spec_constants[j]->default_value.float_value;
+ } break;
+ }
+ sconst.stage_flags = 1 << p_stages[i].shader_stage;
+
+ for (int k = 0; k < specialization_constants.size(); k++) {
+ if (specialization_constants[k].constant.constant_id == sconst.constant.constant_id) {
+ ERR_FAIL_COND_V_MSG(specialization_constants[k].constant.type != sconst.constant.type, RID(), "More than one specialization constant used for id (" + itos(sconst.constant.constant_id) + "), but their types differ.");
+ ERR_FAIL_COND_V_MSG(specialization_constants[k].constant.int_value != sconst.constant.int_value, RID(), "More than one specialization constant used for id (" + itos(sconst.constant.constant_id) + "), but their default values differ.");
+ existing = k;
+ break;
+ }
+ }
+
+ if (existing > 0) {
+ specialization_constants.write[existing].stage_flags |= sconst.stage_flags;
+ } else {
+ specialization_constants.push_back(sconst);
+ }
+ }
+ }
+ }
+
if (stage == SHADER_STAGE_VERTEX) {
uint32_t iv_count = 0;
result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr);
@@ -4646,6 +4712,7 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
shader.compute_local_size[0] = compute_local_size[0];
shader.compute_local_size[1] = compute_local_size[1];
shader.compute_local_size[2] = compute_local_size[2];
+ shader.specialization_constants = specialization_constants;
String error_text;
@@ -5495,6 +5562,13 @@ bool RenderingDeviceVulkan::uniform_set_is_valid(RID p_uniform_set) {
return uniform_set_owner.owns(p_uniform_set);
}
+void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) {
+ UniformSet *us = uniform_set_owner.getornull(p_uniform_set);
+ ERR_FAIL_COND(!us);
+ us->invalidated_callback = p_callback;
+ us->invalidated_callback_userdata = p_userdata;
+}
+
Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier) {
_THREAD_SAFE_METHOD_
@@ -5634,7 +5708,7 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
/**** RENDER PIPELINE ****/
/*************************/
-RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass) {
+RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
_THREAD_SAFE_METHOD_
//needs a shader
@@ -5734,7 +5808,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
tessellation_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tessellation_create_info.pNext = nullptr;
tessellation_create_info.flags = 0;
- ERR_FAIL_COND_V(p_rasterization_state.patch_control_points < 1 || p_rasterization_state.patch_control_points > limits.maxTessellationPatchSize, RID());
+ ERR_FAIL_COND_V(limits.maxTessellationPatchSize > 0 && (p_rasterization_state.patch_control_points < 1 || p_rasterization_state.patch_control_points > limits.maxTessellationPatchSize), RID());
tessellation_create_info.patchControlPoints = p_rasterization_state.patch_control_points;
VkPipelineViewportStateCreateInfo viewport_state_create_info;
@@ -5952,8 +6026,63 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
graphics_pipeline_create_info.pNext = nullptr;
graphics_pipeline_create_info.flags = 0;
- graphics_pipeline_create_info.stageCount = shader->pipeline_stages.size();
- graphics_pipeline_create_info.pStages = shader->pipeline_stages.ptr();
+ Vector<VkPipelineShaderStageCreateInfo> pipeline_stages = shader->pipeline_stages;
+ Vector<VkSpecializationInfo> specialization_info;
+ Vector<Vector<VkSpecializationMapEntry>> specialization_map_entries;
+ Vector<uint32_t> specialization_constant_data;
+
+ if (shader->specialization_constants.size()) {
+ specialization_constant_data.resize(shader->specialization_constants.size());
+ uint32_t *data_ptr = specialization_constant_data.ptrw();
+ specialization_info.resize(pipeline_stages.size());
+ specialization_map_entries.resize(pipeline_stages.size());
+ for (int i = 0; i < shader->specialization_constants.size(); i++) {
+ //see if overriden
+ const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
+ data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
+
+ for (int j = 0; j < p_specialization_constants.size(); j++) {
+ const PipelineSpecializationConstant &psc = p_specialization_constants[j];
+ if (psc.constant_id == sc.constant.constant_id) {
+ ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
+ data_ptr[i] = psc.int_value;
+ break;
+ }
+ }
+
+ VkSpecializationMapEntry entry;
+
+ entry.constantID = sc.constant.constant_id;
+ entry.offset = i * sizeof(uint32_t);
+ entry.size = sizeof(uint32_t);
+
+ for (int j = 0; j < SHADER_STAGE_MAX; j++) {
+ if (sc.stage_flags & (1 << j)) {
+ VkShaderStageFlagBits stage = shader_stage_masks[j];
+ for (int k = 0; k < pipeline_stages.size(); k++) {
+ if (pipeline_stages[k].stage == stage) {
+ specialization_map_entries.write[k].push_back(entry);
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < pipeline_stages.size(); i++) {
+ if (specialization_map_entries[i].size()) {
+ specialization_info.write[i].dataSize = specialization_constant_data.size() * sizeof(uint32_t);
+ specialization_info.write[i].pData = data_ptr;
+ specialization_info.write[i].mapEntryCount = specialization_map_entries[i].size();
+ specialization_info.write[i].pMapEntries = specialization_map_entries[i].ptr();
+
+ pipeline_stages.write[i].pSpecializationInfo = specialization_info.ptr() + i;
+ }
+ }
+ }
+
+ graphics_pipeline_create_info.stageCount = pipeline_stages.size();
+ graphics_pipeline_create_info.pStages = pipeline_stages.ptr();
+
graphics_pipeline_create_info.pVertexInputState = &pipeline_vertex_input_state_create_info;
graphics_pipeline_create_info.pInputAssemblyState = &input_assembly_create_info;
graphics_pipeline_create_info.pTessellationState = &tessellation_create_info;
@@ -6022,7 +6151,7 @@ bool RenderingDeviceVulkan::render_pipeline_is_valid(RID p_pipeline) {
/**** COMPUTE PIPELINE ****/
/**************************/
-RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) {
+RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
_THREAD_SAFE_METHOD_
//needs a shader
@@ -6044,6 +6173,44 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) {
compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
compute_pipeline_create_info.basePipelineIndex = 0;
+ VkSpecializationInfo specialization_info;
+ Vector<VkSpecializationMapEntry> specialization_map_entries;
+ Vector<uint32_t> specialization_constant_data;
+
+ if (shader->specialization_constants.size()) {
+ specialization_constant_data.resize(shader->specialization_constants.size());
+ uint32_t *data_ptr = specialization_constant_data.ptrw();
+ for (int i = 0; i < shader->specialization_constants.size(); i++) {
+ //see if overriden
+ const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
+ data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
+
+ for (int j = 0; j < p_specialization_constants.size(); j++) {
+ const PipelineSpecializationConstant &psc = p_specialization_constants[j];
+ if (psc.constant_id == sc.constant.constant_id) {
+ ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
+ data_ptr[i] = sc.constant.int_value;
+ break;
+ }
+ }
+
+ VkSpecializationMapEntry entry;
+
+ entry.constantID = sc.constant.constant_id;
+ entry.offset = i * sizeof(uint32_t);
+ entry.size = sizeof(uint32_t);
+
+ specialization_map_entries.push_back(entry);
+ }
+
+ specialization_info.dataSize = specialization_constant_data.size() * sizeof(uint32_t);
+ specialization_info.pData = data_ptr;
+ specialization_info.mapEntryCount = specialization_map_entries.size();
+ specialization_info.pMapEntries = specialization_map_entries.ptr();
+
+ compute_pipeline_create_info.stage.pSpecializationInfo = &specialization_info;
+ }
+
ComputePipeline pipeline;
VkResult err = vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_create_info, nullptr, &pipeline.pipeline);
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateComputePipelines failed with error " + itos(err) + ".");
@@ -7834,6 +8001,10 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) {
} else if (uniform_set_owner.owns(p_id)) {
UniformSet *uniform_set = uniform_set_owner.getornull(p_id);
frames[frame].uniform_sets_to_dispose_of.push_back(*uniform_set);
+ if (uniform_set->invalidated_callback != nullptr) {
+ uniform_set->invalidated_callback(p_id, uniform_set->invalidated_callback_userdata);
+ }
+
uniform_set_owner.free(p_id);
} else if (render_pipeline_owner.owns(p_id)) {
RenderPipeline *pipeline = render_pipeline_owner.getornull(p_id);
@@ -8118,6 +8289,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
vkDestroyImageView(device, texture->view, nullptr);
if (texture->owner.is_null()) {
//actually owns the image and the allocation too
+ image_memory -= texture->allocation_info.size;
vmaDestroyImage(allocator, texture->image, texture->allocation);
}
frames[p_frame].textures_to_dispose_of.pop_front();
@@ -8141,10 +8313,16 @@ uint32_t RenderingDeviceVulkan::get_frame_delay() const {
return frame_count;
}
-uint64_t RenderingDeviceVulkan::get_memory_usage() const {
- VmaStats stats;
- vmaCalculateStats(allocator, &stats);
- return stats.total.usedBytes;
+uint64_t RenderingDeviceVulkan::get_memory_usage(MemoryType p_type) const {
+ if (p_type == MEMORY_BUFFERS) {
+ return buffer_memory;
+ } else if (p_type == MEMORY_TEXTURES) {
+ return image_memory;
+ } else {
+ VmaStats stats;
+ vmaCalculateStats(allocator, &stats);
+ return stats.total.usedBytes;
+ }
}
void RenderingDeviceVulkan::_flush(bool p_current_frame) {
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 9f5830103d..8b95ff43b8 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -156,6 +156,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t texture_upload_region_size_px = 0;
Vector<uint8_t> _texture_get_data_from_image(Texture *tex, VkImage p_image, VmaAllocation p_allocation, uint32_t p_layer, bool p_2d = false);
+ Error _texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier, bool p_use_setup_queue);
/*****************/
/**** SAMPLER ****/
@@ -622,11 +623,17 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t compute_local_size[3] = { 0, 0, 0 };
+ struct SpecializationConstant {
+ PipelineSpecializationConstant constant;
+ uint32_t stage_flags = 0;
+ };
+
bool is_compute = false;
int max_output = 0;
Vector<Set> sets;
Vector<uint32_t> set_formats;
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages;
+ Vector<SpecializationConstant> specialization_constants;
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
};
@@ -731,6 +738,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
LocalVector<AttachableTexture> attachable_textures; //used for validation
Vector<Texture *> mutable_sampled_textures; //used for layout change
Vector<Texture *> mutable_storage_textures; //used for layout change
+ UniformSetInvalidatedCallback invalidated_callback = nullptr;
+ void *invalidated_callback_userdata = nullptr;
};
RID_Owner<UniformSet, true> uniform_set_owner;
@@ -1005,6 +1014,9 @@ class RenderingDeviceVulkan : public RenderingDevice {
VulkanContext *context = nullptr;
+ uint64_t image_memory = 0;
+ uint64_t buffer_memory = 0;
+
void _free_internal(RID p_id);
void _flush(bool p_current_frame);
@@ -1084,6 +1096,7 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
virtual bool uniform_set_is_valid(RID p_uniform_set);
+ virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata);
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); //works for any buffer
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL);
@@ -1093,14 +1106,14 @@ public:
/**** RENDER PIPELINE ****/
/*************************/
- virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0);
+ virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());
virtual bool render_pipeline_is_valid(RID p_pipeline);
/**************************/
/**** COMPUTE PIPELINE ****/
/**************************/
- virtual RID compute_pipeline_create(RID p_shader);
+ virtual RID compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());
virtual bool compute_pipeline_is_valid(RID p_pipeline);
/****************/
@@ -1191,7 +1204,7 @@ public:
virtual RenderingDevice *create_local_device();
- virtual uint64_t get_memory_usage() const;
+ virtual uint64_t get_memory_usage(MemoryType p_type) const;
virtual void set_resource_name(RID p_id, const String p_name);
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 6ed43b5d31..d35c519320 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -1013,11 +1013,11 @@ Error VulkanContext::_create_device() {
return OK;
}
-Error VulkanContext::_initialize_queues(VkSurfaceKHR surface) {
+Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) {
// Iterate over each queue to learn whether it supports presenting:
VkBool32 *supportsPresent = (VkBool32 *)malloc(queue_family_count * sizeof(VkBool32));
for (uint32_t i = 0; i < queue_family_count; i++) {
- fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, surface, &supportsPresent[i]);
+ fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, p_surface, &supportsPresent[i]);
}
// Search for a graphics and a present queue in the array of queue
@@ -1091,10 +1091,10 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR surface) {
// Get the list of VkFormat's that are supported:
uint32_t formatCount;
- VkResult err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, nullptr);
+ VkResult err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, p_surface, &formatCount, nullptr);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
- err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, surfFormats);
+ err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, p_surface, &formatCount, surfFormats);
if (err) {
free(surfFormats);
ERR_FAIL_V(ERR_CANT_CREATE);
@@ -1169,9 +1169,6 @@ Error VulkanContext::_create_semaphores() {
err = vkCreateFence(device, &fence_ci, nullptr, &fences[i]);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
- err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &image_acquired_semaphores[i]);
- ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
-
err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &draw_complete_semaphores[i]);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
@@ -1192,7 +1189,7 @@ bool VulkanContext::_use_validation_layers() {
return Engine::get_singleton()->is_validation_layers_enabled();
}
-Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height) {
+Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height) {
ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER);
if (!queues_initialized) {
@@ -1201,15 +1198,40 @@ Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfa
// is created.
Error err = _initialize_queues(p_surface);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
+ } else {
+ // make sure any of the surfaces supports present (validation layer complains if this is not done).
+ bool any_supports_present = false;
+ for (uint32_t i = 0; i < queue_family_count; i++) {
+ VkBool32 supports;
+ fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, p_surface, &supports);
+ if (supports) {
+ any_supports_present = true;
+ break;
+ }
+ }
+
+ ERR_FAIL_COND_V_MSG(!any_supports_present, ERR_CANT_CREATE, "Surface passed for sub-window creation does not support presenting");
}
Window window;
window.surface = p_surface;
window.width = p_width;
window.height = p_height;
+ window.vsync_mode = p_vsync_mode;
Error err = _update_swap_chain(&window);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
+ VkSemaphoreCreateInfo semaphoreCreateInfo = {
+ /*sType*/ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ /*pNext*/ nullptr,
+ /*flags*/ 0,
+ };
+
+ for (uint32_t i = 0; i < FRAME_LAG; i++) {
+ VkResult vkerr = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &window.image_acquired_semaphores[i]);
+ ERR_FAIL_COND_V(vkerr, ERR_CANT_CREATE);
+ }
+
windows[p_window_id] = window;
return OK;
}
@@ -1249,6 +1271,10 @@ VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_wi
void VulkanContext::window_destroy(DisplayServer::WindowID p_window_id) {
ERR_FAIL_COND(!windows.has(p_window_id));
_clean_up_swap_chain(&windows[p_window_id]);
+ for (uint32_t i = 0; i < FRAME_LAG; i++) {
+ vkDestroySemaphore(device, windows[p_window_id].image_acquired_semaphores[i], nullptr);
+ }
+
vkDestroySurfaceKHR(inst, windows[p_window_id].surface, nullptr);
windows.erase(p_window_id);
}
@@ -1335,7 +1361,6 @@ Error VulkanContext::_update_swap_chain(Window *window) {
}
// The FIFO present mode is guaranteed by the spec to be supported
// and to have no tearing. It's a great default present mode to use.
- VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
// There are times when you may wish to use another present mode. The
// following code shows how to select them, and the comments provide some
@@ -1364,16 +1389,41 @@ Error VulkanContext::_update_swap_chain(Window *window) {
// the application wants the late image to be immediately displayed, even
// though that may mean some tearing.
- if (window->presentMode != swapchainPresentMode) {
- for (size_t i = 0; i < presentModeCount; ++i) {
- if (presentModes[i] == window->presentMode) {
- swapchainPresentMode = window->presentMode;
- break;
- }
+ VkPresentModeKHR requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;
+ switch (window->vsync_mode) {
+ case DisplayServer::VSYNC_MAILBOX:
+ requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR;
+ break;
+ case DisplayServer::VSYNC_ADAPTIVE:
+ requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR;
+ break;
+ case DisplayServer::VSYNC_ENABLED:
+ requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;
+ break;
+ case DisplayServer::VSYNC_DISABLED:
+ requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR;
+ break;
+ }
+
+ // Check if the requested mode is available.
+ bool present_mode_available = false;
+ for (uint32_t i = 0; i < presentModeCount; i++) {
+ if (presentModes[i] == requested_present_mode) {
+ present_mode_available = true;
}
}
+
+ // Set the windows present mode if it is available, otherwise FIFO is used (guaranteed supported).
+ if (present_mode_available) {
+ window->presentMode = requested_present_mode;
+ } else {
+ WARN_PRINT("Requested VSync mode is not available!");
+ window->vsync_mode = DisplayServer::VSYNC_ENABLED; //Set to default
+ }
+
+ print_verbose("Using present mode: " + String(string_VkPresentModeKHR(window->presentMode)));
+
free(presentModes);
- ERR_FAIL_COND_V_MSG(swapchainPresentMode != window->presentMode, ERR_CANT_CREATE, "Present mode specified is not supported\n");
// Determine the number of VkImages to use in the swap chain.
// Application desires to acquire 3 images at a time for triple
@@ -1430,7 +1480,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
/*pQueueFamilyIndices*/ nullptr,
/*preTransform*/ (VkSurfaceTransformFlagBitsKHR)preTransform,
/*compositeAlpha*/ compositeAlpha,
- /*presentMode*/ swapchainPresentMode,
+ /*presentMode*/ window->presentMode,
/*clipped*/ true,
/*oldSwapchain*/ VK_NULL_HANDLE,
};
@@ -1703,6 +1753,8 @@ Error VulkanContext::prepare_buffers() {
for (Map<int, Window>::Element *E = windows.front(); E; E = E->next()) {
Window *w = &E->get();
+ w->semaphore_acquired = false;
+
if (w->swapchain == VK_NULL_HANDLE) {
continue;
}
@@ -1711,7 +1763,7 @@ Error VulkanContext::prepare_buffers() {
// Get the index of the next available swapchain image:
err =
fpAcquireNextImageKHR(device, w->swapchain, UINT64_MAX,
- image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer);
+ w->image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer);
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
// swapchain is out of date (e.g. the window was resized) and
@@ -1724,8 +1776,10 @@ Error VulkanContext::prepare_buffers() {
// presentation engine will still present the image correctly.
print_verbose("Vulkan: Early suboptimal swapchain.");
break;
+ } else if (err != VK_SUCCESS) {
+ ERR_BREAK_MSG(err != VK_SUCCESS, "Vulkan: Did not create swapchain successfully.");
} else {
- ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
+ w->semaphore_acquired = true;
}
} while (err != VK_SUCCESS);
}
@@ -1775,14 +1829,25 @@ Error VulkanContext::swap_buffers() {
commands_to_submit = command_buffer_count;
}
+ VkSemaphore *semaphores_to_acquire = (VkSemaphore *)alloca(windows.size() * sizeof(VkSemaphore));
+ uint32_t semaphores_to_acquire_count = 0;
+
+ for (Map<int, Window>::Element *E = windows.front(); E; E = E->next()) {
+ Window *w = &E->get();
+
+ if (w->semaphore_acquired) {
+ semaphores_to_acquire[semaphores_to_acquire_count++] = w->image_acquired_semaphores[frame_index];
+ }
+ }
+
VkPipelineStageFlags pipe_stage_flags;
VkSubmitInfo submit_info;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
submit_info.pWaitDstStageMask = &pipe_stage_flags;
pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- submit_info.waitSemaphoreCount = 1;
- submit_info.pWaitSemaphores = &image_acquired_semaphores[frame_index];
+ submit_info.waitSemaphoreCount = semaphores_to_acquire_count;
+ submit_info.pWaitSemaphores = semaphores_to_acquire;
submit_info.commandBufferCount = commands_to_submit;
submit_info.pCommandBuffers = commands_ptr;
submit_info.signalSemaphoreCount = 1;
@@ -2122,6 +2187,17 @@ String VulkanContext::get_device_pipeline_cache_uuid() const {
return pipeline_cache_id;
}
+DisplayServer::VSyncMode VulkanContext::get_vsync_mode(DisplayServer::WindowID p_window) const {
+ ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
+ return windows[p_window].vsync_mode;
+}
+
+void VulkanContext::set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) {
+ ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
+ windows[p_window].vsync_mode = p_mode;
+ _update_swap_chain(&windows[p_window]);
+}
+
VulkanContext::VulkanContext() {
command_buffer_queue.resize(1); // First one is always the setup command.
command_buffer_queue.write[0] = nullptr;
@@ -2134,7 +2210,6 @@ VulkanContext::~VulkanContext() {
if (device_initialized) {
for (uint32_t i = 0; i < FRAME_LAG; i++) {
vkDestroyFence(device, fences[i], nullptr);
- vkDestroySemaphore(device, image_acquired_semaphores[i], nullptr);
vkDestroySemaphore(device, draw_complete_semaphores[i], nullptr);
if (separate_present_queue) {
vkDestroySemaphore(device, image_ownership_semaphores[i], nullptr);
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 738ead4f96..83e9524046 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -70,7 +70,6 @@ private:
};
VkInstance inst = VK_NULL_HANDLE;
- VkSurfaceKHR surface = VK_NULL_HANDLE;
VkPhysicalDevice gpu = VK_NULL_HANDLE;
VkPhysicalDeviceProperties gpu_props;
uint32_t queue_family_count = 0;
@@ -101,7 +100,6 @@ private:
VkQueue present_queue = VK_NULL_HANDLE;
VkColorSpaceKHR color_space;
VkFormat format;
- VkSemaphore image_acquired_semaphores[FRAME_LAG];
VkSemaphore draw_complete_semaphores[FRAME_LAG];
VkSemaphore image_ownership_semaphores[FRAME_LAG];
int frame_index = 0;
@@ -121,9 +119,12 @@ private:
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
SwapchainImageResources *swapchain_image_resources = VK_NULL_HANDLE;
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ VkSemaphore image_acquired_semaphores[FRAME_LAG];
+ bool semaphore_acquired = false;
uint32_t current_buffer = 0;
int width = 0;
int height = 0;
+ DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
VkCommandPool present_cmd_pool = VK_NULL_HANDLE; // For separate present queue.
VkRenderPass render_pass = VK_NULL_HANDLE;
};
@@ -208,7 +209,7 @@ private:
Error _create_physical_device();
- Error _initialize_queues(VkSurfaceKHR surface);
+ Error _initialize_queues(VkSurfaceKHR p_surface);
Error _create_device();
@@ -222,7 +223,7 @@ private:
protected:
virtual const char *_get_platform_surface_extension() const = 0;
- virtual Error _window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height);
+ virtual Error _window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height);
virtual bool _use_validation_layers();
@@ -276,6 +277,9 @@ public:
String get_device_name() const;
String get_device_pipeline_cache_uuid() const;
+ void set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode);
+ DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const;
+
VulkanContext();
virtual ~VulkanContext();
};
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 0a0c3b1987..9126e0512e 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -200,7 +200,7 @@ void InputEventConfigurationDialog::_tab_selected(int p_tab) {
if (is_connected("window_input", signal_method)) {
disconnect("window_input", signal_method);
}
- input_list_tree->call_deferred("ensure_cursor_is_visible");
+ input_list_tree->call_deferred(SNAME("ensure_cursor_is_visible"));
if (input_list_tree->get_selected() == nullptr) {
// If nothing selected, scroll to top.
input_list_tree->scroll_to_item(input_list_tree->get_root());
@@ -532,14 +532,14 @@ void InputEventConfigurationDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- input_list_search->set_right_icon(input_list_search->get_theme_icon("Search", "EditorIcons"));
+ input_list_search->set_right_icon(input_list_search->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
- physical_key_checkbox->set_icon(get_theme_icon("KeyboardPhysical", "EditorIcons"));
+ physical_key_checkbox->set_icon(get_theme_icon(SNAME("KeyboardPhysical"), SNAME("EditorIcons")));
- icon_cache.keyboard = get_theme_icon("Keyboard", "EditorIcons");
- icon_cache.mouse = get_theme_icon("Mouse", "EditorIcons");
- icon_cache.joypad_button = get_theme_icon("JoyButton", "EditorIcons");
- icon_cache.joypad_axis = get_theme_icon("JoyAxis", "EditorIcons");
+ icon_cache.keyboard = get_theme_icon(SNAME("Keyboard"), SNAME("EditorIcons"));
+ icon_cache.mouse = get_theme_icon(SNAME("Mouse"), SNAME("EditorIcons"));
+ icon_cache.joypad_button = get_theme_icon(SNAME("JoyButton"), SNAME("EditorIcons"));
+ icon_cache.joypad_axis = get_theme_icon(SNAME("JoyAxis"), SNAME("EditorIcons"));
_update_input_list();
} break;
@@ -581,7 +581,7 @@ void InputEventConfigurationDialog::set_allowed_input_types(int p_type_masks) {
InputEventConfigurationDialog::InputEventConfigurationDialog() {
allowed_input_types = INPUT_KEY | INPUT_MOUSE_BUTTON | INPUT_JOY_BUTTON | INPUT_JOY_MOTION;
- set_title("Event Configuration");
+ set_title(TTR("Event Configuration"));
set_min_size(Size2i(550 * EDSCALE, 0)); // Min width
VBoxContainer *main_vbox = memnew(VBoxContainer);
@@ -595,7 +595,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
main_vbox->add_child(tab_container);
CenterContainer *cc = memnew(CenterContainer);
- cc->set_name("Listen for Input");
+ cc->set_name(TTR("Listen for Input"));
event_as_text = memnew(Label);
event_as_text->set_align(Label::ALIGN_CENTER);
cc->add_child(event_as_text);
@@ -604,7 +604,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
// List of all input options to manually select from.
VBoxContainer *manual_vbox = memnew(VBoxContainer);
- manual_vbox->set_name("Manual Selection");
+ manual_vbox->set_name(TTR("Manual Selection"));
manual_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tab_container->add_child(manual_vbox);
@@ -631,7 +631,8 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
additional_options_container->hide();
Label *opts_label = memnew(Label);
- opts_label->set_text("Additional Options");
+ opts_label->set_theme_type_variation("HeaderSmall");
+ opts_label->set_text(TTR("Additional Options"));
additional_options_container->add_child(opts_label);
// Device Selection
@@ -639,7 +640,8 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
device_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *device_label = memnew(Label);
- device_label->set_text("Device:");
+ device_label->set_theme_type_variation("HeaderSmall");
+ device_label->set_text(TTR("Device:"));
device_container->add_child(device_label);
device_id_option = memnew(OptionButton);
@@ -722,7 +724,7 @@ void ActionMapEditor::_event_config_confirmed() {
}
new_action["events"] = events;
- emit_signal("action_edited", current_action_name, new_action);
+ emit_signal(SNAME("action_edited"), current_action_name, new_action);
}
void ActionMapEditor::_add_action_pressed() {
@@ -736,7 +738,7 @@ void ActionMapEditor::_add_action(const String &p_name) {
}
add_edit->clear();
- emit_signal("action_added", p_name);
+ emit_signal(SNAME("action_added"), p_name);
}
void ActionMapEditor::_action_edited() {
@@ -760,7 +762,7 @@ void ActionMapEditor::_action_edited() {
return;
}
- emit_signal("action_renamed", old_name, new_name);
+ emit_signal(SNAME("action_renamed"), old_name, new_name);
} else if (action_tree->get_selected_column() == 1) {
// Deadzone Edited
String name = ti->get_meta("__name");
@@ -769,7 +771,7 @@ void ActionMapEditor::_action_edited() {
new_action["deadzone"] = ti->get_range(1);
// Call deferred so that input can finish propagating through tree, allowing re-making of tree to occur.
- call_deferred("emit_signal", "action_edited", name, new_action);
+ call_deferred(SNAME("emit_signal"), "action_edited", name, new_action);
}
}
@@ -806,7 +808,7 @@ void ActionMapEditor::_tree_button_pressed(Object *p_item, int p_column, int p_i
case ActionMapEditor::BUTTON_REMOVE_ACTION: {
// Send removed action name
String name = item->get_meta("__name");
- emit_signal("action_removed", name);
+ emit_signal(SNAME("action_removed"), name);
} break;
case ActionMapEditor::BUTTON_REMOVE_EVENT: {
// Remove event and send updated action
@@ -819,7 +821,7 @@ void ActionMapEditor::_tree_button_pressed(Object *p_item, int p_column, int p_i
events.remove(event_index);
action["events"] = events;
- emit_signal("action_edited", action_name, action);
+ emit_signal(SNAME("action_edited"), action_name, action);
} break;
default:
break;
@@ -858,6 +860,7 @@ Variant ActionMapEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from
String name = selected->get_text(0);
Label *label = memnew(Label(name));
+ label->set_theme_type_variation("HeaderSmall");
label->set_modulate(Color(1, 1, 1, 1.0f));
action_tree->set_drag_preview(label);
@@ -919,7 +922,7 @@ void ActionMapEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
// Change action order.
String relative_to = target->get_meta("__name");
String action_name = selected->get_meta("__name");
- emit_signal("action_reordered", action_name, relative_to, drop_above);
+ emit_signal(SNAME("action_reordered"), action_name, relative_to, drop_above);
} else if (d["input_type"] == "event") {
// Change event order
@@ -953,7 +956,7 @@ void ActionMapEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
new_action["events"] = new_events;
- emit_signal("action_edited", selected->get_parent()->get_meta("__name"), new_action);
+ emit_signal(SNAME("action_edited"), selected->get_parent()->get_meta("__name"), new_action);
}
}
@@ -961,7 +964,7 @@ void ActionMapEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- action_list_search->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ action_list_search->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
} break;
default:
break;
@@ -1035,11 +1038,11 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
action_item->set_range(1, deadzone);
// Third column - buttons
- action_item->add_button(2, action_tree->get_theme_icon("Add", "EditorIcons"), BUTTON_ADD_EVENT, false, TTR("Add Event"));
- action_item->add_button(2, action_tree->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_ACTION, !action_info.editable, action_info.editable ? "Remove Action" : "Cannot Remove Action");
+ action_item->add_button(2, action_tree->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), BUTTON_ADD_EVENT, false, TTR("Add Event"));
+ action_item->add_button(2, action_tree->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_ACTION, !action_info.editable, action_info.editable ? TTR("Remove Action") : TTR("Cannot Remove Action"));
- action_item->set_custom_bg_color(0, action_tree->get_theme_color("prop_subsection", "Editor"));
- action_item->set_custom_bg_color(1, action_tree->get_theme_color("prop_subsection", "Editor"));
+ action_item->set_custom_bg_color(0, action_tree->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
+ action_item->set_custom_bg_color(1, action_tree->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
for (int evnt_idx = 0; evnt_idx < events.size(); evnt_idx++) {
Ref<InputEvent> event = events[evnt_idx];
@@ -1055,8 +1058,8 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
event_item->set_meta("__index", evnt_idx);
// Third Column - Buttons
- event_item->add_button(2, action_tree->get_theme_icon("Edit", "EditorIcons"), BUTTON_EDIT_EVENT, false, TTR("Edit Event"));
- event_item->add_button(2, action_tree->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_EVENT, false, TTR("Remove Event"));
+ event_item->add_button(2, action_tree->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), BUTTON_EDIT_EVENT, false, TTR("Edit Event"));
+ event_item->add_button(2, action_tree->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_EVENT, false, TTR("Remove Event"));
event_item->set_button_color(2, 0, Color(1, 1, 1, 0.75));
event_item->set_button_color(2, 1, Color(1, 1, 1, 0.75));
}
@@ -1123,11 +1126,12 @@ ActionMapEditor::ActionMapEditor() {
action_tree->set_hide_root(true);
action_tree->set_column_titles_visible(true);
action_tree->set_column_title(0, TTR("Action"));
+ action_tree->set_column_clip_content(0, true);
action_tree->set_column_title(1, TTR("Deadzone"));
action_tree->set_column_expand(1, false);
- action_tree->set_column_min_width(1, 80 * EDSCALE);
+ action_tree->set_column_custom_minimum_width(1, 80 * EDSCALE);
action_tree->set_column_expand(2, false);
- action_tree->set_column_min_width(2, 50 * EDSCALE);
+ action_tree->set_column_custom_minimum_width(2, 50 * EDSCALE);
action_tree->connect("item_edited", callable_mp(this, &ActionMapEditor::_action_edited));
action_tree->connect("item_activated", callable_mp(this, &ActionMapEditor::_tree_item_activated));
action_tree->connect("button_pressed", callable_mp(this, &ActionMapEditor::_tree_button_pressed));
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 63ffab6727..05db9045bd 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -217,19 +217,19 @@ void AnimationBezierTrackEdit::_draw_line_clipped(const Vector2 &p_from, const V
void AnimationBezierTrackEdit::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) {
- bezier_icon = get_theme_icon("KeyBezierPoint", "EditorIcons");
- bezier_handle_icon = get_theme_icon("KeyBezierHandle", "EditorIcons");
- selected_icon = get_theme_icon("KeyBezierSelected", "EditorIcons");
+ bezier_icon = get_theme_icon(SNAME("KeyBezierPoint"), SNAME("EditorIcons"));
+ bezier_handle_icon = get_theme_icon(SNAME("KeyBezierHandle"), SNAME("EditorIcons"));
+ selected_icon = get_theme_icon(SNAME("KeyBezierSelected"), SNAME("EditorIcons"));
if (handle_mode_option->get_item_count() == 0) {
- handle_mode_option->add_icon_item(get_theme_icon("BezierHandlesFree", "EditorIcons"), TTR("Free"), HANDLE_MODE_FREE);
- handle_mode_option->add_icon_item(get_theme_icon("BezierHandlesBalanced", "EditorIcons"), TTR("Balanced"), HANDLE_MODE_BALANCED);
- handle_mode_option->add_icon_item(get_theme_icon("BezierHandlesMirror", "EditorIcons"), TTR("Mirror"), HANDLE_MODE_MIRROR);
+ handle_mode_option->add_icon_item(get_theme_icon(SNAME("BezierHandlesFree"), SNAME("EditorIcons")), TTR("Free"), HANDLE_MODE_FREE);
+ handle_mode_option->add_icon_item(get_theme_icon(SNAME("BezierHandlesBalanced"), SNAME("EditorIcons")), TTR("Balanced"), HANDLE_MODE_BALANCED);
+ handle_mode_option->add_icon_item(get_theme_icon(SNAME("BezierHandlesMirror"), SNAME("EditorIcons")), TTR("Mirror"), HANDLE_MODE_MIRROR);
}
}
if (p_what == NOTIFICATION_RESIZED) {
int right_limit = get_size().width - timeline->get_buttons_width();
- int hsep = get_theme_constant("hseparation", "ItemList");
- int vsep = get_theme_constant("vseparation", "ItemList");
+ int hsep = get_theme_constant(SNAME("hseparation"), SNAME("ItemList"));
+ int vsep = get_theme_constant(SNAME("vseparation"), SNAME("ItemList"));
handle_mode_option->set_position(Vector2(right_limit + hsep, get_size().height - handle_mode_option->get_combined_minimum_size().height - vsep));
handle_mode_option->set_size(Vector2(timeline->get_buttons_width() - hsep * 2, handle_mode_option->get_combined_minimum_size().height));
@@ -242,16 +242,16 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
int limit = timeline->get_name_limit();
if (has_focus()) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
accent.a *= 0.7;
draw_rect(Rect2(Point2(), get_size()), accent, false);
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- Color color = get_theme_color("font_color", "Label");
- int hsep = get_theme_constant("hseparation", "ItemList");
- int vsep = get_theme_constant("vseparation", "ItemList");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
+ int hsep = get_theme_constant(SNAME("hseparation"), SNAME("ItemList"));
+ int vsep = get_theme_constant(SNAME("vseparation"), SNAME("ItemList"));
Color linecolor = color;
linecolor.a = 0.2;
@@ -261,7 +261,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
draw_line(Point2(right_limit, 0), Point2(right_limit, get_size().height), linecolor);
- Ref<Texture2D> close_icon = get_theme_icon("Close", "EditorIcons");
+ Ref<Texture2D> close_icon = get_theme_icon(SNAME("Close"), SNAME("EditorIcons"));
close_icon_rect.position = Vector2(get_size().width - close_icon->get_width() - hsep, hsep);
close_icon_rect.size = close_icon->get_size();
@@ -349,7 +349,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
subtracks[i] = rect;
} else {
- Color ac = get_theme_color("accent_color", "Editor");
+ Color ac = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
ac.a = 0.5;
draw_rect(rect, ac);
}
@@ -360,7 +360,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
vofs += text_buf.get_size().y + vsep;
}
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
{ //guides
float min_left_scale = font->get_height(font_size) + vsep;
@@ -401,7 +401,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
{ //draw OTHER curves
float scale = timeline->get_zoom_scale();
- Ref<Texture2D> point = get_theme_icon("KeyValue", "EditorIcons");
+ Ref<Texture2D> point = get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons"));
for (Map<int, Color>::Element *E = subtrack_colors.front(); E; E = E->next()) {
_draw_track(E->key(), E->get());
@@ -418,7 +418,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
}
//draw edited curve
- const Color highlight = get_theme_color("highlight_color", "Editor");
+ const Color highlight = get_theme_color(SNAME("highlight_color"), SNAME("Editor"));
_draw_track(track, highlight);
}
@@ -547,7 +547,7 @@ void AnimationBezierTrackEdit::_play_position_draw() {
int px = (-timeline->get_value() + play_position_pos) * scale + timeline->get_name_limit();
if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE));
}
}
@@ -576,7 +576,7 @@ String AnimationBezierTrackEdit::get_tooltip(const Point2 &p_pos) const {
void AnimationBezierTrackEdit::_clear_selection() {
selection.clear();
- emit_signal("clear_selection");
+ emit_signal(SNAME("clear_selection"));
update();
}
@@ -597,7 +597,7 @@ void AnimationBezierTrackEdit::_select_at_anim(const Ref<Animation> &p_anim, int
ERR_FAIL_COND(idx < 0);
selection.insert(idx);
- emit_signal("select_key", idx, true);
+ emit_signal(SNAME("select_key"), idx, true);
update();
}
@@ -663,9 +663,9 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
if (selection.size()) {
menu->add_separator();
- menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
+ menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
menu->add_separator();
- menu->add_icon_item(get_theme_icon("Remove", "EditorIcons"), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE);
+ menu->add_icon_item(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE);
}
menu->set_as_minsize();
@@ -676,7 +676,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (close_icon_rect.has_point(mb->get_position())) {
- emit_signal("close_request");
+ emit_signal(SNAME("close_request"));
return;
}
for (Map<int, Rect2>::Element *E = subtracks.front(); E; E = E->next()) {
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index f61fb6bab3..174f19280a 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1290,7 +1290,7 @@ public:
void AnimationTimelineEdit::_zoom_changed(double) {
update();
play_position->update();
- emit_signal("zoom_changed");
+ emit_signal(SNAME("zoom_changed"));
}
float AnimationTimelineEdit::get_zoom_scale() const {
@@ -1321,7 +1321,7 @@ void AnimationTimelineEdit::_anim_length_changed(double p_new_len) {
editing = false;
update();
- emit_signal("length_changed", p_new_len);
+ emit_signal(SNAME("length_changed"), p_new_len);
}
void AnimationTimelineEdit::_anim_loop_pressed() {
@@ -1332,11 +1332,11 @@ void AnimationTimelineEdit::_anim_loop_pressed() {
}
int AnimationTimelineEdit::get_buttons_width() const {
- Ref<Texture2D> interp_mode = get_theme_icon("TrackContinuous", "EditorIcons");
- Ref<Texture2D> interp_type = get_theme_icon("InterpRaw", "EditorIcons");
- Ref<Texture2D> loop_type = get_theme_icon("InterpWrapClamp", "EditorIcons");
- Ref<Texture2D> remove_icon = get_theme_icon("Remove", "EditorIcons");
- Ref<Texture2D> down_icon = get_theme_icon("select_arrow", "Tree");
+ Ref<Texture2D> interp_mode = get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons"));
+ Ref<Texture2D> interp_type = get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons"));
+ Ref<Texture2D> loop_type = get_theme_icon(SNAME("InterpWrapClamp"), SNAME("EditorIcons"));
+ Ref<Texture2D> remove_icon = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
+ Ref<Texture2D> down_icon = get_theme_icon(SNAME("select_arrow"), SNAME("Tree"));
int total_w = interp_mode->get_width() + interp_type->get_width() + loop_type->get_width() + remove_icon->get_width();
total_w += (down_icon->get_width() + 4 * EDSCALE) * 4;
@@ -1345,7 +1345,7 @@ int AnimationTimelineEdit::get_buttons_width() const {
}
int AnimationTimelineEdit::get_name_limit() const {
- Ref<Texture2D> hsize_icon = get_theme_icon("Hsize", "EditorIcons");
+ Ref<Texture2D> hsize_icon = get_theme_icon(SNAME("Hsize"), SNAME("EditorIcons"));
int limit = MAX(name_limit, add_track->get_minimum_size().width + hsize_icon->get_width());
@@ -1356,17 +1356,17 @@ int AnimationTimelineEdit::get_name_limit() const {
void AnimationTimelineEdit::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- add_track->set_icon(get_theme_icon("Add", "EditorIcons"));
- loop->set_icon(get_theme_icon("Loop", "EditorIcons"));
- time_icon->set_texture(get_theme_icon("Time", "EditorIcons"));
+ add_track->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ loop->set_icon(get_theme_icon(SNAME("Loop"), SNAME("EditorIcons")));
+ time_icon->set_texture(get_theme_icon(SNAME("Time"), SNAME("EditorIcons")));
add_track->get_popup()->clear();
- add_track->get_popup()->add_icon_item(get_theme_icon("KeyValue", "EditorIcons"), TTR("Property Track"));
- add_track->get_popup()->add_icon_item(get_theme_icon("KeyXform", "EditorIcons"), TTR("3D Transform Track"));
- add_track->get_popup()->add_icon_item(get_theme_icon("KeyCall", "EditorIcons"), TTR("Call Method Track"));
- add_track->get_popup()->add_icon_item(get_theme_icon("KeyBezier", "EditorIcons"), TTR("Bezier Curve Track"));
- add_track->get_popup()->add_icon_item(get_theme_icon("KeyAudio", "EditorIcons"), TTR("Audio Playback Track"));
- add_track->get_popup()->add_icon_item(get_theme_icon("KeyAnimation", "EditorIcons"), TTR("Animation Playback Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")), TTR("Property Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXform"), SNAME("EditorIcons")), TTR("3D Transform Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")), TTR("Call Method Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")), TTR("Bezier Curve Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")), TTR("Audio Playback Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyAnimation"), SNAME("EditorIcons")), TTR("Animation Playback Track"));
}
if (p_what == NOTIFICATION_RESIZED) {
@@ -1381,9 +1381,9 @@ void AnimationTimelineEdit::_notification(int p_what) {
return;
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- Color color = get_theme_color("font_color", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
int zoomw = key_range;
float scale = get_zoom_scale();
@@ -1394,7 +1394,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
l = 0.001; //avoid crashor
}
- Ref<Texture2D> hsize_icon = get_theme_icon("Hsize", "EditorIcons");
+ Ref<Texture2D> hsize_icon = get_theme_icon(SNAME("Hsize"), SNAME("EditorIcons"));
hsize_rect = Rect2(get_name_limit() - hsize_icon->get_width() - 2 * EDSCALE, (get_size().height - hsize_icon->get_height()) / 2, hsize_icon->get_width(), hsize_icon->get_height());
draw_texture(hsize_icon, hsize_rect.position);
@@ -1443,7 +1443,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
int end_px = (l - get_value()) * scale;
int begin_px = -get_value() * scale;
- Color notimecol = get_theme_color("dark_color_2", "Editor");
+ Color notimecol = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
Color timecolor = color;
timecolor.a = 0.2;
Color linecolor = color;
@@ -1568,10 +1568,10 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation) {
Size2 AnimationTimelineEdit::get_minimum_size() const {
Size2 ms = add_track->get_minimum_size();
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
ms.height = MAX(ms.height, font->get_height(font_size));
- ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_theme_icon("Hsize", "EditorIcons")->get_width() + 2;
+ ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_theme_icon(SNAME("Hsize"), SNAME("EditorIcons"))->get_width() + 2;
return ms;
}
@@ -1633,11 +1633,11 @@ void AnimationTimelineEdit::_play_position_draw() {
int px = (-get_value() + play_position_pos) * scale + get_name_limit();
if (px >= get_name_limit() && px < (play_position->get_size().width - get_buttons_width())) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE));
play_position->draw_texture(
- get_theme_icon("TimelineIndicator", "EditorIcons"),
- Point2(px - get_theme_icon("TimelineIndicator", "EditorIcons")->get_width() * 0.5, 0),
+ get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons")),
+ Point2(px - get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"))->get_width() * 0.5, 0),
color);
}
}
@@ -1685,7 +1685,7 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
int x = mb->get_position().x - get_name_limit();
float ofs = x / get_zoom_scale() + get_value();
- emit_signal("timeline_changed", ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
+ emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
dragging_timeline = true;
}
if (!dragging_timeline && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
@@ -1718,13 +1718,13 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
int ofs = mm->get_position().x - dragging_hsize_from;
name_limit = dragging_hsize_at + ofs;
update();
- emit_signal("name_limit_changed");
+ emit_signal(SNAME("name_limit_changed"));
play_position->update();
}
if (dragging_timeline) {
int x = mm->get_position().x - get_name_limit();
float ofs = x / get_zoom_scale() + get_value();
- emit_signal("timeline_changed", ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
+ emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
}
if (panning_timeline) {
int x = mm->get_position().x - get_name_limit();
@@ -1750,7 +1750,7 @@ void AnimationTimelineEdit::set_hscroll(HScrollBar *p_hscroll) {
}
void AnimationTimelineEdit::_track_added(int p_track) {
- emit_signal("track_added", p_track);
+ emit_signal(SNAME("track_added"), p_track);
}
void AnimationTimelineEdit::_bind_methods() {
@@ -1832,31 +1832,31 @@ void AnimationTrackEdit::_notification(int p_what) {
int limit = timeline->get_name_limit();
if (has_focus()) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
accent.a *= 0.7;
// Offside so the horizontal sides aren't cutoff.
draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), accent, false);
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- Color color = get_theme_color("font_color", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
Ref<Texture2D> type_icons[6] = {
- get_theme_icon("KeyValue", "EditorIcons"),
- get_theme_icon("KeyXform", "EditorIcons"),
- get_theme_icon("KeyCall", "EditorIcons"),
- get_theme_icon("KeyBezier", "EditorIcons"),
- get_theme_icon("KeyAudio", "EditorIcons"),
- get_theme_icon("KeyAnimation", "EditorIcons")
+ get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyXform"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyAnimation"), SNAME("EditorIcons"))
};
- int hsep = get_theme_constant("hseparation", "ItemList");
+ int hsep = get_theme_constant(SNAME("hseparation"), SNAME("ItemList"));
Color linecolor = color;
linecolor.a = 0.2;
// NAMES AND ICONS //
{
- Ref<Texture2D> check = animation->track_is_enabled(track) ? get_theme_icon("checked", "CheckBox") : get_theme_icon("unchecked", "CheckBox");
+ Ref<Texture2D> check = animation->track_is_enabled(track) ? get_theme_icon(SNAME("checked"), SNAME("CheckBox")) : get_theme_icon(SNAME("unchecked"), SNAME("CheckBox"));
int ofs = in_group ? check->get_width() : 0; //not the best reference for margin but..
@@ -1877,7 +1877,7 @@ void AnimationTrackEdit::_notification(int p_what) {
String text;
Color text_color = color;
if (node && EditorNode::get_singleton()->get_editor_selection()->is_selected(node)) {
- text_color = get_theme_color("accent_color", "Editor");
+ text_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
}
if (in_group) {
@@ -1952,25 +1952,25 @@ void AnimationTrackEdit::_notification(int p_what) {
{
Ref<Texture2D> wrap_icon[2] = {
- get_theme_icon("InterpWrapClamp", "EditorIcons"),
- get_theme_icon("InterpWrapLoop", "EditorIcons"),
+ get_theme_icon(SNAME("InterpWrapClamp"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("InterpWrapLoop"), SNAME("EditorIcons")),
};
Ref<Texture2D> interp_icon[3] = {
- get_theme_icon("InterpRaw", "EditorIcons"),
- get_theme_icon("InterpLinear", "EditorIcons"),
- get_theme_icon("InterpCubic", "EditorIcons")
+ get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons"))
};
Ref<Texture2D> cont_icon[4] = {
- get_theme_icon("TrackContinuous", "EditorIcons"),
- get_theme_icon("TrackDiscrete", "EditorIcons"),
- get_theme_icon("TrackTrigger", "EditorIcons"),
- get_theme_icon("TrackCapture", "EditorIcons")
+ get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TrackTrigger"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons"))
};
int ofs = get_size().width - timeline->get_buttons_width();
- Ref<Texture2D> down_icon = get_theme_icon("select_arrow", "Tree");
+ Ref<Texture2D> down_icon = get_theme_icon(SNAME("select_arrow"), SNAME("Tree"));
draw_line(Point2(ofs, 0), Point2(ofs, get_size().height), linecolor, Math::round(EDSCALE));
@@ -2007,7 +2007,7 @@ void AnimationTrackEdit::_notification(int p_what) {
update_mode_rect.size.x += down_icon->get_width();
bezier_edit_rect = Rect2();
} else if (animation->track_get_type(track) == Animation::TYPE_BEZIER) {
- Ref<Texture2D> bezier_icon = get_theme_icon("EditBezier", "EditorIcons");
+ Ref<Texture2D> bezier_icon = get_theme_icon(SNAME("EditBezier"), SNAME("EditorIcons"));
update_mode_rect.size.x += down_icon->get_width();
bezier_edit_rect.position = update_mode_rect.position + (update_mode_rect.size - bezier_icon->get_size()) / 2;
bezier_edit_rect.size = bezier_icon->get_size();
@@ -2092,7 +2092,7 @@ void AnimationTrackEdit::_notification(int p_what) {
{
//erase
- Ref<Texture2D> icon = get_theme_icon("Remove", "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
remove_rect.position.x = ofs + ((get_size().width - ofs) - icon->get_width()) / 2;
remove_rect.position.y = int(get_size().height - icon->get_height()) / 2;
@@ -2109,7 +2109,7 @@ void AnimationTrackEdit::_notification(int p_what) {
}
if (dropping_at != 0) {
- Color drop_color = get_theme_color("accent_color", "Editor");
+ Color drop_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
if (dropping_at < 0) {
draw_line(Vector2(0, 0), Vector2(get_size().width, 0), drop_color, Math::round(EDSCALE));
} else {
@@ -2161,7 +2161,7 @@ void AnimationTrackEdit::draw_key_link(int p_index, float p_pixels_sec, int p_x,
return;
}
- Color color = get_theme_color("font_color", "Label");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
color.a = 0.5;
int from_x = MAX(p_x, p_clip_left);
@@ -2186,16 +2186,16 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
const Variant &v = animation->track_get_key_value(track, p_index);
Variant::Type valid_type = Variant::NIL;
if (!_is_value_key_valid(v, valid_type)) {
- icon_to_draw = get_theme_icon("KeyInvalid", "EditorIcons");
+ icon_to_draw = get_theme_icon(SNAME("KeyInvalid"), SNAME("EditorIcons"));
}
}
Vector2 ofs(p_x - icon_to_draw->get_width() / 2, int(get_size().height - icon_to_draw->get_height()) / 2);
if (animation->track_get_type(track) == Animation::TYPE_METHOD) {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- Color color = get_theme_color("font_color", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
color.a = 0.5;
Dictionary d = animation->track_get_key_value(track, p_index);
@@ -2298,19 +2298,19 @@ void AnimationTrackEdit::set_animation_and_track(const Ref<Animation> &p_animati
update();
Ref<Texture2D> type_icons[6] = {
- get_theme_icon("KeyValue", "EditorIcons"),
- get_theme_icon("KeyXform", "EditorIcons"),
- get_theme_icon("KeyCall", "EditorIcons"),
- get_theme_icon("KeyBezier", "EditorIcons"),
- get_theme_icon("KeyAudio", "EditorIcons"),
- get_theme_icon("KeyAnimation", "EditorIcons")
+ get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyXform"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyAnimation"), SNAME("EditorIcons"))
};
ERR_FAIL_INDEX(track, animation->get_track_count());
node_path = animation->track_get_path(p_track);
type_icon = type_icons[animation->track_get_type(track)];
- selected_icon = get_theme_icon("KeySelected", "EditorIcons");
+ selected_icon = get_theme_icon(SNAME("KeySelected"), SNAME("EditorIcons"));
}
NodePath AnimationTrackEdit::get_path() const {
@@ -2318,10 +2318,10 @@ NodePath AnimationTrackEdit::get_path() const {
}
Size2 AnimationTrackEdit::get_minimum_size() const {
- Ref<Texture2D> texture = get_theme_icon("Object", "EditorIcons");
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- int separation = get_theme_constant("vseparation", "ItemList");
+ Ref<Texture2D> texture = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ int separation = get_theme_constant(SNAME("vseparation"), SNAME("ItemList"));
int max_h = MAX(texture->get_height(), font->get_height(font_size));
max_h = MAX(max_h, get_key_height());
@@ -2355,7 +2355,7 @@ void AnimationTrackEdit::_play_position_draw() {
int px = (-timeline->get_value() + play_position_pos) * scale + timeline->get_name_limit();
if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE));
}
}
@@ -2556,17 +2556,17 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (p_event->is_pressed()) {
if (ED_GET_SHORTCUT("animation_editor/duplicate_selection")->is_shortcut(p_event)) {
- emit_signal("duplicate_request");
+ emit_signal(SNAME("duplicate_request"));
accept_event();
}
if (ED_GET_SHORTCUT("animation_editor/duplicate_selection_transposed")->is_shortcut(p_event)) {
- emit_signal("duplicate_transpose_request");
+ emit_signal(SNAME("duplicate_transpose_request"));
accept_event();
}
if (ED_GET_SHORTCUT("animation_editor/delete_selection")->is_shortcut(p_event)) {
- emit_signal("delete_request");
+ emit_signal(SNAME("delete_request"));
accept_event();
}
}
@@ -2597,10 +2597,10 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
menu->connect("id_pressed", callable_mp(this, &AnimationTrackEdit::_menu_selected));
}
menu->clear();
- menu->add_icon_item(get_theme_icon("TrackContinuous", "EditorIcons"), TTR("Continuous"), MENU_CALL_MODE_CONTINUOUS);
- menu->add_icon_item(get_theme_icon("TrackDiscrete", "EditorIcons"), TTR("Discrete"), MENU_CALL_MODE_DISCRETE);
- menu->add_icon_item(get_theme_icon("TrackTrigger", "EditorIcons"), TTR("Trigger"), MENU_CALL_MODE_TRIGGER);
- menu->add_icon_item(get_theme_icon("TrackCapture", "EditorIcons"), TTR("Capture"), MENU_CALL_MODE_CAPTURE);
+ menu->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), TTR("Continuous"), MENU_CALL_MODE_CONTINUOUS);
+ menu->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), TTR("Discrete"), MENU_CALL_MODE_DISCRETE);
+ menu->add_icon_item(get_theme_icon(SNAME("TrackTrigger"), SNAME("EditorIcons")), TTR("Trigger"), MENU_CALL_MODE_TRIGGER);
+ menu->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), TTR("Capture"), MENU_CALL_MODE_CAPTURE);
menu->set_as_minsize();
Vector2 popup_pos = get_screen_position() + update_mode_rect.position + Vector2(0, update_mode_rect.size.height);
@@ -2616,9 +2616,9 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
menu->connect("id_pressed", callable_mp(this, &AnimationTrackEdit::_menu_selected));
}
menu->clear();
- menu->add_icon_item(get_theme_icon("InterpRaw", "EditorIcons"), TTR("Nearest"), MENU_INTERPOLATION_NEAREST);
- menu->add_icon_item(get_theme_icon("InterpLinear", "EditorIcons"), TTR("Linear"), MENU_INTERPOLATION_LINEAR);
- menu->add_icon_item(get_theme_icon("InterpCubic", "EditorIcons"), TTR("Cubic"), MENU_INTERPOLATION_CUBIC);
+ menu->add_icon_item(get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), TTR("Nearest"), MENU_INTERPOLATION_NEAREST);
+ menu->add_icon_item(get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), TTR("Linear"), MENU_INTERPOLATION_LINEAR);
+ menu->add_icon_item(get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), TTR("Cubic"), MENU_INTERPOLATION_CUBIC);
menu->set_as_minsize();
Vector2 popup_pos = get_screen_position() + interp_mode_rect.position + Vector2(0, interp_mode_rect.size.height);
@@ -2634,8 +2634,8 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
menu->connect("id_pressed", callable_mp(this, &AnimationTrackEdit::_menu_selected));
}
menu->clear();
- menu->add_icon_item(get_theme_icon("InterpWrapClamp", "EditorIcons"), TTR("Clamp Loop Interp"), MENU_LOOP_CLAMP);
- menu->add_icon_item(get_theme_icon("InterpWrapLoop", "EditorIcons"), TTR("Wrap Loop Interp"), MENU_LOOP_WRAP);
+ menu->add_icon_item(get_theme_icon(SNAME("InterpWrapClamp"), SNAME("EditorIcons")), TTR("Clamp Loop Interp"), MENU_LOOP_CLAMP);
+ menu->add_icon_item(get_theme_icon(SNAME("InterpWrapLoop"), SNAME("EditorIcons")), TTR("Wrap Loop Interp"), MENU_LOOP_WRAP);
menu->set_as_minsize();
Vector2 popup_pos = get_screen_position() + loop_mode_rect.position + Vector2(0, loop_mode_rect.size.height);
@@ -2645,13 +2645,13 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
if (remove_rect.has_point(pos)) {
- emit_signal("remove_request", track);
+ emit_signal(SNAME("remove_request"), track);
accept_event();
return;
}
if (bezier_edit_rect.has_point(pos)) {
- emit_signal("bezier_edit");
+ emit_signal(SNAME("bezier_edit"));
accept_event();
}
@@ -2692,16 +2692,16 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (key_idx != -1) {
if (mb->is_command_pressed() || mb->is_shift_pressed()) {
if (editor->is_key_selected(track, key_idx)) {
- emit_signal("deselect_key", key_idx);
+ emit_signal(SNAME("deselect_key"), key_idx);
} else {
- emit_signal("select_key", key_idx, false);
+ emit_signal(SNAME("select_key"), key_idx, false);
moving_selection_attempt = true;
select_single_attempt = -1;
moving_selection_from_ofs = (mb->get_position().x - limit) / timeline->get_zoom_scale();
}
} else {
if (!editor->is_key_selected(track, key_idx)) {
- emit_signal("select_key", key_idx, true);
+ emit_signal(SNAME("select_key"), key_idx, true);
select_single_attempt = -1;
} else {
select_single_attempt = key_idx;
@@ -2727,12 +2727,12 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
menu->clear();
- menu->add_icon_item(get_theme_icon("Key", "EditorIcons"), TTR("Insert Key"), MENU_KEY_INSERT);
+ menu->add_icon_item(get_theme_icon(SNAME("Key"), SNAME("EditorIcons")), TTR("Insert Key"), MENU_KEY_INSERT);
if (editor->is_selection_active()) {
menu->add_separator();
- menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Duplicate Key(s)"), MENU_KEY_DUPLICATE);
+ menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Duplicate Key(s)"), MENU_KEY_DUPLICATE);
menu->add_separator();
- menu->add_icon_item(get_theme_icon("Remove", "EditorIcons"), TTR("Delete Key(s)"), MENU_KEY_DELETE);
+ menu->add_icon_item(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete Key(s)"), MENU_KEY_DELETE);
}
menu->set_as_minsize();
@@ -2757,7 +2757,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
path->set_text(animation->track_get_path(track));
- Vector2 theme_ofs = path->get_theme_stylebox("normal", "LineEdit")->get_offset();
+ Vector2 theme_ofs = path->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->get_offset();
path_popup->set_position(get_screen_position() + path_rect.position - theme_ofs);
path_popup->set_size(path_rect.size);
path_popup->popup();
@@ -2770,9 +2770,9 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
moving_selection_attempt = false;
if (moving_selection) {
- emit_signal("move_selection_commit");
+ emit_signal(SNAME("move_selection_commit"));
} else if (select_single_attempt != -1) {
- emit_signal("select_key", select_single_attempt, true);
+ emit_signal(SNAME("select_key"), select_single_attempt, true);
}
moving_selection = false;
select_single_attempt = -1;
@@ -2781,7 +2781,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (moving_selection && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
moving_selection_attempt = false;
moving_selection = false;
- emit_signal("move_selection_cancel");
+ emit_signal(SNAME("move_selection_cancel"));
}
}
@@ -2789,11 +2789,11 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && moving_selection_attempt) {
if (!moving_selection) {
moving_selection = true;
- emit_signal("move_selection_begin");
+ emit_signal(SNAME("move_selection_begin"));
}
float new_ofs = (mm->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale();
- emit_signal("move_selection", new_ofs - moving_selection_from_ofs);
+ emit_signal(SNAME("move_selection"), new_ofs - moving_selection_from_ofs);
}
}
@@ -2847,7 +2847,7 @@ bool AnimationTrackEdit::can_drop_data(const Point2 &p_point, const Variant &p_d
}
const_cast<AnimationTrackEdit *>(this)->update();
- const_cast<AnimationTrackEdit *>(this)->emit_signal("drop_attempted", track);
+ const_cast<AnimationTrackEdit *>(this)->emit_signal(SNAME("drop_attempted"), track);
return true;
}
@@ -2875,9 +2875,9 @@ void AnimationTrackEdit::drop_data(const Point2 &p_point, const Variant &p_data)
int from_track = d["index"];
if (dropping_at < 0) {
- emit_signal("dropped", from_track, track);
+ emit_signal(SNAME("dropped"), from_track, track);
} else {
- emit_signal("dropped", from_track, track + 1);
+ emit_signal(SNAME("dropped"), from_track, track + 1);
}
}
@@ -2916,14 +2916,14 @@ void AnimationTrackEdit::_menu_selected(int p_index) {
} break;
case MENU_KEY_INSERT: {
- emit_signal("insert_key", insert_at_pos);
+ emit_signal(SNAME("insert_key"), insert_at_pos);
} break;
case MENU_KEY_DUPLICATE: {
- emit_signal("duplicate_request");
+ emit_signal(SNAME("duplicate_request"));
} break;
case MENU_KEY_DELETE: {
- emit_signal("delete_request");
+ emit_signal(SNAME("delete_request"));
} break;
}
@@ -2956,9 +2956,9 @@ void AnimationTrackEdit::append_to_selection(const Rect2 &p_box, bool p_deselect
if (select_rect.intersects(rect)) {
if (p_deselection) {
- emit_signal("deselect_key", i);
+ emit_signal(SNAME("deselect_key"), i);
} else {
- emit_signal("select_key", i, false);
+ emit_signal(SNAME("select_key"), i, false);
}
}
}
@@ -3057,19 +3057,19 @@ AnimationTrackEdit *AnimationTrackEditPlugin::create_animation_track_edit(Object
void AnimationTrackEditGroup::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- int separation = get_theme_constant("hseparation", "ItemList");
- Color color = get_theme_color("font_color", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ int separation = get_theme_constant(SNAME("hseparation"), SNAME("ItemList"));
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
if (root && root->has_node(node)) {
Node *n = root->get_node(node);
if (n && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) {
- color = get_theme_color("accent_color", "Editor");
+ color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
}
}
- Color bgcol = get_theme_color("dark_color_2", "Editor");
+ Color bgcol = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
bgcol.a *= 0.6;
draw_rect(Rect2(Point2(), get_size()), bgcol);
Color linecolor = color;
@@ -3087,7 +3087,7 @@ void AnimationTrackEditGroup::_notification(int p_what) {
int px = (-timeline->get_value() + timeline->get_play_position()) * timeline->get_zoom_scale() + timeline->get_name_limit();
if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_line(Point2(px, 0), Point2(px, get_size().height), accent, Math::round(2 * EDSCALE));
}
}
@@ -3102,9 +3102,9 @@ void AnimationTrackEditGroup::set_type_and_name(const Ref<Texture2D> &p_type, co
}
Size2 AnimationTrackEditGroup::get_minimum_size() const {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- int separation = get_theme_constant("vseparation", "ItemList");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ int separation = get_theme_constant(SNAME("vseparation"), SNAME("ItemList"));
return Vector2(0, MAX(font->get_height(font_size), icon->get_height()) + separation);
}
@@ -3226,7 +3226,7 @@ void AnimationTrackEditor::update_keying() {
keying = keying_enabled;
- emit_signal("keying_changed");
+ emit_signal(SNAME("keying_changed"));
}
bool AnimationTrackEditor::has_keying() const {
@@ -3283,7 +3283,7 @@ void AnimationTrackEditor::_name_limit_changed() {
}
void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only) {
- emit_signal("timeline_changed", p_new_pos, p_drag, p_timeline_only);
+ emit_signal(SNAME("timeline_changed"), p_new_pos, p_drag, p_timeline_only);
}
void AnimationTrackEditor::_track_remove_request(int p_track) {
@@ -3430,14 +3430,14 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
insert_confirm->popup_centered();
insert_query = true;
} else {
- call_deferred("_insert_delay", reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
+ call_deferred(SNAME("_insert_delay"), reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
insert_queue = true;
}
} else {
if (!insert_query && !insert_queue) {
// Create Beziers wouldn't make sense in this case, where no tracks are being created
- call_deferred("_insert_delay", reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), false);
+ call_deferred(SNAME("_insert_delay"), reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), false);
insert_queue = true;
}
}
@@ -3482,7 +3482,7 @@ void AnimationTrackEditor::_insert_delay(bool p_create_reset, bool p_create_bezi
pos = animation->get_length();
}
set_anim_pos(pos);
- emit_signal("timeline_changed", pos, true);
+ emit_signal(SNAME("timeline_changed"), pos, true);
}
insert_queue = false;
}
@@ -4166,7 +4166,7 @@ void AnimationTrackEditor::_update_tracks() {
if (!group_sort.has(base_path)) {
AnimationTrackEditGroup *g = memnew(AnimationTrackEditGroup);
- Ref<Texture2D> icon = get_theme_icon("Node", "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons"));
String name = base_path;
String tooltip;
if (root && root->has_node(base_path)) {
@@ -4245,7 +4245,7 @@ void AnimationTrackEditor::_animation_changed() {
}
animation_changing_awaiting_update = true;
- call_deferred("_animation_update");
+ call_deferred(SNAME("_animation_update"));
}
void AnimationTrackEditor::_snap_mode_changed(int p_mode) {
@@ -4313,8 +4313,8 @@ void AnimationTrackEditor::_animation_update() {
bezier_edit->update();
_update_step_spinbox();
- emit_signal("animation_step_changed", animation->get_step());
- emit_signal("animation_len_changed", animation->get_length());
+ emit_signal(SNAME("animation_step_changed"), animation->get_step());
+ emit_signal(SNAME("animation_len_changed"), animation->get_length());
animation_changing_awaiting_update = false;
}
@@ -4325,13 +4325,13 @@ MenuButton *AnimationTrackEditor::get_edit_menu() {
void AnimationTrackEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) {
- zoom_icon->set_texture(get_theme_icon("Zoom", "EditorIcons"));
- snap->set_icon(get_theme_icon("Snap", "EditorIcons"));
+ zoom_icon->set_texture(get_theme_icon(SNAME("Zoom"), SNAME("EditorIcons")));
+ snap->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
view_group->set_icon(get_theme_icon(view_group->is_pressed() ? "AnimationTrackList" : "AnimationTrackGroup", "EditorIcons"));
- selected_filter->set_icon(get_theme_icon("AnimationFilter", "EditorIcons"));
- imported_anim_warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
- main_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_theme_icon("Reload", "EditorIcons"));
+ selected_filter->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons")));
+ imported_anim_warning->set_icon(get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")));
+ main_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
}
if (p_what == NOTIFICATION_READY) {
@@ -4341,7 +4341,7 @@ void AnimationTrackEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
update_keying();
EditorNode::get_singleton()->update_keying();
- emit_signal("keying_changed");
+ emit_signal(SNAME("keying_changed"));
}
}
@@ -4367,11 +4367,11 @@ void AnimationTrackEditor::_update_step(double p_new_step) {
step->set_block_signals(true);
undo_redo->commit_action();
step->set_block_signals(false);
- emit_signal("animation_step_changed", step_value);
+ emit_signal(SNAME("animation_step_changed"), step_value);
}
void AnimationTrackEditor::_update_length(double p_new_len) {
- emit_signal("animation_len_changed", p_new_len);
+ emit_signal(SNAME("animation_len_changed"), p_new_len);
}
void AnimationTrackEditor::_dropped_track(int p_from_track, int p_to_track) {
@@ -4450,7 +4450,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
}
if (node == AnimationPlayerEditor::singleton->get_player()) {
- EditorNode::get_singleton()->show_warning(TTR("An animation player can't animate itself, only other players."));
+ EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
@@ -4980,8 +4980,8 @@ float AnimationTrackEditor::get_moving_selection_offset() const {
void AnimationTrackEditor::_box_selection_draw() {
const Rect2 selection_rect = Rect2(Point2(), box_selection->get_size());
- box_selection->draw_rect(selection_rect, get_theme_color("box_selection_fill_color", "Editor"));
- box_selection->draw_rect(selection_rect, get_theme_color("box_selection_stroke_color", "Editor"), false, Math::round(EDSCALE));
+ box_selection->draw_rect(selection_rect, get_theme_color(SNAME("box_selection_fill_color"), SNAME("Editor")));
+ box_selection->draw_rect(selection_rect, get_theme_color(SNAME("box_selection_stroke_color"), SNAME("Editor")), false, Math::round(EDSCALE));
}
void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
@@ -5201,7 +5201,7 @@ void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) {
pos = 0;
}
set_anim_pos(pos);
- emit_signal("timeline_changed", pos, true);
+ emit_signal(SNAME("timeline_changed"), pos, true);
}
void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
@@ -5228,7 +5228,7 @@ void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
}
set_anim_pos(pos);
- emit_signal("timeline_changed", pos, true);
+ emit_signal(SNAME("timeline_changed"), pos, true);
}
void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
@@ -5247,7 +5247,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
String text;
- Ref<Texture2D> icon = get_theme_icon("Node", "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons"));
if (node) {
if (has_theme_icon(node->get_class(), "EditorIcons")) {
icon = get_theme_icon(node->get_class(), "EditorIcons");
@@ -5334,7 +5334,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} break;
case EDIT_PASTE_TRACKS: {
if (track_clipboard.size() == 0) {
- EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty"));
+ EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty!"));
break;
}
@@ -5784,7 +5784,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
info_message->set_text(TTR("Select an AnimationPlayer node to create and edit animations."));
info_message->set_valign(Label::VALIGN_CENTER);
info_message->set_align(Label::ALIGN_CENTER);
- info_message->set_autowrap(true);
+ info_message->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
main_panel->add_child(info_message);
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index 54c1e89d1e..0caed1e8e3 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -42,12 +42,12 @@
/// BOOL ///
int AnimationTrackEditBool::get_key_height() const {
- Ref<Texture2D> checked = get_theme_icon("checked", "CheckBox");
+ Ref<Texture2D> checked = get_theme_icon(SNAME("checked"), SNAME("CheckBox"));
return checked->get_height();
}
Rect2 AnimationTrackEditBool::get_key_rect(int p_index, float p_pixels_sec) {
- Ref<Texture2D> checked = get_theme_icon("checked", "CheckBox");
+ Ref<Texture2D> checked = get_theme_icon(SNAME("checked"), SNAME("CheckBox"));
return Rect2(-checked->get_width() / 2, 0, checked->get_width(), get_size().height);
}
@@ -72,7 +72,7 @@ void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x,
draw_texture(icon, ofs);
if (p_selected) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect_clipped(Rect2(ofs, icon->get_size()), color, false);
}
}
@@ -80,14 +80,14 @@ void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x,
/// COLOR ///
int AnimationTrackEditColor::get_key_height() const {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
return font->get_height(font_size) * 0.8;
}
Rect2 AnimationTrackEditColor::get_key_rect(int p_index, float p_pixels_sec) {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
return Rect2(-fh / 2, 0, fh, get_size().height);
}
@@ -97,8 +97,8 @@ bool AnimationTrackEditColor::is_key_selectable_by_distance() const {
}
void AnimationTrackEditColor::draw_key_link(int p_index, float p_pixels_sec, int p_x, int p_next_x, int p_clip_left, int p_clip_right) {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = (font->get_height(font_size) * 0.8);
fh /= 3;
@@ -167,8 +167,8 @@ void AnimationTrackEditColor::draw_key_link(int p_index, float p_pixels_sec, int
void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
Color color = get_animation()->track_get_key_value(get_track(), p_index);
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x - fh / 2, int(get_size().height - fh) / 2), Size2(fh, fh));
@@ -180,7 +180,7 @@ void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x,
draw_rect_clipped(rect, color);
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect_clipped(rect, accent, false);
}
}
@@ -206,8 +206,8 @@ int AnimationTrackEditAudio::get_key_height() const {
return AnimationTrackEdit::get_key_height();
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
return int(font->get_height(font_size) * 1.5);
}
@@ -239,8 +239,8 @@ Rect2 AnimationTrackEditAudio::get_key_rect(int p_index, float p_pixels_sec) {
return Rect2(0, 0, len * p_pixels_sec, get_size().height);
} else {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
return Rect2(0, 0, fh, get_size().height);
}
@@ -303,8 +303,8 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x,
return;
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
float fh = int(font->get_height(font_size) * 1.5);
Rect2 rect = Rect2(from_x, (get_size().height - fh) / 2, to_x - from_x, fh);
draw_rect(rect, Color(0.25, 0.25, 0.25));
@@ -330,20 +330,20 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x,
RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color);
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(rect, accent, false);
}
} else {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
- Color color = get_theme_color("font_color", "Label");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
draw_rect(rect, color);
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(rect, accent, false);
}
}
@@ -367,8 +367,8 @@ int AnimationTrackEditSpriteFrame::get_key_height() const {
return AnimationTrackEdit::get_key_height();
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
return int(font->get_height(font_size) * 2);
}
@@ -435,8 +435,8 @@ Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_se
size = size.floor();
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int height = int(font->get_height(font_size) * 2);
int width = height * size.width / size.height;
@@ -526,8 +526,8 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in
region.size = texture->get_size();
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int height = int(font->get_height(font_size) * 2);
int width = height * region.size.width / region.size.height;
@@ -542,7 +542,7 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in
return;
}
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
Color bg = accent;
bg.a = 0.15;
@@ -570,8 +570,8 @@ int AnimationTrackEditSubAnim::get_key_height() const {
return AnimationTrackEdit::get_key_height();
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
return int(font->get_height(font_size) * 1.5);
}
@@ -599,8 +599,8 @@ Rect2 AnimationTrackEditSubAnim::get_key_rect(int p_index, float p_pixels_sec) {
return Rect2(0, 0, len * p_pixels_sec, get_size().height);
} else {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
return Rect2(0, 0, fh, get_size().height);
}
@@ -654,13 +654,13 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_
return;
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 1.5;
Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh);
- Color color = get_theme_color("font_color", "Label");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color bg = color;
bg.r = 1 - color.r;
bg.g = 1 - color.g;
@@ -703,20 +703,20 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_
}
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(rect, accent, false);
}
} else {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
- Color color = get_theme_color("font_color", "Label");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
draw_rect(rect, color);
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(rect, accent, false);
}
}
@@ -729,12 +729,12 @@ void AnimationTrackEditSubAnim::set_node(Object *p_object) {
//// VOLUME DB ////
int AnimationTrackEditVolumeDB::get_key_height() const {
- Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
+ Ref<Texture2D> volume_texture = get_theme_icon(SNAME("ColorTrackVu"), SNAME("EditorIcons"));
return volume_texture->get_height() * 1.2;
}
void AnimationTrackEditVolumeDB::draw_bg(int p_clip_left, int p_clip_right) {
- Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
+ Ref<Texture2D> volume_texture = get_theme_icon(SNAME("ColorTrackVu"), SNAME("EditorIcons"));
int tex_h = volume_texture->get_height();
int y_from = (get_size().height - tex_h) / 2;
@@ -745,7 +745,7 @@ void AnimationTrackEditVolumeDB::draw_bg(int p_clip_left, int p_clip_right) {
}
void AnimationTrackEditVolumeDB::draw_fg(int p_clip_left, int p_clip_right) {
- Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
+ Ref<Texture2D> volume_texture = get_theme_icon(SNAME("ColorTrackVu"), SNAME("EditorIcons"));
int tex_h = volume_texture->get_height();
int y_from = (get_size().height - tex_h) / 2;
int db0 = y_from + (24 / 80.0) * tex_h;
@@ -780,12 +780,12 @@ void AnimationTrackEditVolumeDB::draw_key_link(int p_index, float p_pixels_sec,
to_x = p_clip_right;
}
- Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons");
+ Ref<Texture2D> volume_texture = get_theme_icon(SNAME("ColorTrackVu"), SNAME("EditorIcons"));
int tex_h = volume_texture->get_height();
int y_from = (get_size().height - tex_h) / 2;
- Color color = get_theme_color("font_color", "Label");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
color.a *= 0.7;
draw_line(Point2(from_x, y_from + h * tex_h), Point2(to_x, y_from + h_n * tex_h), color, 2);
@@ -806,8 +806,8 @@ void AnimationTrackEditTypeAudio::_preview_changed(ObjectID p_which) {
}
int AnimationTrackEditTypeAudio::get_key_height() const {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
return int(font->get_height(font_size) * 1.5);
}
@@ -871,8 +871,8 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int
}
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
float fh = int(font->get_height(font_size) * 1.5);
float len = stream->get_length();
@@ -947,7 +947,7 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int
RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color);
- Color cut_color = get_theme_color("accent_color", "Editor");
+ Color cut_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
cut_color.a = 0.7;
if (start_ofs > 0 && pixel_begin > p_clip_left) {
draw_rect(Rect2(pixel_begin, rect.position.y, 1, rect.size.y), cut_color);
@@ -957,7 +957,7 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int
}
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(rect, accent, false);
}
}
@@ -1143,8 +1143,8 @@ int AnimationTrackEditTypeAnimation::get_key_height() const {
return AnimationTrackEdit::get_key_height();
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
return int(font->get_height(font_size) * 1.5);
}
@@ -1172,8 +1172,8 @@ Rect2 AnimationTrackEditTypeAnimation::get_key_rect(int p_index, float p_pixels_
return Rect2(0, 0, len * p_pixels_sec, get_size().height);
} else {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
return Rect2(0, 0, fh, get_size().height);
}
@@ -1227,13 +1227,13 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec,
return;
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 1.5;
Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh);
- Color color = get_theme_color("font_color", "Label");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color bg = color;
bg.r = 1 - color.r;
bg.g = 1 - color.g;
@@ -1276,20 +1276,20 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec,
}
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(rect, accent, false);
}
} else {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
- Color color = get_theme_color("font_color", "Label");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
draw_rect(rect, color);
if (p_selected) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(rect, accent, false);
}
}
diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp
index ad6e3ac1dc..f7f4988873 100644
--- a/editor/audio_stream_preview.cpp
+++ b/editor/audio_stream_preview.cpp
@@ -97,7 +97,7 @@ AudioStreamPreview::AudioStreamPreview() {
////
void AudioStreamPreviewGenerator::_update_emit(ObjectID p_id) {
- emit_signal("preview_updated", p_id);
+ emit_signal(SNAME("preview_updated"), p_id);
}
void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) {
@@ -150,7 +150,7 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) {
}
frames_todo -= to_read;
- singleton->call_deferred("_update_emit", preview->id);
+ singleton->call_deferred(SNAME("_update_emit"), preview->id);
}
preview->playback->stop();
diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h
index 61567598ed..9cf47fd51a 100644
--- a/editor/audio_stream_preview.h
+++ b/editor/audio_stream_preview.h
@@ -75,6 +75,15 @@ class AudioStreamPreviewGenerator : public Node {
thread = p_rhs.thread;
return *this;
}
+ Preview(const Preview &p_rhs) {
+ preview = p_rhs.preview;
+ base_stream = p_rhs.base_stream;
+ playback = p_rhs.playback;
+ generating.set_to(generating.is_set());
+ id = p_rhs.id;
+ thread = p_rhs.thread;
+ }
+ Preview() {}
};
Map<ObjectID, Preview> previews;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 16f55312bb..b0ec346afe 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -88,23 +88,23 @@ GotoLineDialog::GotoLineDialog() {
void FindReplaceBar::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
- find_prev->set_icon(get_theme_icon("MoveUp", "EditorIcons"));
- find_next->set_icon(get_theme_icon("MoveDown", "EditorIcons"));
- hide_button->set_normal_texture(get_theme_icon("Close", "EditorIcons"));
- hide_button->set_hover_texture(get_theme_icon("Close", "EditorIcons"));
- hide_button->set_pressed_texture(get_theme_icon("Close", "EditorIcons"));
+ find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
+ find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
+ hide_button->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_hover_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_pressed_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size());
} else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
set_process_unhandled_input(is_visible_in_tree());
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- find_prev->set_icon(get_theme_icon("MoveUp", "EditorIcons"));
- find_next->set_icon(get_theme_icon("MoveDown", "EditorIcons"));
- hide_button->set_normal_texture(get_theme_icon("Close", "EditorIcons"));
- hide_button->set_hover_texture(get_theme_icon("Close", "EditorIcons"));
- hide_button->set_pressed_texture(get_theme_icon("Close", "EditorIcons"));
+ find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
+ find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
+ hide_button->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_hover_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_pressed_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size());
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
- matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
+ matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), SNAME("Editor")));
} else if (p_what == NOTIFICATION_PREDELETE) {
if (base_text_editor) {
base_text_editor->remove_find_replace_bar();
@@ -122,7 +122,7 @@ void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) {
}
Control *focus_owner = get_focus_owner();
- if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) {
+ if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_ancestor_of(focus_owner))) {
bool accepted = true;
switch (k->get_keycode()) {
@@ -304,10 +304,10 @@ void FindReplaceBar::_replace_all() {
}
text_editor->set_v_scroll(vsval);
- matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
+ matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), SNAME("Editor")));
matches_label->set_text(vformat(TTR("%d replaced."), rc));
- text_editor->call_deferred("connect", "text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
+ text_editor->call_deferred(SNAME("connect"), "text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
results_count = -1;
}
@@ -368,7 +368,7 @@ void FindReplaceBar::_update_matches_label() {
} else {
matches_label->show();
- matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
+ matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), SNAME("Editor")));
matches_label->set_text(vformat(results_count == 1 ? TTR("%d match.") : TTR("%d matches."), results_count));
}
}
@@ -480,10 +480,10 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) {
if (p_focus_replace) {
search_text->deselect();
- replace_text->call_deferred("grab_focus");
+ replace_text->call_deferred(SNAME("grab_focus"));
} else {
replace_text->deselect();
- search_text->call_deferred("grab_focus");
+ search_text->call_deferred(SNAME("grab_focus"));
}
if (text_editor->is_selection_active() && !selection_only->is_pressed()) {
@@ -585,7 +585,7 @@ bool FindReplaceBar::is_selection_only() const {
}
void FindReplaceBar::set_error(const String &p_label) {
- emit_signal("error", p_label);
+ emit_signal(SNAME("error"), p_label);
}
void FindReplaceBar::set_text_edit(CodeTextEditor *p_text_editor) {
@@ -738,8 +738,8 @@ void CodeTextEditor::_input(const Ref<InputEvent> &event) {
accept_event();
return;
}
- if (ED_IS_SHORTCUT("script_text_editor/clone_down", key_event)) {
- clone_lines_down();
+ if (ED_IS_SHORTCUT("script_text_editor/duplicate_selection", key_event)) {
+ duplicate_selection();
accept_event();
return;
}
@@ -760,10 +760,10 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
if (magnify_gesture.is_valid()) {
- font_size = text_editor->get_theme_font_size("font_size");
+ font_size = text_editor->get_theme_font_size(SNAME("font_size"));
font_size *= powf(magnify_gesture->get_factor(), 0.25);
- _add_font_size((int)font_size - text_editor->get_theme_font_size("font_size"));
+ _add_font_size((int)font_size - text_editor->get_theme_font_size(SNAME("font_size")));
return;
}
@@ -875,38 +875,38 @@ Ref<Texture2D> CodeTextEditor::_get_completion_icon(const ScriptCodeCompletionOp
if (has_theme_icon(p_option.display, "EditorIcons")) {
tex = get_theme_icon(p_option.display, "EditorIcons");
} else {
- tex = get_theme_icon("Object", "EditorIcons");
+ tex = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
}
} break;
case ScriptCodeCompletionOption::KIND_ENUM:
- tex = get_theme_icon("Enum", "EditorIcons");
+ tex = get_theme_icon(SNAME("Enum"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_FILE_PATH:
- tex = get_theme_icon("File", "EditorIcons");
+ tex = get_theme_icon(SNAME("File"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_NODE_PATH:
- tex = get_theme_icon("NodePath", "EditorIcons");
+ tex = get_theme_icon(SNAME("NodePath"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_VARIABLE:
- tex = get_theme_icon("Variant", "EditorIcons");
+ tex = get_theme_icon(SNAME("Variant"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_CONSTANT:
- tex = get_theme_icon("MemberConstant", "EditorIcons");
+ tex = get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_MEMBER:
- tex = get_theme_icon("MemberProperty", "EditorIcons");
+ tex = get_theme_icon(SNAME("MemberProperty"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_SIGNAL:
- tex = get_theme_icon("MemberSignal", "EditorIcons");
+ tex = get_theme_icon(SNAME("MemberSignal"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_FUNCTION:
- tex = get_theme_icon("MemberMethod", "EditorIcons");
+ tex = get_theme_icon(SNAME("MemberMethod"), SNAME("EditorIcons"));
break;
case ScriptCodeCompletionOption::KIND_PLAIN_TEXT:
- tex = get_theme_icon("BoxMesh", "EditorIcons");
+ tex = get_theme_icon(SNAME("BoxMesh"), SNAME("EditorIcons"));
break;
default:
- tex = get_theme_icon("String", "EditorIcons");
+ tex = get_theme_icon(SNAME("String"), SNAME("EditorIcons"));
break;
}
return tex;
@@ -919,7 +919,7 @@ void CodeTextEditor::_font_resize_timeout() {
}
bool CodeTextEditor::_add_font_size(int p_delta) {
- int old_size = text_editor->get_theme_font_size("font_size");
+ int old_size = text_editor->get_theme_font_size(SNAME("font_size"));
int new_size = CLAMP(old_size + p_delta, 8 * EDSCALE, 96 * EDSCALE);
if (new_size != old_size) {
@@ -1287,7 +1287,7 @@ void CodeTextEditor::delete_lines() {
text_editor->end_complex_operation();
}
-void CodeTextEditor::clone_lines_down() {
+void CodeTextEditor::duplicate_selection() {
const int cursor_column = text_editor->cursor_get_column();
int from_line = text_editor->cursor_get_line();
int to_line = text_editor->cursor_get_line();
@@ -1411,19 +1411,19 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
void CodeTextEditor::goto_line(int p_line) {
text_editor->deselect();
text_editor->unfold_line(p_line);
- text_editor->call_deferred("cursor_set_line", p_line);
+ text_editor->call_deferred(SNAME("cursor_set_line"), p_line);
}
void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
text_editor->unfold_line(p_line);
- text_editor->call_deferred("cursor_set_line", p_line);
- text_editor->call_deferred("cursor_set_column", p_begin);
+ text_editor->call_deferred(SNAME("cursor_set_line"), p_line);
+ text_editor->call_deferred(SNAME("cursor_set_column"), p_begin);
text_editor->select(p_line, p_begin, p_line, p_end);
}
void CodeTextEditor::goto_line_centered(int p_line) {
goto_line(p_line);
- text_editor->call_deferred("center_viewport_to_cursor");
+ text_editor->call_deferred(SNAME("center_viewport_to_cursor"));
}
void CodeTextEditor::set_executing_line(int p_line) {
@@ -1542,20 +1542,20 @@ void CodeTextEditor::_update_text_editor_theme() {
text_editor->add_theme_color_override("search_result_color", EDITOR_GET("text_editor/highlighting/search_result_color"));
text_editor->add_theme_color_override("search_result_border_color", EDITOR_GET("text_editor/highlighting/search_result_border_color"));
text_editor->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
- emit_signal("load_theme_settings");
+ emit_signal(SNAME("load_theme_settings"));
_load_theme_settings();
}
void CodeTextEditor::_update_font() {
- text_editor->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
- text_editor->add_theme_font_size_override("font_size", get_theme_font_size("source_size", "EditorFonts"));
+ text_editor->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
+ text_editor->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")));
- error->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts"));
- error->add_theme_font_size_override("font_size", get_theme_font_size("status_source_size", "EditorFonts"));
- error->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ error->add_theme_font_override("font", get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ error->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
+ error->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
- Ref<Font> status_bar_font = get_theme_font("status_source", "EditorFonts");
- int status_bar_font_size = get_theme_font_size("status_source_size", "EditorFonts");
+ Ref<Font> status_bar_font = get_theme_font(SNAME("status_source"), SNAME("EditorFonts"));
+ int status_bar_font_size = get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts"));
error->add_theme_font_override("font", status_bar_font);
error->add_theme_font_size_override("font_size", status_bar_font_size);
int count = status_bar->get_child_count();
@@ -1614,7 +1614,7 @@ void CodeTextEditor::_on_settings_change() {
void CodeTextEditor::_text_changed_idle_timeout() {
_validate_script();
- emit_signal("validate_script");
+ emit_signal(SNAME("validate_script"));
}
void CodeTextEditor::validate_script() {
@@ -1633,19 +1633,19 @@ void CodeTextEditor::_warning_button_pressed() {
void CodeTextEditor::_set_show_errors_panel(bool p_show) {
is_errors_panel_opened = p_show;
- emit_signal("show_errors_panel", p_show);
+ emit_signal(SNAME("show_errors_panel"), p_show);
}
void CodeTextEditor::_set_show_warnings_panel(bool p_show) {
is_warnings_panel_opened = p_show;
- emit_signal("show_warnings_panel", p_show);
+ emit_signal(SNAME("show_warnings_panel"), p_show);
}
void CodeTextEditor::_toggle_scripts_pressed() {
if (is_layout_rtl()) {
- toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon("Forward", "EditorIcons") : get_theme_icon("Back", "EditorIcons"));
+ toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
} else {
- toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons"));
+ toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon(SNAME("Back"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
}
}
@@ -1666,8 +1666,8 @@ void CodeTextEditor::_notification(int p_what) {
_update_font();
} break;
case NOTIFICATION_ENTER_TREE: {
- error_button->set_icon(get_theme_icon("StatusError", "EditorIcons"));
- warning_button->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
+ error_button->set_icon(get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons")));
+ warning_button->set_icon(get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")));
add_theme_constant_override("separation", 4 * EDSCALE);
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -1779,9 +1779,9 @@ void CodeTextEditor::show_toggle_scripts_button() {
void CodeTextEditor::update_toggle_scripts_button() {
if (is_layout_rtl()) {
- toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon("Forward", "EditorIcons") : get_theme_icon("Back", "EditorIcons"));
+ toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
} else {
- toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons"));
+ toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon(SNAME("Back"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
}
toggle_scripts_button->set_tooltip(TTR("Toggle Scripts Panel") + " (" + ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text() + ")");
}
@@ -1871,9 +1871,9 @@ CodeTextEditor::CodeTextEditor() {
error_button->connect("pressed", callable_mp(this, &CodeTextEditor::_error_button_pressed));
error_button->set_tooltip(TTR("Errors"));
- error_button->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"));
- error_button->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
- error_button->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
+ error_button->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ error_button->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ error_button->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
is_errors_panel_opened = false;
set_error_count(0);
@@ -1887,9 +1887,9 @@ CodeTextEditor::CodeTextEditor() {
warning_button->connect("pressed", callable_mp(this, &CodeTextEditor::_warning_button_pressed));
warning_button->set_tooltip(TTR("Warnings"));
- warning_button->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor"));
- warning_button->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
- warning_button->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
+ warning_button->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ warning_button->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ warning_button->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
is_warnings_panel_opened = false;
set_warning_count(0);
@@ -1898,8 +1898,8 @@ CodeTextEditor::CodeTextEditor() {
line_and_col_txt = memnew(Label);
status_bar->add_child(line_and_col_txt);
line_and_col_txt->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
- line_and_col_txt->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
- line_and_col_txt->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
+ line_and_col_txt->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ line_and_col_txt->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
line_and_col_txt->set_tooltip(TTR("Line and column numbers."));
line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP);
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 28b09e0a5d..0e5a84b3d5 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -225,7 +225,7 @@ public:
void move_lines_up();
void move_lines_down();
void delete_lines();
- void clone_lines_down();
+ void duplicate_selection();
/// Toggle inline comment on currently selected lines, or on current line if nothing is selected,
/// by adding or removing comment delimiter
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index de6407da73..c439d6a1d4 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -134,7 +134,7 @@ void ConnectDialog::ok_pressed() {
return;
}
}
- emit_signal("connected");
+ emit_signal(SNAME("connected"));
hide();
}
@@ -360,7 +360,7 @@ void ConnectDialog::init(ConnectionData c, bool bEdit) {
void ConnectDialog::popup_dialog(const String &p_for_signal) {
from_signal->set_text(p_for_signal);
- error_label->add_theme_color_override("font_color", error_label->get_theme_color("error_color", "Editor"));
+ error_label->add_theme_color_override("font_color", error_label->get_theme_color(SNAME("error_color"), SNAME("Editor")));
if (!advanced->is_pressed()) {
error_label->set_visible(!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root()));
}
@@ -509,13 +509,13 @@ ConnectDialog::~ConnectDialog() {
// Originally copied and adapted from EditorProperty, try to keep style in sync.
Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const {
EditorHelpBit *help_bit = memnew(EditorHelpBit);
- help_bit->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel"));
+ help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")));
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
String text = TTR("Signal:") + " [u][b]" + p_text.get_slice("::", 0) + "[/b][/u]";
text += p_text.get_slice("::", 1).strip_edges() + "\n";
text += p_text.get_slice("::", 2).strip_edges();
- help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene
+ help_bit->call_deferred(SNAME("set_text"), text); //hack so it uses proper theme once inside scene
return help_bit;
}
@@ -591,7 +591,7 @@ void ConnectionsDock::_make_or_edit_connection() {
it = nullptr;
if (add_script_function) {
- editor->emit_signal("script_add_function_request", target, cToMake.method, script_function_args);
+ editor->emit_signal(SNAME("script_add_function_request"), target, cToMake.method, script_function_args);
hide();
}
@@ -921,14 +921,14 @@ void ConnectionsDock::update_tree() {
}
} else {
ClassDB::get_signal_list(base, &node_signals2, true);
- if (has_theme_icon(base, "EditorIcons")) {
- icon = get_theme_icon(base, "EditorIcons");
+ if (has_theme_icon(base, SNAME("EditorIcons"))) {
+ icon = get_theme_icon(base, SNAME("EditorIcons"));
}
name = base;
}
if (!icon.is_valid()) {
- icon = get_theme_icon("Object", "EditorIcons");
+ icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
}
TreeItem *section_item = nullptr;
@@ -940,7 +940,7 @@ void ConnectionsDock::update_tree() {
section_item->set_icon(0, icon);
section_item->set_selectable(0, false);
section_item->set_editable(0, false);
- section_item->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor"));
+ section_item->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
node_signals2.sort();
}
@@ -982,7 +982,7 @@ void ConnectionsDock::update_tree() {
sinfo["name"] = signal_name;
sinfo["args"] = argnames;
signal_item->set_metadata(0, sinfo);
- signal_item->set_icon(0, get_theme_icon("Signal", "EditorIcons"));
+ signal_item->set_icon(0, get_theme_icon(SNAME("Signal"), SNAME("EditorIcons")));
// Set tooltip with the signal's documentation.
{
@@ -1059,7 +1059,7 @@ void ConnectionsDock::update_tree() {
connection_item->set_text(0, path);
Connection cd = c;
connection_item->set_metadata(0, cd);
- connection_item->set_icon(0, get_theme_icon("Slot", "EditorIcons"));
+ connection_item->set_icon(0, get_theme_icon(SNAME("Slot"), SNAME("EditorIcons")));
}
}
@@ -1083,7 +1083,7 @@ ConnectionsDock::ConnectionsDock(EditorNode *p_editor) {
search_box = memnew(LineEdit);
search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search_box->set_placeholder(TTR("Filter signals"));
- search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
search_box->connect("text_changed", callable_mp(this, &ConnectionsDock::_filter_changed));
vbc->add_child(search_box);
@@ -1121,7 +1121,7 @@ ConnectionsDock::ConnectionsDock(EditorNode *p_editor) {
add_child(slot_menu);
slot_menu->connect("id_pressed", callable_mp(this, &ConnectionsDock::_handle_slot_menu_option));
slot_menu->add_item(TTR("Edit..."), EDIT);
- slot_menu->add_item(TTR("Go To Method"), GO_TO_SCRIPT);
+ slot_menu->add_item(TTR("Go to Method"), GO_TO_SCRIPT);
slot_menu->add_item(TTR("Disconnect"), DISCONNECT);
connect_dialog->connect("connected", callable_mp(this, &ConnectionsDock::_make_or_edit_connection));
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 027cee3f1c..bfbd697409 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -40,7 +40,7 @@
void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_select_type) {
_fill_type_list();
- icon_fallback = search_options->has_theme_icon(base_type, "EditorIcons") ? base_type : "Object";
+ icon_fallback = search_options->has_theme_icon(base_type, SNAME("EditorIcons")) ? base_type : "Object";
if (p_dont_clear) {
search_box->select_all();
@@ -168,7 +168,7 @@ void CreateDialog::_update_search() {
TreeItem *root = search_options->create_item();
root->set_text(0, base_type);
- root->set_icon(0, search_options->get_theme_icon(icon_fallback, "EditorIcons"));
+ root->set_icon(0, search_options->get_theme_icon(icon_fallback, SNAME("EditorIcons")));
search_options_types[base_type] = root;
_configure_search_option_item(root, base_type, ClassDB::class_exists(base_type));
@@ -195,7 +195,8 @@ void CreateDialog::_update_search() {
select_type(_top_result(candidates, search_text));
} else {
favorite->set_disabled(true);
- help_bit->set_text("");
+ help_bit->set_text(vformat(TTR("No results for \"%s\"."), search_text));
+ help_bit->get_rich_text()->set_self_modulate(Color(1, 1, 1, 0.5));
get_ok_button()->set_disabled(true);
search_options->deselect_all();
}
@@ -236,7 +237,7 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
bool can_instantiate = (p_cpp_type && ClassDB::can_instantiate(p_type)) || !p_cpp_type;
if (!can_instantiate) {
- r_item->set_custom_color(0, search_options->get_theme_color("disabled_font_color", "Editor"));
+ r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, "NodeDisabled"));
r_item->set_selectable(0, false);
} else {
@@ -338,7 +339,7 @@ void CreateDialog::_confirmed() {
memdelete(f);
}
- emit_signal("create");
+ emit_signal(SNAME("create"));
hide();
_cleanup();
}
@@ -366,16 +367,16 @@ void CreateDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
connect("confirmed", callable_mp(this, &CreateDialog::_confirmed));
- search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(search_options->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
- favorite->set_icon(search_options->get_theme_icon("Favorites", "EditorIcons"));
+ favorite->set_icon(search_options->get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_EXIT_TREE: {
disconnect("confirmed", callable_mp(this, &CreateDialog::_confirmed));
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
if (is_visible()) {
- search_box->call_deferred("grab_focus"); // still not visible
+ search_box->call_deferred(SNAME("grab_focus")); // still not visible
search_box->select_all();
} else {
EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "create_new_node", Rect2(get_position(), get_size()));
@@ -393,8 +394,15 @@ void CreateDialog::select_type(const String &p_type) {
to_select->select(0);
search_options->scroll_to_item(to_select);
- if (EditorHelp::get_doc_data()->class_list.has(p_type)) {
- help_bit->set_text(DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description));
+ if (EditorHelp::get_doc_data()->class_list.has(p_type) && !DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description).is_empty()) {
+ // Display both class name and description, since the help bit may be displayed
+ // far away from the location (especially if the dialog was resized to be taller).
+ help_bit->set_text(vformat("[b]%s[/b]: %s", p_type, DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description)));
+ help_bit->get_rich_text()->set_self_modulate(Color(1, 1, 1, 1));
+ } else {
+ // Use nested `vformat()` as translators shouldn't interfere with BBCode tags.
+ help_bit->set_text(vformat(TTR("No description available for %s."), vformat("[b]%s[/b]", p_type)));
+ help_bit->get_rich_text()->set_self_modulate(Color(1, 1, 1, 0.5));
}
favorite->set_disabled(false);
@@ -607,7 +615,7 @@ void CreateDialog::_save_and_update_favorite_list() {
memdelete(f);
}
- emit_signal("favorites_updated");
+ emit_signal(SNAME("favorites_updated"));
}
void CreateDialog::_load_favorites_and_history() {
diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp
index 6035cc072e..a629bf6159 100644
--- a/editor/debugger/editor_debugger_inspector.cpp
+++ b/editor/debugger/editor_debugger_inspector.cpp
@@ -41,7 +41,7 @@ bool EditorDebuggerRemoteObject::_set(const StringName &p_name, const Variant &p
}
prop_values[p_name] = p_value;
- emit_signal("value_edited", remote_object_id, p_name, p_value);
+ emit_signal(SNAME("value_edited"), remote_object_id, p_name, p_value);
return true;
}
@@ -114,11 +114,11 @@ void EditorDebuggerInspector::_notification(int p_what) {
}
void EditorDebuggerInspector::_object_edited(ObjectID p_id, const String &p_prop, const Variant &p_value) {
- emit_signal("object_edited", p_id, p_prop, p_value);
+ emit_signal(SNAME("object_edited"), p_id, p_prop, p_value);
}
void EditorDebuggerInspector::_object_selected(ObjectID p_object) {
- emit_signal("object_selected", p_object);
+ emit_signal(SNAME("object_selected"), p_object);
}
ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) {
@@ -190,7 +190,7 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) {
if (old_prop_size == debugObj->prop_list.size() && new_props_added == 0) {
//only some may have changed, if so, then update those, if exist
for (Set<String>::Element *E = changed.front(); E; E = E->next()) {
- emit_signal("object_property_updated", debugObj->remote_object_id, E->get());
+ emit_signal(SNAME("object_property_updated"), debugObj->remote_object_id, E->get());
}
} else {
//full update, because props were added or removed
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index 5f90680115..690ce98cb9 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -55,8 +55,8 @@ EditorDebuggerNode::EditorDebuggerNode() {
singleton = this;
}
- add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_LEFT));
- add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_RIGHT));
+ add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles"))->get_margin(SIDE_LEFT));
+ add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles"))->get_margin(SIDE_RIGHT));
tabs = memnew(TabContainer);
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
@@ -112,7 +112,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
if (tabs->get_tab_count() > 1) {
node->clear_style();
tabs->set_tabs_visible(true);
- tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles"));
+ tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("DebuggerPanel"), SNAME("EditorStyles")));
}
if (!debugger_plugins.is_empty()) {
@@ -135,7 +135,7 @@ void EditorDebuggerNode::_stack_frame_selected(int p_debugger) {
void EditorDebuggerNode::_error_selected(const String &p_file, int p_line, int p_debugger) {
Ref<Script> s = ResourceLoader::load(p_file);
- emit_signal("goto_script_line", s, p_line - 1);
+ emit_signal(SNAME("goto_script_line"), s, p_line - 1);
}
void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_debugger) {
@@ -145,8 +145,8 @@ void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_d
}
stack_script = ResourceLoader::load(file);
const int line = p_debugger->get_stack_script_line() - 1;
- emit_signal("goto_script_line", stack_script, line);
- emit_signal("set_execution", stack_script, line);
+ emit_signal(SNAME("goto_script_line"), stack_script, line);
+ emit_signal(SNAME("set_execution"), stack_script, line);
stack_script.unref(); // Why?!?
}
@@ -226,10 +226,10 @@ void EditorDebuggerNode::_notification(int p_what) {
switch (p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
if (tabs->get_tab_count() > 1) {
- add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_LEFT));
- add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_RIGHT));
+ add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles"))->get_margin(SIDE_LEFT));
+ add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles"))->get_margin(SIDE_RIGHT));
- tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles"));
+ tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("DebuggerPanel"), SNAME("EditorStyles")));
}
} break;
case NOTIFICATION_READY: {
@@ -268,11 +268,11 @@ void EditorDebuggerNode::_notification(int p_what) {
} else {
debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count + warning_count) + ")");
if (error_count >= 1 && warning_count >= 1) {
- debugger_button->set_icon(get_theme_icon("ErrorWarning", "EditorIcons"));
+ debugger_button->set_icon(get_theme_icon(SNAME("ErrorWarning"), SNAME("EditorIcons")));
} else if (error_count >= 1) {
- debugger_button->set_icon(get_theme_icon("Error", "EditorIcons"));
+ debugger_button->set_icon(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
} else {
- debugger_button->set_icon(get_theme_icon("Warning", "EditorIcons"));
+ debugger_button->set_icon(get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
}
}
last_error_count = error_count;
@@ -359,7 +359,7 @@ void EditorDebuggerNode::_debugger_wants_stop(int p_id) {
// Ask editor to kill PID.
int pid = get_debugger(p_id)->get_remote_pid();
if (pid) {
- EditorNode::get_singleton()->call_deferred("stop_child_process", pid);
+ EditorNode::get_singleton()->call_deferred(SNAME("stop_child_process"), pid);
}
}
@@ -475,7 +475,7 @@ void EditorDebuggerNode::_breaked(bool p_breaked, bool p_can_debug, int p_debugg
}
_break_state_changed();
EditorNode::get_singleton()->get_pause_button()->set_pressed(p_breaked);
- emit_signal("breaked", p_breaked, p_can_debug);
+ emit_signal(SNAME("breaked"), p_breaked, p_can_debug);
}
bool EditorDebuggerNode::is_skip_breakpoints() const {
diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h
index 3510ac0726..9a40383c17 100644
--- a/editor/debugger/editor_debugger_node.h
+++ b/editor/debugger/editor_debugger_node.h
@@ -123,7 +123,7 @@ protected:
void _save_node_requested(ObjectID p_id, const String &p_file, int p_debugger);
void _clear_execution(REF p_script) {
- emit_signal("clear_execution", p_script);
+ emit_signal(SNAME("clear_execution"), p_script);
}
void _text_editor_stack_goto(const ScriptEditorDebugger *p_debugger);
diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp
index ec92edc795..1feab98948 100644
--- a/editor/debugger/editor_debugger_tree.cpp
+++ b/editor/debugger/editor_debugger_tree.cpp
@@ -75,7 +75,7 @@ void EditorDebuggerTree::_scene_tree_selected() {
inspected_object_id = uint64_t(item->get_metadata(0));
- emit_signal("object_selected", inspected_object_id, debugger_id);
+ emit_signal(SNAME("object_selected"), inspected_object_id, debugger_id);
}
void EditorDebuggerTree::_scene_tree_folded(Object *p_obj) {
@@ -105,8 +105,8 @@ void EditorDebuggerTree::_scene_tree_rmb_selected(const Vector2 &p_position) {
item->select(0);
item_menu->clear();
- item_menu->add_icon_item(get_theme_icon("CreateNewSceneFrom", "EditorIcons"), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE);
- item_menu->add_icon_item(get_theme_icon("CopyNodePath", "EditorIcons"), TTR("Copy Node Path"), ITEM_MENU_COPY_NODE_PATH);
+ item_menu->add_icon_item(get_theme_icon(SNAME("CreateNewSceneFrom"), SNAME("EditorIcons")), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE);
+ item_menu->add_icon_item(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), TTR("Copy Node Path"), ITEM_MENU_COPY_NODE_PATH);
item_menu->set_position(get_screen_transform().xform(get_local_mouse_position()));
item_menu->popup();
}
@@ -211,7 +211,7 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
}
debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree
if (scroll_item) {
- call_deferred("scroll_to_item", scroll_item);
+ call_deferred(SNAME("scroll_to_item"), scroll_item);
}
last_filter = filter;
updating_scene_tree = false;
@@ -279,5 +279,5 @@ void EditorDebuggerTree::_file_selected(const String &p_file) {
if (inspected_object_id.is_null()) {
return;
}
- emit_signal("save_node", inspected_object_id, p_file, debugger_id);
+ emit_signal(SNAME("save_node"), inspected_object_id, p_file, debugger_id);
}
diff --git a/editor/debugger/editor_network_profiler.cpp b/editor/debugger/editor_network_profiler.cpp
index 2d57dff69d..9479fbd5d4 100644
--- a/editor/debugger/editor_network_profiler.cpp
+++ b/editor/debugger/editor_network_profiler.cpp
@@ -40,14 +40,14 @@ void EditorNetworkProfiler::_bind_methods() {
void EditorNetworkProfiler::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- activate->set_icon(get_theme_icon("Play", "EditorIcons"));
- clear_button->set_icon(get_theme_icon("Clear", "EditorIcons"));
- incoming_bandwidth_text->set_right_icon(get_theme_icon("ArrowDown", "EditorIcons"));
- outgoing_bandwidth_text->set_right_icon(get_theme_icon("ArrowUp", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
+ incoming_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons")));
+ outgoing_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")));
// This needs to be done here to set the faded color when the profiler is first opened
- incoming_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color("font_color", "Editor") * Color(1, 1, 1, 0.5));
- outgoing_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color("font_color", "Editor") * Color(1, 1, 1, 0.5));
+ incoming_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5));
+ outgoing_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5));
}
}
@@ -73,13 +73,13 @@ void EditorNetworkProfiler::_update_frame() {
void EditorNetworkProfiler::_activate_pressed() {
if (activate->is_pressed()) {
- activate->set_icon(get_theme_icon("Stop", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
activate->set_text(TTR("Stop"));
} else {
- activate->set_icon(get_theme_icon("Play", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
activate->set_text(TTR("Start"));
}
- emit_signal("enable_profiling", activate->is_pressed());
+ emit_signal(SNAME("enable_profiling"), activate->is_pressed());
}
void EditorNetworkProfiler::_clear_pressed() {
@@ -114,10 +114,10 @@ void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) {
// Make labels more prominent when the bandwidth is greater than 0 to attract user attention
incoming_bandwidth_text->add_theme_color_override(
"font_uneditable_color",
- get_theme_color("font_color", "Editor") * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5));
+ get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5));
outgoing_bandwidth_text->add_theme_color_override(
"font_uneditable_color",
- get_theme_color("font_color", "Editor") * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5));
+ get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5));
}
bool EditorNetworkProfiler::is_profiling() {
@@ -178,19 +178,24 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
counters_display->set_column_titles_visible(true);
counters_display->set_column_title(0, TTR("Node"));
counters_display->set_column_expand(0, true);
- counters_display->set_column_min_width(0, 60 * EDSCALE);
+ counters_display->set_column_clip_content(0, true);
+ counters_display->set_column_custom_minimum_width(0, 60 * EDSCALE);
counters_display->set_column_title(1, TTR("Incoming RPC"));
counters_display->set_column_expand(1, false);
- counters_display->set_column_min_width(1, 120 * EDSCALE);
+ counters_display->set_column_clip_content(1, true);
+ counters_display->set_column_custom_minimum_width(1, 120 * EDSCALE);
counters_display->set_column_title(2, TTR("Incoming RSET"));
counters_display->set_column_expand(2, false);
- counters_display->set_column_min_width(2, 120 * EDSCALE);
+ counters_display->set_column_clip_content(2, true);
+ counters_display->set_column_custom_minimum_width(2, 120 * EDSCALE);
counters_display->set_column_title(3, TTR("Outgoing RPC"));
counters_display->set_column_expand(3, false);
- counters_display->set_column_min_width(3, 120 * EDSCALE);
+ counters_display->set_column_clip_content(3, true);
+ counters_display->set_column_custom_minimum_width(3, 120 * EDSCALE);
counters_display->set_column_title(4, TTR("Outgoing RSET"));
counters_display->set_column_expand(4, false);
- counters_display->set_column_min_width(4, 120 * EDSCALE);
+ counters_display->set_column_clip_content(4, true);
+ counters_display->set_column_custom_minimum_width(4, 120 * EDSCALE);
add_child(counters_display);
frame_delay = memnew(Timer);
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index fc0104c07a..08ed675d16 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -109,9 +109,9 @@ void EditorPerformanceProfiler::_monitor_draw() {
info_message->hide();
- Ref<StyleBox> graph_style_box = get_theme_stylebox("normal", "TextEdit");
- Ref<Font> graph_font = get_theme_font("font", "TextEdit");
- int font_size = get_theme_font_size("font_size", "TextEdit");
+ Ref<StyleBox> graph_style_box = get_theme_stylebox(SNAME("normal"), SNAME("TextEdit"));
+ Ref<Font> graph_font = get_theme_font(SNAME("font"), SNAME("TextEdit"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("TextEdit"));
int columns = int(Math::ceil(Math::sqrt(float(active.size()))));
int rows = int(Math::ceil(float(active.size()) / float(columns)));
@@ -130,7 +130,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
rect.position += graph_style_box->get_offset();
rect.size -= graph_style_box->get_minimum_size();
- Color draw_color = get_theme_color("accent_color", "Editor");
+ Color draw_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_color.set_hsv(Math::fmod(hue_shift * float(current.frame_index), 0.9f), draw_color.get_s() * 0.9f, draw_color.get_v() * value_multiplier, 0.6f);
monitor_draw->draw_string(graph_font, rect.position + Point2(0, graph_font->get_ascent(font_size)), current.item->get_text(0), HALIGN_LEFT, rect.size.x, font_size, draw_color);
@@ -271,7 +271,7 @@ void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) {
} else {
marker_key = "";
}
- Ref<StyleBox> graph_style_box = get_theme_stylebox("normal", "TextEdit");
+ Ref<StyleBox> graph_style_box = get_theme_stylebox(SNAME("normal"), SNAME("TextEdit"));
rect.position += graph_style_box->get_offset();
rect.size -= graph_style_box->get_minimum_size();
Vector2 point = mb->get_position() - rect.position;
@@ -380,7 +380,7 @@ EditorPerformanceProfiler::EditorPerformanceProfiler() {
info_message->set_text(TTR("Pick one or more items from the list to display the graph."));
info_message->set_valign(Label::VALIGN_CENTER);
info_message->set_align(Label::ALIGN_CENTER);
- info_message->set_autowrap(true);
+ info_message->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
monitor_draw->add_child(info_message);
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 1bfef67e8c..6b015e1fda 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -135,11 +135,11 @@ String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_ca
}
Color EditorProfiler::_get_color_from_signature(const StringName &p_signature) const {
- Color bc = get_theme_color("error_color", "Editor");
+ Color bc = get_theme_color(SNAME("error_color"), SNAME("Editor"));
double rot = ABS(double(p_signature.hash()) / double(0x7FFFFFFF));
Color c;
c.set_hsv(rot, bc.get_s(), bc.get_v());
- return c.lerp(get_theme_color("base_color", "Editor"), 0.07);
+ return c.lerp(get_theme_color(SNAME("base_color"), SNAME("Editor")), 0.07);
}
void EditorProfiler::_item_edited() {
@@ -180,7 +180,7 @@ void EditorProfiler::_update_plot() {
}
uint8_t *wr = graph_image.ptrw();
- const Color background_color = get_theme_color("dark_color_2", "Editor");
+ const Color background_color = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
// Clear the previous frame and set the background color.
for (int i = 0; i < desired_len; i += 4) {
@@ -315,7 +315,7 @@ void EditorProfiler::_update_plot() {
graph_texture->create_from_image(img);
}
- graph_texture->update(img, true);
+ graph_texture->update(img);
graph->set_texture(graph_texture);
graph->update();
@@ -356,7 +356,7 @@ void EditorProfiler::_update_frame() {
item->set_metadata(1, it.script);
item->set_metadata(2, it.line);
item->set_text_align(2, TreeItem::ALIGN_RIGHT);
- item->set_tooltip(0, it.script + ":" + itos(it.line));
+ item->set_tooltip(0, it.name + "\n" + it.script + ":" + itos(it.line));
float time = dtime == DISPLAY_SELF_TIME ? it.self : it.total;
@@ -376,14 +376,14 @@ void EditorProfiler::_update_frame() {
void EditorProfiler::_activate_pressed() {
if (activate->is_pressed()) {
- activate->set_icon(get_theme_icon("Stop", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
activate->set_text(TTR("Stop"));
_clear_pressed();
} else {
- activate->set_icon(get_theme_icon("Play", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
activate->set_text(TTR("Start"));
}
- emit_signal("enable_profiling", activate->is_pressed());
+ emit_signal(SNAME("enable_profiling"), activate->is_pressed());
}
void EditorProfiler::_clear_pressed() {
@@ -394,8 +394,8 @@ void EditorProfiler::_clear_pressed() {
void EditorProfiler::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
- activate->set_icon(get_theme_icon("Play", "EditorIcons"));
- clear_button->set_icon(get_theme_icon("Clear", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
}
}
@@ -462,7 +462,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
if (activate->is_pressed()) {
if (!seeking) {
- emit_signal("break_request");
+ emit_signal(SNAME("break_request"));
}
}
@@ -631,13 +631,16 @@ EditorProfiler::EditorProfiler() {
variables->set_column_titles_visible(true);
variables->set_column_title(0, TTR("Name"));
variables->set_column_expand(0, true);
- variables->set_column_min_width(0, 60 * EDSCALE);
+ variables->set_column_clip_content(0, true);
+ variables->set_column_expand_ratio(0, 60);
variables->set_column_title(1, TTR("Time"));
variables->set_column_expand(1, false);
- variables->set_column_min_width(1, 100 * EDSCALE);
+ variables->set_column_clip_content(1, true);
+ variables->set_column_expand_ratio(1, 100);
variables->set_column_title(2, TTR("Calls"));
variables->set_column_expand(2, false);
- variables->set_column_min_width(2, 60 * EDSCALE);
+ variables->set_column_clip_content(2, true);
+ variables->set_column_expand_ratio(2, 60);
variables->connect("item_edited", callable_mp(this, &EditorProfiler::_item_edited));
graph = memnew(TextureRect);
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index cc2e00d021..a61e9bd73e 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -123,11 +123,11 @@ String EditorVisualProfiler::_get_time_as_text(float p_time) {
}
Color EditorVisualProfiler::_get_color_from_signature(const StringName &p_signature) const {
- Color bc = get_theme_color("error_color", "Editor");
+ Color bc = get_theme_color(SNAME("error_color"), SNAME("Editor"));
double rot = ABS(double(p_signature.hash()) / double(0x7FFFFFFF));
Color c;
c.set_hsv(rot, bc.get_s(), bc.get_v());
- return c.lerp(get_theme_color("base_color", "Editor"), 0.07);
+ return c.lerp(get_theme_color(SNAME("base_color"), SNAME("Editor")), 0.07);
}
void EditorVisualProfiler::_item_selected() {
@@ -309,7 +309,7 @@ void EditorVisualProfiler::_update_plot() {
graph_texture->create_from_image(img);
}
- graph_texture->update(img, true);
+ graph_texture->update(img);
graph->set_texture(graph_texture);
graph->update();
@@ -318,7 +318,7 @@ void EditorVisualProfiler::_update_plot() {
void EditorVisualProfiler::_update_frame(bool p_focus_selected) {
int cursor_metric = _get_cursor_index();
- Ref<Texture> track_icon = get_theme_icon("TrackColor", "EditorIcons");
+ Ref<Texture> track_icon = get_theme_icon(SNAME("TrackColor"), SNAME("EditorIcons"));
ERR_FAIL_INDEX(cursor_metric, frame_metrics.size());
@@ -407,14 +407,14 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) {
void EditorVisualProfiler::_activate_pressed() {
if (activate->is_pressed()) {
- activate->set_icon(get_theme_icon("Stop", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
activate->set_text(TTR("Stop"));
_clear_pressed(); //always clear on start
} else {
- activate->set_icon(get_theme_icon("Play", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
activate->set_text(TTR("Start"));
}
- emit_signal("enable_profiling", activate->is_pressed());
+ emit_signal(SNAME("enable_profiling"), activate->is_pressed());
}
void EditorVisualProfiler::_clear_pressed() {
@@ -425,11 +425,11 @@ void EditorVisualProfiler::_clear_pressed() {
void EditorVisualProfiler::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
if (is_layout_rtl()) {
- activate->set_icon(get_theme_icon("PlayBackwards", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("PlayBackwards"), SNAME("EditorIcons")));
} else {
- activate->set_icon(get_theme_icon("Play", "EditorIcons"));
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
}
- clear_button->set_icon(get_theme_icon("Clear", "EditorIcons"));
+ clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
}
}
@@ -437,8 +437,8 @@ void EditorVisualProfiler::_graph_tex_draw() {
if (last_metric < 0) {
return;
}
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
if (seeking) {
int max_frames = frame_metrics.size();
int frame = cursor_metric_edit->get_value() - (frame_metrics[last_metric].frame_number - max_frames + 1);
@@ -773,13 +773,16 @@ EditorVisualProfiler::EditorVisualProfiler() {
variables->set_column_titles_visible(true);
variables->set_column_title(0, TTR("Name"));
variables->set_column_expand(0, true);
- variables->set_column_min_width(0, 60);
+ variables->set_column_clip_content(0, true);
+ variables->set_column_custom_minimum_width(0, 60);
variables->set_column_title(1, TTR("CPU"));
variables->set_column_expand(1, false);
- variables->set_column_min_width(1, 60 * EDSCALE);
+ variables->set_column_clip_content(1, true);
+ variables->set_column_custom_minimum_width(1, 60 * EDSCALE);
variables->set_column_title(2, TTR("GPU"));
variables->set_column_expand(2, false);
- variables->set_column_min_width(2, 60 * EDSCALE);
+ variables->set_column_clip_content(2, true);
+ variables->set_column_custom_minimum_width(2, 60 * EDSCALE);
variables->connect("cell_selected", callable_mp(this, &EditorVisualProfiler::_item_selected));
graph = memnew(TextureRect);
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 7493cc2a8d..06b02cceb4 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -87,9 +87,9 @@ void ScriptEditorDebugger::debug_copy() {
void ScriptEditorDebugger::debug_skip_breakpoints() {
skip_breakpoints_value = !skip_breakpoints_value;
if (skip_breakpoints_value) {
- skip_breakpoints->set_icon(get_theme_icon("DebugSkipBreakpointsOn", "EditorIcons"));
+ skip_breakpoints->set_icon(get_theme_icon(SNAME("DebugSkipBreakpointsOn"), SNAME("EditorIcons")));
} else {
- skip_breakpoints->set_icon(get_theme_icon("DebugSkipBreakpointsOff", "EditorIcons"));
+ skip_breakpoints->set_icon(get_theme_icon(SNAME("DebugSkipBreakpointsOff"), SNAME("EditorIcons")));
}
Array msg;
@@ -136,11 +136,11 @@ void ScriptEditorDebugger::update_tabs() {
} else {
errors_tab->set_name(TTR("Errors") + " (" + itos(error_count + warning_count) + ")");
if (error_count >= 1 && warning_count >= 1) {
- tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon("ErrorWarning", "EditorIcons"));
+ tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon(SNAME("ErrorWarning"), SNAME("EditorIcons")));
} else if (error_count >= 1) {
- tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon("Error", "EditorIcons"));
+ tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
} else {
- tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon("Warning", "EditorIcons"));
+ tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
}
}
}
@@ -264,7 +264,7 @@ Object *ScriptEditorDebugger::get_remote_object(ObjectID p_id) {
}
void ScriptEditorDebugger::_remote_object_selected(ObjectID p_id) {
- emit_signal("remote_object_requested", p_id);
+ emit_signal(SNAME("remote_object_requested"), p_id);
}
void ScriptEditorDebugger::_remote_object_edited(ObjectID p_id, const String &p_prop, const Variant &p_value) {
@@ -273,7 +273,7 @@ void ScriptEditorDebugger::_remote_object_edited(ObjectID p_id, const String &p_
}
void ScriptEditorDebugger::_remote_object_property_updated(ObjectID p_id, const String &p_property) {
- emit_signal("remote_object_property_updated", p_id, p_property);
+ emit_signal(SNAME("remote_object_property_updated"), p_id, p_property);
}
void ScriptEditorDebugger::_video_mem_request() {
@@ -305,7 +305,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
can_debug = can_continue;
_update_buttons_state();
_set_reason_text(error, MESSAGE_ERROR);
- emit_signal("breaked", true, can_continue);
+ emit_signal(SNAME("breaked"), true, can_continue);
DisplayServer::get_singleton()->window_move_to_foreground();
if (error != "") {
tabs->set_current_tab(0);
@@ -319,7 +319,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
_clear_execution();
_update_buttons_state();
_set_reason_text(TTR("Execution resumed."), MESSAGE_SUCCESS);
- emit_signal("breaked", false, false);
+ emit_signal(SNAME("breaked"), false, false);
profiler->set_enabled(true);
profiler->disable_seeking();
} else if (p_msg == "set_pid") {
@@ -332,12 +332,12 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
} else if (p_msg == "scene:scene_tree") {
scene_tree->nodes.clear();
scene_tree->deserialize(p_data);
- emit_signal("remote_tree_updated");
+ emit_signal(SNAME("remote_tree_updated"));
_update_buttons_state();
} else if (p_msg == "scene:inspect_object") {
ObjectID id = inspector->add_object(p_data);
if (id.is_valid()) {
- emit_signal("remote_object_updated", id);
+ emit_signal(SNAME("remote_object_updated"), id);
}
} else if (p_msg == "memory:usage") {
vmem_tree->clear();
@@ -357,8 +357,8 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
it->set_text(3, String::humanize_size(bytes));
total += bytes;
- if (has_theme_icon(type, "EditorIcons")) {
- it->set_icon(0, get_theme_icon(type, "EditorIcons"));
+ if (has_theme_icon(type, SNAME("EditorIcons"))) {
+ it->set_icon(0, get_theme_icon(type, SNAME("EditorIcons")));
}
}
@@ -698,7 +698,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
network_profiler->set_bandwidth(p_data[0], p_data[1]);
} else if (p_msg == "request_quit") {
- emit_signal("stop_requested");
+ emit_signal(SNAME("stop_requested"));
_stop_and_notify();
} else if (p_msg == "performance:profile_names") {
@@ -739,13 +739,13 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType p_type) {
switch (p_type) {
case MESSAGE_ERROR:
- reason->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ reason->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
break;
case MESSAGE_WARNING:
- reason->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"));
+ reason->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
break;
default:
- reason->add_theme_color_override("font_color", get_theme_color("success_color", "Editor"));
+ reason->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor")));
}
reason->set_text(p_reason);
reason->set_tooltip(p_reason.word_wrap(80));
@@ -754,21 +754,21 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType
void ScriptEditorDebugger::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- skip_breakpoints->set_icon(get_theme_icon("DebugSkipBreakpointsOff", "EditorIcons"));
- copy->set_icon(get_theme_icon("ActionCopy", "EditorIcons"));
+ skip_breakpoints->set_icon(get_theme_icon(SNAME("DebugSkipBreakpointsOff"), SNAME("EditorIcons")));
+ copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
- step->set_icon(get_theme_icon("DebugStep", "EditorIcons"));
- next->set_icon(get_theme_icon("DebugNext", "EditorIcons"));
- dobreak->set_icon(get_theme_icon("Pause", "EditorIcons"));
- docontinue->set_icon(get_theme_icon("DebugContinue", "EditorIcons"));
+ step->set_icon(get_theme_icon(SNAME("DebugStep"), SNAME("EditorIcons")));
+ next->set_icon(get_theme_icon(SNAME("DebugNext"), SNAME("EditorIcons")));
+ dobreak->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
+ docontinue->set_icon(get_theme_icon(SNAME("DebugContinue"), SNAME("EditorIcons")));
le_set->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_live_edit_set));
le_clear->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_live_edit_clear));
error_tree->connect("item_selected", callable_mp(this, &ScriptEditorDebugger::_error_selected));
error_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_error_activated));
- vmem_refresh->set_icon(get_theme_icon("Reload", "EditorIcons"));
- vmem_export->set_icon(get_theme_icon("Save", "EditorIcons"));
+ vmem_refresh->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
+ vmem_export->set_icon(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")));
- reason->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ reason->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
} break;
case NOTIFICATION_PROCESS: {
@@ -793,7 +793,7 @@ void ScriptEditorDebugger::_notification(int p_what) {
} else if (camera_override >= CameraOverride::OVERRIDE_3D_1) {
int viewport_idx = camera_override - CameraOverride::OVERRIDE_3D_1;
Node3DEditorViewport *viewport = Node3DEditor::get_singleton()->get_editor_viewport(viewport_idx);
- Camera3D *const cam = viewport->get_camera();
+ Camera3D *const cam = viewport->get_camera_3d();
Array msg;
msg.push_back(cam->get_camera_transform());
@@ -831,16 +831,16 @@ void ScriptEditorDebugger::_notification(int p_what) {
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
if (tabs->has_theme_stylebox_override("panel")) {
- tabs->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles"));
+ tabs->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox(SNAME("DebuggerPanel"), SNAME("EditorStyles")));
}
- copy->set_icon(get_theme_icon("ActionCopy", "EditorIcons"));
- step->set_icon(get_theme_icon("DebugStep", "EditorIcons"));
- next->set_icon(get_theme_icon("DebugNext", "EditorIcons"));
- dobreak->set_icon(get_theme_icon("Pause", "EditorIcons"));
- docontinue->set_icon(get_theme_icon("DebugContinue", "EditorIcons"));
- vmem_refresh->set_icon(get_theme_icon("Reload", "EditorIcons"));
- vmem_export->set_icon(get_theme_icon("Save", "EditorIcons"));
+ copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
+ step->set_icon(get_theme_icon(SNAME("DebugStep"), SNAME("EditorIcons")));
+ next->set_icon(get_theme_icon(SNAME("DebugNext"), SNAME("EditorIcons")));
+ dobreak->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
+ docontinue->set_icon(get_theme_icon(SNAME("DebugContinue"), SNAME("EditorIcons")));
+ vmem_refresh->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
+ vmem_export->set_icon(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")));
} break;
}
}
@@ -854,7 +854,7 @@ void ScriptEditorDebugger::_clear_execution() {
Dictionary d = ti->get_metadata(0);
stack_script = ResourceLoader::load(d["file"]);
- emit_signal("clear_execution", stack_script);
+ emit_signal(SNAME("clear_execution"), stack_script);
stack_script.unref();
stack_dump->clear();
inspector->clear_stack_variables();
@@ -878,7 +878,7 @@ void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) {
tabs->set_current_tab(0);
_set_reason_text(TTR("Debug session started."), MESSAGE_SUCCESS);
_update_buttons_state();
- emit_signal("started");
+ emit_signal(SNAME("started"));
}
void ScriptEditorDebugger::_update_buttons_state() {
@@ -896,7 +896,7 @@ void ScriptEditorDebugger::_update_buttons_state() {
void ScriptEditorDebugger::_stop_and_notify() {
stop();
- emit_signal("stopped");
+ emit_signal(SNAME("stopped"));
_set_reason_text(TTR("Debug session closed."), MESSAGE_WARNING);
}
@@ -959,7 +959,7 @@ void ScriptEditorDebugger::_profiler_seeked() {
}
void ScriptEditorDebugger::_stack_dump_frame_selected() {
- emit_signal("stack_frame_selected");
+ emit_signal(SNAME("stack_frame_selected"));
int frame = get_stack_script_frame();
@@ -1332,7 +1332,7 @@ void ScriptEditorDebugger::_error_selected() {
return;
}
- emit_signal("error_selected", String(meta[0]), int(meta[1]));
+ emit_signal(SNAME("error_selected"), String(meta[0]), int(meta[1]));
}
void ScriptEditorDebugger::_expand_errors_list() {
@@ -1373,8 +1373,8 @@ void ScriptEditorDebugger::_error_tree_item_rmb_selected(const Vector2 &p_pos) {
item_menu->set_size(Size2(1, 1));
if (error_tree->is_anything_selected()) {
- item_menu->add_icon_item(get_theme_icon("ActionCopy", "EditorIcons"), TTR("Copy Error"), ACTION_COPY_ERROR);
- item_menu->add_icon_item(get_theme_icon("Instance", "EditorIcons"), TTR("Open C++ Source on GitHub"), ACTION_OPEN_SOURCE);
+ 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);
}
if (item_menu->get_item_count() > 0) {
@@ -1393,9 +1393,9 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
String type;
- if (ti->get_icon(0) == get_theme_icon("Warning", "EditorIcons")) {
+ if (ti->get_icon(0) == get_theme_icon(SNAME("Warning"), SNAME("EditorIcons"))) {
type = "W ";
- } else if (ti->get_icon(0) == get_theme_icon("Error", "EditorIcons")) {
+ } else if (ti->get_icon(0) == get_theme_icon(SNAME("Error"), SNAME("EditorIcons"))) {
type = "E ";
}
@@ -1518,7 +1518,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
tabs = memnew(TabContainer);
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
- tabs->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles"));
+ tabs->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox(SNAME("DebuggerPanel"), SNAME("EditorStyles")));
tabs->connect("tab_changed", callable_mp(this, &ScriptEditorDebugger::_tab_changed));
add_child(tabs);
@@ -1535,7 +1535,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
reason->set_text("");
hbc->add_child(reason);
reason->set_h_size_flags(SIZE_EXPAND_FILL);
- reason->set_autowrap(true);
+ reason->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
reason->set_max_lines_visible(3);
reason->set_mouse_filter(Control::MOUSE_FILTER_PASS);
@@ -1643,9 +1643,11 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
error_tree->set_columns(2);
error_tree->set_column_expand(0, false);
- error_tree->set_column_min_width(0, 140);
+ error_tree->set_column_custom_minimum_width(0, 140);
+ error_tree->set_column_clip_content(0, true);
error_tree->set_column_expand(1, true);
+ error_tree->set_column_clip_content(1, true);
error_tree->set_select_mode(Tree::SELECT_ROW);
error_tree->set_hide_root(true);
@@ -1698,6 +1700,8 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
VBoxContainer *vmem_vb = memnew(VBoxContainer);
HBoxContainer *vmem_hb = memnew(HBoxContainer);
Label *vmlb = memnew(Label(TTR("List of Video Memory Usage by Resource:") + " "));
+ vmlb->set_theme_type_variation("HeaderSmall");
+
vmlb->set_h_size_flags(SIZE_EXPAND_FILL);
vmem_hb->add_child(vmlb);
vmem_hb->add_child(memnew(Label(TTR("Total:") + " ")));
@@ -1731,13 +1735,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
vmem_tree->set_column_expand(0, true);
vmem_tree->set_column_expand(1, false);
vmem_tree->set_column_title(1, TTR("Type"));
- vmem_tree->set_column_min_width(1, 100 * EDSCALE);
+ vmem_tree->set_column_custom_minimum_width(1, 100 * EDSCALE);
vmem_tree->set_column_expand(2, false);
vmem_tree->set_column_title(2, TTR("Format"));
- vmem_tree->set_column_min_width(2, 150 * EDSCALE);
+ vmem_tree->set_column_custom_minimum_width(2, 150 * EDSCALE);
vmem_tree->set_column_expand(3, false);
vmem_tree->set_column_title(3, TTR("Usage"));
- vmem_tree->set_column_min_width(3, 80 * EDSCALE);
+ vmem_tree->set_column_custom_minimum_width(3, 80 * EDSCALE);
vmem_tree->set_hide_root(true);
tabs->add_child(vmem_vb);
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 7534b419fe..c18b8743cd 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -162,7 +162,7 @@ void DependencyEditor::_update_list() {
TreeItem *root = tree->create_item();
- Ref<Texture2D> folder = tree->get_theme_icon("folder", "FileDialog");
+ Ref<Texture2D> folder = tree->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
bool broken = false;
@@ -226,12 +226,18 @@ DependencyEditor::DependencyEditor() {
tree->set_columns(2);
tree->set_column_titles_visible(true);
tree->set_column_title(0, TTR("Resource"));
+ tree->set_column_clip_content(0, true);
+ tree->set_column_expand_ratio(0, 2);
tree->set_column_title(1, TTR("Path"));
+ tree->set_column_clip_content(1, true);
+ tree->set_column_expand_ratio(1, 1);
tree->set_hide_root(true);
tree->connect("button_pressed", callable_mp(this, &DependencyEditor::_load_pressed));
HBoxContainer *hbc = memnew(HBoxContainer);
Label *label = memnew(Label(TTR("Dependencies:")));
+ label->set_theme_type_variation("HeaderSmall");
+
hbc->add_child(label);
hbc->add_spacer();
fixdeps = memnew(Button(TTR("Fix Broken")));
@@ -272,7 +278,7 @@ void DependencyEditorOwners::_select_file(int p_idx) {
if (ResourceLoader::get_resource_type(fpath) == "PackedScene") {
editor->open_request(fpath);
hide();
- emit_signal("confirmed");
+ emit_signal(SNAME("confirmed"));
}
}
@@ -406,17 +412,17 @@ void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<Removed
if (!tree_items.has(rd.dependency_folder)) {
TreeItem *folder_item = owners->create_item(owners->get_root());
folder_item->set_text(0, rd.dependency_folder);
- folder_item->set_icon(0, owners->get_theme_icon("Folder", "EditorIcons"));
+ folder_item->set_icon(0, owners->get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
tree_items[rd.dependency_folder] = folder_item;
}
TreeItem *dependency_item = owners->create_item(tree_items[rd.dependency_folder]);
dependency_item->set_text(0, rd.dependency);
- dependency_item->set_icon(0, owners->get_theme_icon("Warning", "EditorIcons"));
+ dependency_item->set_icon(0, owners->get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
tree_items[rd.dependency] = dependency_item;
} else {
TreeItem *dependency_item = owners->create_item(owners->get_root());
dependency_item->set_text(0, rd.dependency);
- dependency_item->set_icon(0, owners->get_theme_icon("Warning", "EditorIcons"));
+ dependency_item->set_icon(0, owners->get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
tree_items[rd.dependency] = dependency_item;
}
}
@@ -502,7 +508,7 @@ void DependencyRemoveDialog::ok_pressed() {
if (err != OK) {
EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:") + "\n" + files_to_delete[i] + "\n");
} else {
- emit_signal("file_removed", files_to_delete[i]);
+ emit_signal(SNAME("file_removed"), files_to_delete[i]);
}
}
@@ -519,7 +525,7 @@ void DependencyRemoveDialog::ok_pressed() {
if (err != OK) {
EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:") + "\n" + dirs_to_delete[i] + "\n");
} else {
- emit_signal("folder_removed", dirs_to_delete[i]);
+ emit_signal(SNAME("folder_removed"), dirs_to_delete[i]);
}
}
@@ -659,7 +665,7 @@ bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd, HashMa
if (p_parent) {
dir_item = files->create_item(p_parent);
dir_item->set_text(0, efsd->get_subdir(i)->get_name());
- dir_item->set_icon(0, files->get_theme_icon("folder", "FileDialog"));
+ dir_item->set_icon(0, files->get_theme_icon(SNAME("folder"), SNAME("FileDialog")));
}
bool children = _fill_owners(efsd->get_subdir(i), refs, dir_item);
@@ -695,7 +701,7 @@ bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd, HashMa
int ds = efsd->get_file_deps(i).size();
ti->set_text(1, itos(ds));
if (ds) {
- ti->add_button(1, files->get_theme_icon("GuiVisibilityVisible", "EditorIcons"), -1, false, TTR("Show Dependencies"));
+ ti->add_button(1, files->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")), -1, false, TTR("Show Dependencies"));
}
ti->set_metadata(0, path);
has_children = true;
@@ -769,9 +775,11 @@ OrphanResourcesDialog::OrphanResourcesDialog() {
files = memnew(Tree);
files->set_columns(2);
files->set_column_titles_visible(true);
- files->set_column_min_width(1, 100);
+ files->set_column_custom_minimum_width(1, 100 * EDSCALE);
files->set_column_expand(0, true);
+ files->set_column_clip_content(0, true);
files->set_column_expand(1, false);
+ files->set_column_clip_content(1, true);
files->set_column_title(0, TTR("Resource"));
files->set_column_title(1, TTR("Owns"));
files->set_hide_root(true);
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index b8504ad02a..c895e2c158 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -41,15 +41,15 @@
static const String META_TEXT_TO_COPY = "text_to_copy";
void EditorAbout::_theme_changed() {
- const Ref<Font> font = get_theme_font("source", "EditorFonts");
- const int font_size = get_theme_font_size("source_size", "EditorFonts");
+ const Ref<Font> font = get_theme_font(SNAME("source"), SNAME("EditorFonts"));
+ const int font_size = get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts"));
_tpl_text->add_theme_font_override("normal_font", font);
_tpl_text->add_theme_font_size_override("normal_font_size", font_size);
_tpl_text->add_theme_constant_override("line_separation", 6 * EDSCALE);
_license_text->add_theme_font_override("normal_font", font);
_license_text->add_theme_font_size_override("normal_font_size", font_size);
_license_text->add_theme_constant_override("line_separation", 6 * EDSCALE);
- _logo->set_texture(get_theme_icon("Logo", "EditorIcons"));
+ _logo->set_texture(get_theme_icon(SNAME("Logo"), SNAME("EditorIcons")));
}
void EditorAbout::_notification(int p_what) {
@@ -92,6 +92,7 @@ ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List<St
const char *const *names_ptr = p_src[i];
if (*names_ptr) {
Label *lbl = memnew(Label);
+ lbl->set_theme_type_variation("HeaderSmall");
lbl->set_text(p_sections[i]);
vbc->add_child(lbl);
@@ -212,7 +213,7 @@ EditorAbout::EditorAbout() {
Label *tpl_label = memnew(Label);
tpl_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- tpl_label->set_autowrap(true);
+ tpl_label->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
tpl_label->set_text(TTR("Godot Engine relies on a number of third-party free and open source libraries, all compatible with the terms of its MIT license. The following is an exhaustive list of all such third-party components with their respective copyright statements and license terms."));
tpl_label->set_size(Size2(630, 1) * EDSCALE);
license_thirdparty->add_child(tpl_label);
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 38f417a8ce..8dd3045887 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -112,7 +112,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io);
if (!pkg) {
- error->set_text(TTR("Error opening package file, not in ZIP format."));
+ error->set_text(vformat(TTR("Error opening asset file for \"%s\" (not in ZIP format)."), asset_name));
return;
}
@@ -132,17 +132,57 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
Map<String, Ref<Texture2D>> extension_guess;
{
- extension_guess["png"] = tree->get_theme_icon("ImageTexture", "EditorIcons");
- extension_guess["jpg"] = tree->get_theme_icon("ImageTexture", "EditorIcons");
- extension_guess["atlastex"] = tree->get_theme_icon("AtlasTexture", "EditorIcons");
- extension_guess["scn"] = tree->get_theme_icon("PackedScene", "EditorIcons");
- extension_guess["tscn"] = tree->get_theme_icon("PackedScene", "EditorIcons");
- extension_guess["gdshader"] = tree->get_theme_icon("Shader", "EditorIcons");
- extension_guess["gd"] = tree->get_theme_icon("GDScript", "EditorIcons");
- extension_guess["vs"] = tree->get_theme_icon("VisualScript", "EditorIcons");
+ extension_guess["bmp"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["dds"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["exr"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["hdr"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["jpg"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["jpeg"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["png"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["svg"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["svgz"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["tga"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+ extension_guess["webp"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
+
+ extension_guess["wav"] = tree->get_theme_icon(SNAME("AudioStreamSample"), SNAME("EditorIcons"));
+ extension_guess["ogg"] = tree->get_theme_icon(SNAME("AudioStreamOGGVorbis"), SNAME("EditorIcons"));
+ extension_guess["mp3"] = tree->get_theme_icon(SNAME("AudioStreamMP3"), SNAME("EditorIcons"));
+
+ extension_guess["scn"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
+ extension_guess["tscn"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
+ extension_guess["escn"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
+ extension_guess["dae"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
+ extension_guess["gltf"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
+ extension_guess["glb"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
+
+ extension_guess["gdshader"] = tree->get_theme_icon(SNAME("Shader"), SNAME("EditorIcons"));
+ extension_guess["gd"] = tree->get_theme_icon(SNAME("GDScript"), SNAME("EditorIcons"));
+ if (Engine::get_singleton()->has_singleton("GodotSharp")) {
+ extension_guess["cs"] = tree->get_theme_icon(SNAME("CSharpScript"), SNAME("EditorIcons"));
+ } else {
+ // Mark C# support as unavailable.
+ extension_guess["cs"] = tree->get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"));
+ }
+ extension_guess["vs"] = tree->get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons"));
+
+ extension_guess["res"] = tree->get_theme_icon(SNAME("Resource"), SNAME("EditorIcons"));
+ extension_guess["tres"] = tree->get_theme_icon(SNAME("Resource"), SNAME("EditorIcons"));
+ extension_guess["atlastex"] = tree->get_theme_icon(SNAME("AtlasTexture"), SNAME("EditorIcons"));
+ // By default, OBJ files are imported as Mesh resources rather than PackedScenes.
+ extension_guess["obj"] = tree->get_theme_icon(SNAME("Mesh"), SNAME("EditorIcons"));
+
+ extension_guess["txt"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["md"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["rst"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["json"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["yml"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["yaml"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["toml"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["cfg"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ extension_guess["ini"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
}
- Ref<Texture2D> generic_extension = tree->get_theme_icon("Object", "EditorIcons");
+ Ref<Texture2D> generic_extension = tree->get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
unzClose(pkg);
@@ -151,11 +191,13 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
TreeItem *root = tree->create_item();
root->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
root->set_checked(0, true);
- root->set_icon(0, tree->get_theme_icon("folder", "FileDialog"));
+ root->set_icon(0, tree->get_theme_icon(SNAME("folder"), SNAME("FileDialog")));
root->set_text(0, "res://");
root->set_editable(0, true);
Map<String, TreeItem *> dir_map;
+ int num_file_conflicts = 0;
+
for (Set<String>::Element *E = files_sorted.front(); E; E = E->next()) {
String path = E->get();
int depth = p_depth;
@@ -200,7 +242,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
if (isdir) {
dir_map[path] = ti;
ti->set_text(0, path.get_file() + "/");
- ti->set_icon(0, tree->get_theme_icon("folder", "FileDialog"));
+ ti->set_icon(0, tree->get_theme_icon(SNAME("folder"), SNAME("FileDialog")));
ti->set_metadata(0, String());
} else {
String file = path.get_file();
@@ -214,8 +256,9 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
String res_path = "res://" + path;
if (FileAccess::exists(res_path)) {
- ti->set_custom_color(0, tree->get_theme_color("error_color", "Editor"));
- ti->set_tooltip(0, vformat(TTR("%s (Already Exists)"), res_path));
+ num_file_conflicts += 1;
+ ti->set_custom_color(0, tree->get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ ti->set_tooltip(0, vformat(TTR("%s (already exists)"), res_path));
ti->set_checked(0, false);
} else {
ti->set_tooltip(0, res_path);
@@ -226,6 +269,13 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
status_map[E->get()] = ti;
}
+
+ if (num_file_conflicts >= 1) {
+ asset_contents->set_text(vformat(TTR("Contents of asset \"%s\" - %d file(s) conflict with your project:"), asset_name, num_file_conflicts));
+ } else {
+ asset_contents->set_text(vformat(TTR("Contents of asset \"%s\" - No files conflict with your project:"), asset_name));
+ }
+
popup_centered_ratio();
updating = false;
}
@@ -236,7 +286,7 @@ void EditorAssetInstaller::ok_pressed() {
unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io);
if (!pkg) {
- error->set_text(TTR("Error opening package file, not in ZIP format."));
+ error->set_text(vformat(TTR("Error opening asset file for \"%s\" (not in ZIP format)."), asset_name));
return;
}
@@ -303,10 +353,10 @@ void EditorAssetInstaller::ok_pressed() {
unzClose(pkg);
if (failed_files.size()) {
- String msg = TTR("The following files failed extraction from package:") + "\n\n";
+ String msg = vformat(TTR("The following files failed extraction from asset \"%s\":"), asset_name) + "\n\n";
for (int i = 0; i < failed_files.size(); i++) {
if (i > 15) {
- msg += "\n" + vformat(TTR("And %s more files."), itos(failed_files.size() - i));
+ msg += "\n" + vformat(TTR("(and %s more files)"), itos(failed_files.size() - i));
break;
}
msg += failed_files[i];
@@ -316,12 +366,20 @@ void EditorAssetInstaller::ok_pressed() {
}
} else {
if (EditorNode::get_singleton() != nullptr) {
- EditorNode::get_singleton()->show_warning(TTR("Package installed successfully!"), TTR("Success!"));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Asset \"%s\" installed successfully!"), asset_name), TTR("Success!"));
}
}
EditorFileSystem::get_singleton()->scan_changes();
}
+void EditorAssetInstaller::set_asset_name(const String &p_asset_name) {
+ asset_name = p_asset_name;
+}
+
+String EditorAssetInstaller::get_asset_name() const {
+ return asset_name;
+}
+
void EditorAssetInstaller::_bind_methods() {
}
@@ -329,14 +387,18 @@ EditorAssetInstaller::EditorAssetInstaller() {
VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);
+ asset_contents = memnew(Label);
+ vb->add_child(asset_contents);
+
tree = memnew(Tree);
- vb->add_margin_child(TTR("Package Contents:"), tree, true);
+ tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_edited));
+ vb->add_child(tree);
error = memnew(AcceptDialog);
add_child(error);
get_ok_button()->set_text(TTR("Install"));
- set_title(TTR("Package Installer"));
+ set_title(TTR("Asset Installer"));
updating = false;
diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h
index d9233a5ce8..9fafe2792a 100644
--- a/editor/editor_asset_installer.h
+++ b/editor/editor_asset_installer.h
@@ -37,7 +37,9 @@ class EditorAssetInstaller : public ConfirmationDialog {
GDCLASS(EditorAssetInstaller, ConfirmationDialog);
Tree *tree;
+ Label *asset_contents;
String package_path;
+ String asset_name;
AcceptDialog *error;
Map<String, TreeItem *> status_map;
bool updating;
@@ -51,6 +53,10 @@ protected:
public:
void open(const String &p_path, int p_depth = 0);
+
+ void set_asset_name(const String &p_asset_name);
+ String get_asset_name() const;
+
EditorAssetInstaller();
};
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 3e3428ad93..d94ac21837 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -64,42 +64,42 @@ void EditorAudioBus::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
for (int i = 0; i < CHANNELS_MAX; i++) {
- channel[i].vu_l->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_l->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons"));
- channel[i].vu_r->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_r->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons"));
+ channel[i].vu_l->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons")));
+ channel[i].vu_l->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons")));
+ channel[i].vu_r->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons")));
+ channel[i].vu_r->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons")));
channel[i].prev_active = true;
}
- disabled_vu = get_theme_icon("BusVuFrozen", "EditorIcons");
+ disabled_vu = get_theme_icon(SNAME("BusVuFrozen"), SNAME("EditorIcons"));
Color solo_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.89, 0.22) : Color(1.0, 0.92, 0.44);
Color mute_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.16, 0.16) : Color(1.0, 0.44, 0.44);
Color bypass_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(0.13, 0.8, 1.0) : Color(0.44, 0.87, 1.0);
- solo->set_icon(get_theme_icon("AudioBusSolo", "EditorIcons"));
+ solo->set_icon(get_theme_icon(SNAME("AudioBusSolo"), SNAME("EditorIcons")));
solo->add_theme_color_override("icon_pressed_color", solo_color);
- mute->set_icon(get_theme_icon("AudioBusMute", "EditorIcons"));
+ mute->set_icon(get_theme_icon(SNAME("AudioBusMute"), SNAME("EditorIcons")));
mute->add_theme_color_override("icon_pressed_color", mute_color);
- bypass->set_icon(get_theme_icon("AudioBusBypass", "EditorIcons"));
+ bypass->set_icon(get_theme_icon(SNAME("AudioBusBypass"), SNAME("EditorIcons")));
bypass->add_theme_color_override("icon_pressed_color", bypass_color);
- bus_options->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
+ bus_options->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
update_bus();
set_process(true);
} break;
case NOTIFICATION_DRAW: {
if (is_master) {
- draw_style_box(get_theme_stylebox("disabled", "Button"), Rect2(Vector2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("disabled"), SNAME("Button")), Rect2(Vector2(), get_size()));
} else if (has_focus()) {
- draw_style_box(get_theme_stylebox("focus", "Button"), Rect2(Vector2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("focus"), SNAME("Button")), Rect2(Vector2(), get_size()));
} else {
- draw_style_box(get_theme_stylebox("panel", "TabContainer"), Rect2(Vector2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")), Rect2(Vector2(), get_size()));
}
if (get_index() != 0 && hovering_drop) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
accent.a *= 0.7;
draw_rect(Rect2(Point2(), get_size()), accent, false);
}
@@ -159,23 +159,23 @@ void EditorAudioBus::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
for (int i = 0; i < CHANNELS_MAX; i++) {
- channel[i].vu_l->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_l->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons"));
- channel[i].vu_r->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_r->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons"));
+ channel[i].vu_l->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons")));
+ channel[i].vu_l->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons")));
+ channel[i].vu_r->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons")));
+ channel[i].vu_r->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons")));
channel[i].prev_active = true;
}
- disabled_vu = get_theme_icon("BusVuFrozen", "EditorIcons");
+ disabled_vu = get_theme_icon(SNAME("BusVuFrozen"), SNAME("EditorIcons"));
- solo->set_icon(get_theme_icon("AudioBusSolo", "EditorIcons"));
- mute->set_icon(get_theme_icon("AudioBusMute", "EditorIcons"));
- bypass->set_icon(get_theme_icon("AudioBusBypass", "EditorIcons"));
+ solo->set_icon(get_theme_icon(SNAME("AudioBusSolo"), SNAME("EditorIcons")));
+ mute->set_icon(get_theme_icon(SNAME("AudioBusMute"), SNAME("EditorIcons")));
+ bypass->set_icon(get_theme_icon(SNAME("AudioBusBypass"), SNAME("EditorIcons")));
- bus_options->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
+ bus_options->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- audio_value_preview_box->add_theme_color_override("font_color", get_theme_color("font_color", "TooltipLabel"));
- audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel"));
+ audio_value_preview_box->add_theme_color_override("font_color", get_theme_color(SNAME("font_color"), SNAME("TooltipLabel")));
+ audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")));
} break;
case NOTIFICATION_MOUSE_EXIT:
case NOTIFICATION_DRAG_END: {
@@ -567,12 +567,12 @@ void EditorAudioBus::_effects_gui_input(Ref<InputEvent> p_event) {
void EditorAudioBus::_bus_popup_pressed(int p_option) {
if (p_option == 2) {
// Reset volume
- emit_signal("vol_reset_request");
+ emit_signal(SNAME("vol_reset_request"));
} else if (p_option == 1) {
- emit_signal("delete_request");
+ emit_signal(SNAME("delete_request"));
} else if (p_option == 0) {
//duplicate
- emit_signal("duplicate_request", get_index());
+ emit_signal(SNAME("duplicate_request"), get_index());
}
}
@@ -585,7 +585,7 @@ Variant EditorAudioBus::get_drag_data(const Point2 &p_point) {
Panel *p = memnew(Panel);
c->add_child(p);
p->set_modulate(Color(1, 1, 1, 0.7));
- p->add_theme_style_override("panel", get_theme_stylebox("focus", "Button"));
+ p->add_theme_style_override("panel", get_theme_stylebox(SNAME("focus"), SNAME("Button")));
p->set_size(get_size());
p->set_position(-p_point);
set_drag_preview(c);
@@ -594,7 +594,7 @@ Variant EditorAudioBus::get_drag_data(const Point2 &p_point) {
d["index"] = get_index();
if (get_index() < AudioServer::get_singleton()->get_bus_count() - 1) {
- emit_signal("drop_end_request");
+ emit_signal(SNAME("drop_end_request"));
}
return d;
@@ -616,7 +616,7 @@ bool EditorAudioBus::can_drop_data(const Point2 &p_point, const Variant &p_data)
void EditorAudioBus::drop_data(const Point2 &p_point, const Variant &p_data) {
Dictionary d = p_data;
- emit_signal("dropped", d["index"], get_index());
+ emit_signal(SNAME("dropped"), d["index"], get_index());
}
Variant EditorAudioBus::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
@@ -842,13 +842,13 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
audio_value_preview_label->set_v_size_flags(SIZE_EXPAND_FILL);
audio_value_preview_label->set_h_size_flags(SIZE_EXPAND_FILL);
audio_value_preview_label->set_mouse_filter(MOUSE_FILTER_PASS);
- audio_value_preview_box->add_theme_color_override("font_color", get_theme_color("font_color", "TooltipLabel"));
+ audio_value_preview_box->add_theme_color_override("font_color", get_theme_color(SNAME("font_color"), SNAME("TooltipLabel")));
audioprev_hbc->add_child(audio_value_preview_label);
slider->add_child(audio_value_preview_box);
audio_value_preview_box->set_as_top_level(true);
- audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel"));
+ audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")));
audio_value_preview_box->set_mouse_filter(MOUSE_FILTER_PASS);
audio_value_preview_box->hide();
@@ -955,10 +955,10 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
void EditorAudioBusDrop::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- draw_style_box(get_theme_stylebox("normal", "Button"), Rect2(Vector2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("normal"), SNAME("Button")), Rect2(Vector2(), get_size()));
if (hovering_drop) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
accent.a *= 0.7;
draw_rect(Rect2(Point2(), get_size()), accent, false);
}
@@ -986,7 +986,7 @@ bool EditorAudioBusDrop::can_drop_data(const Point2 &p_point, const Variant &p_d
void EditorAudioBusDrop::drop_data(const Point2 &p_point, const Variant &p_data) {
Dictionary d = p_data;
- emit_signal("dropped", d["index"], AudioServer::get_singleton()->get_bus_count());
+ emit_signal(SNAME("dropped"), d["index"], AudioServer::get_singleton()->get_bus_count());
}
void EditorAudioBusDrop::_bind_methods() {
@@ -1026,7 +1026,7 @@ void EditorAudioBuses::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- bus_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ bus_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
} break;
case NOTIFICATION_READY: {
_update_buses();
@@ -1217,7 +1217,7 @@ void EditorAudioBuses::_load_default_layout() {
AudioServer::get_singleton()->set_bus_layout(state);
_update_buses();
EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
+ call_deferred(SNAME("_select_layout"));
}
void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
@@ -1233,7 +1233,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
AudioServer::get_singleton()->set_bus_layout(state);
_update_buses();
EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
+ call_deferred(SNAME("_select_layout"));
} else if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) {
if (new_layout) {
@@ -1253,7 +1253,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
file->set_text(String(TTR("Layout")) + ": " + p_string.get_file());
_update_buses();
EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
+ call_deferred(SNAME("_select_layout"));
}
}
@@ -1354,7 +1354,7 @@ void EditorAudioBuses::open_layout(const String &p_path) {
AudioServer::get_singleton()->set_bus_layout(state);
_update_buses();
EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
+ call_deferred(SNAME("_select_layout"));
}
void AudioBusesEditorPlugin::edit(Object *p_node) {
@@ -1385,8 +1385,8 @@ void EditorAudioMeterNotches::add_notch(float p_normalized_offset, float p_db_va
}
Size2 EditorAudioMeterNotches::get_minimum_size() const {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
float font_height = font->get_height(font_size);
float width = 0;
@@ -1411,7 +1411,7 @@ void EditorAudioMeterNotches::_bind_methods() {
void EditorAudioMeterNotches::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- notch_color = get_theme_color("font_color", "Editor");
+ notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
} break;
case NOTIFICATION_DRAW: {
_draw_audio_notches();
@@ -1420,8 +1420,8 @@ void EditorAudioMeterNotches::_notification(int p_what) {
}
void EditorAudioMeterNotches::_draw_audio_notches() {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
float font_height = font->get_height(font_size);
for (int i = 0; i < notches.size(); i++) {
@@ -1443,5 +1443,5 @@ void EditorAudioMeterNotches::_draw_audio_notches() {
}
EditorAudioMeterNotches::EditorAudioMeterNotches() {
- notch_color = get_theme_color("font_color", "Editor");
+ notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
}
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index dbb23d8603..c6d52107cd 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -53,12 +53,12 @@ void EditorAutoloadSettings::_notification(int p_what) {
for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
AutoLoadInfo &info = E->get();
if (info.node && info.in_editor) {
- get_tree()->get_root()->call_deferred("add_child", info.node);
+ get_tree()->get_root()->call_deferred(SNAME("add_child"), info.node);
}
}
- browse_button->set_icon(get_theme_icon("Folder", "EditorIcons"));
+ browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
- browse_button->set_icon(get_theme_icon("Folder", "EditorIcons"));
+ browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
}
}
@@ -453,10 +453,10 @@ void EditorAutoloadSettings::update_autoload() {
item->set_editable(2, true);
item->set_text(2, TTR("Enable"));
item->set_checked(2, info.is_singleton);
- item->add_button(3, get_theme_icon("Load", "EditorIcons"), BUTTON_OPEN);
- item->add_button(3, get_theme_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP);
- item->add_button(3, get_theme_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN);
- item->add_button(3, get_theme_icon("Remove", "EditorIcons"), BUTTON_DELETE);
+ item->add_button(3, get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), BUTTON_OPEN);
+ item->add_button(3, get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")), BUTTON_MOVE_UP);
+ item->add_button(3, get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")), BUTTON_MOVE_DOWN);
+ item->add_button(3, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_DELETE);
item->set_selectable(3, false);
}
@@ -470,7 +470,7 @@ void EditorAutoloadSettings::update_autoload() {
}
if (info.in_editor) {
ERR_CONTINUE(!info.node);
- get_tree()->get_root()->call_deferred("remove_child", info.node);
+ get_tree()->get_root()->call_deferred(SNAME("remove_child"), info.node);
}
if (info.node) {
@@ -882,19 +882,17 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
tree->set_column_title(0, TTR("Name"));
tree->set_column_expand(0, true);
- tree->set_column_min_width(0, 100 * EDSCALE);
+ tree->set_column_expand_ratio(0, 1);
tree->set_column_title(1, TTR("Path"));
tree->set_column_expand(1, true);
- tree->set_column_min_width(1, 100 * EDSCALE);
+ tree->set_column_clip_content(1, true);
+ tree->set_column_expand_ratio(1, 2);
tree->set_column_title(2, TTR("Global Variable"));
tree->set_column_expand(2, false);
- // Reserve enough space for translations of "Global Variable" which may be longer.
- tree->set_column_min_width(2, 150 * EDSCALE);
tree->set_column_expand(3, false);
- tree->set_column_min_width(3, 120 * EDSCALE);
tree->connect("cell_selected", callable_mp(this, &EditorAutoloadSettings::_autoload_selected));
tree->connect("item_edited", callable_mp(this, &EditorAutoloadSettings::_autoload_edited));
@@ -916,7 +914,7 @@ EditorAutoloadSettings::~EditorAutoloadSettings() {
void EditorAutoloadSettings::_set_autoload_add_path(const String &p_text) {
autoload_add_path->set_text(p_text);
- autoload_add_path->emit_signal("text_submitted", p_text);
+ autoload_add_path->emit_signal(SNAME("text_submitted"), p_text);
}
void EditorAutoloadSettings::_browse_autoload_add_path() {
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 3823d7e14f..3529a4fbdc 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -1048,7 +1048,7 @@ void EditorSelection::add_node(Node *p_node) {
p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed), varray(p_node), CONNECT_ONESHOT);
- //emit_signal("selection_changed");
+ //emit_signal(SNAME("selection_changed"));
}
void EditorSelection::remove_node(Node *p_node) {
@@ -1066,7 +1066,7 @@ void EditorSelection::remove_node(Node *p_node) {
}
selection.erase(p_node);
p_node->disconnect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed));
- //emit_signal("selection_changed");
+ //emit_signal(SNAME("selection_changed"));
}
bool EditorSelection::is_selected(Node *p_node) const {
@@ -1144,12 +1144,12 @@ void EditorSelection::update() {
changed = false;
if (!emitted) {
emitted = true;
- call_deferred("_emit_change");
+ call_deferred(SNAME("_emit_change"));
}
}
void EditorSelection::_emit_change() {
- emit_signal("selection_changed");
+ emit_signal(SNAME("selection_changed"));
emitted = false;
}
diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp
index 4366d83fe2..5df392b91e 100644
--- a/editor/editor_dir_dialog.cpp
+++ b/editor/editor_dir_dialog.cpp
@@ -43,7 +43,7 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p
String path = p_dir->get_path();
p_item->set_metadata(0, p_dir->get_path());
- p_item->set_icon(0, tree->get_theme_icon("Folder", "EditorIcons"));
+ p_item->set_icon(0, tree->get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
if (!p_item->get_parent()) {
p_item->set_text(0, "res://");
@@ -129,7 +129,7 @@ void EditorDirDialog::ok_pressed() {
}
String dir = ti->get_metadata(0);
- emit_signal("dir_selected", dir);
+ emit_signal(SNAME("dir_selected"), dir);
hide();
}
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 58d2b6e86e..e36cc7bc2e 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -497,7 +497,7 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S
bool disabled_editor = edited->is_class_editor_disabled(p_class);
bool disabled_properties = edited->has_class_properties_disabled(p_class);
if (disabled) {
- class_item->set_custom_color(0, class_list->get_theme_color("disabled_font_color", "Editor"));
+ class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
} else if (disabled_editor && disabled_properties) {
text += " " + TTR("(Editor Disabled, Properties Disabled)");
} else if (disabled_properties) {
@@ -834,7 +834,7 @@ void EditorFeatureProfileManager::_save_and_update() {
}
void EditorFeatureProfileManager::_emit_current_profile_changed() {
- emit_signal("current_feature_profile_changed");
+ emit_signal(SNAME("current_feature_profile_changed"));
}
void EditorFeatureProfileManager::notify_changed() {
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index fe4c6f490d..ed2edb5a5d 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -61,22 +61,22 @@ VBoxContainer *EditorFileDialog::get_vbox() {
void EditorFileDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED || p_what == Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
// Update icons.
- mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons"));
- mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons"));
+ mode_thumbnails->set_icon(item_list->get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
+ mode_list->set_icon(item_list->get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
- dir_prev->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
- dir_next->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
+ dir_prev->set_icon(item_list->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
+ dir_next->set_icon(item_list->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
} else {
- dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
- dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
+ dir_prev->set_icon(item_list->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
+ dir_next->set_icon(item_list->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
}
- dir_up->set_icon(item_list->get_theme_icon("ArrowUp", "EditorIcons"));
- refresh->set_icon(item_list->get_theme_icon("Reload", "EditorIcons"));
- favorite->set_icon(item_list->get_theme_icon("Favorites", "EditorIcons"));
- show_hidden->set_icon(item_list->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
+ dir_up->set_icon(item_list->get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")));
+ refresh->set_icon(item_list->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
+ favorite->set_icon(item_list->get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")));
+ show_hidden->set_icon(item_list->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
- fav_up->set_icon(item_list->get_theme_icon("MoveUp", "EditorIcons"));
- fav_down->set_icon(item_list->get_theme_icon("MoveDown", "EditorIcons"));
+ fav_up->set_icon(item_list->get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
+ fav_down->set_icon(item_list->get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
} else if (p_what == NOTIFICATION_PROCESS) {
if (preview_waiting) {
@@ -100,21 +100,21 @@ void EditorFileDialog::_notification(int p_what) {
set_display_mode((DisplayMode)EditorSettings::get_singleton()->get("filesystem/file_dialog/display_mode").operator int());
// Update icons.
- mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons"));
- mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons"));
+ mode_thumbnails->set_icon(item_list->get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
+ mode_list->set_icon(item_list->get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
- dir_prev->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
- dir_next->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
+ dir_prev->set_icon(item_list->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
+ dir_next->set_icon(item_list->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
} else {
- dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
- dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
+ dir_prev->set_icon(item_list->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
+ dir_next->set_icon(item_list->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
}
- dir_up->set_icon(item_list->get_theme_icon("ArrowUp", "EditorIcons"));
- refresh->set_icon(item_list->get_theme_icon("Reload", "EditorIcons"));
- favorite->set_icon(item_list->get_theme_icon("Favorites", "EditorIcons"));
+ dir_up->set_icon(item_list->get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")));
+ refresh->set_icon(item_list->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
+ favorite->set_icon(item_list->get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")));
- fav_up->set_icon(item_list->get_theme_icon("MoveUp", "EditorIcons"));
- fav_down->set_icon(item_list->get_theme_icon("MoveDown", "EditorIcons"));
+ fav_up->set_icon(item_list->get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
+ fav_down->set_icon(item_list->get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
// DO NOT CALL UPDATE FILE LIST HERE, ALL HUNDREDS OF HIDDEN DIALOGS WILL RESPOND, CALL INVALIDATE INSTEAD
invalidate();
} else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
@@ -245,7 +245,7 @@ void EditorFileDialog::_save_confirm_pressed() {
String f = dir_access->get_current_dir().plus_file(file->get_text());
_save_to_recent();
hide();
- emit_signal("file_selected", f);
+ emit_signal(SNAME("file_selected"), f);
}
void EditorFileDialog::_post_popup() {
@@ -279,8 +279,8 @@ void EditorFileDialog::_post_popup() {
}
if (is_visible()) {
- Ref<Texture2D> folder = item_list->get_theme_icon("folder", "FileDialog");
- const Color folder_color = item_list->get_theme_color("folder_icon_modulate", "FileDialog");
+ Ref<Texture2D> folder = item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
+ const Color folder_color = item_list->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
recent->clear();
bool res = access == ACCESS_RESOURCES;
@@ -379,7 +379,7 @@ void EditorFileDialog::_action_pressed() {
if (files.size()) {
_save_to_recent();
hide();
- emit_signal("files_selected", files);
+ emit_signal(SNAME("files_selected"), files);
}
return;
@@ -390,7 +390,7 @@ void EditorFileDialog::_action_pressed() {
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
_save_to_recent();
hide();
- emit_signal("file_selected", f);
+ emit_signal(SNAME("file_selected"), f);
} else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) {
String path = dir_access->get_current_dir();
@@ -409,7 +409,7 @@ void EditorFileDialog::_action_pressed() {
_save_to_recent();
hide();
- emit_signal("dir_selected", path);
+ emit_signal(SNAME("dir_selected"), path);
}
if (mode == FILE_MODE_SAVE_FILE) {
@@ -474,7 +474,7 @@ void EditorFileDialog::_action_pressed() {
} else {
_save_to_recent();
hide();
- emit_signal("file_selected", f);
+ emit_signal(SNAME("file_selected"), f);
}
}
}
@@ -563,8 +563,8 @@ void EditorFileDialog::_item_dc_selected(int p_item) {
if (d["dir"]) {
dir_access->change_dir(d["name"]);
- call_deferred("_update_file_list");
- call_deferred("_update_dir");
+ call_deferred(SNAME("_update_file_list"));
+ call_deferred(SNAME("_update_dir"));
_push_history();
@@ -595,16 +595,16 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p
}
if (single_item_selected) {
- item_menu->add_icon_item(item_list->get_theme_icon("ActionCopy", "EditorIcons"), TTR("Copy Path"), ITEM_MENU_COPY_PATH);
+ item_menu->add_icon_item(item_list->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), TTR("Copy Path"), ITEM_MENU_COPY_PATH);
}
if (allow_delete) {
- item_menu->add_icon_item(item_list->get_theme_icon("Remove", "EditorIcons"), TTR("Delete"), ITEM_MENU_DELETE, KEY_DELETE);
+ item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete"), ITEM_MENU_DELETE, KEY_DELETE);
}
if (single_item_selected) {
item_menu->add_separator();
Dictionary item_meta = item_list->get_item_metadata(p_item);
String item_text = item_meta["dir"] ? TTR("Open in File Manager") : TTR("Show in File Manager");
- item_menu->add_icon_item(item_list->get_theme_icon("Filesystem", "EditorIcons"), item_text, ITEM_MENU_SHOW_IN_EXPLORER);
+ item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), item_text, ITEM_MENU_SHOW_IN_EXPLORER);
}
if (item_menu->get_item_count() > 0) {
@@ -623,11 +623,11 @@ void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) {
item_menu->set_size(Size2(1, 1));
if (can_create_dir) {
- item_menu->add_icon_item(item_list->get_theme_icon("folder", "FileDialog"), TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KEY_MASK_CMD | KEY_N);
+ item_menu->add_icon_item(item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog")), TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KEY_MASK_CMD | KEY_N);
}
- item_menu->add_icon_item(item_list->get_theme_icon("Reload", "EditorIcons"), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5);
+ item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5);
item_menu->add_separator();
- item_menu->add_icon_item(item_list->get_theme_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
+ item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
item_menu->set_position(item_list->get_global_position() + p_pos);
item_menu->popup();
@@ -731,11 +731,11 @@ void EditorFileDialog::update_file_list() {
item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
if (thumbnail_size < 64) {
- folder_thumbnail = item_list->get_theme_icon("FolderMediumThumb", "EditorIcons");
- file_thumbnail = item_list->get_theme_icon("FileMediumThumb", "EditorIcons");
+ folder_thumbnail = item_list->get_theme_icon(SNAME("FolderMediumThumb"), SNAME("EditorIcons"));
+ file_thumbnail = item_list->get_theme_icon(SNAME("FileMediumThumb"), SNAME("EditorIcons"));
} else {
- folder_thumbnail = item_list->get_theme_icon("FolderBigThumb", "EditorIcons");
- file_thumbnail = item_list->get_theme_icon("FileBigThumb", "EditorIcons");
+ folder_thumbnail = item_list->get_theme_icon(SNAME("FolderBigThumb"), SNAME("EditorIcons"));
+ file_thumbnail = item_list->get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons"));
}
preview_vb->hide();
@@ -755,8 +755,8 @@ void EditorFileDialog::update_file_list() {
dir_access->list_dir_begin();
- Ref<Texture2D> folder = item_list->get_theme_icon("folder", "FileDialog");
- const Color folder_color = item_list->get_theme_color("folder_icon_modulate", "FileDialog");
+ Ref<Texture2D> folder = item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
+ const Color folder_color = item_list->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
List<String> files;
List<String> dirs;
@@ -1206,8 +1206,8 @@ void EditorFileDialog::_update_favorites() {
bool res = access == ACCESS_RESOURCES;
String current = get_current_dir();
- Ref<Texture2D> folder_icon = item_list->get_theme_icon("Folder", "EditorIcons");
- const Color folder_color = item_list->get_theme_color("folder_icon_modulate", "FileDialog");
+ Ref<Texture2D> folder_icon = item_list->get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"));
+ const Color folder_color = item_list->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
favorites->clear();
favorite->set_pressed(false);
@@ -1510,7 +1510,9 @@ EditorFileDialog::EditorFileDialog() {
dir_next->connect("pressed", callable_mp(this, &EditorFileDialog::_go_forward));
dir_up->connect("pressed", callable_mp(this, &EditorFileDialog::_go_up));
- pathhb->add_child(memnew(Label(TTR("Path:"))));
+ Label *l = memnew(Label(TTR("Path:")));
+ l->set_theme_type_variation("HeaderSmall");
+ pathhb->add_child(l);
drives_container = memnew(HBoxContainer);
pathhb->add_child(drives_container);
@@ -1591,7 +1593,11 @@ EditorFileDialog::EditorFileDialog() {
fav_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
HBoxContainer *fav_hb = memnew(HBoxContainer);
fav_vb->add_child(fav_hb);
- fav_hb->add_child(memnew(Label(TTR("Favorites:"))));
+
+ l = memnew(Label(TTR("Favorites:")));
+ l->set_theme_type_variation("HeaderSmall");
+ fav_hb->add_child(l);
+
fav_hb->add_spacer();
fav_up = memnew(Button);
fav_up->set_flat(true);
@@ -1626,7 +1632,10 @@ EditorFileDialog::EditorFileDialog() {
VBoxContainer *list_vb = memnew(VBoxContainer);
list_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- list_vb->add_child(memnew(Label(TTR("Directories & Files:"))));
+
+ l = memnew(Label(TTR("Directories & Files:")));
+ l->set_theme_type_variation("HeaderSmall");
+ list_vb->add_child(l);
preview_hb->add_child(list_vb);
// Item (files and folders) list with context menu.
@@ -1653,7 +1662,11 @@ EditorFileDialog::EditorFileDialog() {
preview_vb->hide();
file_box = memnew(HBoxContainer);
- file_box->add_child(memnew(Label(TTR("File:"))));
+
+ l = memnew(Label(TTR("File:")));
+ l->set_theme_type_variation("HeaderSmall");
+ file_box->add_child(l);
+
file = memnew(LineEdit);
file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index a2507f3cf2..82a71c0e0c 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -592,7 +592,7 @@ bool EditorFileSystem::_update_scan_actions() {
}
if (reloads.size()) {
- emit_signal("resources_reload", reloads);
+ emit_signal(SNAME("resources_reload"), reloads);
}
scan_actions.clear();
@@ -623,8 +623,8 @@ void EditorFileSystem::scan() {
new_filesystem = nullptr;
_update_scan_actions();
scanning = false;
- emit_signal("filesystem_changed");
- emit_signal("sources_changed", sources_changed.size() > 0);
+ emit_signal(SNAME("filesystem_changed"));
+ emit_signal(SNAME("sources_changed"), sources_changed.size() > 0);
_queue_update_script_classes();
first_scan = false;
} else {
@@ -1073,12 +1073,12 @@ void EditorFileSystem::scan_changes() {
scan_total = 0;
_scan_fs_changes(filesystem, sp);
if (_update_scan_actions()) {
- emit_signal("filesystem_changed");
+ emit_signal(SNAME("filesystem_changed"));
}
}
scanning_changes = false;
scanning_changes_done = true;
- emit_signal("sources_changed", sources_changed.size() > 0);
+ emit_signal(SNAME("sources_changed"), sources_changed.size() > 0);
} else {
ERR_FAIL_COND(thread_sources.is_started());
set_process(true);
@@ -1092,7 +1092,7 @@ void EditorFileSystem::scan_changes() {
void EditorFileSystem::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- call_deferred("scan"); //this should happen after every editor node entered the tree
+ call_deferred(SNAME("scan")); //this should happen after every editor node entered the tree
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -1128,9 +1128,9 @@ void EditorFileSystem::_notification(int p_what) {
thread_sources.wait_to_finish();
if (_update_scan_actions()) {
- emit_signal("filesystem_changed");
+ emit_signal(SNAME("filesystem_changed"));
}
- emit_signal("sources_changed", sources_changed.size() > 0);
+ emit_signal(SNAME("sources_changed"), sources_changed.size() > 0);
_queue_update_script_classes();
first_scan = false;
}
@@ -1144,8 +1144,8 @@ void EditorFileSystem::_notification(int p_what) {
new_filesystem = nullptr;
thread.wait_to_finish();
_update_scan_actions();
- emit_signal("filesystem_changed");
- emit_signal("sources_changed", sources_changed.size() > 0);
+ emit_signal(SNAME("filesystem_changed"));
+ emit_signal(SNAME("sources_changed"), sources_changed.size() > 0);
_queue_update_script_classes();
first_scan = false;
}
@@ -1445,7 +1445,7 @@ void EditorFileSystem::_queue_update_script_classes() {
}
update_script_classes_queued.set();
- call_deferred("update_script_classes");
+ call_deferred(SNAME("update_script_classes"));
}
void EditorFileSystem::update_file(const String &p_file) {
@@ -1466,7 +1466,7 @@ void EditorFileSystem::update_file(const String &p_file) {
fs->files.remove(cpos);
}
- call_deferred("emit_signal", "filesystem_changed"); //update later
+ call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later
_queue_update_script_classes();
return;
}
@@ -1513,7 +1513,7 @@ void EditorFileSystem::update_file(const String &p_file) {
// Update preview
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
- call_deferred("emit_signal", "filesystem_changed"); //update later
+ call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later
_queue_update_script_classes();
}
@@ -2026,10 +2026,10 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
_save_filesystem_cache();
importing = false;
if (!is_scanning()) {
- emit_signal("filesystem_changed");
+ emit_signal(SNAME("filesystem_changed"));
}
- emit_signal("resources_reimported", p_files);
+ emit_signal(SNAME("resources_reimported"), p_files);
}
Error EditorFileSystem::_resource_import(const String &p_path) {
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index d548196a2d..1e3db1a7b0 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -37,19 +37,34 @@
#include "scene/resources/default_theme/default_theme.h"
#include "scene/resources/font.h"
-#define MAKE_FALLBACKS(m_name) \
- m_name->add_data(FontArabic); \
- m_name->add_data(FontBengali); \
- m_name->add_data(FontGeorgian); \
- m_name->add_data(FontMalayalam); \
- m_name->add_data(FontOriya); \
- m_name->add_data(FontSinhala); \
- m_name->add_data(FontTamil); \
- m_name->add_data(FontTelugu); \
- m_name->add_data(FontHebrew); \
- m_name->add_data(FontThai); \
- m_name->add_data(FontHindi); \
- m_name->add_data(FontJapanese); \
+#define MAKE_FALLBACKS(m_name) \
+ m_name->add_data(FontArabic); \
+ m_name->add_data(FontBengali); \
+ m_name->add_data(FontDevanagari); \
+ m_name->add_data(FontGeorgian); \
+ m_name->add_data(FontHebrew); \
+ m_name->add_data(FontMalayalam); \
+ m_name->add_data(FontOriya); \
+ m_name->add_data(FontSinhala); \
+ m_name->add_data(FontTamil); \
+ m_name->add_data(FontTelugu); \
+ m_name->add_data(FontThai); \
+ m_name->add_data(FontJapanese); \
+ m_name->add_data(FontFallback);
+
+#define MAKE_FALLBACKS_BOLD(m_name) \
+ m_name->add_data(FontArabicBold); \
+ m_name->add_data(FontBengaliBold); \
+ m_name->add_data(FontDevanagariBold); \
+ m_name->add_data(FontGeorgianBold); \
+ m_name->add_data(FontHebrewBold); \
+ m_name->add_data(FontMalayalamBold); \
+ m_name->add_data(FontOriyaBold); \
+ m_name->add_data(FontSinhalaBold); \
+ m_name->add_data(FontTamilBold); \
+ m_name->add_data(FontTeluguBold); \
+ m_name->add_data(FontThaiBold); \
+ m_name->add_data(FontJapanese); \
m_name->add_data(FontFallback);
// the custom spacings might only work with Noto Sans
@@ -77,7 +92,7 @@
} \
m_name->set_spacing(Font::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(Font::SPACING_BOTTOM, -EDSCALE); \
- MAKE_FALLBACKS(m_name);
+ MAKE_FALLBACKS_BOLD(m_name);
#define MAKE_SOURCE_FONT(m_name) \
Ref<Font> m_name; \
@@ -175,36 +190,22 @@ void editor_register_fonts(Ref<Theme> p_theme) {
memdelete(dir);
- /* Droid Sans */
+ /* Noto Sans UI */
Ref<FontData> DefaultFont;
DefaultFont.instantiate();
- DefaultFont->load_memory(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size, "ttf", default_font_size);
+ DefaultFont->load_memory(_font_NotoSans_Regular, _font_NotoSans_Regular_size, "ttf", default_font_size);
DefaultFont->set_antialiased(font_antialiased);
DefaultFont->set_hinting(font_hinting);
DefaultFont->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> DefaultFontBold;
DefaultFontBold.instantiate();
- DefaultFontBold->load_memory(_font_NotoSansUI_Bold, _font_NotoSansUI_Bold_size, "ttf", default_font_size);
+ DefaultFontBold->load_memory(_font_NotoSans_Bold, _font_NotoSans_Bold_size, "ttf", default_font_size);
DefaultFontBold->set_antialiased(font_antialiased);
DefaultFontBold->set_hinting(font_hinting);
DefaultFontBold->set_force_autohinter(true); // just looks better..i think?
- Ref<FontData> FontFallback;
- FontFallback.instantiate();
- FontFallback->load_memory(_font_DroidSansFallback, _font_DroidSansFallback_size, "ttf", default_font_size);
- FontFallback->set_antialiased(font_antialiased);
- FontFallback->set_hinting(font_hinting);
- FontFallback->set_force_autohinter(true); //just looks better..i think?
-
- Ref<FontData> FontJapanese;
- FontJapanese.instantiate();
- FontJapanese->load_memory(_font_DroidSansJapanese, _font_DroidSansJapanese_size, "ttf", default_font_size);
- FontJapanese->set_antialiased(font_antialiased);
- FontJapanese->set_hinting(font_hinting);
- FontJapanese->set_force_autohinter(true); //just looks better..i think?
-
Ref<FontData> FontArabic;
FontArabic.instantiate();
FontArabic->load_memory(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, "ttf", default_font_size);
@@ -212,13 +213,41 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontArabic->set_hinting(font_hinting);
FontArabic->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontArabicBold;
+ FontArabicBold.instantiate();
+ FontArabicBold->load_memory(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, "ttf", default_font_size);
+ FontArabicBold->set_antialiased(font_antialiased);
+ FontArabicBold->set_hinting(font_hinting);
+ FontArabicBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontBengali;
FontBengali.instantiate();
- FontBengali->load_memory(_font_NotoSansBengali_Regular, _font_NotoSansBengali_Regular_size, "ttf", default_font_size);
+ FontBengali->load_memory(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, "ttf", default_font_size);
FontBengali->set_antialiased(font_antialiased);
FontBengali->set_hinting(font_hinting);
FontBengali->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontBengaliBold;
+ FontBengaliBold.instantiate();
+ FontBengaliBold->load_memory(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, "ttf", default_font_size);
+ FontBengaliBold->set_antialiased(font_antialiased);
+ FontBengaliBold->set_hinting(font_hinting);
+ FontBengaliBold->set_force_autohinter(true); //just looks better..i think?
+
+ Ref<FontData> FontDevanagari;
+ FontDevanagari.instantiate();
+ FontDevanagari->load_memory(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, "ttf", default_font_size);
+ FontDevanagari->set_antialiased(font_antialiased);
+ FontDevanagari->set_hinting(font_hinting);
+ FontDevanagari->set_force_autohinter(true); //just looks better..i think?
+
+ Ref<FontData> FontDevanagariBold;
+ FontDevanagariBold.instantiate();
+ FontDevanagariBold->load_memory(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, "ttf", default_font_size);
+ FontDevanagariBold->set_antialiased(font_antialiased);
+ FontDevanagariBold->set_hinting(font_hinting);
+ FontDevanagariBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontGeorgian;
FontGeorgian.instantiate();
FontGeorgian->load_memory(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, "ttf", default_font_size);
@@ -226,6 +255,13 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontGeorgian->set_hinting(font_hinting);
FontGeorgian->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontGeorgianBold;
+ FontGeorgianBold.instantiate();
+ FontGeorgianBold->load_memory(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, "ttf", default_font_size);
+ FontGeorgianBold->set_antialiased(font_antialiased);
+ FontGeorgianBold->set_hinting(font_hinting);
+ FontGeorgianBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontHebrew;
FontHebrew.instantiate();
FontHebrew->load_memory(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, "ttf", default_font_size);
@@ -233,6 +269,13 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontHebrew->set_hinting(font_hinting);
FontHebrew->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontHebrewBold;
+ FontHebrewBold.instantiate();
+ FontHebrewBold->load_memory(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, "ttf", default_font_size);
+ FontHebrewBold->set_antialiased(font_antialiased);
+ FontHebrewBold->set_hinting(font_hinting);
+ FontHebrewBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontMalayalam;
FontMalayalam.instantiate();
FontMalayalam->load_memory(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, "ttf", default_font_size);
@@ -240,6 +283,13 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontMalayalam->set_hinting(font_hinting);
FontMalayalam->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontMalayalamBold;
+ FontMalayalamBold.instantiate();
+ FontMalayalamBold->load_memory(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, "ttf", default_font_size);
+ FontMalayalamBold->set_antialiased(font_antialiased);
+ FontMalayalamBold->set_hinting(font_hinting);
+ FontMalayalamBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontOriya;
FontOriya.instantiate();
FontOriya->load_memory(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, "ttf", default_font_size);
@@ -247,6 +297,13 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontOriya->set_hinting(font_hinting);
FontOriya->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontOriyaBold;
+ FontOriyaBold.instantiate();
+ FontOriyaBold->load_memory(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, "ttf", default_font_size);
+ FontOriyaBold->set_antialiased(font_antialiased);
+ FontOriyaBold->set_hinting(font_hinting);
+ FontOriyaBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontSinhala;
FontSinhala.instantiate();
FontSinhala->load_memory(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, "ttf", default_font_size);
@@ -254,6 +311,13 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontSinhala->set_hinting(font_hinting);
FontSinhala->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontSinhalaBold;
+ FontSinhalaBold.instantiate();
+ FontSinhalaBold->load_memory(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, "ttf", default_font_size);
+ FontSinhalaBold->set_antialiased(font_antialiased);
+ FontSinhalaBold->set_hinting(font_hinting);
+ FontSinhalaBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontTamil;
FontTamil.instantiate();
FontTamil->load_memory(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, "ttf", default_font_size);
@@ -261,6 +325,13 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontTamil->set_hinting(font_hinting);
FontTamil->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontTamilBold;
+ FontTamilBold.instantiate();
+ FontTamilBold->load_memory(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, "ttf", default_font_size);
+ FontTamilBold->set_antialiased(font_antialiased);
+ FontTamilBold->set_hinting(font_hinting);
+ FontTamilBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontTelugu;
FontTelugu.instantiate();
FontTelugu->load_memory(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, "ttf", default_font_size);
@@ -268,6 +339,13 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontTelugu->set_hinting(font_hinting);
FontTelugu->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontTeluguBold;
+ FontTeluguBold.instantiate();
+ FontTeluguBold->load_memory(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, "ttf", default_font_size);
+ FontTeluguBold->set_antialiased(font_antialiased);
+ FontTeluguBold->set_hinting(font_hinting);
+ FontTeluguBold->set_force_autohinter(true); //just looks better..i think?
+
Ref<FontData> FontThai;
FontThai.instantiate();
FontThai->load_memory(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, "ttf", default_font_size);
@@ -275,12 +353,30 @@ void editor_register_fonts(Ref<Theme> p_theme) {
FontThai->set_hinting(font_hinting);
FontThai->set_force_autohinter(true); //just looks better..i think?
- Ref<FontData> FontHindi;
- FontHindi.instantiate();
- FontHindi->load_memory(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, "ttf", default_font_size);
- FontHindi->set_antialiased(font_antialiased);
- FontHindi->set_hinting(font_hinting);
- FontHindi->set_force_autohinter(true); //just looks better..i think?
+ Ref<FontData> FontThaiBold;
+ FontThaiBold.instantiate();
+ FontThaiBold->load_memory(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, "ttf", default_font_size);
+ FontThaiBold->set_antialiased(font_antialiased);
+ FontThaiBold->set_hinting(font_hinting);
+ FontThaiBold->set_force_autohinter(true); //just looks better..i think?
+
+ /* Droid Sans Fallback */
+
+ Ref<FontData> FontFallback;
+ FontFallback.instantiate();
+ FontFallback->load_memory(_font_DroidSansFallback, _font_DroidSansFallback_size, "ttf", default_font_size);
+ FontFallback->set_antialiased(font_antialiased);
+ FontFallback->set_hinting(font_hinting);
+ FontFallback->set_force_autohinter(true); //just looks better..i think?
+
+ /* Droid Sans Japanese */
+
+ Ref<FontData> FontJapanese;
+ FontJapanese.instantiate();
+ FontJapanese->load_memory(_font_DroidSansJapanese, _font_DroidSansJapanese_size, "ttf", default_font_size);
+ FontJapanese->set_antialiased(font_antialiased);
+ FontJapanese->set_hinting(font_hinting);
+ FontJapanese->set_force_autohinter(true); //just looks better..i think?
/* Hack */
@@ -319,7 +415,19 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font_size("main_button_font_size", "EditorFonts", default_font_size + 1 * EDSCALE);
p_theme->set_font("main_button_font", "EditorFonts", df_bold);
- p_theme->set_font("font", "Label", df_bold);
+ p_theme->set_font("font", "Label", df);
+
+ p_theme->set_type_variation("HeaderSmall", "Label");
+ p_theme->set_font("font", "HeaderSmall", df_bold);
+ p_theme->set_font_size("font_size", "HeaderSmall", default_font_size);
+
+ p_theme->set_type_variation("HeaderMedium", "Label");
+ p_theme->set_font("font", "HeaderMedium", df_bold);
+ p_theme->set_font_size("font_size", "HeaderMedium", default_font_size + 1 * EDSCALE);
+
+ p_theme->set_type_variation("HeaderLarge", "Label");
+ p_theme->set_font("font", "HeaderLarge", df_bold);
+ p_theme->set_font_size("font_size", "HeaderLarge", default_font_size + 3 * EDSCALE);
// Documentation fonts
MAKE_SOURCE_FONT(df_code);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 7365e8fd7d..569a28215c 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -43,16 +43,16 @@
DocTools *EditorHelp::doc = nullptr;
void EditorHelp::_init_colors() {
- title_color = get_theme_color("accent_color", "Editor");
- text_color = get_theme_color("default_color", "RichTextLabel");
- headline_color = get_theme_color("headline_color", "EditorHelp");
+ title_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ text_color = get_theme_color(SNAME("default_color"), SNAME("RichTextLabel"));
+ headline_color = get_theme_color(SNAME("headline_color"), SNAME("EditorHelp"));
base_type_color = title_color.lerp(text_color, 0.5);
comment_color = text_color * Color(1, 1, 1, 0.6);
symbol_color = comment_color;
value_color = text_color * Color(1, 1, 1, 0.6);
qualifier_color = text_color * Color(1, 1, 1, 0.8);
- type_color = get_theme_color("accent_color", "Editor").lerp(text_color, 0.5);
- class_desc->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
+ type_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")).lerp(text_color, 0.5);
+ class_desc->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
class_desc->add_theme_constant_override("line_separation", Math::round(5 * EDSCALE));
}
@@ -78,10 +78,10 @@ void EditorHelp::_class_desc_select(const String &p_select) {
} else {
class_name = "@GlobalScope";
}
- emit_signal("go_to_help", "class_enum:" + class_name + ":" + select);
+ emit_signal(SNAME("go_to_help"), "class_enum:" + class_name + ":" + select);
return;
} else if (p_select.begins_with("#")) {
- emit_signal("go_to_help", "class_name:" + p_select.substr(1, p_select.length()));
+ emit_signal(SNAME("go_to_help"), "class_name:" + p_select.substr(1, p_select.length()));
return;
} else if (p_select.begins_with("@")) {
int tag_end = p_select.find(" ");
@@ -112,7 +112,7 @@ void EditorHelp::_class_desc_select(const String &p_select) {
}
if (link.find(".") != -1) {
- emit_signal("go_to_help", topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
+ emit_signal(SNAME("go_to_help"), topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
} else {
if (table->has(link)) {
// Found in the current page
@@ -125,7 +125,7 @@ void EditorHelp::_class_desc_select(const String &p_select) {
for (int i = 0; i < cd.constants.size(); i++) {
if (cd.constants[i].enumeration == link) {
// Found in @GlobalScope
- emit_signal("go_to_help", topic + ":@GlobalScope:" + link);
+ emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link);
break;
}
}
@@ -136,7 +136,7 @@ void EditorHelp::_class_desc_select(const String &p_select) {
for (int i = 0; i < cd.constants.size(); i++) {
if (cd.constants[i].name == link) {
// Found in @GlobalScope
- emit_signal("go_to_help", topic + ":@GlobalScope:" + link);
+ emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link);
break;
}
}
@@ -154,12 +154,12 @@ void EditorHelp::_class_desc_input(const Ref<InputEvent> &p_input) {
void EditorHelp::_class_desc_resized() {
// Add extra horizontal margins for better readability.
// The margins increase as the width of the editor help container increases.
- Ref<Font> doc_code_font = get_theme_font("doc_source", "EditorFonts");
- int font_size = get_theme_font_size("doc_source_size", "EditorFonts");
+ Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("doc_source_size"), SNAME("EditorFonts"));
real_t char_width = doc_code_font->get_char_size('x', 0, font_size).width;
const int display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5;
- Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox("normal", "RichTextLabel")->duplicate();
+ Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox(SNAME("normal"), SNAME("RichTextLabel"))->duplicate();
class_desc_stylebox->set_default_margin(SIDE_LEFT, display_margin);
class_desc_stylebox->set_default_margin(SIDE_RIGHT, display_margin);
class_desc->add_theme_style_override("normal", class_desc_stylebox);
@@ -179,8 +179,8 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
t = p_enum.get_slice(".", 0);
}
}
- const Color text_color = get_theme_color("default_color", "RichTextLabel");
- const Color type_color = get_theme_color("accent_color", "Editor").lerp(text_color, 0.5);
+ const Color text_color = get_theme_color(SNAME("default_color"), SNAME("RichTextLabel"));
+ const Color type_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")).lerp(text_color, 0.5);
class_desc->push_color(type_color);
bool add_array = false;
if (can_ref) {
@@ -344,10 +344,10 @@ void EditorHelp::_update_doc() {
DocData::ClassDoc cd = doc->class_list[edited_class]; //make a copy, so we can sort without worrying
- Ref<Font> doc_font = get_theme_font("doc", "EditorFonts");
- Ref<Font> doc_bold_font = get_theme_font("doc_bold", "EditorFonts");
- Ref<Font> doc_title_font = get_theme_font("doc_title", "EditorFonts");
- Ref<Font> doc_code_font = get_theme_font("doc_source", "EditorFonts");
+ Ref<Font> doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts"));
+ Ref<Font> doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts"));
+ Ref<Font> doc_title_font = get_theme_font(SNAME("doc_title"), SNAME("EditorFonts"));
+ Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
String link_color_text = title_color.to_html(false);
// Class name
@@ -1177,7 +1177,7 @@ void EditorHelp::_update_doc() {
if (!cd.properties[i].description.strip_edges().is_empty()) {
_add_text(DTR(cd.properties[i].description));
} else {
- class_desc->add_image(get_theme_icon("Error", "EditorIcons"));
+ class_desc->add_image(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
class_desc->add_text(" ");
class_desc->push_color(comment_color);
if (cd.is_script_doc) {
@@ -1232,7 +1232,7 @@ void EditorHelp::_update_doc() {
if (!methods_filtered[i].description.strip_edges().is_empty()) {
_add_text(DTR(methods_filtered[i].description));
} else {
- class_desc->add_image(get_theme_icon("Error", "EditorIcons"));
+ class_desc->add_image(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
class_desc->add_text(" ");
class_desc->push_color(comment_color);
if (cd.is_script_doc) {
@@ -1319,21 +1319,21 @@ void EditorHelp::_help_callback(const String &p_topic) {
}
}
- class_desc->call_deferred("scroll_to_line", line);
+ class_desc->call_deferred(SNAME("scroll_to_line"), line);
}
static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
DocTools *doc = EditorHelp::get_doc_data();
String base_path;
- Ref<Font> doc_font = p_rt->get_theme_font("doc", "EditorFonts");
- Ref<Font> doc_bold_font = p_rt->get_theme_font("doc_bold", "EditorFonts");
- Ref<Font> doc_code_font = p_rt->get_theme_font("doc_source", "EditorFonts");
- Ref<Font> doc_kbd_font = p_rt->get_theme_font("doc_keyboard", "EditorFonts");
+ Ref<Font> doc_font = p_rt->get_theme_font(SNAME("doc"), SNAME("EditorFonts"));
+ Ref<Font> doc_bold_font = p_rt->get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts"));
+ Ref<Font> doc_code_font = p_rt->get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
+ Ref<Font> doc_kbd_font = p_rt->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts"));
- Color headline_color = p_rt->get_theme_color("headline_color", "EditorHelp");
- Color accent_color = p_rt->get_theme_color("accent_color", "Editor");
- Color property_color = p_rt->get_theme_color("property_color", "Editor");
+ Color headline_color = p_rt->get_theme_color(SNAME("headline_color"), SNAME("EditorHelp"));
+ Color accent_color = p_rt->get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ Color property_color = p_rt->get_theme_color(SNAME("property_color"), SNAME("Editor"));
Color link_color = accent_color.lerp(headline_color, 0.8);
Color code_color = accent_color.lerp(headline_color, 0.6);
Color kbd_color = accent_color.lerp(property_color, 0.6);
@@ -1667,7 +1667,7 @@ EditorHelp::EditorHelp() {
class_desc = memnew(RichTextLabel);
add_child(class_desc);
class_desc->set_v_size_flags(SIZE_EXPAND_FILL);
- class_desc->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
+ class_desc->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
class_desc->connect("meta_clicked", callable_mp(this, &EditorHelp::_class_desc_select));
class_desc->connect("gui_input", callable_mp(this, &EditorHelp::_class_desc_input));
@@ -1693,7 +1693,7 @@ EditorHelp::~EditorHelp() {
void EditorHelpBit::_go_to_help(String p_what) {
EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
ScriptEditor::get_singleton()->goto_help(p_what);
- emit_signal("request_hide");
+ emit_signal(SNAME("request_hide"));
}
void EditorHelpBit::_meta_clicked(String p_select) {
@@ -1733,7 +1733,7 @@ void EditorHelpBit::_notification(int p_what) {
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- rich_text->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
+ rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
} break;
default:
break;
@@ -1750,7 +1750,7 @@ EditorHelpBit::EditorHelpBit() {
rich_text = memnew(RichTextLabel);
add_child(rich_text);
rich_text->connect("meta_clicked", callable_mp(this, &EditorHelpBit::_meta_clicked));
- rich_text->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
+ rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
rich_text->set_override_selected_font_color(false);
set_custom_minimum_size(Size2(0, 70 * EDSCALE));
}
@@ -1812,13 +1812,13 @@ void FindBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- find_prev->set_icon(get_theme_icon("MoveUp", "EditorIcons"));
- find_next->set_icon(get_theme_icon("MoveDown", "EditorIcons"));
- hide_button->set_normal_texture(get_theme_icon("Close", "EditorIcons"));
- hide_button->set_hover_texture(get_theme_icon("Close", "EditorIcons"));
- hide_button->set_pressed_texture(get_theme_icon("Close", "EditorIcons"));
+ find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
+ find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
+ hide_button->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_hover_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_pressed_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size());
- matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
+ matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), SNAME("Editor")));
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
set_process_unhandled_input(is_visible_in_tree());
@@ -1891,7 +1891,7 @@ void FindBar::_update_matches_label() {
} else {
matches_label->show();
- matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
+ matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), SNAME("Editor")));
matches_label->set_text(vformat(results_count == 1 ? TTR("%d match.") : TTR("%d matches."), results_count));
}
}
@@ -1909,7 +1909,7 @@ void FindBar::_unhandled_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
- if (k->is_pressed() && (rich_text_label->has_focus() || is_a_parent_of(get_focus_owner()))) {
+ if (k->is_pressed() && (rich_text_label->has_focus() || is_ancestor_of(get_focus_owner()))) {
bool accepted = true;
switch (k->get_keycode()) {
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index b93ffa9321..fabbf97f49 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -36,11 +36,11 @@
#include "editor_scale.h"
void EditorHelpSearch::_update_icons() {
- search_box->set_right_icon(results_tree->get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(results_tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
- search_box->add_theme_icon_override("right_icon", results_tree->get_theme_icon("Search", "EditorIcons"));
- case_sensitive_button->set_icon(results_tree->get_theme_icon("MatchCase", "EditorIcons"));
- hierarchy_button->set_icon(results_tree->get_theme_icon("ClassList", "EditorIcons"));
+ search_box->add_theme_icon_override("right_icon", results_tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
+ case_sensitive_button->set_icon(results_tree->get_theme_icon(SNAME("MatchCase"), SNAME("EditorIcons")));
+ hierarchy_button->set_icon(results_tree->get_theme_icon(SNAME("ClassList"), SNAME("EditorIcons")));
if (is_visible()) {
_update_results();
@@ -95,7 +95,7 @@ void EditorHelpSearch::_confirmed() {
// Activate the script editor and emit the signal with the documentation link to display.
EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
- emit_signal("go_to_help", item->get_metadata(0));
+ emit_signal(SNAME("go_to_help"), item->get_metadata(0));
hide();
}
@@ -104,7 +104,7 @@ void EditorHelpSearch::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
- results_tree->call_deferred("clear"); // Wait for the Tree's mouse event propagation.
+ results_tree->call_deferred(SNAME("clear")); // Wait for the Tree's mouse event propagation.
get_ok_button()->set_disabled(true);
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "search_help", Rect2(get_position(), get_size()));
}
@@ -237,9 +237,11 @@ EditorHelpSearch::EditorHelpSearch() {
results_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
results_tree->set_columns(2);
results_tree->set_column_title(0, TTR("Name"));
+ results_tree->set_column_clip_content(0, true);
results_tree->set_column_title(1, TTR("Member Type"));
results_tree->set_column_expand(1, false);
- results_tree->set_column_min_width(1, 150 * EDSCALE);
+ results_tree->set_column_custom_minimum_width(1, 150 * EDSCALE);
+ results_tree->set_column_clip_content(1, true);
results_tree->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
results_tree->set_hide_root(true);
results_tree->set_select_mode(Tree::SELECT_ROW);
@@ -504,7 +506,7 @@ TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const
if (ui_service->has_theme_icon(p_doc->name, "EditorIcons")) {
icon = ui_service->get_theme_icon(p_doc->name, "EditorIcons");
} else if (ClassDB::class_exists(p_doc->name) && ClassDB::is_parent_class(p_doc->name, "Object")) {
- icon = ui_service->get_theme_icon("Object", "EditorIcons");
+ icon = ui_service->get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
}
String tooltip = p_doc->brief_description.strip_edges();
@@ -578,10 +580,10 @@ TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, cons
Ref<Texture2D> icon;
String text;
if (search_flags & SEARCH_SHOW_HIERARCHY) {
- icon = ui_service->get_theme_icon(p_icon, "EditorIcons");
+ icon = ui_service->get_theme_icon(p_icon, SNAME("EditorIcons"));
text = p_text;
} else {
- icon = ui_service->get_theme_icon(p_icon, "EditorIcons");
+ icon = ui_service->get_theme_icon(p_icon, SNAME("EditorIcons"));
/*// In flat mode, show the class icon.
if (ui_service->has_icon(p_class_name, "EditorIcons"))
icon = ui_service->get_icon(p_class_name, "EditorIcons");
@@ -619,6 +621,6 @@ EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree,
results_tree(p_results_tree),
term((p_search_flags & SEARCH_CASE_SENSITIVE) == 0 ? p_term.strip_edges().to_lower() : p_term.strip_edges()),
search_flags(p_search_flags),
- empty_icon(ui_service->get_theme_icon("ArrowRight", "EditorIcons")),
- disabled_color(ui_service->get_theme_color("disabled_font_color", "Editor")) {
+ empty_icon(ui_service->get_theme_icon(SNAME("ArrowRight"), SNAME("EditorIcons"))),
+ disabled_color(ui_service->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))) {
}
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index cfce37ea1b..9fa2007597 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -41,8 +41,8 @@
Size2 EditorProperty::get_minimum_size() const {
Size2 ms;
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
ms.height = font->get_height(font_size);
for (int i = 0; i < get_child_count(); i++) {
@@ -66,22 +66,22 @@ Size2 EditorProperty::get_minimum_size() const {
}
if (keying) {
- Ref<Texture2D> key = get_theme_icon("Key", "EditorIcons");
- ms.width += key->get_width() + get_theme_constant("hseparator", "Tree");
+ Ref<Texture2D> key = get_theme_icon(SNAME("Key"), SNAME("EditorIcons"));
+ ms.width += key->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
}
if (deletable) {
- Ref<Texture2D> key = get_theme_icon("Close", "EditorIcons");
- ms.width += key->get_width() + get_theme_constant("hseparator", "Tree");
+ Ref<Texture2D> key = get_theme_icon(SNAME("Close"), SNAME("EditorIcons"));
+ ms.width += key->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
}
if (checkable) {
- Ref<Texture2D> check = get_theme_icon("checked", "CheckBox");
- ms.width += check->get_width() + get_theme_constant("hseparation", "CheckBox") + get_theme_constant("hseparator", "Tree");
+ Ref<Texture2D> check = get_theme_icon(SNAME("checked"), SNAME("CheckBox"));
+ ms.width += check->get_width() + get_theme_constant(SNAME("hseparation"), SNAME("CheckBox")) + get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
}
if (bottom_editor != nullptr && bottom_editor->is_visible()) {
- ms.height += get_theme_constant("vseparation");
+ ms.height += get_theme_constant(SNAME("vseparation"));
Size2 bems = bottom_editor->get_combined_minimum_size();
//bems.width += get_constant("item_margin", "Tree");
ms.height += bems.height;
@@ -96,7 +96,7 @@ void EditorProperty::emit_changed(const StringName &p_property, const Variant &p
const Variant *argptrs[4] = { &args[0], &args[1], &args[2], &args[3] };
cache[p_property] = p_value;
- emit_signal("property_changed", (const Variant **)argptrs, 4);
+ emit_signal(SNAME("property_changed"), (const Variant **)argptrs, 4);
}
void EditorProperty::_notification(int p_what) {
@@ -110,8 +110,8 @@ void EditorProperty::_notification(int p_what) {
{
int child_room = size.width * (1.0 - split_ratio);
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
int height = font->get_height(font_size);
bool no_children = true;
@@ -149,21 +149,21 @@ void EditorProperty::_notification(int p_what) {
if (bottom_editor) {
int m = 0; //get_constant("item_margin", "Tree");
- bottom_rect = Rect2(m, rect.size.height + get_theme_constant("vseparation"), size.width - m, bottom_editor->get_combined_minimum_size().height);
+ bottom_rect = Rect2(m, rect.size.height + get_theme_constant(SNAME("vseparation")), size.width - m, bottom_editor->get_combined_minimum_size().height);
}
if (keying) {
Ref<Texture2D> key;
if (use_keying_next()) {
- key = get_theme_icon("KeyNext", "EditorIcons");
+ key = get_theme_icon(SNAME("KeyNext"), SNAME("EditorIcons"));
} else {
- key = get_theme_icon("Key", "EditorIcons");
+ key = get_theme_icon(SNAME("Key"), SNAME("EditorIcons"));
}
- rect.size.x -= key->get_width() + get_theme_constant("hseparator", "Tree");
+ rect.size.x -= key->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
if (is_layout_rtl()) {
- rect.position.x += key->get_width() + get_theme_constant("hseparator", "Tree");
+ rect.position.x += key->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
}
if (no_children) {
@@ -174,12 +174,12 @@ void EditorProperty::_notification(int p_what) {
if (deletable) {
Ref<Texture2D> close;
- close = get_theme_icon("Close", "EditorIcons");
+ close = get_theme_icon(SNAME("Close"), SNAME("EditorIcons"));
- rect.size.x -= close->get_width() + get_theme_constant("hseparator", "Tree");
+ rect.size.x -= close->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
if (is_layout_rtl()) {
- rect.position.x += close->get_width() + get_theme_constant("hseparator", "Tree");
+ rect.position.x += close->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
}
if (no_children) {
@@ -214,9 +214,9 @@ void EditorProperty::_notification(int p_what) {
}
if (p_what == NOTIFICATION_DRAW) {
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
- Color dark_color = get_theme_color("dark_color_2", "Editor");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
+ Color dark_color = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
bool rtl = is_layout_rtl();
Size2 size = get_size();
@@ -228,9 +228,9 @@ void EditorProperty::_notification(int p_what) {
Ref<StyleBox> sb;
if (selected) {
- sb = get_theme_stylebox("bg_selected");
+ sb = get_theme_stylebox(SNAME("bg_selected"));
} else {
- sb = get_theme_stylebox("bg");
+ sb = get_theme_stylebox(SNAME("bg"));
}
draw_style_box(sb, Rect2(Vector2(), size));
@@ -244,23 +244,23 @@ void EditorProperty::_notification(int p_what) {
Color color;
if (draw_red) {
- color = get_theme_color("error_color");
+ color = get_theme_color(SNAME("error_color"));
} else {
- color = get_theme_color("property_color");
+ color = get_theme_color(SNAME("property_color"));
}
if (label.find(".") != -1) {
color.a = 0.5; //this should be un-hacked honestly, as it's used for editor overrides
}
- int ofs = get_theme_constant("font_offset");
+ int ofs = get_theme_constant(SNAME("font_offset"));
int text_limit = text_size;
if (checkable) {
Ref<Texture2D> checkbox;
if (checked) {
- checkbox = get_theme_icon("GuiChecked", "EditorIcons");
+ checkbox = get_theme_icon(SNAME("GuiChecked"), SNAME("EditorIcons"));
} else {
- checkbox = get_theme_icon("GuiUnchecked", "EditorIcons");
+ checkbox = get_theme_icon(SNAME("GuiUnchecked"), SNAME("EditorIcons"));
}
Color color2(1, 1, 1);
@@ -275,16 +275,16 @@ void EditorProperty::_notification(int p_what) {
} else {
draw_texture(checkbox, check_rect.position, color2);
}
- ofs += get_theme_constant("hseparator", "Tree") + checkbox->get_width() + get_theme_constant("hseparation", "CheckBox");
+ ofs += get_theme_constant(SNAME("hseparator"), SNAME("Tree")) + checkbox->get_width() + get_theme_constant(SNAME("hseparation"), SNAME("CheckBox"));
text_limit -= ofs;
} else {
check_rect = Rect2();
}
if (can_revert) {
- Ref<Texture2D> reload_icon = get_theme_icon("ReloadSmall", "EditorIcons");
- text_limit -= reload_icon->get_width() + get_theme_constant("hseparator", "Tree") * 2;
- revert_rect = Rect2(text_limit + get_theme_constant("hseparator", "Tree"), (size.height - reload_icon->get_height()) / 2, reload_icon->get_width(), reload_icon->get_height());
+ Ref<Texture2D> reload_icon = get_theme_icon(SNAME("ReloadSmall"), SNAME("EditorIcons"));
+ text_limit -= reload_icon->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree")) * 2;
+ revert_rect = Rect2(text_limit + get_theme_constant(SNAME("hseparator"), SNAME("Tree")), (size.height - reload_icon->get_height()) / 2, reload_icon->get_width(), reload_icon->get_height());
Color color2(1, 1, 1);
if (revert_hover) {
@@ -312,12 +312,12 @@ void EditorProperty::_notification(int p_what) {
Ref<Texture2D> key;
if (use_keying_next()) {
- key = get_theme_icon("KeyNext", "EditorIcons");
+ key = get_theme_icon(SNAME("KeyNext"), SNAME("EditorIcons"));
} else {
- key = get_theme_icon("Key", "EditorIcons");
+ key = get_theme_icon(SNAME("Key"), SNAME("EditorIcons"));
}
- ofs = size.width - key->get_width() - get_theme_constant("hseparator", "Tree");
+ ofs = size.width - key->get_width() - get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
Color color2(1, 1, 1);
if (keying_hover) {
@@ -339,9 +339,9 @@ void EditorProperty::_notification(int p_what) {
if (deletable) {
Ref<Texture2D> close;
- close = get_theme_icon("Close", "EditorIcons");
+ close = get_theme_icon(SNAME("Close"), SNAME("EditorIcons"));
- ofs = size.width - close->get_width() - get_theme_constant("hseparator", "Tree");
+ ofs = size.width - close->get_width() - get_theme_constant(SNAME("hseparator"), SNAME("Tree"));
Color color2(1, 1, 1);
if (delete_hover) {
@@ -646,7 +646,7 @@ void EditorProperty::_focusable_focused(int p_index) {
selected_focusable = p_index;
update();
if (!already_selected && selected) {
- emit_signal("selected", property, selected_focusable);
+ emit_signal(SNAME("selected"), property, selected_focusable);
}
}
@@ -667,7 +667,7 @@ void EditorProperty::select(int p_focusable) {
}
if (!already_selected && selected) {
- emit_signal("selected", property, selected_focusable);
+ emit_signal(SNAME("selected"), property, selected_focusable);
}
}
@@ -732,12 +732,12 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
if (!selected && selectable) {
selected = true;
- emit_signal("selected", property, -1);
+ emit_signal(SNAME("selected"), property, -1);
update();
}
if (keying_rect.has_point(mpos)) {
- emit_signal("property_keyed", property, use_keying_next());
+ emit_signal(SNAME("property_keyed"), property, use_keying_next());
if (use_keying_next()) {
if (property == "frame_coords" && (object->is_class("Sprite2D") || object->is_class("Sprite3D"))) {
@@ -748,16 +748,16 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
new_coords.y++;
}
- call_deferred("emit_changed", property, new_coords, "", false);
+ call_deferred(SNAME("emit_changed"), property, new_coords, "", false);
} else {
- call_deferred("emit_changed", property, object->get(property).operator int64_t() + 1, "", false);
+ call_deferred(SNAME("emit_changed"), property, object->get(property).operator int64_t() + 1, "", false);
}
- call_deferred("_update_property");
+ call_deferred(SNAME("_update_property"));
}
}
if (delete_rect.has_point(mpos)) {
- emit_signal("property_deleted", property);
+ emit_signal(SNAME("property_deleted"), property);
}
if (revert_rect.has_point(mpos)) {
@@ -799,7 +799,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
if (check_rect.has_point(mpos)) {
checked = !checked;
update();
- emit_signal("property_checked", property, checked);
+ emit_signal(SNAME("property_checked"), property, checked);
}
}
}
@@ -889,7 +889,7 @@ void EditorProperty::set_object_and_property(Object *p_object, const StringName
Control *EditorProperty::make_custom_tooltip(const String &p_text) const {
tooltip_text = p_text;
EditorHelpBit *help_bit = memnew(EditorHelpBit);
- //help_bit->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel"));
+ //help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")));
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
String text;
@@ -1038,7 +1038,7 @@ void EditorInspectorPlugin::parse_category(Object *p_object, const String &p_par
}
}
-bool EditorInspectorPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+bool EditorInspectorPlugin::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) {
if (get_script_instance()) {
Variant arg[6] = {
p_object, p_type, p_path, p_hint, p_hint_text, p_usage
@@ -1076,14 +1076,14 @@ void EditorInspectorPlugin::_bind_methods() {
void EditorInspectorCategory::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<StyleBox> sb = get_theme_stylebox("prop_category_style", "Editor");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("prop_category_style"), SNAME("Editor"));
draw_style_box(sb, Rect2(Vector2(), get_size()));
- Ref<Font> font = get_theme_font("bold", "EditorFonts");
- int font_size = get_theme_font_size("bold_size", "EditorFonts");
+ Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
- int hs = get_theme_constant("hseparation", "Tree");
+ int hs = get_theme_constant(SNAME("hseparation"), SNAME("Tree"));
int w = font->get_string_size(label, font_size).width;
if (icon.is_valid()) {
@@ -1097,7 +1097,7 @@ void EditorInspectorCategory::_notification(int p_what) {
ofs += hs + icon->get_width();
}
- Color color = get_theme_color("font_color", "Tree");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Tree"));
draw_string(font, Point2(ofs, font->get_ascent(font_size) + (get_size().height - font->get_height(font_size)) / 2).floor(), label, HALIGN_LEFT, get_size().width, font_size, color);
}
}
@@ -1105,7 +1105,7 @@ void EditorInspectorCategory::_notification(int p_what) {
Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) const {
tooltip_text = p_text;
EditorHelpBit *help_bit = memnew(EditorHelpBit);
- help_bit->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel"));
+ help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")));
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
PackedStringArray slices = p_text.split("::", false);
@@ -1126,8 +1126,8 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons
}
Size2 EditorInspectorCategory::get_minimum_size() const {
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
Size2 ms;
ms.width = 1;
@@ -1135,7 +1135,7 @@ Size2 EditorInspectorCategory::get_minimum_size() const {
if (icon.is_valid()) {
ms.height = MAX(icon->get_height(), ms.height);
}
- ms.height += get_theme_constant("vseparation", "Tree");
+ ms.height += get_theme_constant(SNAME("vseparation"), SNAME("Tree"));
return ms;
}
@@ -1163,34 +1163,38 @@ void EditorInspectorSection::_test_unfold() {
void EditorInspectorSection::_notification(int p_what) {
if (p_what == NOTIFICATION_SORT_CHILDREN) {
- Ref<Font> font = get_theme_font("bold", "EditorFonts");
- int font_size = get_theme_font_size("bold_size", "EditorFonts");
+ Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
Ref<Texture2D> arrow;
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
- arrow = get_theme_icon("arrow", "Tree");
+ arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree"));
} else {
if (is_layout_rtl()) {
- arrow = get_theme_icon("arrow_collapsed_mirrored", "Tree");
+ arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
} else {
- arrow = get_theme_icon("arrow_collapsed", "Tree");
+ arrow = get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree"));
}
}
}
Size2 size = get_size();
Point2 offset;
+ Rect2 rect;
offset.y = font->get_height(font_size);
if (arrow.is_valid()) {
offset.y = MAX(offset.y, arrow->get_height());
}
- offset.y += get_theme_constant("vseparation", "Tree");
- offset.x += get_theme_constant("inspector_margin", "Editor");
-
- Rect2 rect(offset, size - offset);
+ offset.y += get_theme_constant(SNAME("vseparation"), SNAME("Tree"));
+ if (is_layout_rtl()) {
+ rect = Rect2(offset, size - offset - Vector2(get_theme_constant(SNAME("inspector_margin"), SNAME("Editor")), 0));
+ } else {
+ offset.x += get_theme_constant(SNAME("inspector_margin"), SNAME("Editor"));
+ rect = Rect2(offset, size - offset);
+ }
//set children
for (int i = 0; i < get_child_count(); i++) {
@@ -1217,24 +1221,24 @@ void EditorInspectorSection::_notification(int p_what) {
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
- arrow = get_theme_icon("arrow", "Tree");
+ arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree"));
} else {
if (is_layout_rtl()) {
- arrow = get_theme_icon("arrow_collapsed_mirrored", "Tree");
+ arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
} else {
- arrow = get_theme_icon("arrow_collapsed", "Tree");
+ arrow = get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree"));
}
}
}
- Ref<Font> font = get_theme_font("bold", "EditorFonts");
- int font_size = get_theme_font_size("bold_size", "EditorFonts");
+ Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
int h = font->get_height(font_size);
if (arrow.is_valid()) {
h = MAX(h, arrow->get_height());
}
- h += get_theme_constant("vseparation", "Tree");
+ h += get_theme_constant(SNAME("vseparation"), SNAME("Tree"));
Color c = bg_color;
c.a *= 0.4;
@@ -1242,7 +1246,7 @@ void EditorInspectorSection::_notification(int p_what) {
const int arrow_margin = 2;
const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0;
- Color color = get_theme_color("font_color");
+ Color color = get_theme_color(SNAME("font_color"));
float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE);
draw_string(font, Point2(rtl ? 0 : Math::round(arrow_width + arrow_margin * EDSCALE), font->get_ascent(font_size) + (h - font->get_height(font_size)) / 2).floor(), label, rtl ? HALIGN_RIGHT : HALIGN_LEFT, text_width, font_size, color);
@@ -1255,7 +1259,7 @@ void EditorInspectorSection::_notification(int p_what) {
}
if (dropping && !vbox->is_visible_in_tree()) {
- Color accent_color = get_theme_color("accent_color", "Editor");
+ Color accent_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
draw_rect(Rect2(Point2(), get_size()), accent_color, false);
}
}
@@ -1315,10 +1319,10 @@ Size2 EditorInspectorSection::get_minimum_size() const {
ms.height = MAX(ms.height, minsize.height);
}
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
- ms.height += font->get_height(font_size) + get_theme_constant("vseparation", "Tree");
- ms.width += get_theme_constant("inspector_margin", "Editor");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
+ ms.height += font->get_height(font_size) + get_theme_constant(SNAME("vseparation"), SNAME("Tree"));
+ ms.width += get_theme_constant(SNAME("inspector_margin"), SNAME("Editor"));
return ms;
}
@@ -1354,8 +1358,8 @@ void EditorInspectorSection::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
if (mb->get_position().y > font->get_height(font_size)) { //clicked outside
return;
}
@@ -1433,7 +1437,7 @@ EditorInspectorSection::~EditorInspectorSection() {
Ref<EditorInspectorPlugin> EditorInspector::inspector_plugins[MAX_PLUGINS];
int EditorInspector::inspector_plugin_count = 0;
-EditorProperty *EditorInspector::instantiate_property_editor(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+EditorProperty *EditorInspector::instantiate_property_editor(Object *p_object, const Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
for (int i = inspector_plugin_count - 1; i >= 0; i--) {
inspector_plugins[i]->parse_property(p_object, p_type, p_path, p_hint, p_hint_text, p_usage, p_wide);
if (inspector_plugins[i]->added_editors.size()) {
@@ -1642,7 +1646,7 @@ void EditorInspector::update_tree() {
item_path[""] = main_vbox;
- Color sscolor = get_theme_color("prop_subsection", "Editor");
+ Color sscolor = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
Ref<EditorInspectorPlugin> ped = E->get();
@@ -1716,8 +1720,8 @@ void EditorInspector::update_tree() {
}
s = s->get_base_script();
}
- if (category->icon.is_null() && has_theme_icon(base_type, "EditorIcons")) {
- category->icon = get_theme_icon(base_type, "EditorIcons");
+ if (category->icon.is_null() && has_theme_icon(base_type, SNAME("EditorIcons"))) {
+ category->icon = get_theme_icon(base_type, SNAME("EditorIcons"));
}
}
if (category->icon.is_null()) {
@@ -2201,7 +2205,7 @@ void EditorInspector::_update_inspector_bg() {
count_subinspectors = MIN(15, count_subinspectors);
add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg" + itos(count_subinspectors), "Editor"));
} else {
- add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
}
}
void EditorInspector::set_sub_inspector(bool p_enable) {
@@ -2257,7 +2261,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
_edit_request_change(object, p_name);
emit_signal(_prop_edited, p_name);
} else {
- undo_redo->create_action(TTR("Set") + " " + p_name, UndoRedo::MERGE_ENDS);
+ undo_redo->create_action(vformat(TTR("Set %s"), p_name), UndoRedo::MERGE_ENDS);
undo_redo->add_do_property(object, p_name, p_value);
undo_redo->add_undo_property(object, p_name, object->get(p_name));
@@ -2324,7 +2328,7 @@ void EditorInspector::_property_changed(const String &p_path, const Variant &p_v
}
if (restart_request_props.has(p_path)) {
- emit_signal("restart_requested");
+ emit_signal(SNAME("restart_requested"));
}
}
@@ -2346,7 +2350,7 @@ void EditorInspector::_multiple_properties_changed(Vector<String> p_paths, Array
for (int i = 0; i < p_paths.size(); i++) {
_edit_set(p_paths[i], p_values[i], false, "");
if (restart_request_props.has(p_paths[i])) {
- emit_signal("restart_requested");
+ emit_signal(SNAME("restart_requested"));
}
}
changing++;
@@ -2359,16 +2363,15 @@ void EditorInspector::_property_keyed(const String &p_path, bool p_advance) {
return;
}
- emit_signal("property_keyed", p_path, object->get(p_path), p_advance); //second param is deprecated
+ emit_signal(SNAME("property_keyed"), p_path, object->get(p_path), p_advance); //second param is deprecated
}
void EditorInspector::_property_deleted(const String &p_path) {
- print_line("deleted pressed?");
if (!object) {
return;
}
- emit_signal("property_deleted", p_path); //second param is deprecated
+ emit_signal(SNAME("property_deleted"), p_path); //second param is deprecated
}
void EditorInspector::_property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance) {
@@ -2376,7 +2379,7 @@ void EditorInspector::_property_keyed_with_value(const String &p_path, const Var
return;
}
- emit_signal("property_keyed", p_path, p_value, p_advance); //second param is deprecated
+ emit_signal(SNAME("property_keyed"), p_path, p_value, p_advance); //second param is deprecated
}
void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
@@ -2411,7 +2414,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
}
} else {
- emit_signal("property_toggled", p_path, p_checked);
+ emit_signal(SNAME("property_toggled"), p_path, p_checked);
}
}
@@ -2430,15 +2433,15 @@ void EditorInspector::_property_selected(const String &p_path, int p_focusable)
}
}
- emit_signal("property_selected", p_path);
+ emit_signal(SNAME("property_selected"), p_path);
}
void EditorInspector::_object_id_selected(const String &p_path, ObjectID p_id) {
- emit_signal("object_id_selected", p_id);
+ emit_signal(SNAME("object_id_selected"), p_id);
}
void EditorInspector::_resource_selected(const String &p_path, RES p_resource) {
- emit_signal("resource_selected", p_resource, p_path);
+ emit_signal(SNAME("resource_selected"), p_resource, p_path);
}
void EditorInspector::_node_removed(Node *p_node) {
@@ -2475,7 +2478,7 @@ void EditorInspector::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
if (update_scroll_request >= 0) {
- get_v_scrollbar()->call_deferred("set_value", update_scroll_request);
+ get_v_scrollbar()->call_deferred(SNAME("set_value"), update_scroll_request);
update_scroll_request = -1;
}
if (refresh_countdown > 0) {
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index f493290b09..ee70bd4397 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -198,7 +198,7 @@ public:
virtual bool can_handle(Object *p_object);
virtual void parse_begin(Object *p_object);
virtual void parse_category(Object *p_object, const String &p_parse_category);
- virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
+ virtual bool 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 = false);
virtual void parse_end();
};
@@ -356,7 +356,7 @@ public:
static void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
static void cleanup_plugins();
- static EditorProperty *instantiate_property_editor(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false);
+ static EditorProperty *instantiate_property_editor(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 = false);
void set_undo_redo(UndoRedo *p_undo_redo);
diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp
index 437841ccc1..16538a2376 100644
--- a/editor/editor_layouts_dialog.cpp
+++ b/editor/editor_layouts_dialog.cpp
@@ -70,10 +70,10 @@ void EditorLayoutsDialog::ok_pressed() {
if (layout_names->is_anything_selected()) {
Vector<int> const selected_items = layout_names->get_selected_items();
for (int i = 0; i < selected_items.size(); ++i) {
- emit_signal("name_confirmed", layout_names->get_item_text(selected_items[i]));
+ emit_signal(SNAME("name_confirmed"), layout_names->get_item_text(selected_items[i]));
}
} else if (name->is_visible() && name->get_text() != "") {
- emit_signal("name_confirmed", name->get_text());
+ emit_signal(SNAME("name_confirmed"), name->get_text());
}
}
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 437de97332..2cb73664f5 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -57,35 +57,43 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f
}
}
+void EditorLog::_update_theme() {
+ Ref<Font> normal_font = get_theme_font(SNAME("output_source"), SNAME("EditorFonts"));
+ if (normal_font.is_valid()) {
+ log->add_theme_font_override("normal_font", normal_font);
+ }
+
+ log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts")));
+ log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
+
+ Ref<Font> bold_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ if (bold_font.is_valid()) {
+ log->add_theme_font_override("bold_font", bold_font);
+ }
+
+ type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_theme_icon(SNAME("Popup"), SNAME("EditorIcons")));
+ type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons")));
+ type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
+ type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+
+ clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
+ copy_button->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
+ collapse_button->set_icon(get_theme_icon(SNAME("CombineLines"), SNAME("EditorIcons")));
+ show_search_button->set_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
+}
+
void EditorLog::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- //button->set_icon(get_icon("Console","EditorIcons"));
- log->add_theme_font_override("normal_font", get_theme_font("output_source", "EditorFonts"));
- log->add_theme_font_size_override("normal_font_size", get_theme_font_size("output_source_size", "EditorFonts"));
- log->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
- log->add_theme_font_override("bold_font", get_theme_font("bold", "EditorFonts"));
-
- type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_theme_icon("Popup", "EditorIcons"));
- type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_theme_icon("StatusError", "EditorIcons"));
- type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon("StatusWarning", "EditorIcons"));
- type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
-
- clear_button->set_icon(get_theme_icon("Clear", "EditorIcons"));
- copy_button->set_icon(get_theme_icon("ActionCopy", "EditorIcons"));
- collapse_button->set_icon(get_theme_icon("CombineLines", "EditorIcons"));
- show_search_button->set_icon(get_theme_icon("Search", "EditorIcons"));
-
- _load_state();
-
- } else if (p_what == NOTIFICATION_THEME_CHANGED) {
- Ref<Font> df_output_code = get_theme_font("output_source", "EditorFonts");
- if (df_output_code.is_valid()) {
- if (log != nullptr) {
- log->add_theme_font_override("normal_font", get_theme_font("output_source", "EditorFonts"));
- log->add_theme_font_size_override("normal_font_size", get_theme_font_size("output_source_size", "EditorFonts"));
- log->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
- }
- }
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ _update_theme();
+ _load_state();
+ } break;
+ case NOTIFICATION_THEME_CHANGED: {
+ _update_theme();
+ _rebuild_log();
+ } break;
+ default:
+ break;
}
}
@@ -123,21 +131,20 @@ void EditorLog::_load_state() {
Ref<ConfigFile> config;
config.instantiate();
- Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
-
- if (err == OK) {
- const String section = "editor_log";
- for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) {
- E->get()->set_active(config->get_value(section, "log_filter_" + itos(E->key()), false));
- }
+ config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
- collapse = config->get_value(section, "collapse", false);
- collapse_button->set_pressed(collapse);
- bool show_search = config->get_value(section, "show_search", true);
- search_box->set_visible(show_search);
- show_search_button->set_pressed(show_search);
+ // Run the below code even if config->load returns an error, since we want the defaults to be set even if the file does not exist yet.
+ const String section = "editor_log";
+ for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) {
+ E->get()->set_active(config->get_value(section, "log_filter_" + itos(E->key()), true));
}
+ collapse = config->get_value(section, "collapse", false);
+ collapse_button->set_pressed(collapse);
+ bool show_search = config->get_value(section, "show_search", true);
+ search_box->set_visible(show_search);
+ show_search_button->set_pressed(show_search);
+
is_loading_state = false;
}
@@ -243,22 +250,22 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) {
case MSG_TYPE_STD: {
} break;
case MSG_TYPE_ERROR: {
- log->push_color(get_theme_color("error_color", "Editor"));
- Ref<Texture2D> icon = get_theme_icon("Error", "EditorIcons");
+ log->push_color(get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Error"), SNAME("EditorIcons"));
log->add_image(icon);
log->add_text(" ");
tool_button->set_icon(icon);
} break;
case MSG_TYPE_WARNING: {
- log->push_color(get_theme_color("warning_color", "Editor"));
- Ref<Texture2D> icon = get_theme_icon("Warning", "EditorIcons");
+ log->push_color(get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Warning"), SNAME("EditorIcons"));
log->add_image(icon);
log->add_text(" ");
tool_button->set_icon(icon);
} break;
case MSG_TYPE_EDITOR: {
// Distinguish editor messages from messages printed by the project
- log->push_color(get_theme_color("font_color", "Editor") * Color(1, 1, 1, 0.6));
+ log->push_color(get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.6));
} break;
}
@@ -337,7 +344,7 @@ EditorLog::EditorLog() {
search_box = memnew(LineEdit);
search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search_box->set_placeholder(TTR("Filter messages"));
- search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
search_box->set_visible(true);
search_box->connect("text_changed", callable_mp(this, &EditorLog::_search_changed));
@@ -399,22 +406,22 @@ EditorLog::EditorLog() {
vb_right->add_child(memnew(HSeparator));
LogFilter *std_filter = memnew(LogFilter(MSG_TYPE_STD));
- std_filter->initialize_button("Toggle visibility of standard output messages.", callable_mp(this, &EditorLog::_set_filter_active));
+ std_filter->initialize_button(TTR("Toggle visibility of standard output messages."), callable_mp(this, &EditorLog::_set_filter_active));
vb_right->add_child(std_filter->toggle_button);
type_filter_map.insert(MSG_TYPE_STD, std_filter);
LogFilter *error_filter = memnew(LogFilter(MSG_TYPE_ERROR));
- error_filter->initialize_button("Toggle visibility of errors.", callable_mp(this, &EditorLog::_set_filter_active));
+ error_filter->initialize_button(TTR("Toggle visibility of errors."), callable_mp(this, &EditorLog::_set_filter_active));
vb_right->add_child(error_filter->toggle_button);
type_filter_map.insert(MSG_TYPE_ERROR, error_filter);
LogFilter *warning_filter = memnew(LogFilter(MSG_TYPE_WARNING));
- warning_filter->initialize_button("Toggle visibility of warnings.", callable_mp(this, &EditorLog::_set_filter_active));
+ warning_filter->initialize_button(TTR("Toggle visibility of warnings."), callable_mp(this, &EditorLog::_set_filter_active));
vb_right->add_child(warning_filter->toggle_button);
type_filter_map.insert(MSG_TYPE_WARNING, warning_filter);
LogFilter *editor_filter = memnew(LogFilter(MSG_TYPE_EDITOR));
- editor_filter->initialize_button("Toggle visibility of editor messages.", callable_mp(this, &EditorLog::_set_filter_active));
+ editor_filter->initialize_button(TTR("Toggle visibility of editor messages."), callable_mp(this, &EditorLog::_set_filter_active));
vb_right->add_child(editor_filter->toggle_button);
type_filter_map.insert(MSG_TYPE_EDITOR, editor_filter);
diff --git a/editor/editor_log.h b/editor/editor_log.h
index 3b6476634a..6cbf4bedee 100644
--- a/editor/editor_log.h
+++ b/editor/editor_log.h
@@ -163,6 +163,8 @@ private:
void _save_state();
void _load_state();
+ void _update_theme();
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index f8c2f2910b..6bdf428f81 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -31,7 +31,7 @@
#include "editor_node.h"
#include "core/config/project_settings.h"
-#include "core/core_bind.h"
+#include "core/extension/native_extension_manager.h"
#include "core/input/input.h"
#include "core/io/config_file.h"
#include "core/io/file_access.h"
@@ -136,6 +136,7 @@
#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
#include "editor/plugins/gradient_editor_plugin.h"
+#include "editor/plugins/input_event_editor_plugin.h"
#include "editor/plugins/item_list_editor_plugin.h"
#include "editor/plugins/light_occluder_2d_editor_plugin.h"
#include "editor/plugins/lightmap_gi_editor_plugin.h"
@@ -166,6 +167,7 @@
#include "editor/plugins/sprite_2d_editor_plugin.h"
#include "editor/plugins/sprite_frames_editor_plugin.h"
#include "editor/plugins/style_box_editor_plugin.h"
+#include "editor/plugins/sub_viewport_preview_editor_plugin.h"
#include "editor/plugins/text_editor.h"
#include "editor/plugins/texture_3d_editor_plugin.h"
#include "editor/plugins/texture_editor_plugin.h"
@@ -314,7 +316,7 @@ void EditorNode::_update_scene_tabs() {
disambiguate_filenames(full_path_names, disambiguated_scene_names);
scene_tabs->clear_tabs();
- Ref<Texture2D> script_icon = gui_base->get_theme_icon("Script", "EditorIcons");
+ Ref<Texture2D> script_icon = gui_base->get_theme_icon(SNAME("Script"), SNAME("EditorIcons"));
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
Node *type_node = editor_data.get_edited_scene_root(i);
Ref<Texture2D> icon;
@@ -425,7 +427,7 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
} else if (ED_IS_SHORTCUT("editor/editor_script", p_event)) {
_editor_select(EDITOR_SCRIPT);
} else if (ED_IS_SHORTCUT("editor/editor_help", p_event)) {
- emit_signal("request_help_search", "");
+ emit_signal(SNAME("request_help_search"), "");
} else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && StreamPeerSSL::is_available()) {
_editor_select(EDITOR_ASSETLIB);
} else if (ED_IS_SHORTCUT("editor/editor_next", p_event)) {
@@ -506,6 +508,9 @@ void EditorNode::_update_from_settings() {
float lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
scene_root->set_lod_threshold(lod_threshold);
+
+ RS::get_singleton()->decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
+ RS::get_singleton()->light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
}
void EditorNode::_notification(int p_what) {
@@ -551,7 +556,7 @@ void EditorNode::_notification(int p_what) {
if (settings_changed) {
_update_from_settings();
settings_changed = false;
- emit_signal("project_settings_changed");
+ emit_signal(SNAME("project_settings_changed"));
}
} break;
@@ -590,8 +595,7 @@ void EditorNode::_notification(int p_what) {
_initializing_addons = false;
}
- RenderingServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(), true);
- RenderingServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true);
+ RenderingServer::get_singleton()->viewport_set_disable_2d(get_scene_root()->get_viewport_rid(), true);
RenderingServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true);
feature_profile_manager->notify_changed();
@@ -641,17 +645,17 @@ void EditorNode::_notification(int p_what) {
theme_base->set_theme(theme);
gui_base->set_theme(theme);
- gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox("Background", "EditorStyles"));
- scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox("Content", "EditorStyles"));
- bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer"));
- scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox("SceneTabFG", "EditorStyles"));
- scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox("SceneTabBG", "EditorStyles"));
+ gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles")));
+ scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), SNAME("EditorStyles")));
+ bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
+ scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles")));
+ scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles")));
- file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
- project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
- debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
- settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
- help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
+ file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
+ project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
+ debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
+ settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
+ help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
if (EDITOR_GET("interface/scene_tabs/resize_if_many_tabs")) {
scene_tabs->set_min_width(int(EDITOR_GET("interface/scene_tabs/minimum_width")) * EDSCALE);
@@ -664,7 +668,7 @@ void EditorNode::_notification(int p_what) {
// debugger area
if (EditorDebuggerNode::get_singleton()->is_visible()) {
- bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
+ bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles")));
}
// update_icons
@@ -682,17 +686,17 @@ void EditorNode::_notification(int p_what) {
_build_icon_type_cache();
- play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons"));
- play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons"));
- play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons"));
- pause_button->set_icon(gui_base->get_theme_icon("Pause", "EditorIcons"));
- stop_button->set_icon(gui_base->get_theme_icon("Stop", "EditorIcons"));
+ play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")));
+ play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons")));
+ pause_button->set_icon(gui_base->get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
+ stop_button->set_icon(gui_base->get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
- prev_scene->set_icon(gui_base->get_theme_icon("PrevScene", "EditorIcons"));
- distraction_free->set_icon(gui_base->get_theme_icon("DistractionFree", "EditorIcons"));
- scene_tab_add->set_icon(gui_base->get_theme_icon("Add", "EditorIcons"));
+ prev_scene->set_icon(gui_base->get_theme_icon(SNAME("PrevScene"), SNAME("EditorIcons")));
+ distraction_free->set_icon(gui_base->get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons")));
+ scene_tab_add->set_icon(gui_base->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- bottom_panel_raise->set_icon(gui_base->get_theme_icon("ExpandBottomDock", "EditorIcons"));
+ bottom_panel_raise->set_icon(gui_base->get_theme_icon(SNAME("ExpandBottomDock"), SNAME("EditorIcons")));
// clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property
if (gui_base->is_layout_rtl()) {
@@ -704,18 +708,19 @@ 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("HelpSearch", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_theme_icon("Instance", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_theme_icon("Instance", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_REPORT_A_BUG), gui_base->get_theme_icon("Instance", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_theme_icon("Instance", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_theme_icon("Instance", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_theme_icon("Godot", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), gui_base->get_theme_icon("Heart", "EditorIcons"));
+ 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_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")));
for (int i = 0; i < main_editor_buttons.size(); i++) {
- main_editor_buttons.write[i]->add_theme_font_override("font", gui_base->get_theme_font("main_button_font", "EditorFonts"));
- main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size("main_button_font_size", "EditorFonts"));
+ main_editor_buttons.write[i]->add_theme_font_override("font", gui_base->get_theme_font(SNAME("main_button_font"), SNAME("EditorFonts")));
+ main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("main_button_font_size"), SNAME("EditorFonts")));
}
_update_update_spinner();
@@ -970,7 +975,7 @@ void EditorNode::_scan_external_changes() {
}
if (need_reload) {
- disk_changed->call_deferred("popup_centered_ratio", 0.5);
+ disk_changed->call_deferred(SNAME("popup_centered_ratio"), 0.5);
}
}
@@ -1103,7 +1108,7 @@ void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const St
}
((Resource *)p_resource.ptr())->set_path(path);
- emit_signal("resource_saved", p_resource);
+ emit_signal(SNAME("resource_saved"), p_resource);
editor_data.notify_resource_saved(p_resource);
}
@@ -2215,11 +2220,11 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
}
play_button->set_pressed(false);
- play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons"));
+ play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
play_scene_button->set_pressed(false);
- play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons"));
+ play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")));
play_custom_scene_button->set_pressed(false);
- play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons"));
+ play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons")));
String run_filename;
String args;
@@ -2292,17 +2297,17 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
return;
}
- emit_signal("play_pressed");
+ emit_signal(SNAME("play_pressed"));
if (p_current) {
play_scene_button->set_pressed(true);
- play_scene_button->set_icon(gui_base->get_theme_icon("Reload", "EditorIcons"));
+ play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
} else if (p_custom != "") {
run_custom_filename = p_custom;
play_custom_scene_button->set_pressed(true);
- play_custom_scene_button->set_icon(gui_base->get_theme_icon("Reload", "EditorIcons"));
+ play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
} else {
play_button->set_pressed(true);
- play_button->set_icon(gui_base->get_theme_icon("Reload", "EditorIcons"));
+ play_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
}
stop_button->set_disabled(false);
@@ -2322,11 +2327,14 @@ void EditorNode::_run_native(const Ref<EditorExportPreset> &p_preset) {
}
EditorDebuggerNode::get_singleton()->start(p_preset->get_platform()->get_debug_protocol());
- emit_signal("play_pressed");
+ emit_signal(SNAME("play_pressed"));
editor_run.run_native_notify();
}
}
+void EditorNode::_android_build_source_selected(const String &p_file) {
+ export_template_manager->install_android_template_from_file(p_file);
+}
void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (!p_confirmed) { //this may be a hack..
current_option = (MenuOptions)p_option;
@@ -2634,11 +2642,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
editor_run.stop();
run_custom_filename.clear();
play_button->set_pressed(false);
- play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons"));
+ play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
play_scene_button->set_pressed(false);
- play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons"));
+ play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")));
play_custom_scene_button->set_pressed(false);
- play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons"));
+ play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons")));
stop_button->set_disabled(true);
if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) {
@@ -2650,7 +2658,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
}
EditorDebuggerNode::get_singleton()->stop();
- emit_signal("stop_pressed");
+ emit_signal(SNAME("stop_pressed"));
} break;
@@ -2711,7 +2719,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
save_confirmation->get_ok_button()->set_text(TTR("Save & Quit"));
- save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes the following scene(s) before opening Project Manager?")) + unsaved_scenes);
+ save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes to the following scene(s) before opening Project Manager?")) + unsaved_scenes);
save_confirmation->popup_centered();
}
}
@@ -2751,6 +2759,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
export_template_manager->popup_manager();
} break;
+ case SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE: {
+ custom_build_manage_templates->hide();
+ file_android_build_source->popup_centered_ratio();
+ } break;
case SETTINGS_MANAGE_FEATURE_PROFILES: {
feature_profile_manager->popup_centered_clamped(Size2(900, 800) * EDSCALE, 0.8);
} break;
@@ -2784,7 +2796,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case HELP_SEARCH: {
- emit_signal("request_help_search", "");
+ emit_signal(SNAME("request_help_search"), "");
} break;
case HELP_DOCS: {
OS::get_singleton()->shell_open("https://docs.godotengine.org/");
@@ -2795,6 +2807,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case HELP_REPORT_A_BUG: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot/issues");
} break;
+ case HELP_SUGGEST_A_FEATURE: {
+ OS::get_singleton()->shell_open("https://github.com/godotengine/godot-proposals#readme");
+ } break;
case HELP_SEND_DOCS_FEEDBACK: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot-docs/issues");
} break;
@@ -3055,8 +3070,8 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed
tb->set_icon(singleton->gui_base->get_theme_icon(p_editor->get_name(), "EditorIcons"));
}
- tb->add_theme_font_override("font", singleton->gui_base->get_theme_font("main_button_font", "EditorFonts"));
- tb->add_theme_font_size_override("font_size", singleton->gui_base->get_theme_font_size("main_button_font_size", "EditorFonts"));
+ tb->add_theme_font_override("font", singleton->gui_base->get_theme_font(SNAME("main_button_font"), SNAME("EditorFonts")));
+ tb->add_theme_font_size_override("font_size", singleton->gui_base->get_theme_font_size(SNAME("main_button_font_size"), SNAME("EditorFonts")));
tb->set_name(p_editor->get_name());
singleton->main_editor_buttons.push_back(tb);
@@ -3354,7 +3369,7 @@ void EditorNode::set_current_scene(int p_idx) {
editor_folding.load_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
}
- call_deferred("_clear_undo_history");
+ call_deferred(SNAME("_clear_undo_history"));
}
changing_scene = true;
@@ -3391,7 +3406,7 @@ void EditorNode::set_current_scene(int p_idx) {
_update_title();
- call_deferred("_set_main_scene_state", state, get_edited_scene()); //do after everything else is done setting up
+ call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); //do after everything else is done setting up
}
bool EditorNode::is_scene_open(const String &p_path) {
@@ -3638,7 +3653,7 @@ void EditorNode::_add_to_recent_scenes(const String &p_scene) {
void EditorNode::_open_recent_scene(int p_idx) {
if (p_idx == recent_scenes->get_item_count() - 1) {
EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", Array());
- call_deferred("_update_recent_scenes");
+ call_deferred(SNAME("_update_recent_scenes"));
} else {
Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
ERR_FAIL_INDEX(p_idx, rc.size());
@@ -3700,7 +3715,7 @@ void EditorNode::add_io_error(const String &p_error) {
void EditorNode::_load_error_notify(void *p_ud, const String &p_text) {
EditorNode *en = (EditorNode *)p_ud;
- en->load_errors->add_image(en->gui_base->get_theme_icon("Error", "EditorIcons"));
+ en->load_errors->add_image(en->gui_base->get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
en->load_errors->add_text(p_text + "\n");
en->load_error_dialog->popup_centered_ratio(0.5);
}
@@ -3731,49 +3746,52 @@ void EditorNode::register_editor_types() {
ResourceLoader::set_timestamp_on_load(true);
ResourceSaver::set_timestamp_on_save(true);
- ClassDB::register_class<EditorPaths>();
- ClassDB::register_class<EditorPlugin>();
- ClassDB::register_class<EditorTranslationParserPlugin>();
- ClassDB::register_class<EditorImportPlugin>();
- ClassDB::register_class<EditorScript>();
- ClassDB::register_class<EditorSelection>();
- ClassDB::register_class<EditorFileDialog>();
- ClassDB::register_virtual_class<EditorSettings>();
- ClassDB::register_class<EditorNode3DGizmo>();
- ClassDB::register_class<EditorNode3DGizmoPlugin>();
- ClassDB::register_virtual_class<EditorResourcePreview>();
- ClassDB::register_class<EditorResourcePreviewGenerator>();
- ClassDB::register_virtual_class<EditorFileSystem>();
- ClassDB::register_class<EditorFileSystemDirectory>();
- ClassDB::register_class<EditorVCSInterface>();
- ClassDB::register_virtual_class<ScriptEditor>();
- ClassDB::register_virtual_class<ScriptEditorBase>();
- ClassDB::register_class<EditorSyntaxHighlighter>();
- ClassDB::register_virtual_class<EditorInterface>();
- ClassDB::register_class<EditorExportPlugin>();
- ClassDB::register_class<EditorResourceConversionPlugin>();
- ClassDB::register_class<EditorSceneImporter>();
- ClassDB::register_class<EditorInspector>();
- ClassDB::register_class<EditorInspectorPlugin>();
- ClassDB::register_class<EditorProperty>();
- ClassDB::register_class<AnimationTrackEditPlugin>();
- ClassDB::register_class<ScriptCreateDialog>();
- ClassDB::register_class<EditorFeatureProfile>();
- ClassDB::register_class<EditorSpinSlider>();
- ClassDB::register_class<EditorResourcePicker>();
- ClassDB::register_class<EditorScriptPicker>();
- ClassDB::register_class<EditorSceneImporterMesh>();
- ClassDB::register_class<EditorSceneImporterMeshNode3D>();
-
- ClassDB::register_virtual_class<FileSystemDock>();
+ GDREGISTER_CLASS(EditorPaths);
+ GDREGISTER_CLASS(EditorPlugin);
+ GDREGISTER_CLASS(EditorTranslationParserPlugin);
+ GDREGISTER_CLASS(EditorImportPlugin);
+ GDREGISTER_CLASS(EditorScript);
+ GDREGISTER_CLASS(EditorSelection);
+ GDREGISTER_CLASS(EditorFileDialog);
+ GDREGISTER_VIRTUAL_CLASS(EditorSettings);
+ GDREGISTER_CLASS(EditorNode3DGizmo);
+ GDREGISTER_CLASS(EditorNode3DGizmoPlugin);
+ GDREGISTER_VIRTUAL_CLASS(EditorResourcePreview);
+ GDREGISTER_CLASS(EditorResourcePreviewGenerator);
+ GDREGISTER_VIRTUAL_CLASS(EditorFileSystem);
+ GDREGISTER_CLASS(EditorFileSystemDirectory);
+ GDREGISTER_CLASS(EditorVCSInterface);
+ GDREGISTER_VIRTUAL_CLASS(ScriptEditor);
+ GDREGISTER_VIRTUAL_CLASS(ScriptEditorBase);
+ GDREGISTER_CLASS(EditorSyntaxHighlighter);
+ GDREGISTER_VIRTUAL_CLASS(EditorInterface);
+ GDREGISTER_CLASS(EditorExportPlugin);
+ GDREGISTER_CLASS(EditorResourceConversionPlugin);
+ GDREGISTER_CLASS(EditorSceneImporter);
+ GDREGISTER_CLASS(EditorInspector);
+ GDREGISTER_CLASS(EditorInspectorPlugin);
+ GDREGISTER_CLASS(EditorProperty);
+ GDREGISTER_CLASS(AnimationTrackEditPlugin);
+ GDREGISTER_CLASS(ScriptCreateDialog);
+ GDREGISTER_CLASS(EditorFeatureProfile);
+ GDREGISTER_CLASS(EditorSpinSlider);
+ GDREGISTER_CLASS(EditorResourcePicker);
+ GDREGISTER_CLASS(EditorScriptPicker);
+ GDREGISTER_CLASS(EditorSceneImporterMesh);
+ GDREGISTER_CLASS(EditorSceneImporterMeshNode3D);
+
+ GDREGISTER_VIRTUAL_CLASS(FileSystemDock);
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
- ClassDB::register_class<EditorScenePostImport>();
+ GDREGISTER_CLASS(EditorScenePostImport);
//ClassDB::register_type<EditorImportExport>();
- ClassDB::register_class<EditorDebuggerPlugin>();
+ GDREGISTER_CLASS(EditorDebuggerPlugin);
+
+ NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
}
void EditorNode::unregister_editor_types() {
+ NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
_init_callbacks.clear();
if (EditorPaths::get_singleton()) {
EditorPaths::free();
@@ -3867,6 +3885,21 @@ Ref<ImageTexture> EditorNode::_load_custom_class_icon(const String &p_path) cons
return nullptr;
}
+void EditorNode::_pick_main_scene_custom_action(const String &p_custom_action_name) {
+ if (p_custom_action_name == "select_current") {
+ Node *scene = editor_data.get_edited_scene_root();
+
+ if (!scene) {
+ show_accept(TTR("There is no defined scene to run."), TTR("OK"));
+ return;
+ }
+
+ pick_main_scene->hide();
+ current_option = SETTINGS_PICK_MAIN_SCENE;
+ _dialog_action(scene->get_filename());
+ }
+}
+
Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String &p_fallback) const {
ERR_FAIL_COND_V(!p_object || !gui_base, nullptr);
@@ -3909,7 +3942,7 @@ Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String
}
if (p_fallback.length()) {
- return gui_base->get_theme_icon(p_fallback, "EditorIcons");
+ return gui_base->get_theme_icon(p_fallback, SNAME("EditorIcons"));
}
return nullptr;
@@ -3950,12 +3983,12 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p
}
}
- if (gui_base->has_theme_icon(p_class, "EditorIcons")) {
- return gui_base->get_theme_icon(p_class, "EditorIcons");
+ if (gui_base->has_theme_icon(p_class, SNAME("EditorIcons"))) {
+ return gui_base->get_theme_icon(p_class, SNAME("EditorIcons"));
}
- if (p_fallback.length() && gui_base->has_theme_icon(p_fallback, "EditorIcons")) {
- return gui_base->get_theme_icon(p_fallback, "EditorIcons");
+ if (p_fallback.length() && gui_base->has_theme_icon(p_fallback, SNAME("EditorIcons"))) {
+ return gui_base->get_theme_icon(p_fallback, SNAME("EditorIcons"));
}
return nullptr;
@@ -4259,7 +4292,7 @@ void EditorNode::_dock_select_draw() {
Color used = Color(0.6, 0.6, 0.6, 0.8);
Color used_selected = Color(0.8, 0.8, 0.8, 0.8);
- Color tab_selected = theme_base->get_theme_color("mono_color", "Editor");
+ Color tab_selected = theme_base->get_theme_color(SNAME("mono_color"), SNAME("Editor"));
Color unused = used;
unused.a = 0.4;
Color unusable = unused;
@@ -4661,6 +4694,14 @@ bool EditorNode::ensure_main_scene(bool p_from_native) {
current_option = -1;
pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in \"Project Settings\" under the 'application' category."));
pick_main_scene->popup_centered();
+
+ if (editor_data.get_edited_scene_root()) {
+ select_current_scene_button->set_disabled(false);
+ select_current_scene_button->grab_focus();
+ } else {
+ select_current_scene_button->set_disabled(true);
+ }
+
return false;
}
@@ -5014,9 +5055,9 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
bottom_panel_items[i].control->set_visible(i == p_idx);
}
if (EditorDebuggerNode::get_singleton() == bottom_panel_items[p_idx].control) { // this is the debug panel which uses tabs, so the top section should be smaller
- bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
+ bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles")));
} else {
- bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer"));
+ bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
}
center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);
center_split->set_collapsed(false);
@@ -5026,7 +5067,7 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
bottom_panel_raise->show();
} else {
- bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer"));
+ bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
bottom_panel_items[p_idx].button->set_pressed(false);
bottom_panel_items[p_idx].control->set_visible(false);
center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
@@ -5115,7 +5156,7 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
{
//todo make proper previews
- Ref<ImageTexture> texture = gui_base->get_theme_icon("FileBigThumb", "EditorIcons");
+ Ref<ImageTexture> texture = gui_base->get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons"));
Ref<Image> img = texture->get_image();
img = img->duplicate();
img->resize(48, 48); //meh
@@ -5167,10 +5208,10 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control *
if (p_paths[i].ends_with("/")) {
label->set_text(p_paths[i].substr(0, p_paths[i].length() - 1).get_file());
- icon->set_texture(gui_base->get_theme_icon("Folder", "EditorIcons"));
+ icon->set_texture(gui_base->get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
} else {
label->set_text(p_paths[i].get_file());
- icon->set_texture(gui_base->get_theme_icon("File", "EditorIcons"));
+ icon->set_texture(gui_base->get_theme_icon(SNAME("File"), SNAME("EditorIcons")));
}
icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
icon->set_size(Size2(16, 16));
@@ -5442,7 +5483,7 @@ void EditorNode::_update_video_driver_color() {
if (video_driver->get_text() == "GLES2") {
video_driver->add_theme_color_override("font_color", Color::hex(0x5586a4ff));
} else if (video_driver->get_text() == "Vulkan") {
- video_driver->add_theme_color_override("font_color", theme_base->get_theme_color("vulkan_color", "Editor"));
+ video_driver->add_theme_color_override("font_color", theme_base->get_theme_color(SNAME("vulkan_color"), SNAME("Editor")));
}
}
@@ -5872,7 +5913,7 @@ EditorNode::EditorNode() {
theme_base->set_theme(theme);
gui_base->set_theme(theme);
- gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox("Background", "EditorStyles"));
+ gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles")));
resource_preview = memnew(EditorResourcePreview);
add_child(resource_preview);
@@ -6053,8 +6094,8 @@ EditorNode::EditorNode() {
tab_preview_panel->add_child(tab_preview);
scene_tabs = memnew(Tabs);
- scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox("SceneTabFG", "EditorStyles"));
- scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox("SceneTabBG", "EditorStyles"));
+ scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles")));
+ scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles")));
scene_tabs->set_select_with_rmb(true);
scene_tabs->add_tab("unsaved");
scene_tabs->set_tab_align(Tabs::ALIGN_LEFT);
@@ -6088,7 +6129,7 @@ EditorNode::EditorNode() {
#endif
distraction_free->set_tooltip(TTR("Toggle distraction-free mode."));
distraction_free->connect("pressed", callable_mp(this, &EditorNode::_toggle_distraction_free_mode));
- distraction_free->set_icon(gui_base->get_theme_icon("DistractionFree", "EditorIcons"));
+ distraction_free->set_icon(gui_base->get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons")));
distraction_free->set_toggle_mode(true);
scene_tab_add = memnew(Button);
@@ -6096,21 +6137,21 @@ EditorNode::EditorNode() {
tabbar_container->add_child(scene_tab_add);
tabbar_container->add_child(distraction_free);
scene_tab_add->set_tooltip(TTR("Add a new scene."));
- scene_tab_add->set_icon(gui_base->get_theme_icon("Add", "EditorIcons"));
+ scene_tab_add->set_icon(gui_base->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
scene_tab_add->add_theme_color_override("icon_normal_color", Color(0.6f, 0.6f, 0.6f, 0.8f));
scene_tab_add->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_NEW_SCENE));
scene_root_parent = memnew(PanelContainer);
scene_root_parent->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
- scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox("Content", "EditorStyles"));
+ scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), SNAME("EditorStyles")));
scene_root_parent->set_draw_behind_parent(true);
srt->add_child(scene_root_parent);
scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
scene_root = memnew(SubViewport);
- //scene_root->set_usage(Viewport::USAGE_2D); canvas BG mode prevents usage of this as 2D
+ scene_root->set_embed_subwindows_hint(true);
+ scene_root->set_disable_3d(true);
- RenderingServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(), true);
scene_root->set_disable_input(true);
scene_root->set_as_audio_listener_2d(true);
@@ -6126,12 +6167,12 @@ EditorNode::EditorNode() {
file_menu->set_flat(false);
file_menu->set_switch_on_hover(true);
file_menu->set_text(TTR("Scene"));
- file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
+ file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
left_menu_hb->add_child(file_menu);
prev_scene = memnew(Button);
prev_scene->set_flat(true);
- prev_scene->set_icon(gui_base->get_theme_icon("PrevScene", "EditorIcons"));
+ prev_scene->set_icon(gui_base->get_theme_icon(SNAME("PrevScene"), SNAME("EditorIcons")));
prev_scene->set_tooltip(TTR("Go to previously opened scene."));
prev_scene->set_disabled(true);
prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_OPEN_PREV));
@@ -6230,7 +6271,7 @@ EditorNode::EditorNode() {
project_menu->set_switch_on_hover(true);
project_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools."));
project_menu->set_text(TTR("Project"));
- project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
+ project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
left_menu_hb->add_child(project_menu);
p = project_menu->get_popup();
@@ -6264,7 +6305,7 @@ EditorNode::EditorNode() {
tool_menu->add_item(TTR("Orphan Resource Explorer..."), TOOLS_ORPHAN_RESOURCES);
p->add_separator();
- p->add_item(TTR("Reload Current Project"), RUN_RELOAD_CURRENT_PROJECT);
+ p->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTR("Reload Current Project")), RUN_RELOAD_CURRENT_PROJECT);
#ifdef OSX_ENABLED
p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true);
#else
@@ -6281,7 +6322,7 @@ EditorNode::EditorNode() {
debug_menu->set_flat(false);
debug_menu->set_switch_on_hover(true);
debug_menu->set_text(TTR("Debug"));
- debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
+ debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
left_menu_hb->add_child(debug_menu);
menu_hb->add_spacer();
@@ -6290,7 +6331,7 @@ EditorNode::EditorNode() {
settings_menu->set_flat(false);
settings_menu->set_switch_on_hover(true);
settings_menu->set_text(TTR("Editor"));
- settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
+ settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
left_menu_hb->add_child(settings_menu);
p = settings_menu->get_popup();
@@ -6343,25 +6384,26 @@ EditorNode::EditorNode() {
help_menu->set_flat(false);
help_menu->set_switch_on_hover(true);
help_menu->set_text(TTR("Help"));
- help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
+ help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles")));
left_menu_hb->add_child(help_menu);
p = help_menu->get_popup();
p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
#ifdef OSX_ENABLED
- p->add_icon_shortcut(gui_base->get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE), HELP_SEARCH);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE), HELP_SEARCH);
#else
- p->add_icon_shortcut(gui_base->get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F1), HELP_SEARCH);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F1), HELP_SEARCH);
#endif
p->add_separator();
- p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
- p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Questions & Answers")), HELP_QA);
- p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
- p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
- p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/q&a", TTR("Questions & Answers")), HELP_QA);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("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("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("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("editor/community", TTR("Community")), HELP_COMMUNITY);
p->add_separator();
- p->add_icon_shortcut(gui_base->get_theme_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About Godot")), HELP_ABOUT);
- p->add_icon_shortcut(gui_base->get_theme_icon("Heart", "EditorIcons"), ED_SHORTCUT("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Godot"), SNAME("EditorIcons")), ED_SHORTCUT("editor/about", TTR("About Godot")), HELP_ABOUT);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Heart"), SNAME("EditorIcons")), ED_SHORTCUT("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
HBoxContainer *play_hb = memnew(HBoxContainer);
menu_hb->add_child(play_hb);
@@ -6370,7 +6412,7 @@ EditorNode::EditorNode() {
play_button->set_flat(true);
play_hb->add_child(play_button);
play_button->set_toggle_mode(true);
- play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons"));
+ play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
play_button->set_focus_mode(Control::FOCUS_NONE);
play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY));
play_button->set_tooltip(TTR("Play the project."));
@@ -6383,7 +6425,7 @@ EditorNode::EditorNode() {
pause_button = memnew(Button);
pause_button->set_flat(true);
pause_button->set_toggle_mode(true);
- pause_button->set_icon(gui_base->get_theme_icon("Pause", "EditorIcons"));
+ pause_button->set_icon(gui_base->get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
pause_button->set_focus_mode(Control::FOCUS_NONE);
pause_button->set_tooltip(TTR("Pause the scene execution for debugging."));
pause_button->set_disabled(true);
@@ -6398,7 +6440,7 @@ EditorNode::EditorNode() {
stop_button->set_flat(true);
play_hb->add_child(stop_button);
stop_button->set_focus_mode(Control::FOCUS_NONE);
- stop_button->set_icon(gui_base->get_theme_icon("Stop", "EditorIcons"));
+ stop_button->set_icon(gui_base->get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_STOP));
stop_button->set_tooltip(TTR("Stop the scene."));
stop_button->set_disabled(true);
@@ -6417,7 +6459,7 @@ EditorNode::EditorNode() {
play_hb->add_child(play_scene_button);
play_scene_button->set_toggle_mode(true);
play_scene_button->set_focus_mode(Control::FOCUS_NONE);
- play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons"));
+ play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")));
play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_SCENE));
play_scene_button->set_tooltip(TTR("Play the edited scene."));
#ifdef OSX_ENABLED
@@ -6431,7 +6473,7 @@ EditorNode::EditorNode() {
play_hb->add_child(play_custom_scene_button);
play_custom_scene_button->set_toggle_mode(true);
play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE);
- play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons"));
+ play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons")));
play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_CUSTOM_SCENE));
play_custom_scene_button->set_tooltip(TTR("Play custom scene"));
#ifdef OSX_ENABLED
@@ -6447,8 +6489,8 @@ EditorNode::EditorNode() {
video_driver = memnew(OptionButton);
video_driver->set_focus_mode(Control::FOCUS_NONE);
video_driver->connect("item_selected", callable_mp(this, &EditorNode::_video_driver_selected));
- video_driver->add_theme_font_override("font", gui_base->get_theme_font("bold", "EditorFonts"));
- video_driver->add_theme_font_size_override("font_size", gui_base->get_theme_font_size("bold_size", "EditorFonts"));
+ video_driver->add_theme_font_override("font", gui_base->get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
+ video_driver->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts")));
// TODO: Show again when OpenGL is ported.
video_driver->set_visible(false);
right_menu_hb->add_child(video_driver);
@@ -6490,7 +6532,7 @@ EditorNode::EditorNode() {
update_spinner = memnew(MenuButton);
update_spinner->set_tooltip(TTR("Spins when the editor window redraws."));
right_menu_hb->add_child(update_spinner);
- update_spinner->set_icon(gui_base->get_theme_icon("Progress1", "EditorIcons"));
+ update_spinner->set_icon(gui_base->get_theme_icon(SNAME("Progress1"), SNAME("EditorIcons")));
update_spinner->get_popup()->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
p = update_spinner->get_popup();
p->add_radio_check_item(TTR("Update Continuously"), SETTINGS_UPDATE_CONTINUOUSLY);
@@ -6567,7 +6609,7 @@ EditorNode::EditorNode() {
// Bottom panels
bottom_panel = memnew(PanelContainer);
- bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer"));
+ bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
center_split->add_child(bottom_panel);
center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
@@ -6610,7 +6652,7 @@ EditorNode::EditorNode() {
bottom_panel_raise = memnew(Button);
bottom_panel_raise->set_flat(true);
- bottom_panel_raise->set_icon(gui_base->get_theme_icon("ExpandBottomDock", "EditorIcons"));
+ bottom_panel_raise->set_icon(gui_base->get_theme_icon(SNAME("ExpandBottomDock"), SNAME("EditorIcons")));
bottom_panel_raise->set_shortcut(ED_SHORTCUT("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12));
@@ -6646,9 +6688,18 @@ EditorNode::EditorNode() {
custom_build_manage_templates = memnew(ConfirmationDialog);
custom_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates."));
custom_build_manage_templates->get_ok_button()->set_text(TTR("Manage Templates"));
+ custom_build_manage_templates->add_button(TTR("Install from file"))->connect("pressed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE));
custom_build_manage_templates->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_MANAGE_EXPORT_TEMPLATES));
gui_base->add_child(custom_build_manage_templates);
+ file_android_build_source = memnew(EditorFileDialog);
+ file_android_build_source->set_title(TTR("Select android sources file"));
+ file_android_build_source->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file_android_build_source->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ file_android_build_source->add_filter("*.zip");
+ file_android_build_source->connect("file_selected", callable_mp(this, &EditorNode::_android_build_source_selected));
+ gui_base->add_child(file_android_build_source);
+
install_android_build_template = memnew(ConfirmationDialog);
install_android_build_template->set_text(TTR("This will set up your project for custom Android builds by installing the source template to \"res://android/build\".\nYou can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.).\nNote that in order to make custom builds instead of using pre-built APKs, the \"Use Custom Build\" option should be enabled in the Android export preset."));
install_android_build_template->get_ok_button()->set_text(TTR("Install"));
@@ -6808,6 +6859,8 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(MeshEditorPlugin(this)));
add_editor_plugin(memnew(MaterialEditorPlugin(this)));
add_editor_plugin(memnew(GPUParticlesCollisionSDFEditorPlugin(this)));
+ add_editor_plugin(memnew(InputEventEditorPlugin(this)));
+ add_editor_plugin(memnew(SubViewportPreviewEditorPlugin(this)));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {
add_editor_plugin(EditorPlugins::create(i, this));
@@ -6936,6 +6989,8 @@ EditorNode::EditorNode() {
gui_base->add_child(pick_main_scene);
pick_main_scene->get_ok_button()->set_text(TTR("Select"));
pick_main_scene->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_PICK_MAIN_SCENE));
+ select_current_scene_button = pick_main_scene->add_button(TTR("Select Current"), true, "select_current");
+ pick_main_scene->connect("custom_action", callable_mp(this, &EditorNode::_pick_main_scene_custom_action));
for (int i = 0; i < _init_callbacks.size(); i++) {
_init_callbacks[i]();
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 9a135cfdd7..6b91856a59 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -181,6 +181,7 @@ private:
SETTINGS_EDITOR_CONFIG_FOLDER,
SETTINGS_MANAGE_EXPORT_TEMPLATES,
SETTINGS_MANAGE_FEATURE_PROFILES,
+ SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE,
SETTINGS_PICK_MAIN_SCENE,
SETTINGS_TOGGLE_CONSOLE,
SETTINGS_TOGGLE_FULLSCREEN,
@@ -194,6 +195,7 @@ private:
HELP_DOCS,
HELP_QA,
HELP_REPORT_A_BUG,
+ HELP_SUGGEST_A_FEATURE,
HELP_SEND_DOCS_FEEDBACK,
HELP_COMMUNITY,
HELP_ABOUT,
@@ -300,6 +302,7 @@ private:
ConfirmationDialog *save_confirmation;
ConfirmationDialog *import_confirmation;
ConfirmationDialog *pick_main_scene;
+ Button *select_current_scene_button;
AcceptDialog *accept;
EditorAbout *about;
AcceptDialog *warning;
@@ -325,6 +328,7 @@ private:
EditorFileDialog *file_templates;
EditorFileDialog *file_export_lib;
EditorFileDialog *file_script;
+ EditorFileDialog *file_android_build_source;
CheckBox *file_export_lib_merge;
String current_path;
MenuButton *update_spinner;
@@ -453,6 +457,8 @@ private:
void _menu_confirm_current();
void _menu_option_confirm(int p_option, bool p_confirmed);
+ void _android_build_source_selected(const String &p_file);
+
void _request_screenshot();
void _screenshot(bool p_use_utc = false);
void _save_screenshot(NodePath p_path);
@@ -662,6 +668,8 @@ private:
bool _is_class_editor_disabled_by_feature_profile(const StringName &p_class);
Ref<ImageTexture> _load_custom_class_icon(const String &p_path) const;
+ void _pick_main_scene_custom_action(const String &p_custom_action_name);
+
protected:
void _notification(int p_what);
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index 63281ae1aa..a31b9fd0c7 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -180,8 +180,8 @@ void EditorPath::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
update_path();
- sub_objects_icon->set_texture(get_theme_icon("select_arrow", "Tree"));
- current_object_label->add_theme_font_override("font", get_theme_font("main", "EditorFonts"));
+ sub_objects_icon->set_texture(get_theme_icon(SNAME("select_arrow"), SNAME("Tree")));
+ current_object_label->add_theme_font_override("font", get_theme_font(SNAME("main"), SNAME("EditorFonts")));
} break;
case NOTIFICATION_READY: {
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 63de06d5e2..07e9357e67 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -532,7 +532,7 @@ void EditorPlugin::set_force_draw_over_forwarding_enabled() {
}
void EditorPlugin::notify_scene_changed(const Node *scn_root) {
- emit_signal("scene_changed", scn_root);
+ emit_signal(SNAME("scene_changed"), scn_root);
}
void EditorPlugin::notify_main_screen_changed(const String &screen_name) {
@@ -540,16 +540,16 @@ void EditorPlugin::notify_main_screen_changed(const String &screen_name) {
return;
}
- emit_signal("main_screen_changed", screen_name);
+ emit_signal(SNAME("main_screen_changed"), screen_name);
last_main_screen_name = screen_name;
}
void EditorPlugin::notify_scene_closed(const String &scene_filepath) {
- emit_signal("scene_closed", scene_filepath);
+ emit_signal(SNAME("scene_closed"), scene_filepath);
}
void EditorPlugin::notify_resource_saved(const Ref<Resource> &p_resource) {
- emit_signal("resource_saved", p_resource);
+ emit_signal(SNAME("resource_saved"), p_resource);
}
bool EditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
@@ -729,13 +729,13 @@ void EditorPlugin::remove_translation_parser_plugin(const Ref<EditorTranslationP
void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
ERR_FAIL_COND(!p_importer.is_valid());
ResourceFormatImporter::get_singleton()->add_importer(p_importer);
- EditorFileSystem::get_singleton()->call_deferred("scan");
+ EditorFileSystem::get_singleton()->call_deferred(SNAME("scan"));
}
void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
ERR_FAIL_COND(!p_importer.is_valid());
ResourceFormatImporter::get_singleton()->remove_importer(p_importer);
- EditorFileSystem::get_singleton()->call_deferred("scan");
+ EditorFileSystem::get_singleton()->call_deferred(SNAME("scan"));
}
void EditorPlugin::add_export_plugin(const Ref<EditorExportPlugin> &p_exporter) {
@@ -854,7 +854,7 @@ void EditorPlugin::remove_debugger_plugin(const Ref<Script> &p_script) {
}
void EditorPlugin::_editor_project_settings_changed() {
- emit_signal("project_settings_changed");
+ emit_signal(SNAME("project_settings_changed"));
}
void EditorPlugin::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 67ce1ade4d..a8b08dc9ed 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -108,7 +108,7 @@ void EditorPluginSettings::update_plugins() {
bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(path);
item->set_checked(3, is_active);
item->set_editable(3, true);
- item->add_button(4, get_theme_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin"));
+ item->add_button(4, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin"));
}
}
}
@@ -192,7 +192,9 @@ EditorPluginSettings::EditorPluginSettings() {
add_child(plugin_config_dialog);
HBoxContainer *title_hb = memnew(HBoxContainer);
- title_hb->add_child(memnew(Label(TTR("Installed Plugins:"))));
+ Label *l = memnew(Label(TTR("Installed Plugins:")));
+ l->set_theme_type_variation("HeaderSmall");
+ title_hb->add_child(l);
title_hb->add_spacer();
create_plugin = memnew(Button(TTR("Create")));
create_plugin->connect("pressed", callable_mp(this, &EditorPluginSettings::_create_clicked));
@@ -212,14 +214,19 @@ EditorPluginSettings::EditorPluginSettings() {
plugin_list->set_column_title(3, TTR("Status:"));
plugin_list->set_column_title(4, TTR("Edit:"));
plugin_list->set_column_expand(0, true);
+ plugin_list->set_column_clip_content(0, true);
plugin_list->set_column_expand(1, false);
+ plugin_list->set_column_clip_content(1, true);
plugin_list->set_column_expand(2, false);
+ plugin_list->set_column_clip_content(2, true);
plugin_list->set_column_expand(3, false);
+ plugin_list->set_column_clip_content(3, true);
plugin_list->set_column_expand(4, false);
- plugin_list->set_column_min_width(1, 100 * EDSCALE);
- plugin_list->set_column_min_width(2, 250 * EDSCALE);
- plugin_list->set_column_min_width(3, 80 * EDSCALE);
- plugin_list->set_column_min_width(4, 40 * EDSCALE);
+ plugin_list->set_column_clip_content(4, true);
+ plugin_list->set_column_custom_minimum_width(1, 100 * EDSCALE);
+ plugin_list->set_column_custom_minimum_width(2, 250 * EDSCALE);
+ plugin_list->set_column_custom_minimum_width(3, 80 * EDSCALE);
+ plugin_list->set_column_custom_minimum_width(4, 40 * EDSCALE);
plugin_list->set_hide_root(true);
plugin_list->connect("item_edited", callable_mp(this, &EditorPluginSettings::_plugin_activity_changed));
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index c28a61fecd..df763d5bf0 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -147,10 +147,10 @@ void EditorPropertyMultilineText::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_ENTER_TREE: {
- Ref<Texture2D> df = get_theme_icon("DistractionFree", "EditorIcons");
+ Ref<Texture2D> df = get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons"));
open_big_text->set_icon(df);
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6));
} break;
@@ -180,44 +180,150 @@ EditorPropertyMultilineText::EditorPropertyMultilineText() {
///////////////////// TEXT ENUM /////////////////////////
-void EditorPropertyTextEnum::_option_selected(int p_which) {
+void EditorPropertyTextEnum::_emit_changed_value(String p_string) {
if (string_name) {
- emit_changed(get_edited_property(), StringName(options->get_item_text(p_which)));
+ emit_changed(get_edited_property(), StringName(p_string));
} else {
- emit_changed(get_edited_property(), options->get_item_text(p_which));
+ emit_changed(get_edited_property(), p_string);
}
}
+void EditorPropertyTextEnum::_option_selected(int p_which) {
+ _emit_changed_value(option_button->get_item_text(p_which));
+}
+
+void EditorPropertyTextEnum::_edit_custom_value() {
+ default_layout->hide();
+ edit_custom_layout->show();
+ custom_value_edit->grab_focus();
+}
+
+void EditorPropertyTextEnum::_custom_value_submitted(String p_value) {
+ edit_custom_layout->hide();
+ default_layout->show();
+
+ _emit_changed_value(p_value.strip_edges());
+}
+
+void EditorPropertyTextEnum::_custom_value_accepted() {
+ String new_value = custom_value_edit->get_text().strip_edges();
+ _custom_value_submitted(new_value);
+}
+
+void EditorPropertyTextEnum::_custom_value_cancelled() {
+ custom_value_edit->set_text(get_edited_object()->get(get_edited_property()));
+
+ edit_custom_layout->hide();
+ default_layout->show();
+}
+
void EditorPropertyTextEnum::update_property() {
- String which = get_edited_object()->get(get_edited_property());
- for (int i = 0; i < options->get_item_count(); i++) {
- String t = options->get_item_text(i);
- if (t == which) {
- options->select(i);
- return;
+ String current_value = get_edited_object()->get(get_edited_property());
+ int default_option = options.find(current_value);
+
+ // The list can change in the loose mode.
+ if (loose_mode) {
+ custom_value_edit->set_text(current_value);
+ option_button->clear();
+
+ // Manually entered value.
+ if (default_option < 0 && !current_value.is_empty()) {
+ option_button->add_item(current_value, options.size() + 1001);
+ option_button->select(0);
+
+ option_button->add_separator();
+ }
+
+ // Add an explicit empty value for clearing the property.
+ option_button->add_item("", options.size() + 1000);
+
+ for (int i = 0; i < options.size(); i++) {
+ option_button->add_item(options[i], i);
+ if (options[i] == current_value) {
+ option_button->select(option_button->get_item_count() - 1);
+ }
}
+ } else {
+ option_button->select(default_option);
}
}
-void EditorPropertyTextEnum::setup(const Vector<String> &p_options, bool p_string_name) {
+void EditorPropertyTextEnum::setup(const Vector<String> &p_options, bool p_string_name, bool p_loose_mode) {
+ string_name = p_string_name;
+ loose_mode = p_loose_mode;
+
+ options.clear();
+
+ if (loose_mode) {
+ // Add an explicit empty value for clearing the property in the loose mode.
+ option_button->add_item("", options.size() + 1000);
+ }
+
for (int i = 0; i < p_options.size(); i++) {
- options->add_item(p_options[i], i);
+ options.append(p_options[i]);
+ option_button->add_item(p_options[i], i);
+ }
+
+ if (loose_mode) {
+ edit_button->show();
}
- string_name = p_string_name;
}
void EditorPropertyTextEnum::_bind_methods() {
}
-EditorPropertyTextEnum::EditorPropertyTextEnum() {
- options = memnew(OptionButton);
- options->set_clip_text(true);
- options->set_flat(true);
- string_name = false;
+void EditorPropertyTextEnum::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED:
+ edit_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ accept_button->set_icon(get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons")));
+ cancel_button->set_icon(get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons")));
+ break;
+ }
+}
- add_child(options);
- add_focusable(options);
- options->connect("item_selected", callable_mp(this, &EditorPropertyTextEnum::_option_selected));
+EditorPropertyTextEnum::EditorPropertyTextEnum() {
+ default_layout = memnew(HBoxContainer);
+ add_child(default_layout);
+
+ edit_custom_layout = memnew(HBoxContainer);
+ edit_custom_layout->hide();
+ add_child(edit_custom_layout);
+
+ option_button = memnew(OptionButton);
+ option_button->set_h_size_flags(SIZE_EXPAND_FILL);
+ option_button->set_clip_text(true);
+ option_button->set_flat(true);
+ default_layout->add_child(option_button);
+ option_button->connect("item_selected", callable_mp(this, &EditorPropertyTextEnum::_option_selected));
+
+ edit_button = memnew(Button);
+ edit_button->set_flat(true);
+ edit_button->hide();
+ default_layout->add_child(edit_button);
+ edit_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_edit_custom_value));
+
+ custom_value_edit = memnew(LineEdit);
+ custom_value_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit_custom_layout->add_child(custom_value_edit);
+ custom_value_edit->connect("text_submitted", callable_mp(this, &EditorPropertyTextEnum::_custom_value_submitted));
+
+ accept_button = memnew(Button);
+ accept_button->set_flat(true);
+ edit_custom_layout->add_child(accept_button);
+ accept_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_custom_value_accepted));
+
+ cancel_button = memnew(Button);
+ cancel_button->set_flat(true);
+ edit_custom_layout->add_child(cancel_button);
+ cancel_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_custom_value_cancelled));
+
+ add_focusable(option_button);
+ add_focusable(edit_button);
+ add_focusable(custom_value_edit);
+ add_focusable(accept_button);
+ add_focusable(cancel_button);
}
///////////////////// PATH /////////////////////////
@@ -280,7 +386,7 @@ void EditorPropertyPath::set_save_mode() {
void EditorPropertyPath::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- path_edit->set_icon(get_theme_icon("Folder", "EditorIcons"));
+ path_edit->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
}
}
@@ -491,6 +597,7 @@ void EditorPropertyEnum::update_property() {
}
void EditorPropertyEnum::setup(const Vector<String> &p_options) {
+ options->clear();
int64_t current_val = 0;
for (int i = 0; i < p_options.size(); i++) {
Vector<String> text_split = p_options[i].split(":");
@@ -592,8 +699,8 @@ public:
int hovered_index;
virtual Size2 get_minimum_size() const override {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
return Vector2(0, font->get_height(font_size) * 2);
}
@@ -630,7 +737,7 @@ public:
value |= (1 << hovered_index);
}
- emit_signal("flag_changed", value);
+ emit_signal(SNAME("flag_changed"), value);
update();
}
}
@@ -646,7 +753,7 @@ public:
const int h = bsize * 2 + 1;
const int vofs = (rect.size.height - h) / 2;
- Color color = get_theme_color("highlight_color", "Editor");
+ Color color = get_theme_color(SNAME("highlight_color"), SNAME("Editor"));
for (int i = 0; i < 2; i++) {
Point2 ofs(4, vofs);
if (i == 1) {
@@ -850,7 +957,7 @@ EditorPropertyInteger::EditorPropertyInteger() {
///////////////////// OBJECT ID /////////////////////////
void EditorPropertyObjectID::_edit_pressed() {
- emit_signal("object_id_selected", get_edited_property(), get_edited_object()->get(get_edited_property()));
+ emit_signal(SNAME("object_id_selected"), get_edited_property(), get_edited_object()->get(get_edited_property()));
}
void EditorPropertyObjectID::update_property() {
@@ -892,11 +999,17 @@ void EditorPropertyFloat::_value_changed(double val) {
return;
}
+ if (angle_in_radians) {
+ val = Math::deg2rad(val);
+ }
emit_changed(get_edited_property(), val);
}
void EditorPropertyFloat::update_property() {
double val = get_edited_object()->get(get_edited_property());
+ if (angle_in_radians) {
+ val = Math::rad2deg(val);
+ }
setting = true;
spin->set_value(val);
setting = false;
@@ -905,7 +1018,8 @@ void EditorPropertyFloat::update_property() {
void EditorPropertyFloat::_bind_methods() {
}
-void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_exp_range, bool p_greater, bool p_lesser) {
+void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_exp_range, bool p_greater, bool p_lesser, const String &p_suffix, bool p_angle_in_radians) {
+ angle_in_radians = p_angle_in_radians;
spin->set_min(p_min);
spin->set_max(p_max);
spin->set_step(p_step);
@@ -913,6 +1027,7 @@ void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool
spin->set_exp_ratio(p_exp_range);
spin->set_allow_greater(p_greater);
spin->set_allow_lesser(p_lesser);
+ spin->set_suffix(p_suffix);
}
EditorPropertyFloat::EditorPropertyFloat() {
@@ -921,7 +1036,6 @@ EditorPropertyFloat::EditorPropertyFloat() {
add_child(spin);
add_focusable(spin);
spin->connect("value_changed", callable_mp(this, &EditorPropertyFloat::_value_changed));
- setting = false;
}
///////////////////// EASING /////////////////////////
@@ -998,14 +1112,14 @@ void EditorPropertyEasing::_draw_easing() {
const float exp = get_edited_object()->get(get_edited_property());
- const Ref<Font> f = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- const Color font_color = get_theme_color("font_color", "Label");
+ const Ref<Font> f = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ const Color font_color = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color line_color;
if (dragging) {
- line_color = get_theme_color("accent_color", "Editor");
+ line_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
} else {
- line_color = get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.9);
+ line_color = get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.9);
}
Vector<Point2> points;
@@ -1091,15 +1205,15 @@ void EditorPropertyEasing::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_ENTER_TREE: {
preset->clear();
- preset->add_icon_item(get_theme_icon("CurveConstant", "EditorIcons"), "Zero", EASING_ZERO);
- preset->add_icon_item(get_theme_icon("CurveLinear", "EditorIcons"), "Linear", EASING_LINEAR);
- preset->add_icon_item(get_theme_icon("CurveIn", "EditorIcons"), "In", EASING_IN);
- preset->add_icon_item(get_theme_icon("CurveOut", "EditorIcons"), "Out", EASING_OUT);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")), "Linear", EASING_LINEAR);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "In", EASING_IN);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Out", EASING_OUT);
if (full) {
- preset->add_icon_item(get_theme_icon("CurveInOut", "EditorIcons"), "In-Out", EASING_IN_OUT);
- preset->add_icon_item(get_theme_icon("CurveOutIn", "EditorIcons"), "Out-In", EASING_OUT_IN);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "In-Out", EASING_IN_OUT);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Out-In", EASING_OUT_IN);
}
- easing_draw->set_custom_minimum_size(Size2(0, get_theme_font("font", "Label")->get_height(get_theme_font_size("font_size", "Label")) * 2));
+ easing_draw->set_custom_minimum_size(Size2(0, get_theme_font(SNAME("font"), SNAME("Label"))->get_height(get_theme_font_size(SNAME("font_size"), SNAME("Label"))) * 2));
} break;
}
}
@@ -1159,7 +1273,7 @@ void EditorPropertyVector2::update_property() {
void EditorPropertyVector2::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 2; i++) {
Color c = base;
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1171,7 +1285,7 @@ void EditorPropertyVector2::_notification(int p_what) {
void EditorPropertyVector2::_bind_methods() {
}
-void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 2; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1179,6 +1293,7 @@ void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, boo
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1245,7 +1360,7 @@ void EditorPropertyRect2::update_property() {
void EditorPropertyRect2::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 4; i++) {
Color c = base;
c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1257,7 +1372,7 @@ void EditorPropertyRect2::_notification(int p_what) {
void EditorPropertyRect2::_bind_methods() {
}
-void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 4; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1265,6 +1380,7 @@ void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1325,6 +1441,11 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) {
v3.x = spin[0]->get_value();
v3.y = spin[1]->get_value();
v3.z = spin[2]->get_value();
+ if (angle_in_radians) {
+ v3.x = Math::deg2rad(v3.x);
+ v3.y = Math::deg2rad(v3.y);
+ v3.z = Math::deg2rad(v3.z);
+ }
emit_changed(get_edited_property(), v3, p_name);
}
@@ -1333,6 +1454,11 @@ void EditorPropertyVector3::update_property() {
}
void EditorPropertyVector3::update_using_vector(Vector3 p_vector) {
+ if (angle_in_radians) {
+ p_vector.x = Math::rad2deg(p_vector.x);
+ p_vector.y = Math::rad2deg(p_vector.y);
+ p_vector.z = Math::rad2deg(p_vector.z);
+ }
setting = true;
spin[0]->set_value(p_vector.x);
spin[1]->set_value(p_vector.y);
@@ -1345,12 +1471,18 @@ Vector3 EditorPropertyVector3::get_vector() {
v3.x = spin[0]->get_value();
v3.y = spin[1]->get_value();
v3.z = spin[2]->get_value();
+ if (angle_in_radians) {
+ v3.x = Math::deg2rad(v3.x);
+ v3.y = Math::deg2rad(v3.y);
+ v3.z = Math::deg2rad(v3.z);
+ }
+
return v3;
}
void EditorPropertyVector3::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 3; i++) {
Color c = base;
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1362,7 +1494,8 @@ void EditorPropertyVector3::_notification(int p_what) {
void EditorPropertyVector3::_bind_methods() {
}
-void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix, bool p_angle_in_radians) {
+ angle_in_radians = p_angle_in_radians;
for (int i = 0; i < 3; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1370,6 +1503,7 @@ void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, boo
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1406,7 +1540,6 @@ EditorPropertyVector3::EditorPropertyVector3(bool p_force_wide) {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// VECTOR2i /////////////////////////
@@ -1432,7 +1565,7 @@ void EditorPropertyVector2i::update_property() {
void EditorPropertyVector2i::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 2; i++) {
Color c = base;
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1444,7 +1577,7 @@ void EditorPropertyVector2i::_notification(int p_what) {
void EditorPropertyVector2i::_bind_methods() {
}
-void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider) {
+void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 2; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1452,6 +1585,7 @@ void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider) {
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1518,7 +1652,7 @@ void EditorPropertyRect2i::update_property() {
void EditorPropertyRect2i::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 4; i++) {
Color c = base;
c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1530,7 +1664,7 @@ void EditorPropertyRect2i::_notification(int p_what) {
void EditorPropertyRect2i::_bind_methods() {
}
-void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider) {
+void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 4; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1538,6 +1672,7 @@ void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider) {
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1612,7 +1747,7 @@ void EditorPropertyVector3i::update_property() {
void EditorPropertyVector3i::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 3; i++) {
Color c = base;
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1624,7 +1759,7 @@ void EditorPropertyVector3i::_notification(int p_what) {
void EditorPropertyVector3i::_bind_methods() {
}
-void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider) {
+void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 3; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1632,6 +1767,7 @@ void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider) {
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1697,7 +1833,7 @@ void EditorPropertyPlane::update_property() {
void EditorPropertyPlane::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 3; i++) {
Color c = base;
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1709,7 +1845,7 @@ void EditorPropertyPlane::_notification(int p_what) {
void EditorPropertyPlane::_bind_methods() {
}
-void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 4; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1717,6 +1853,7 @@ void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1783,7 +1920,7 @@ void EditorPropertyQuaternion::update_property() {
void EditorPropertyQuaternion::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 3; i++) {
Color c = base;
c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1795,7 +1932,7 @@ void EditorPropertyQuaternion::_notification(int p_what) {
void EditorPropertyQuaternion::_bind_methods() {
}
-void EditorPropertyQuaternion::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyQuaternion::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 4; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1803,6 +1940,7 @@ void EditorPropertyQuaternion::setup(double p_min, double p_max, double p_step,
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1872,7 +2010,7 @@ void EditorPropertyAABB::update_property() {
void EditorPropertyAABB::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 6; i++) {
Color c = base;
c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1884,7 +2022,7 @@ void EditorPropertyAABB::_notification(int p_what) {
void EditorPropertyAABB::_bind_methods() {
}
-void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 6; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1892,6 +2030,7 @@ void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -1948,7 +2087,7 @@ void EditorPropertyTransform2D::update_property() {
void EditorPropertyTransform2D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 6; i++) {
Color c = base;
c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -1960,7 +2099,7 @@ void EditorPropertyTransform2D::_notification(int p_what) {
void EditorPropertyTransform2D::_bind_methods() {
}
-void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 6; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -1968,6 +2107,7 @@ void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step,
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -2029,7 +2169,7 @@ void EditorPropertyBasis::update_property() {
void EditorPropertyBasis::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 9; i++) {
Color c = base;
c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -2041,7 +2181,7 @@ void EditorPropertyBasis::_notification(int p_what) {
void EditorPropertyBasis::_bind_methods() {
}
-void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 9; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -2049,6 +2189,7 @@ void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -2118,7 +2259,7 @@ void EditorPropertyTransform3D::update_using_transform(Transform3D p_transform)
void EditorPropertyTransform3D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < 12; i++) {
Color c = base;
c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v());
@@ -2130,7 +2271,7 @@ void EditorPropertyTransform3D::_notification(int p_what) {
void EditorPropertyTransform3D::_bind_methods() {
}
-void EditorPropertyTransform3D::setup(double p_min, double p_max, double p_step, bool p_no_slider) {
+void EditorPropertyTransform3D::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 12; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
@@ -2138,6 +2279,7 @@ void EditorPropertyTransform3D::setup(double p_min, double p_max, double p_step,
spin[i]->set_hide_slider(p_no_slider);
spin[i]->set_allow_greater(true);
spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
}
}
@@ -2333,7 +2475,7 @@ void EditorPropertyNodePath::setup(const NodePath &p_base_hint, Vector<StringNam
void EditorPropertyNodePath::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Ref<Texture2D> t = get_theme_icon("Clear", "EditorIcons");
+ Ref<Texture2D> t = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"));
clear->set_icon(t);
}
}
@@ -2385,7 +2527,7 @@ void EditorPropertyResource::_resource_selected(const RES &p_resource) {
get_edited_object()->editor_set_section_unfold(get_edited_property(), unfold);
update_property();
} else {
- emit_signal("resource_selected", get_edited_property(), p_resource);
+ emit_signal(SNAME("resource_selected"), get_edited_property(), p_resource);
}
}
@@ -2438,22 +2580,22 @@ void EditorPropertyResource::_resource_changed(const RES &p_resource) {
}
void EditorPropertyResource::_sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool) {
- emit_signal("property_keyed_with_value", String(get_edited_property()) + ":" + p_property, p_value, false);
+ emit_signal(SNAME("property_keyed_with_value"), String(get_edited_property()) + ":" + p_property, p_value, false);
}
void EditorPropertyResource::_sub_inspector_resource_selected(const RES &p_resource, const String &p_property) {
- emit_signal("resource_selected", String(get_edited_property()) + ":" + p_property, p_resource);
+ emit_signal(SNAME("resource_selected"), String(get_edited_property()) + ":" + p_property, p_resource);
}
void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) {
- emit_signal("object_id_selected", get_edited_property(), p_id);
+ emit_signal(SNAME("object_id_selected"), get_edited_property(), p_id);
}
void EditorPropertyResource::_open_editor_pressed() {
RES res = get_edited_object()->get(get_edited_property());
if (res.is_valid()) {
// May clear the editor so do it deferred.
- EditorNode::get_singleton()->call_deferred("edit_item_resource", res);
+ EditorNode::get_singleton()->call_deferred(SNAME("edit_item_resource"), res);
}
}
@@ -2509,18 +2651,18 @@ void EditorPropertyResource::_update_property_bg() {
}
count_subinspectors = MIN(15, count_subinspectors);
- add_theme_color_override("property_color", get_theme_color("sub_inspector_property_color", "Editor"));
+ add_theme_color_override("property_color", get_theme_color(SNAME("sub_inspector_property_color"), SNAME("Editor")));
add_theme_style_override("bg_selected", get_theme_stylebox("sub_inspector_property_bg_selected" + itos(count_subinspectors), "Editor"));
add_theme_style_override("bg", get_theme_stylebox("sub_inspector_property_bg" + itos(count_subinspectors), "Editor"));
- add_theme_constant_override("font_offset", get_theme_constant("sub_inspector_font_offset", "Editor"));
+ add_theme_constant_override("font_offset", get_theme_constant(SNAME("sub_inspector_font_offset"), SNAME("Editor")));
add_theme_constant_override("vseparation", 0);
} else {
- add_theme_color_override("property_color", get_theme_color("property_color", "EditorProperty"));
- add_theme_style_override("bg_selected", get_theme_stylebox("bg_selected", "EditorProperty"));
- add_theme_style_override("bg", get_theme_stylebox("bg", "EditorProperty"));
- add_theme_constant_override("vseparation", get_theme_constant("vseparation", "EditorProperty"));
- add_theme_constant_override("font_offset", get_theme_constant("font_offset", "EditorProperty"));
+ add_theme_color_override("property_color", get_theme_color(SNAME("property_color"), SNAME("EditorProperty")));
+ add_theme_style_override("bg_selected", get_theme_stylebox(SNAME("bg_selected"), SNAME("EditorProperty")));
+ add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("EditorProperty")));
+ add_theme_constant_override("vseparation", get_theme_constant(SNAME("vseparation"), SNAME("EditorProperty")));
+ add_theme_constant_override("font_offset", get_theme_constant(SNAME("font_offset"), SNAME("EditorProperty")));
}
updating_theme = false;
@@ -2618,7 +2760,7 @@ void EditorPropertyResource::update_property() {
// Open editor directly and hide other such editors which are currently open.
_open_editor_pressed();
if (is_inside_tree()) {
- get_tree()->call_deferred("call_group", "_editor_resource_properties", "_fold_other_editors", this);
+ get_tree()->call_deferred(SNAME("call_group"), "_editor_resource_properties", "_fold_other_editors", this);
}
opened_editor = true;
}
@@ -2698,31 +2840,97 @@ void EditorInspectorDefaultPlugin::parse_begin(Object *p_object) {
//do none
}
-bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+bool EditorInspectorDefaultPlugin::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) {
+ Control *editor = EditorInspectorDefaultPlugin::get_editor_for_property(p_object, p_type, p_path, p_hint, p_hint_text, p_usage, p_wide);
+ if (editor) {
+ add_property_editor(p_path, editor);
+ }
+ return false;
+}
+
+void EditorInspectorDefaultPlugin::parse_end() {
+ //do none
+}
+
+struct EditorPropertyRangeHint {
+ bool angle_in_degrees = false;
+ bool greater = true;
+ bool lesser = true;
+ double min = -99999;
+ double max = 99999;
+ double step = 0;
+ String suffix;
+ bool exp_range = false;
+ bool hide_slider = true;
+ bool radians = false;
+};
+
+static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step) {
+ EditorPropertyRangeHint hint;
+ hint.step = p_default_step;
+ bool degrees = false;
+ if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
+ hint.greater = false; //if using ranged, assume false by default
+ hint.lesser = false;
+
+ hint.min = p_hint_text.get_slice(",", 0).to_float();
+ hint.max = p_hint_text.get_slice(",", 1).to_float();
+ if (p_hint_text.get_slice_count(",") >= 3) {
+ hint.step = p_hint_text.get_slice(",", 2).to_float();
+ }
+ hint.hide_slider = false;
+ for (int i = 2; i < p_hint_text.get_slice_count(","); i++) {
+ String slice = p_hint_text.get_slice(",", i).strip_edges();
+ if (slice == "radians") {
+ hint.radians = true;
+ } else if (slice == "degrees") {
+ degrees = true;
+ } else if (slice == "or_greater") {
+ hint.greater = true;
+ } else if (slice == "or_lesser") {
+ hint.lesser = true;
+ } else if (slice == "noslider") {
+ hint.hide_slider = true;
+ } else if (slice == "exp") {
+ hint.exp_range = true;
+ } else if (slice.begins_with("suffix:")) {
+ hint.suffix = " " + slice.replace_first("suffix:", "").strip_edges();
+ }
+ }
+ }
+
+ if ((hint.radians || degrees) && hint.suffix == String()) {
+ hint.suffix = U"\u00B0";
+ }
+
+ return hint;
+}
+
+EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_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) {
double default_float_step = EDITOR_GET("interface/inspector/default_float_step");
switch (p_type) {
// atomic types
case Variant::NIL: {
EditorPropertyNil *editor = memnew(EditorPropertyNil);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::BOOL: {
EditorPropertyCheck *editor = memnew(EditorPropertyCheck);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::INT: {
if (p_hint == PROPERTY_HINT_ENUM) {
EditorPropertyEnum *editor = memnew(EditorPropertyEnum);
Vector<String> options = p_hint_text.split(",");
editor->setup(options);
- add_property_editor(p_path, editor);
+ return editor;
} else if (p_hint == PROPERTY_HINT_FLAGS) {
EditorPropertyFlags *editor = memnew(EditorPropertyFlags);
Vector<String> options = p_hint_text.split(",");
editor->setup(options);
- add_property_editor(p_path, editor);
+ return editor;
} else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS ||
p_hint == PROPERTY_HINT_LAYERS_2D_RENDER ||
@@ -2755,41 +2963,20 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
}
EditorPropertyLayers *editor = memnew(EditorPropertyLayers);
editor->setup(lt);
- add_property_editor(p_path, editor);
+ return editor;
} else if (p_hint == PROPERTY_HINT_OBJECT_ID) {
EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID);
editor->setup(p_hint_text);
- add_property_editor(p_path, editor);
+ return editor;
} else {
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
- int min = 0, max = 65535, step = 1;
- bool greater = true, lesser = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- greater = false; //if using ranged, assume false by default
- lesser = false;
- min = p_hint_text.get_slice(",", 0).to_int();
- max = p_hint_text.get_slice(",", 1).to_int();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_int();
- }
-
- for (int i = 2; i < p_hint_text.get_slice_count(","); i++) {
- String slice = p_hint_text.get_slice(",", i).strip_edges();
- if (slice == "or_greater") {
- greater = true;
- }
- if (slice == "or_lesser") {
- lesser = true;
- }
- }
- }
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
- editor->setup(min, max, step, greater, lesser);
+ editor->setup(hint.min, hint.max, hint.step, hint.greater, hint.lesser);
- add_property_editor(p_path, editor);
+ return editor;
}
} break;
case Variant::FLOAT: {
@@ -2809,54 +2996,30 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
}
editor->setup(full, flip);
- add_property_editor(p_path, editor);
+ return editor;
} else {
EditorPropertyFloat *editor = memnew(EditorPropertyFloat);
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
- bool exp_range = false;
- bool greater = true, lesser = true;
-
- if ((p_hint == PROPERTY_HINT_RANGE || p_hint == PROPERTY_HINT_EXP_RANGE) && p_hint_text.get_slice_count(",") >= 2) {
- greater = false; //if using ranged, assume false by default
- lesser = false;
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- exp_range = p_hint == PROPERTY_HINT_EXP_RANGE;
- for (int i = 2; i < p_hint_text.get_slice_count(","); i++) {
- String slice = p_hint_text.get_slice(",", i).strip_edges();
- if (slice == "or_greater") {
- greater = true;
- }
- if (slice == "or_lesser") {
- lesser = true;
- }
- }
- }
- editor->setup(min, max, step, hide_slider, exp_range, greater, lesser);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.exp_range, hint.greater, hint.lesser, hint.suffix, hint.radians);
- add_property_editor(p_path, editor);
+ return editor;
}
} break;
case Variant::STRING: {
- if (p_hint == PROPERTY_HINT_ENUM) {
+ if (p_hint == PROPERTY_HINT_ENUM || p_hint == PROPERTY_HINT_ENUM_SUGGESTION) {
EditorPropertyTextEnum *editor = memnew(EditorPropertyTextEnum);
- Vector<String> options = p_hint_text.split(",");
- editor->setup(options);
- add_property_editor(p_path, editor);
+ Vector<String> options = p_hint_text.split(",", false);
+ editor->setup(options, false, (p_hint == PROPERTY_HINT_ENUM_SUGGESTION));
+ return editor;
} else if (p_hint == PROPERTY_HINT_MULTILINE_TEXT) {
EditorPropertyMultilineText *editor = memnew(EditorPropertyMultilineText);
- add_property_editor(p_path, editor);
+ return editor;
} else if (p_hint == PROPERTY_HINT_TYPE_STRING) {
EditorPropertyClassName *editor = memnew(EditorPropertyClassName);
editor->setup("Object", p_hint_text);
- add_property_editor(p_path, editor);
+ return editor;
} else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) {
Vector<String> extensions = p_hint_text.split(",");
bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE;
@@ -2867,7 +3030,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
if (save) {
editor->set_save_mode();
}
- add_property_editor(p_path, editor);
+ return editor;
} else if (p_hint == PROPERTY_HINT_METHOD_OF_VARIANT_TYPE ||
p_hint == PROPERTY_HINT_METHOD_OF_BASE_TYPE ||
p_hint == PROPERTY_HINT_METHOD_OF_INSTANCE ||
@@ -2905,14 +3068,14 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
}
}
editor->setup(type, p_hint_text);
- add_property_editor(p_path, editor);
+ return editor;
} else {
EditorPropertyText *editor = memnew(EditorPropertyText);
if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) {
editor->set_placeholder(p_hint_text);
}
- add_property_editor(p_path, editor);
+ return editor;
}
} break;
@@ -2920,204 +3083,82 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
case Variant::VECTOR2: {
EditorPropertyVector2 *editor = memnew(EditorPropertyVector2(p_wide));
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::VECTOR2I: {
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide));
- int min = -65535, max = 65535;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- hide_slider = false;
- }
-
- editor->setup(min, max, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::RECT2: {
EditorPropertyRect2 *editor = memnew(EditorPropertyRect2(p_wide));
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::RECT2I: {
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i(p_wide));
- int min = -65535, max = 65535;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- hide_slider = false;
- }
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix);
- editor->setup(min, max, hide_slider);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::VECTOR3: {
EditorPropertyVector3 *editor = memnew(EditorPropertyVector3(p_wide));
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix, hint.radians);
+ return editor;
} break;
case Variant::VECTOR3I: {
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide));
- int min = -65535, max = 65535;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
-
- hide_slider = false;
- }
-
- editor->setup(min, max, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::TRANSFORM2D: {
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::PLANE: {
EditorPropertyPlane *editor = memnew(EditorPropertyPlane(p_wide));
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::QUATERNION: {
EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion);
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::AABB: {
EditorPropertyAABB *editor = memnew(EditorPropertyAABB);
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::BASIS: {
EditorPropertyBasis *editor = memnew(EditorPropertyBasis);
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
case Variant::TRANSFORM3D: {
EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D);
- double min = -65535, max = 65535, step = default_float_step;
- bool hide_slider = true;
-
- if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) {
- min = p_hint_text.get_slice(",", 0).to_float();
- max = p_hint_text.get_slice(",", 1).to_float();
- if (p_hint_text.get_slice_count(",") >= 3) {
- step = p_hint_text.get_slice(",", 2).to_float();
- }
- hide_slider = false;
- }
-
- editor->setup(min, max, step, hide_slider);
- add_property_editor(p_path, editor);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
} break;
@@ -3125,21 +3166,21 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
case Variant::COLOR: {
EditorPropertyColor *editor = memnew(EditorPropertyColor);
editor->setup(p_hint != PROPERTY_HINT_COLOR_NO_ALPHA);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::STRING_NAME: {
- if (p_hint == PROPERTY_HINT_ENUM) {
+ if (p_hint == PROPERTY_HINT_ENUM || p_hint == PROPERTY_HINT_ENUM_SUGGESTION) {
EditorPropertyTextEnum *editor = memnew(EditorPropertyTextEnum);
- Vector<String> options = p_hint_text.split(",");
- editor->setup(options, true);
- add_property_editor(p_path, editor);
+ Vector<String> options = p_hint_text.split(",", false);
+ editor->setup(options, true, (p_hint == PROPERTY_HINT_ENUM_SUGGESTION));
+ return editor;
} else {
EditorPropertyText *editor = memnew(EditorPropertyText);
if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) {
editor->set_placeholder(p_hint_text);
}
editor->set_string_name(true);
- add_property_editor(p_path, editor);
+ return editor;
}
} break;
case Variant::NODE_PATH: {
@@ -3152,12 +3193,12 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
Vector<StringName> sn = Variant(types); //convert via variant
editor->setup(NodePath(), sn, (p_usage & PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT));
}
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::RID: {
EditorPropertyRID *editor = memnew(EditorPropertyRID);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::OBJECT: {
EditorPropertyResource *editor = memnew(EditorPropertyResource);
@@ -3176,70 +3217,66 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
}
}
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::DICTIONARY: {
EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::ARRAY, p_hint_text);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_BYTE_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_BYTE_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_INT32_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_INT32_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_INT64_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_INT64_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_FLOAT32_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_FLOAT32_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_FLOAT64_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_FLOAT64_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_STRING_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_STRING_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_VECTOR2_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_VECTOR2_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_VECTOR3_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_VECTOR3_ARRAY);
- add_property_editor(p_path, editor);
+ return editor;
} break;
case Variant::PACKED_COLOR_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_COLOR_ARRAY);
- add_property_editor(p_path, editor);
+
} break;
default: {
}
}
- return false; //can be overridden, although it will most likely be last anyway
-}
-
-void EditorInspectorDefaultPlugin::parse_end() {
- //do none
+ return nullptr;
}
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index dcde7dda3d..0cb21bb391 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -91,16 +91,35 @@ public:
class EditorPropertyTextEnum : public EditorProperty {
GDCLASS(EditorPropertyTextEnum, EditorProperty);
- OptionButton *options;
+ HBoxContainer *default_layout;
+ HBoxContainer *edit_custom_layout;
+
+ OptionButton *option_button;
+ Button *edit_button;
+
+ LineEdit *custom_value_edit;
+ Button *accept_button;
+ Button *cancel_button;
+
+ Vector<String> options;
+ bool string_name = false;
+ bool loose_mode = false;
+
+ void _emit_changed_value(String p_string);
void _option_selected(int p_which);
- bool string_name;
+
+ void _edit_custom_value();
+ void _custom_value_submitted(String p_value);
+ void _custom_value_accepted();
+ void _custom_value_cancelled();
protected:
static void _bind_methods();
+ void _notification(int p_what);
public:
- void setup(const Vector<String> &p_options, bool p_string_name = false);
+ void setup(const Vector<String> &p_options, bool p_string_name = false, bool p_loose_mode = false);
virtual void update_property() override;
EditorPropertyTextEnum();
};
@@ -298,7 +317,8 @@ public:
class EditorPropertyFloat : public EditorProperty {
GDCLASS(EditorPropertyFloat, EditorProperty);
EditorSpinSlider *spin;
- bool setting;
+ bool setting = false;
+ bool angle_in_radians = false;
void _value_changed(double p_val);
protected:
@@ -306,7 +326,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_exp_range, bool p_greater, bool p_lesser);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_exp_range, bool p_greater, bool p_lesser, const String &p_suffix = String(), bool p_angle_in_radians = false);
EditorPropertyFloat();
};
@@ -363,7 +383,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyVector2(bool p_force_wide = false);
};
@@ -379,14 +399,15 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyRect2(bool p_force_wide = false);
};
class EditorPropertyVector3 : public EditorProperty {
GDCLASS(EditorPropertyVector3, EditorProperty);
EditorSpinSlider *spin[3];
- bool setting;
+ bool setting = false;
+ bool angle_in_radians = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -397,7 +418,7 @@ public:
virtual void update_property() override;
virtual void update_using_vector(Vector3 p_vector);
virtual Vector3 get_vector();
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String(), bool p_angle_in_radians = false);
EditorPropertyVector3(bool p_force_wide = false);
};
@@ -413,7 +434,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int p_min, int p_max, bool p_no_slider);
+ void setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix = String());
EditorPropertyVector2i(bool p_force_wide = false);
};
@@ -429,7 +450,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int p_min, int p_max, bool p_no_slider);
+ void setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix = String());
EditorPropertyRect2i(bool p_force_wide = false);
};
@@ -445,7 +466,7 @@ protected:
public:
virtual void update_property() override;
- void setup(int p_min, int p_max, bool p_no_slider);
+ void setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix = String());
EditorPropertyVector3i(bool p_force_wide = false);
};
@@ -461,7 +482,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyPlane(bool p_force_wide = false);
};
@@ -477,7 +498,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyQuaternion();
};
@@ -493,7 +514,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyAABB();
};
@@ -509,7 +530,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyTransform2D();
};
@@ -525,7 +546,7 @@ protected:
public:
virtual void update_property() override;
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyBasis();
};
@@ -542,7 +563,7 @@ protected:
public:
virtual void update_property() override;
virtual void update_using_transform(Transform3D p_transform);
- void setup(double p_min, double p_max, double p_step, bool p_no_slider);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyTransform3D();
};
@@ -647,8 +668,10 @@ class EditorInspectorDefaultPlugin : public EditorInspectorPlugin {
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
- virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false) override;
+ virtual bool 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 = false) override;
virtual void parse_end() override;
+
+ static EditorProperty *get_editor_for_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 = false);
};
#endif // EDITOR_PROPERTIES_H
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 9987aaf3fe..596f515067 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -30,16 +30,18 @@
#include "editor_properties_array_dict.h"
+#include "core/input/input.h"
#include "core/io/marshalls.h"
+#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor_properties.h"
bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_value) {
- String pn = p_name;
+ String name = p_name;
- if (pn.begins_with("indices")) {
- int idx = pn.get_slicec('/', 1).to_int();
- array.set(idx, p_value);
+ if (name.begins_with("indices")) {
+ int index = name.get_slicec('/', 1).to_int();
+ array.set(index, p_value);
return true;
}
@@ -47,12 +49,12 @@ bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_
}
bool EditorPropertyArrayObject::_get(const StringName &p_name, Variant &r_ret) const {
- String pn = p_name;
+ String name = p_name;
- if (pn.begins_with("indices")) {
- int idx = pn.get_slicec('/', 1).to_int();
+ if (name.begins_with("indices")) {
+ int index = name.get_slicec('/', 1).to_int();
bool valid;
- r_ret = array.get(idx, &valid);
+ r_ret = array.get(index, &valid);
if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
}
@@ -77,21 +79,21 @@ EditorPropertyArrayObject::EditorPropertyArrayObject() {
///////////////////
bool EditorPropertyDictionaryObject::_set(const StringName &p_name, const Variant &p_value) {
- String pn = p_name;
+ String name = p_name;
- if (pn == "new_item_key") {
+ if (name == "new_item_key") {
new_item_key = p_value;
return true;
}
- if (pn == "new_item_value") {
+ if (name == "new_item_value") {
new_item_value = p_value;
return true;
}
- if (pn.begins_with("indices")) {
- int idx = pn.get_slicec('/', 1).to_int();
- Variant key = dict.get_key_at_index(idx);
+ if (name.begins_with("indices")) {
+ int index = name.get_slicec('/', 1).to_int();
+ Variant key = dict.get_key_at_index(index);
dict[key] = p_value;
return true;
}
@@ -100,21 +102,21 @@ bool EditorPropertyDictionaryObject::_set(const StringName &p_name, const Varian
}
bool EditorPropertyDictionaryObject::_get(const StringName &p_name, Variant &r_ret) const {
- String pn = p_name;
+ String name = p_name;
- if (pn == "new_item_key") {
+ if (name == "new_item_key") {
r_ret = new_item_key;
return true;
}
- if (pn == "new_item_value") {
+ if (name == "new_item_value") {
r_ret = new_item_value;
return true;
}
- if (pn.begins_with("indices")) {
- int idx = pn.get_slicec('/', 1).to_int();
- Variant key = dict.get_key_at_index(idx);
+ if (name.begins_with("indices")) {
+ int index = name.get_slicec('/', 1).to_int();
+ Variant key = dict.get_key_at_index(index);
r_ret = dict[key];
if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
@@ -157,13 +159,13 @@ EditorPropertyDictionaryObject::EditorPropertyDictionaryObject() {
void EditorPropertyArray::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
if (p_property.begins_with("indices")) {
- int idx = p_property.get_slice("/", 1).to_int();
+ int index = p_property.get_slice("/", 1).to_int();
Variant array = object->get_array();
- array.set(idx, p_value);
+ array.set(index, p_value);
emit_changed(get_edited_property(), array, "", true);
if (array.get_type() == Variant::ARRAY) {
- array = array.call("duplicate"); //dupe, so undo/redo works better
+ array = array.call("duplicate"); // Duplicate, so undo/redo works better.
}
object->set_array(array);
}
@@ -171,7 +173,7 @@ void EditorPropertyArray::_property_changed(const String &p_property, Variant p_
void EditorPropertyArray::_change_type(Object *p_button, int p_index) {
Button *button = Object::cast_to<Button>(p_button);
- changing_type_idx = p_index;
+ changing_type_index = p_index;
Rect2 rect = button->get_screen_rect();
change_type->set_as_minsize();
change_type->set_position(rect.position + rect.size - Vector2(change_type->get_contents_minimum_size().x, 0));
@@ -180,7 +182,7 @@ void EditorPropertyArray::_change_type(Object *p_button, int p_index) {
void EditorPropertyArray::_change_type_menu(int p_index) {
if (p_index == Variant::VARIANT_MAX) {
- _remove_pressed(changing_type_idx);
+ _remove_pressed(changing_type_index);
return;
}
@@ -188,12 +190,12 @@ void EditorPropertyArray::_change_type_menu(int p_index) {
Callable::CallError ce;
Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
Variant array = object->get_array();
- array.set(changing_type_idx, value);
+ array.set(changing_type_index, value);
emit_changed(get_edited_property(), array, "", true);
if (array.get_type() == Variant::ARRAY) {
- array = array.call("duplicate"); //dupe, so undo/redo works better
+ array = array.call("duplicate"); // Duplicate, so undo/redo works better.
}
object->set_array(array);
@@ -201,7 +203,7 @@ void EditorPropertyArray::_change_type_menu(int p_index) {
}
void EditorPropertyArray::_object_id_selected(const StringName &p_property, ObjectID p_id) {
- emit_signal("object_id_selected", p_property, p_id);
+ emit_signal(SNAME("object_id_selected"), p_property, p_id);
}
void EditorPropertyArray::update_property() {
@@ -213,7 +215,7 @@ void EditorPropertyArray::update_property() {
arrtype = "Array";
} break;
- // arrays
+ // Arrays.
case Variant::PACKED_BYTE_ARRAY: {
arrtype = "PackedByteArray";
} break;
@@ -256,7 +258,12 @@ void EditorPropertyArray::update_property() {
return;
}
- edit->set_text(arrtype + " (size " + itos(array.call("size")) + ")");
+ int size = array.call("size");
+ int pages = MAX(0, size - 1) / page_length + 1;
+ page_index = MIN(page_index, pages - 1);
+ int offset = page_index * page_length;
+
+ edit->set_text(arrtype + " (size " + itos(size) + ")");
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (edit->is_pressed() != unfolded) {
@@ -270,50 +277,50 @@ void EditorPropertyArray::update_property() {
vbox = memnew(VBoxContainer);
add_child(vbox);
set_bottom_editor(vbox);
- HBoxContainer *hbc = memnew(HBoxContainer);
- vbox->add_child(hbc);
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ vbox->add_child(hbox);
+
Label *label = memnew(Label(TTR("Size: ")));
label->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(label);
- length = memnew(EditorSpinSlider);
- length->set_step(1);
- length->set_max(1000000);
- length->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(length);
- length->connect("value_changed", callable_mp(this, &EditorPropertyArray::_length_changed));
-
- page_hb = memnew(HBoxContainer);
- vbox->add_child(page_hb);
- label = memnew(Label(TTR("Page: ")));
- label->set_h_size_flags(SIZE_EXPAND_FILL);
- page_hb->add_child(label);
- page = memnew(EditorSpinSlider);
- page->set_step(1);
- page_hb->add_child(page);
- page->set_h_size_flags(SIZE_EXPAND_FILL);
- page->connect("value_changed", callable_mp(this, &EditorPropertyArray::_page_changed));
- } else {
- //bye bye children of the box
- while (vbox->get_child_count() > 2) {
- vbox->get_child(2)->queue_delete(); // button still needed after pressed is called
- vbox->remove_child(vbox->get_child(2));
- }
- }
+ hbox->add_child(label);
- int len = array.call("size");
+ size_slider = memnew(EditorSpinSlider);
+ size_slider->set_step(1);
+ size_slider->set_max(1000000);
+ size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
+ size_slider->connect("value_changed", callable_mp(this, &EditorPropertyArray::_length_changed));
+ hbox->add_child(size_slider);
- length->set_value(len);
+ page_hbox = memnew(HBoxContainer);
+ vbox->add_child(page_hbox);
- int pages = MAX(0, len - 1) / page_len + 1;
+ label = memnew(Label(TTR("Page: ")));
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+ page_hbox->add_child(label);
- page->set_max(pages);
- page_idx = MIN(page_idx, pages - 1);
- page->set_value(page_idx);
- page_hb->set_visible(pages > 1);
+ page_slider = memnew(EditorSpinSlider);
+ page_slider->set_step(1);
+ page_slider->set_h_size_flags(SIZE_EXPAND_FILL);
+ page_slider->connect("value_changed", callable_mp(this, &EditorPropertyArray::_page_changed));
+ page_hbox->add_child(page_slider);
+ } else {
+ // Bye bye children of the box.
+ for (int i = vbox->get_child_count() - 1; i >= 2; i--) {
+ Node *child = vbox->get_child(i);
+ if (child == reorder_selected_element_hbox) {
+ continue; // Don't remove the property that the user is moving.
+ }
- int offset = page_idx * page_len;
+ child->queue_delete(); // Button still needed after pressed is called.
+ vbox->remove_child(child);
+ }
+ }
- int amount = MIN(len - offset, page_len);
+ size_slider->set_value(size);
+ page_slider->set_max(pages);
+ page_slider->set_value(page_index);
+ page_hbox->set_visible(pages > 1);
if (array.get_type() == Variant::ARRAY) {
array = array.call("duplicate");
@@ -321,7 +328,31 @@ void EditorPropertyArray::update_property() {
object->set_array(array);
+ int amount = MIN(size - offset, page_length);
for (int i = 0; i < amount; i++) {
+ bool reorder_is_from_current_page = reorder_from_index / page_length == page_index;
+ if (reorder_is_from_current_page && i == reorder_from_index % page_length) {
+ // Don't duplicate the property that the user is moving.
+ continue;
+ }
+ if (!reorder_is_from_current_page && i == reorder_to_index % page_length) {
+ // Don't create the property the moving property will take the place of,
+ // e.g. (if page_length == 20) don't create element 20 if dragging an item from
+ // the first page to the second page because element 20 would become element 19.
+ continue;
+ }
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ vbox->add_child(hbox);
+
+ Button *reorder_button = memnew(Button);
+ reorder_button->set_icon(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons")));
+ reorder_button->set_default_cursor_shape(Control::CURSOR_MOVE);
+ reorder_button->connect("gui_input", callable_mp(this, &EditorPropertyArray::_reorder_button_gui_input));
+ reorder_button->connect("button_down", callable_mp(this, &EditorPropertyArray::_reorder_button_down), varray(i + offset));
+ reorder_button->connect("button_up", callable_mp(this, &EditorPropertyArray::_reorder_button_up));
+ hbox->add_child(reorder_button);
+
String prop_name = "indices/" + itos(i + offset);
EditorProperty *prop = nullptr;
@@ -337,7 +368,7 @@ void EditorPropertyArray::update_property() {
editor->setup("Object");
prop = editor;
} else {
- prop = EditorInspector::instantiate_property_editor(nullptr, value_type, "", subtype_hint, subtype_hint_string, 0);
+ prop = EditorInspector::instantiate_property_editor(nullptr, value_type, "", subtype_hint, subtype_hint_string, PROPERTY_USAGE_NONE);
}
prop->set_object_and_property(object.ptr(), prop_name);
@@ -346,29 +377,29 @@ void EditorPropertyArray::update_property() {
prop->connect("property_changed", callable_mp(this, &EditorPropertyArray::_property_changed));
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyArray::_object_id_selected));
prop->set_h_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *hb = memnew(HBoxContainer);
-
- vbox->add_child(hb);
- hb->add_child(prop);
+ hbox->add_child(prop);
bool is_untyped_array = array.get_type() == Variant::ARRAY && subtype == Variant::NIL;
if (is_untyped_array) {
Button *edit = memnew(Button);
- edit->set_icon(get_theme_icon("Edit", "EditorIcons"));
- hb->add_child(edit);
+ edit->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ hbox->add_child(edit);
edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type), varray(edit, i + offset));
} else {
Button *remove = memnew(Button);
- remove->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
remove->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed), varray(i + offset));
- hb->add_child(remove);
+ hbox->add_child(remove);
}
prop->update_property();
}
+ if (reorder_to_index % page_length > 0) {
+ vbox->move_child(vbox->get_child(2), reorder_to_index % page_length + 2);
+ }
+
updating = false;
} else {
@@ -384,18 +415,13 @@ void EditorPropertyArray::_remove_pressed(int p_index) {
Variant array = object->get_array();
array.call("remove", p_index);
- if (array.get_type() == Variant::ARRAY) {
- array = array.call("duplicate");
- }
-
emit_changed(get_edited_property(), array, "", false);
- object->set_array(array);
update_property();
}
void EditorPropertyArray::_button_draw() {
if (dropping) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
edit->draw_rect(Rect2(Point2(), edit->get_size()), color, false);
}
}
@@ -414,14 +440,14 @@ bool EditorPropertyArray::_is_drop_valid(const Dictionary &p_drag_data) const {
for (int j = 0; j < allowed_type.get_slice_count(","); j++) {
String at = allowed_type.get_slice(",", j).strip_edges();
- // Fail if one of the files is not of allowed type
+ // Fail if one of the files is not of allowed type.
if (!ClassDB::is_parent_class(ftype, at)) {
return false;
}
}
}
- // If no files fail, drop is valid
+ // If no files fail, drop is valid.
return true;
}
@@ -442,13 +468,13 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d
Variant array = object->get_array();
- // Handle the case where array is not initialised yet
+ // Handle the case where array is not initialised yet.
if (!array.is_array()) {
Callable::CallError ce;
Variant::construct(array_type, array, nullptr, 0, ce);
}
- // Loop the file array and add to existing array
+ // Loop the file array and add to existing array.
for (int i = 0; i < files.size(); i++) {
String file = files[i];
@@ -504,7 +530,7 @@ void EditorPropertyArray::_page_changed(double p_page) {
if (updating) {
return;
}
- page_idx = p_page;
+ page_index = p_page;
update_property();
}
@@ -530,10 +556,10 @@ void EditorPropertyArray::_length_changed(double p_page) {
}
}
}
- array = array.call("duplicate"); //dupe, so undo/redo works better
+ array = array.call("duplicate"); // Duplicate, so undo/redo works better.
} else {
int size = array.call("size");
- // Pool*Array don't initialize their elements, have to do it manually
+ // Pool*Array don't initialize their elements, have to do it manually.
for (int i = previous_size; i < size; i++) {
Callable::CallError ce;
Variant r;
@@ -551,7 +577,7 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint
array_type = p_array_type;
// The format of p_hint_string is:
- // subType/subTypeHint:nextSubtype ... etc
+ // subType/subTypeHint:nextSubtype ... etc.
if (array_type == Variant::ARRAY && !p_hint_string.is_empty()) {
int hint_subtype_separator = p_hint_string.find(":");
if (hint_subtype_separator >= 0) {
@@ -568,6 +594,73 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint
}
}
+void EditorPropertyArray::_reorder_button_gui_input(const Ref<InputEvent> &p_event) {
+ if (reorder_from_index < 0) {
+ return;
+ }
+
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ Variant array = object->get_array();
+ int size = array.call("size");
+
+ if ((reorder_to_index == 0 && mm->get_relative().y < 0.0f) || (reorder_to_index == size - 1 && mm->get_relative().y > 0.0f)) {
+ return;
+ }
+
+ reorder_mouse_y_delta += mm->get_relative().y;
+ float required_y_distance = 20.0f * EDSCALE;
+ if (ABS(reorder_mouse_y_delta) > required_y_distance) {
+ int direction = reorder_mouse_y_delta > 0.0f ? 1 : -1;
+ reorder_mouse_y_delta -= required_y_distance * direction;
+
+ reorder_to_index += direction;
+ if ((direction < 0 && reorder_to_index % page_length == page_length - 1) || (direction > 0 && reorder_to_index % page_length == 0)) {
+ // Automatically move to the next/previous page.
+ page_slider->set_value(page_index + direction);
+ }
+ vbox->move_child(reorder_selected_element_hbox, reorder_to_index % page_length + 2);
+ // Ensure the moving element is visible.
+ EditorNode::get_singleton()->get_inspector()->ensure_control_visible(reorder_selected_element_hbox);
+ }
+ }
+}
+
+void EditorPropertyArray::_reorder_button_down(int p_index) {
+ reorder_from_index = p_index;
+ reorder_to_index = p_index;
+ reorder_selected_element_hbox = Object::cast_to<HBoxContainer>(vbox->get_child(p_index % page_length + 2));
+ reorder_selected_button = Object::cast_to<Button>(reorder_selected_element_hbox->get_child(0));
+ // Ideally it'd to be able to show the mouse but I had issues with
+ // Control's `mouse_exit()`/`mouse_entered()` signals not getting called.
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
+}
+
+void EditorPropertyArray::_reorder_button_up() {
+ if (reorder_from_index != reorder_to_index) {
+ // Move the element.
+ Variant array = object->get_array();
+
+ Variant value_to_move = array.get(reorder_from_index);
+ array.call("remove", reorder_from_index);
+ array.call("insert", reorder_to_index, value_to_move);
+
+ emit_changed(get_edited_property(), array, "", false);
+ object->set_array(array);
+ update_property();
+ }
+
+ reorder_from_index = -1;
+ reorder_to_index = -1;
+ reorder_mouse_y_delta = 0.0f;
+
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ reorder_selected_button->warp_mouse(reorder_selected_button->get_size() / 2.0f);
+
+ reorder_selected_element_hbox = nullptr;
+ reorder_selected_button = nullptr;
+}
+
void EditorPropertyArray::_bind_methods() {
ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorPropertyArray::can_drop_data_fw);
ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorPropertyArray::drop_data_fw);
@@ -575,7 +668,7 @@ void EditorPropertyArray::_bind_methods() {
EditorPropertyArray::EditorPropertyArray() {
object.instantiate();
- page_len = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
+ page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
edit = memnew(Button);
edit->set_h_size_flags(SIZE_EXPAND_FILL);
edit->set_clip_text(true);
@@ -586,8 +679,8 @@ EditorPropertyArray::EditorPropertyArray() {
add_child(edit);
add_focusable(edit);
vbox = nullptr;
- page = nullptr;
- length = nullptr;
+ page_slider = nullptr;
+ size_slider = nullptr;
updating = false;
change_type = memnew(PopupMenu);
add_child(change_type);
@@ -599,7 +692,7 @@ EditorPropertyArray::EditorPropertyArray() {
}
change_type->add_separator();
change_type->add_item(TTR("Remove Item"), Variant::VARIANT_MAX);
- changing_type_idx = -1;
+ changing_type_index = -1;
subtype = Variant::NIL;
subtype_hint = PROPERTY_HINT_NONE;
@@ -616,14 +709,14 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia
} else if (p_property == "new_item_value") {
object->set_new_item_value(p_value);
} else if (p_property.begins_with("indices")) {
- int idx = p_property.get_slice("/", 1).to_int();
+ int index = p_property.get_slice("/", 1).to_int();
Dictionary dict = object->get_dict();
- Variant key = dict.get_key_at_index(idx);
+ Variant key = dict.get_key_at_index(index);
dict[key] = p_value;
emit_changed(get_edited_property(), dict, "", true);
- dict = dict.duplicate(); //dupe, so undo/redo works better
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
object->set_dict(dict);
}
}
@@ -635,7 +728,7 @@ void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) {
change_type->set_as_minsize();
change_type->set_position(rect.position + rect.size - Vector2(change_type->get_contents_minimum_size().x, 0));
change_type->popup();
- changing_type_idx = p_index;
+ changing_type_index = p_index;
}
void EditorPropertyDictionary::_add_key_value() {
@@ -652,17 +745,17 @@ void EditorPropertyDictionary::_add_key_value() {
emit_changed(get_edited_property(), dict, "", false);
- dict = dict.duplicate(); //dupe, so undo/redo works better
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
void EditorPropertyDictionary::_change_type_menu(int p_index) {
- if (changing_type_idx < 0) {
+ if (changing_type_index < 0) {
Variant value;
Callable::CallError ce;
Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
- if (changing_type_idx == -1) {
+ if (changing_type_index == -1) {
object->set_new_item_key(value);
} else {
object->set_new_item_value(value);
@@ -677,16 +770,16 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
Variant value;
Callable::CallError ce;
Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
- Variant key = dict.get_key_at_index(changing_type_idx);
+ Variant key = dict.get_key_at_index(changing_type_index);
dict[key] = value;
} else {
- Variant key = dict.get_key_at_index(changing_type_idx);
+ Variant key = dict.get_key_at_index(changing_type_index);
dict.erase(key);
}
emit_changed(get_edited_property(), dict, "", false);
- dict = dict.duplicate(); //dupe, so undo/redo works better
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
object->set_dict(dict);
update_property();
}
@@ -695,7 +788,7 @@ void EditorPropertyDictionary::update_property() {
Variant updated_val = get_edited_object()->get(get_edited_property());
if (updated_val.get_type() == Variant::NIL) {
- edit->set_text("Dictionary (Nil)"); //This provides symmetry with the array property.
+ edit->set_text("Dictionary (Nil)"); // This provides symmetry with the array property.
edit->set_pressed(false);
if (vbox) {
set_bottom_editor(nullptr);
@@ -722,16 +815,16 @@ void EditorPropertyDictionary::update_property() {
add_child(vbox);
set_bottom_editor(vbox);
- page_hb = memnew(HBoxContainer);
- vbox->add_child(page_hb);
+ page_hbox = memnew(HBoxContainer);
+ vbox->add_child(page_hbox);
Label *label = memnew(Label(TTR("Page: ")));
label->set_h_size_flags(SIZE_EXPAND_FILL);
- page_hb->add_child(label);
- page = memnew(EditorSpinSlider);
- page->set_step(1);
- page_hb->add_child(page);
- page->set_h_size_flags(SIZE_EXPAND_FILL);
- page->connect("value_changed", callable_mp(this, &EditorPropertyDictionary::_page_changed));
+ page_hbox->add_child(label);
+ page_slider = memnew(EditorSpinSlider);
+ page_slider->set_step(1);
+ page_hbox->add_child(page_slider);
+ page_slider->set_h_size_flags(SIZE_EXPAND_FILL);
+ page_slider->connect("value_changed", callable_mp(this, &EditorPropertyDictionary::_page_changed));
} else {
// Queue children for deletion, deleting immediately might cause errors.
for (int i = 1; i < vbox->get_child_count(); i++) {
@@ -739,18 +832,18 @@ void EditorPropertyDictionary::update_property() {
}
}
- int len = dict.size();
+ int size = dict.size();
- int pages = MAX(0, len - 1) / page_len + 1;
+ int pages = MAX(0, size - 1) / page_length + 1;
- page->set_max(pages);
- page_idx = MIN(page_idx, pages - 1);
- page->set_value(page_idx);
- page_hb->set_visible(pages > 1);
+ page_slider->set_max(pages);
+ page_index = MIN(page_index, pages - 1);
+ page_slider->set_value(page_index);
+ page_hbox->set_visible(pages > 1);
- int offset = page_idx * page_len;
+ int offset = page_index * page_length;
- int amount = MIN(len - offset, page_len);
+ int amount = MIN(size - offset, page_length);
dict = dict.duplicate();
@@ -782,7 +875,7 @@ void EditorPropertyDictionary::update_property() {
} break;
- // atomic types
+ // Atomic types.
case Variant::BOOL: {
prop = memnew(EditorPropertyCheck);
@@ -803,7 +896,7 @@ void EditorPropertyDictionary::update_property() {
} break;
- // math types
+ // Math types.
case Variant::VECTOR2: {
EditorPropertyVector2 *editor = memnew(EditorPropertyVector2);
editor->setup(-100000, 100000, 0.001, true);
@@ -877,7 +970,7 @@ void EditorPropertyDictionary::update_property() {
} break;
- // misc types
+ // Miscellaneous types.
case Variant::COLOR: {
prop = memnew(EditorPropertyColor);
@@ -919,7 +1012,7 @@ void EditorPropertyDictionary::update_property() {
prop = editor;
} break;
- // arrays
+ // Arrays.
case Variant::PACKED_BYTE_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_BYTE_ARRAY);
@@ -977,7 +1070,7 @@ void EditorPropertyDictionary::update_property() {
for (int j = 0; j < 4; j++) {
flat->set_default_margin(Side(j), 2 * EDSCALE);
}
- flat->set_bg_color(get_theme_color("prop_subsection", "Editor"));
+ flat->set_bg_color(get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
pc->add_theme_style_override("panel", flat);
add_vbox = memnew(VBoxContainer);
@@ -1003,17 +1096,17 @@ void EditorPropertyDictionary::update_property() {
prop->connect("property_changed", callable_mp(this, &EditorPropertyDictionary::_property_changed));
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyDictionary::_object_id_selected));
- HBoxContainer *hb = memnew(HBoxContainer);
+ HBoxContainer *hbox = memnew(HBoxContainer);
if (add_vbox) {
- add_vbox->add_child(hb);
+ add_vbox->add_child(hbox);
} else {
- vbox->add_child(hb);
+ vbox->add_child(hbox);
}
- hb->add_child(prop);
+ hbox->add_child(prop);
prop->set_h_size_flags(SIZE_EXPAND_FILL);
Button *edit = memnew(Button);
- edit->set_icon(get_theme_icon("Edit", "EditorIcons"));
- hb->add_child(edit);
+ edit->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ hbox->add_child(edit);
edit->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type), varray(edit, change_index));
prop->update_property();
@@ -1038,7 +1131,7 @@ void EditorPropertyDictionary::update_property() {
}
void EditorPropertyDictionary::_object_id_selected(const StringName &p_property, ObjectID p_id) {
- emit_signal("object_id_selected", p_property, p_id);
+ emit_signal(SNAME("object_id_selected"), p_property, p_id);
}
void EditorPropertyDictionary::_notification(int p_what) {
@@ -1060,7 +1153,7 @@ void EditorPropertyDictionary::_page_changed(double p_page) {
if (updating) {
return;
}
- page_idx = p_page;
+ page_index = p_page;
update_property();
}
@@ -1069,7 +1162,7 @@ void EditorPropertyDictionary::_bind_methods() {
EditorPropertyDictionary::EditorPropertyDictionary() {
object.instantiate();
- page_len = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
+ page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
edit = memnew(Button);
edit->set_h_size_flags(SIZE_EXPAND_FILL);
edit->set_clip_text(true);
@@ -1078,7 +1171,7 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
add_child(edit);
add_focusable(edit);
vbox = nullptr;
- page = nullptr;
+ page_slider = nullptr;
updating = false;
change_type = memnew(PopupMenu);
add_child(change_type);
@@ -1090,5 +1183,5 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
}
change_type->add_separator();
change_type->add_item(TTR("Remove Item"), Variant::VARIANT_MAX);
- changing_type_idx = -1;
+ changing_type_index = -1;
}
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index aa2d8744b1..7547d57346 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -84,19 +84,25 @@ class EditorPropertyArray : public EditorProperty {
bool dropping;
Ref<EditorPropertyArrayObject> object;
- int page_len = 20;
- int page_idx = 0;
- int changing_type_idx;
+ int page_length = 20;
+ int page_index = 0;
+ int changing_type_index;
Button *edit;
VBoxContainer *vbox;
- EditorSpinSlider *length;
- EditorSpinSlider *page;
- HBoxContainer *page_hb;
+ EditorSpinSlider *size_slider;
+ EditorSpinSlider *page_slider;
+ HBoxContainer *page_hbox;
Variant::Type array_type;
Variant::Type subtype;
PropertyHint subtype_hint;
String subtype_hint_string;
+ int reorder_from_index = -1;
+ int reorder_to_index = -1;
+ float reorder_mouse_y_delta = 0.0f;
+ HBoxContainer *reorder_selected_element_hbox = nullptr;
+ Button *reorder_selected_button = nullptr;
+
void _page_changed(double p_page);
void _length_changed(double p_page);
void _edit_pressed();
@@ -112,6 +118,10 @@ class EditorPropertyArray : public EditorProperty {
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ void _reorder_button_gui_input(const Ref<InputEvent> &p_event);
+ void _reorder_button_down(int p_index);
+ void _reorder_button_up();
+
protected:
static void _bind_methods();
void _notification(int p_what);
@@ -129,14 +139,14 @@ class EditorPropertyDictionary : public EditorProperty {
bool updating;
Ref<EditorPropertyDictionaryObject> object;
- int page_len = 20;
- int page_idx = 0;
- int changing_type_idx;
+ int page_length = 20;
+ int page_index = 0;
+ int changing_type_index;
Button *edit;
VBoxContainer *vbox;
- EditorSpinSlider *length;
- EditorSpinSlider *page;
- HBoxContainer *page_hb;
+ EditorSpinSlider *size_slider;
+ EditorSpinSlider *page_slider;
+ HBoxContainer *page_hbox;
void _page_changed(double p_page);
void _edit_pressed();
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 350fc5eccb..8bb6c590dc 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -76,7 +76,7 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const
}
if (p_preview.is_valid()) {
- preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox("normal")->get_default_margin(SIDE_LEFT) + get_theme_constant("hseparation", "Button"));
+ preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("hseparation"), SNAME("Button")));
if (type == "GradientTexture") {
preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE);
@@ -100,7 +100,7 @@ void EditorResourcePicker::_resource_selected() {
return;
}
- emit_signal("resource_selected", edited_resource);
+ emit_signal(SNAME("resource_selected"), edited_resource);
}
void EditorResourcePicker::_file_selected(const String &p_path) {
@@ -125,7 +125,7 @@ void EditorResourcePicker::_file_selected(const String &p_path) {
}
edited_resource = loaded_resource;
- emit_signal("resource_changed", edited_resource);
+ emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
}
@@ -141,20 +141,21 @@ void EditorResourcePicker::_update_menu() {
}
void EditorResourcePicker::_update_menu_items() {
+ _ensure_resource_menu();
edit_menu->clear();
// Add options for creating specific subtypes of the base resource type.
set_create_options(edit_menu);
// Add an option to load a resource from a file.
- edit_menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD);
+ edit_menu->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Load"), OBJ_MENU_LOAD);
// Add options for changing existing value of the resource.
if (edited_resource.is_valid()) {
- edit_menu->add_icon_item(get_theme_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT);
- edit_menu->add_icon_item(get_theme_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR);
- edit_menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
- edit_menu->add_icon_item(get_theme_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE);
+ edit_menu->add_icon_item(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), TTR("Edit"), OBJ_MENU_EDIT);
+ edit_menu->add_icon_item(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), TTR("Clear"), OBJ_MENU_CLEAR);
+ edit_menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
+ edit_menu->add_icon_item(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")), TTR("Save"), OBJ_MENU_SAVE);
if (edited_resource->get_path().is_resource_file()) {
edit_menu->add_separator();
@@ -199,13 +200,13 @@ void EditorResourcePicker::_update_menu_items() {
for (int i = 0; i < conversions.size(); i++) {
String what = conversions[i]->converts_to();
Ref<Texture2D> icon;
- if (has_theme_icon(what, "EditorIcons")) {
- icon = get_theme_icon(what, "EditorIcons");
+ if (has_theme_icon(what, SNAME("EditorIcons"))) {
+ icon = get_theme_icon(what, SNAME("EditorIcons"));
} else {
- icon = get_theme_icon(what, "Resource");
+ icon = get_theme_icon(what, SNAME("Resource"));
}
- edit_menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
+ edit_menu->add_icon_item(icon, vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i);
}
}
}
@@ -241,13 +242,13 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
case OBJ_MENU_EDIT: {
if (edited_resource.is_valid()) {
- emit_signal("resource_selected", edited_resource);
+ emit_signal(SNAME("resource_selected"), edited_resource);
}
} break;
case OBJ_MENU_CLEAR: {
edited_resource = RES();
- emit_signal("resource_changed", edited_resource);
+ emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
} break;
@@ -281,7 +282,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
}
edited_resource = unique_resource;
- emit_signal("resource_changed", edited_resource);
+ emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
} break;
@@ -298,7 +299,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
case OBJ_MENU_PASTE: {
edited_resource = EditorSettings::get_singleton()->get_resource_clipboard();
- emit_signal("resource_changed", edited_resource);
+ emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
} break;
@@ -323,7 +324,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
ERR_FAIL_INDEX(to_type, conversions.size());
edited_resource = conversions[to_type]->convert(edited_resource);
- emit_signal("resource_changed", edited_resource);
+ emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
break;
}
@@ -353,13 +354,14 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
ERR_BREAK(!resp);
edited_resource = RES(resp);
- emit_signal("resource_changed", edited_resource);
+ emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
} break;
}
}
void EditorResourcePicker::set_create_options(Object *p_menu_node) {
+ _ensure_resource_menu();
// If a subclass implements this method, use it to replace all create items.
if (get_script_instance() && get_script_instance()->has_method("_set_create_options")) {
get_script_instance()->call("_set_create_options", p_menu_node);
@@ -402,7 +404,7 @@ void EditorResourcePicker::set_create_options(Object *p_menu_node) {
inheritors_array.push_back(t);
if (!icon.is_valid()) {
- icon = get_theme_icon(has_theme_icon(t, "EditorIcons") ? t : "Object", "EditorIcons");
+ icon = get_theme_icon(has_theme_icon(t, SNAME("EditorIcons")) ? t : String("Object"), SNAME("EditorIcons"));
}
int id = TYPE_BASE_ID + idx;
@@ -427,7 +429,7 @@ bool EditorResourcePicker::handle_menu_selected(int p_which) {
void EditorResourcePicker::_button_draw() {
if (dropping) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
assign_button->draw_rect(Rect2(Point2(), assign_button->get_size()), color, false);
}
}
@@ -618,7 +620,7 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_
}
edited_resource = dropped_resource;
- emit_signal("resource_changed", edited_resource);
+ emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
}
}
@@ -659,11 +661,11 @@ void EditorResourcePicker::_notification(int p_what) {
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
- edit_button->set_icon(get_theme_icon("select_arrow", "Tree"));
+ edit_button->set_icon(get_theme_icon(SNAME("select_arrow"), SNAME("Tree")));
} break;
case NOTIFICATION_DRAW: {
- draw_style_box(get_theme_stylebox("bg", "Tree"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("bg"), SNAME("Tree")), Rect2(Point2(), get_size()));
} break;
case NOTIFICATION_DRAG_BEGIN: {
@@ -783,6 +785,15 @@ bool EditorResourcePicker::is_editable() const {
return editable;
}
+void EditorResourcePicker::_ensure_resource_menu() {
+ if (edit_menu) {
+ return;
+ }
+ edit_menu = memnew(PopupMenu);
+ add_child(edit_menu);
+ edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk));
+ edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed), varray(false));
+}
EditorResourcePicker::EditorResourcePicker() {
assign_button = memnew(Button);
assign_button->set_flat(true);
@@ -808,10 +819,6 @@ EditorResourcePicker::EditorResourcePicker() {
edit_button->connect("pressed", callable_mp(this, &EditorResourcePicker::_update_menu));
add_child(edit_button);
edit_button->connect("gui_input", callable_mp(this, &EditorResourcePicker::_button_input));
- edit_menu = memnew(PopupMenu);
- add_child(edit_menu);
- edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk));
- edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed), varray(false));
}
void EditorScriptPicker::set_create_options(Object *p_menu_node) {
@@ -820,8 +827,8 @@ void EditorScriptPicker::set_create_options(Object *p_menu_node) {
return;
}
- menu_node->add_icon_item(get_theme_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT);
- menu_node->add_icon_item(get_theme_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT);
+ menu_node->add_icon_item(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons")), TTR("New Script"), OBJ_MENU_NEW_SCRIPT);
+ menu_node->add_icon_item(get_theme_icon(SNAME("ScriptExtend"), SNAME("EditorIcons")), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT);
menu_node->add_separator();
}
diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h
index 9a4b945bc7..82a4817dfc 100644
--- a/editor/editor_resource_picker.h
+++ b/editor/editor_resource_picker.h
@@ -67,7 +67,7 @@ class EditorResourcePicker : public HBoxContainer {
CONVERT_BASE_ID = 1000,
};
- PopupMenu *edit_menu;
+ PopupMenu *edit_menu = nullptr;
void _update_resource();
void _update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj);
@@ -90,6 +90,8 @@ class EditorResourcePicker : public HBoxContainer {
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ void _ensure_resource_menu();
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index f904ae80a7..7f4ee7848f 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -161,7 +161,7 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
}
r_texture = generated;
- int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_theme_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retrieve the default icon size
+ int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_theme_icon(SNAME("Object"), SNAME("EditorIcons"))->get_width(); // Kind of a workaround to retrieve the default icon size
if (preview_generators[i]->can_generate_small_preview()) {
Ref<Texture2D> generated_small;
@@ -419,7 +419,7 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
}
if (call_invalidated) { //do outside mutex
- call_deferred("emit_signal", "preview_invalidated", p_path);
+ call_deferred(SNAME("emit_signal"), "preview_invalidated", p_path);
}
}
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index a604022391..e115cd77e1 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -127,7 +127,7 @@ void EditorRunNative::_run_native(int p_idx, int p_platform) {
return;
}
- emit_signal("native_run", preset);
+ emit_signal(SNAME("native_run"), preset);
int flags = 0;
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index 6bfb17f9c2..1209df50ed 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -250,8 +250,8 @@ void SectionedInspector::update_category_list() {
for (int i = 0; i < sc; i++) {
TreeItem *parent = section_map[metasection];
- //parent->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor"));
- parent->set_custom_font(0, get_theme_font("bold", "EditorFonts"));
+ //parent->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
+ parent->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
if (i > 0) {
metasection += "/" + sectionarr[i];
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 3f02b76ff6..0667d7116f 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -63,7 +63,7 @@ bool EditorSettings::_set(const StringName &p_name, const Variant &p_value) {
bool changed = _set_only(p_name, p_value);
if (changed) {
- emit_signal("settings_changed");
+ emit_signal(SNAME("settings_changed"));
}
return true;
}
@@ -240,19 +240,19 @@ void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const {
}
for (Set<_EVCSort>::Element *E = vclist.front(); E; E = E->next()) {
- int pinfo = 0;
+ uint32_t pusage = PROPERTY_USAGE_NONE;
if (E->get().save || !optimize_save) {
- pinfo |= PROPERTY_USAGE_STORAGE;
+ pusage |= PROPERTY_USAGE_STORAGE;
}
if (!E->get().name.begins_with("_") && !E->get().name.begins_with("projects/")) {
- pinfo |= PROPERTY_USAGE_EDITOR;
+ pusage |= PROPERTY_USAGE_EDITOR;
} else {
- pinfo |= PROPERTY_USAGE_STORAGE; //hiddens must always be saved
+ pusage |= PROPERTY_USAGE_STORAGE; //hiddens must always be saved
}
PropertyInfo pi(E->get().type, E->get().name);
- pi.usage = pinfo;
+ pi.usage = pusage;
if (hints.has(E->get().name)) {
pi = hints[E->get().name];
}
@@ -631,6 +631,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/3d/navigation/zoom_style", 0);
hints["editors/3d/navigation/zoom_style"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_style", PROPERTY_HINT_ENUM, "Vertical, Horizontal");
+ _initial_set("editors/3d/navigation/emulate_numpad", false);
_initial_set("editors/3d/navigation/emulate_3_button_mouse", false);
_initial_set("editors/3d/navigation/orbit_modifier", 0);
hints["editors/3d/navigation/orbit_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/orbit_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
@@ -883,7 +884,7 @@ void EditorSettings::create() {
return;
}
- ClassDB::register_class<EditorSettings>(); // Otherwise it can't be unserialized.
+ GDREGISTER_CLASS(EditorSettings); // Otherwise it can't be unserialized.
String config_file_path;
Ref<ConfigFile> extra_config = memnew(ConfigFile);
@@ -1343,7 +1344,7 @@ void EditorSettings::load_text_editor_theme() {
}
}
}
- emit_signal("settings_changed");
+ emit_signal(SNAME("settings_changed"));
// if it doesn't load just use what is currently loaded
}
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index d8c765911c..58ab7d3cef 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -88,7 +88,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
}
} else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP || mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
if (grabber->is_visible()) {
- call_deferred("update");
+ call_deferred(SNAME("update"));
}
}
}
@@ -185,6 +185,27 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
}
}
+void EditorSpinSlider::_update_value_input_stylebox() {
+ if (!value_input) {
+ return;
+ }
+ // Add a left margin to the stylebox to make the number align with the Label
+ // when it's edited. The LineEdit "focus" stylebox uses the "normal" stylebox's
+ // default margins.
+ Ref<StyleBoxFlat> stylebox =
+ EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->duplicate();
+ // EditorSpinSliders with a label have more space on the left, so add an
+ // higher margin to match the location where the text begins.
+ // The margin values below were determined by empirical testing.
+ if (is_layout_rtl()) {
+ stylebox->set_default_margin(SIDE_LEFT, 0);
+ stylebox->set_default_margin(SIDE_RIGHT, (get_label() != String() ? 23 : 16) * EDSCALE);
+ } else {
+ stylebox->set_default_margin(SIDE_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE);
+ stylebox->set_default_margin(SIDE_RIGHT, 0);
+ }
+ value_input->add_theme_style_override("normal", stylebox);
+}
void EditorSpinSlider::_notification(int p_what) {
if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_OUT ||
p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN ||
@@ -197,35 +218,30 @@ void EditorSpinSlider::_notification(int p_what) {
}
}
- if (p_what == NOTIFICATION_READY) {
- // Add a left margin to the stylebox to make the number align with the Label
- // when it's edited. The LineEdit "focus" stylebox uses the "normal" stylebox's
- // default margins.
- Ref<StyleBoxFlat> stylebox =
- EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox("normal", "LineEdit")->duplicate();
- // EditorSpinSliders with a label have more space on the left, so add an
- // higher margin to match the location where the text begins.
- // The margin values below were determined by empirical testing.
- stylebox->set_default_margin(SIDE_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE);
- value_input->add_theme_style_override("normal", stylebox);
+ if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED) {
+ _update_value_input_stylebox();
}
if (p_what == NOTIFICATION_DRAW) {
updown_offset = -1;
- Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit");
+ RID ci = get_canvas_item();
+ bool rtl = is_layout_rtl();
+ Vector2 size = get_size();
+
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"));
if (!flat) {
- draw_style_box(sb, Rect2(Vector2(), get_size()));
+ draw_style_box(sb, Rect2(Vector2(), size));
}
- Ref<Font> font = get_theme_font("font", "LineEdit");
- int font_size = get_theme_font_size("font_size", "LineEdit");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("LineEdit"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("LineEdit"));
int sep_base = 4 * EDSCALE;
int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better
- int string_width = font->get_string_size(label, font_size).width;
- int number_width = get_size().width - sb->get_minimum_size().width - string_width - sep;
+ int label_width = font->get_string_size(label, font_size).width;
+ int number_width = size.width - sb->get_minimum_size().width - label_width - sep;
- Ref<Texture2D> updown = get_theme_icon("updown", "SpinBox");
+ Ref<Texture2D> updown = get_theme_icon(SNAME("updown"), SNAME("SpinBox"));
if (get_step() == 1) {
number_width -= updown->get_width();
@@ -233,9 +249,9 @@ void EditorSpinSlider::_notification(int p_what) {
String numstr = get_text_value();
- int vofs = (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size);
+ int vofs = (size.height - font->get_height(font_size)) / 2 + font->get_ascent(font_size);
- Color fc = get_theme_color("font_color", "LineEdit");
+ Color fc = get_theme_color(SNAME("font_color"), SNAME("LineEdit"));
Color lc;
if (use_custom_label_color) {
lc = custom_label_color;
@@ -244,23 +260,60 @@ void EditorSpinSlider::_notification(int p_what) {
}
if (flat && label != String()) {
- Color label_bg_color = get_theme_color("dark_color_3", "Editor");
- draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + string_width, get_size().height)), label_bg_color);
+ Color label_bg_color = get_theme_color(SNAME("dark_color_3"), SNAME("Editor"));
+ if (rtl) {
+ draw_rect(Rect2(Vector2(size.width - (sb->get_offset().x * 2 + label_width), 0), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color);
+ } else {
+ draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color);
+ }
}
if (has_focus()) {
- Ref<StyleBox> focus = get_theme_stylebox("focus", "LineEdit");
- draw_style_box(focus, Rect2(Vector2(), get_size()));
+ Ref<StyleBox> focus = get_theme_stylebox(SNAME("focus"), SNAME("LineEdit"));
+ draw_style_box(focus, Rect2(Vector2(), size));
}
- draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, HALIGN_LEFT, -1, font_size, lc * Color(1, 1, 1, 0.5));
+ if (rtl) {
+ draw_string(font, Vector2(Math::round(size.width - sb->get_offset().x - label_width), vofs), label, HALIGN_RIGHT, -1, font_size, lc * Color(1, 1, 1, 0.5));
+ } else {
+ draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, HALIGN_LEFT, -1, font_size, lc * Color(1, 1, 1, 0.5));
+ }
- draw_string(font, Vector2(Math::round(sb->get_offset().x + string_width + sep), vofs), numstr, HALIGN_LEFT, number_width, font_size, fc);
+ int suffix_start = numstr.length();
+ RID num_rid = TS->create_shaped_text();
+ TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size);
+
+ float text_start = rtl ? Math::round(sb->get_offset().x) : Math::round(sb->get_offset().x + label_width + sep);
+ Vector2 text_ofs = rtl ? Vector2(text_start + (number_width - TS->shaped_text_get_width(num_rid)), vofs) : Vector2(text_start, vofs);
+ const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(num_rid);
+ int v_size = visual.size();
+ const TextServer::Glyph *glyphs = visual.ptr();
+ for (int i = 0; i < v_size; i++) {
+ for (int j = 0; j < glyphs[i].repeat; j++) {
+ if (text_ofs.x >= text_start && (text_ofs.x + glyphs[i].advance) <= (text_start + number_width)) {
+ Color color = fc;
+ if (glyphs[i].start >= suffix_start) {
+ color.a *= 0.4;
+ }
+ if (glyphs[i].font_rid != RID()) {
+ TS->font_draw_glyph(glyphs[i].font_rid, ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color);
+ } else if ((glyphs[i].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ TS->draw_hex_code_box(ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color);
+ }
+ }
+ text_ofs.x += glyphs[i].advance;
+ }
+ }
+ TS->free(num_rid);
if (get_step() == 1) {
- Ref<Texture2D> updown2 = get_theme_icon("updown", "SpinBox");
- int updown_vofs = (get_size().height - updown2->get_height()) / 2;
- updown_offset = get_size().width - sb->get_margin(SIDE_RIGHT) - updown2->get_width();
+ Ref<Texture2D> updown2 = get_theme_icon(SNAME("updown"), SNAME("SpinBox"));
+ int updown_vofs = (size.height - updown2->get_height()) / 2;
+ if (rtl) {
+ updown_offset = sb->get_margin(SIDE_LEFT);
+ } else {
+ updown_offset = size.width - sb->get_margin(SIDE_RIGHT) - updown2->get_width();
+ }
Color c(1, 1, 1);
if (hover_updown) {
c *= Color(1.2, 1.2, 1.2);
@@ -271,9 +324,9 @@ void EditorSpinSlider::_notification(int p_what) {
}
} else if (!hide_slider) {
int grabber_w = 4 * EDSCALE;
- int width = get_size().width - sb->get_minimum_size().width - grabber_w;
+ int width = size.width - sb->get_minimum_size().width - grabber_w;
int ofs = sb->get_offset().x;
- int svofs = (get_size().height + vofs) / 2 - 1;
+ int svofs = (size.height + vofs) / 2 - 1;
Color c = fc;
c.a = 0.2;
@@ -285,7 +338,7 @@ void EditorSpinSlider::_notification(int p_what) {
grabbing_spinner_mouse_pos = get_global_position() + grabber_rect.position + grabber_rect.size * 0.5;
- bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !value_input_popup->is_visible();
+ bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !(value_input_popup && value_input_popup->is_visible());
if (grabber->is_visible() != display_grabber) {
if (display_grabber) {
grabber->show();
@@ -297,9 +350,9 @@ void EditorSpinSlider::_notification(int p_what) {
if (display_grabber) {
Ref<Texture2D> grabber_tex;
if (mouse_over_grabber) {
- grabber_tex = get_theme_icon("grabber_highlight", "HSlider");
+ grabber_tex = get_theme_icon(SNAME("grabber_highlight"), SNAME("HSlider"));
} else {
- grabber_tex = get_theme_icon("grabber", "HSlider");
+ grabber_tex = get_theme_icon(SNAME("grabber"), SNAME("HSlider"));
}
if (grabber->get_texture() != grabber_tex) {
@@ -336,10 +389,15 @@ void EditorSpinSlider::_notification(int p_what) {
}
}
+LineEdit *EditorSpinSlider::get_line_edit() {
+ _ensure_input_popup();
+ return value_input;
+}
+
Size2 EditorSpinSlider::get_minimum_size() const {
- Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit");
- Ref<Font> font = get_theme_font("font", "LineEdit");
- int font_size = get_theme_font_size("font_size", "LineEdit");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"));
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("LineEdit"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("LineEdit"));
Size2 ms = sb->get_minimum_size();
ms.height += font->get_height(font_size);
@@ -365,6 +423,15 @@ String EditorSpinSlider::get_label() const {
return label;
}
+void EditorSpinSlider::set_suffix(const String &p_suffix) {
+ suffix = p_suffix;
+ update();
+}
+
+String EditorSpinSlider::get_suffix() const {
+ return suffix;
+}
+
void EditorSpinSlider::_evaluate_input_text() {
// Replace comma with dot to support it as decimal separator (GH-6028).
// This prevents using functions like `pow()`, but using functions
@@ -389,7 +456,9 @@ void EditorSpinSlider::_evaluate_input_text() {
//text_submitted signal
void EditorSpinSlider::_value_input_submitted(const String &p_text) {
value_input_just_closed = true;
- value_input_popup->hide();
+ if (value_input_popup) {
+ value_input_popup->hide();
+ }
}
//modal_closed signal
@@ -401,7 +470,7 @@ void EditorSpinSlider::_value_input_closed() {
//focus_exited signal
void EditorSpinSlider::_value_focus_exited() {
// discontinue because the focus_exit was caused by right-click context menu
- if (value_input->get_menu()->is_visible()) {
+ if (value_input->is_menu_visible()) {
return;
}
@@ -412,7 +481,9 @@ void EditorSpinSlider::_value_focus_exited() {
// -> modal_close was not called
// -> need to close/hide manually
if (!value_input_just_closed) { //value_input_just_closed should do the same
- value_input_popup->hide();
+ if (value_input_popup) {
+ value_input_popup->hide();
+ }
//tab was pressed
} else {
//enter, click, esc
@@ -453,13 +524,14 @@ void EditorSpinSlider::set_custom_label_color(bool p_use_custom_label_color, Col
}
void EditorSpinSlider::_focus_entered() {
+ _ensure_input_popup();
Rect2 gr = get_screen_rect();
value_input->set_text(get_text_value());
value_input_popup->set_position(gr.position);
value_input_popup->set_size(gr.size);
- value_input_popup->call_deferred("popup");
- value_input->call_deferred("grab_focus");
- value_input->call_deferred("select_all");
+ value_input_popup->call_deferred(SNAME("popup"));
+ value_input->call_deferred(SNAME("grab_focus"));
+ value_input->call_deferred(SNAME("select_all"));
value_input->set_focus_next(find_next_valid_focus()->get_path());
value_input->set_focus_previous(find_prev_valid_focus()->get_path());
}
@@ -468,6 +540,9 @@ void EditorSpinSlider::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_label", "label"), &EditorSpinSlider::set_label);
ClassDB::bind_method(D_METHOD("get_label"), &EditorSpinSlider::get_label);
+ ClassDB::bind_method(D_METHOD("set_suffix", "suffix"), &EditorSpinSlider::set_suffix);
+ ClassDB::bind_method(D_METHOD("get_suffix"), &EditorSpinSlider::get_suffix);
+
ClassDB::bind_method(D_METHOD("set_read_only", "read_only"), &EditorSpinSlider::set_read_only);
ClassDB::bind_method(D_METHOD("is_read_only"), &EditorSpinSlider::is_read_only);
@@ -477,10 +552,28 @@ void EditorSpinSlider::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &EditorSpinSlider::_gui_input);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
}
+void EditorSpinSlider::_ensure_input_popup() {
+ if (value_input_popup) {
+ return;
+ }
+ value_input_popup = memnew(Popup);
+ add_child(value_input_popup);
+ value_input = memnew(LineEdit);
+ value_input_popup->add_child(value_input);
+ value_input_popup->set_wrap_controls(true);
+ value_input->set_anchors_and_offsets_preset(PRESET_WIDE);
+ value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
+ value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted));
+ value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
+ if (is_inside_tree()) {
+ _update_value_input_stylebox();
+ }
+}
EditorSpinSlider::EditorSpinSlider() {
flat = false;
grabbing_spinner_attempt = false;
@@ -503,15 +596,6 @@ EditorSpinSlider::EditorSpinSlider() {
mousewheel_over_grabber = false;
grabbing_grabber = false;
grabber_range = 1;
- value_input_popup = memnew(Popup);
- add_child(value_input_popup);
- value_input = memnew(LineEdit);
- value_input_popup->add_child(value_input);
- value_input_popup->set_wrap_controls(true);
- value_input->set_anchors_and_offsets_preset(PRESET_WIDE);
- value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
- value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted));
- value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
value_input_just_closed = false;
hide_slider = false;
read_only = false;
diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h
index 50d04c9583..5b99f88505 100644
--- a/editor/editor_spin_slider.h
+++ b/editor/editor_spin_slider.h
@@ -39,6 +39,7 @@ class EditorSpinSlider : public Range {
GDCLASS(EditorSpinSlider, Range);
String label;
+ String suffix;
int updown_offset;
bool hover_updown;
bool mouse_hover;
@@ -62,9 +63,9 @@ class EditorSpinSlider : public Range {
Vector2 grabbing_spinner_mouse_pos;
double pre_grab_value;
- Popup *value_input_popup;
- LineEdit *value_input;
- bool value_input_just_closed;
+ Popup *value_input_popup = nullptr;
+ LineEdit *value_input = nullptr;
+ bool value_input_just_closed = false;
void _grabber_gui_input(const Ref<InputEvent> &p_event);
void _value_input_closed();
@@ -78,6 +79,9 @@ class EditorSpinSlider : public Range {
void _evaluate_input_text();
+ void _update_value_input_stylebox();
+ void _ensure_input_popup();
+
protected:
void _notification(int p_what);
void _gui_input(const Ref<InputEvent> &p_event);
@@ -93,6 +97,9 @@ public:
void set_label(const String &p_label);
String get_label() const;
+ void set_suffix(const String &p_suffix);
+ String get_suffix() const;
+
void set_hide_slider(bool p_hide);
bool is_hiding_slider() const;
@@ -105,7 +112,7 @@ public:
void set_custom_label_color(bool p_use_custom_label_color, Color p_custom_label_color);
void setup_and_show() { _focus_entered(); }
- LineEdit *get_line_edit() { return value_input; }
+ LineEdit *get_line_edit();
virtual Size2 get_minimum_size() const override;
EditorSpinSlider();
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 131a77e52f..0c908be441 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -996,7 +996,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger);
Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
- int stylebox_offset = theme->get_font("tab_selected", "TabContainer")->get_height(theme->get_font_size("tab_selected", "TabContainer")) + theme->get_stylebox("tab_selected", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(SIDE_TOP);
+ int stylebox_offset = theme->get_font("tab_selected", "TabContainer")->get_height(theme->get_font_size("tab_selected", "TabContainer")) + theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height + theme->get_stylebox(SNAME("panel"), SNAME("TabContainer"))->get_default_margin(SIDE_TOP);
style_panel_invisible_top->set_expand_margin_size(SIDE_TOP, -stylebox_offset);
style_panel_invisible_top->set_default_margin(SIDE_TOP, 0);
theme->set_stylebox("BottomPanelDebuggerOverride", "EditorStyles", style_panel_invisible_top);
@@ -1004,6 +1004,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// LineEdit
Ref<StyleBoxFlat> style_line_edit = style_widget->duplicate();
+ // The original style_widget style has an extra 1 pixel offset that makes LineEdits not align with Buttons,
+ // so this compensates for that.
+ style_line_edit->set_default_margin(SIDE_TOP, style_line_edit->get_default_margin(SIDE_TOP) - 1 * EDSCALE);
// Add a bottom line to make LineEdits more visible, especially in sectioned inspectors
// such as the Project Settings.
style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
@@ -1021,6 +1024,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("read_only", "LineEdit", style_line_edit_disabled);
theme->set_icon("clear", "LineEdit", theme->get_icon("GuiClose", "EditorIcons"));
theme->set_color("read_only", "LineEdit", font_disabled_color);
+ theme->set_color("font_uneditable_color", "LineEdit", font_disabled_color);
theme->set_color("font_color", "LineEdit", font_color);
theme->set_color("font_selected_color", "LineEdit", mono_color);
theme->set_color("caret_color", "LineEdit", font_color);
@@ -1186,7 +1190,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_tooltip->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE * 0.5);
style_tooltip->set_default_margin(SIDE_RIGHT, default_margin_size * EDSCALE);
style_tooltip->set_default_margin(SIDE_BOTTOM, default_margin_size * EDSCALE * 0.5);
- style_tooltip->set_bg_color(mono_color.inverted() * Color(1, 1, 1, 0.8));
+ style_tooltip->set_bg_color(mono_color.inverted());
style_tooltip->set_border_width_all(0);
theme->set_color("font_color", "TooltipLabel", font_hover_color);
theme->set_color("font_color_shadow", "TooltipLabel", Color(0, 0, 0, 0));
@@ -1362,6 +1366,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme_preview_picker_sb->set_border_color(accent_color);
theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE);
theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb);
+ Color theme_preview_picker_label_bg_color = accent_color;
+ theme_preview_picker_label_bg_color.set_v(0.5);
+ Ref<StyleBoxFlat> theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0);
+ theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb);
// adaptive script theme constants
// for comments and elements with lower relevance
diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h
index af952eaffc..52ab6d68ee 100644
--- a/editor/editor_vcs_interface.h
+++ b/editor/editor_vcs_interface.h
@@ -46,16 +46,16 @@ protected:
static void _bind_methods();
// Implemented by addons as end points for the proxy functions
- bool _initialize(String p_project_root_path);
- bool _is_vcs_initialized();
- Dictionary _get_modified_files_data();
- void _stage_file(String p_file_path);
- void _unstage_file(String p_file_path);
- void _commit(String p_msg);
- Array _get_file_diff(String p_file_path);
- bool _shut_down();
- String _get_project_name();
- String _get_vcs_name();
+ virtual bool _initialize(String p_project_root_path);
+ virtual bool _is_vcs_initialized();
+ virtual Dictionary _get_modified_files_data();
+ virtual void _stage_file(String p_file_path);
+ virtual void _unstage_file(String p_file_path);
+ virtual void _commit(String p_msg);
+ virtual Array _get_file_diff(String p_file_path);
+ virtual bool _shut_down();
+ virtual String _get_project_name();
+ virtual String _get_vcs_name();
public:
static EditorVCSInterface *get_singleton();
diff --git a/editor/editor_zoom_widget.cpp b/editor/editor_zoom_widget.cpp
index f9be829493..420aeb03fe 100644
--- a/editor/editor_zoom_widget.cpp
+++ b/editor/editor_zoom_widget.cpp
@@ -51,18 +51,18 @@ void EditorZoomWidget::_update_zoom_label() {
}
void EditorZoomWidget::_button_zoom_minus() {
- set_zoom_by_increments(-6);
- emit_signal("zoom_changed", zoom);
+ set_zoom_by_increments(-6, Input::get_singleton()->is_key_pressed(KEY_ALT));
+ emit_signal(SNAME("zoom_changed"), zoom);
}
void EditorZoomWidget::_button_zoom_reset() {
- set_zoom(1.0);
- emit_signal("zoom_changed", zoom);
+ set_zoom(1.0 * MAX(1, EDSCALE));
+ emit_signal(SNAME("zoom_changed"), zoom);
}
void EditorZoomWidget::_button_zoom_plus() {
- set_zoom_by_increments(6);
- emit_signal("zoom_changed", zoom);
+ set_zoom_by_increments(6, Input::get_singleton()->is_key_pressed(KEY_ALT));
+ emit_signal(SNAME("zoom_changed"), zoom);
}
float EditorZoomWidget::get_zoom() {
@@ -76,39 +76,77 @@ void EditorZoomWidget::set_zoom(float p_zoom) {
}
}
-void EditorZoomWidget::set_zoom_by_increments(int p_increment_count) {
- // Base increment factor defined as the twelveth root of two.
- // This allow a smooth geometric evolution of the zoom, with the advantage of
- // visiting all integer power of two scale factors.
- // note: this is analogous to the 'semitones' interval in the music world
- // In order to avoid numerical imprecisions, we compute and edit a zoom index
- // with the following relation: zoom = 2 ^ (index / 12)
-
- if (zoom < CMP_EPSILON || p_increment_count == 0) {
- return;
- }
+void EditorZoomWidget::set_zoom_by_increments(int p_increment_count, bool p_integer_only) {
+ // Remove editor scale from the index computation.
+ const float zoom_noscale = zoom / MAX(1, EDSCALE);
+
+ if (p_integer_only) {
+ // Only visit integer scaling factors above 100%, and fractions with an integer denominator below 100%
+ // (1/2 = 50%, 1/3 = 33.33%, 1/4 = 25%, …).
+ // This is useful when working on pixel art projects to avoid distortion.
+ // This algorithm is designed to handle fractional start zoom values correctly
+ // (e.g. 190% will zoom up to 200% and down to 100%).
+ if (zoom_noscale + p_increment_count * 0.001 >= 1.0 - CMP_EPSILON) {
+ // New zoom is certain to be above 100%.
+ if (p_increment_count >= 1) {
+ // Zooming.
+ set_zoom(Math::floor(zoom_noscale + p_increment_count) * MAX(1, EDSCALE));
+ } else {
+ // Dezooming.
+ set_zoom(Math::ceil(zoom_noscale + p_increment_count) * MAX(1, EDSCALE));
+ }
+ } else {
+ if (p_increment_count >= 1) {
+ // Zooming. Convert the current zoom into a denominator.
+ float new_zoom = 1.0 / Math::ceil(1.0 / zoom_noscale - p_increment_count);
+ if (Math::is_equal_approx(zoom_noscale, new_zoom)) {
+ // New zoom is identical to the old zoom, so try again.
+ // This can happen due to floating-point precision issues.
+ new_zoom = 1.0 / Math::ceil(1.0 / zoom_noscale - p_increment_count - 1);
+ }
+ set_zoom(new_zoom * MAX(1, EDSCALE));
+ } else {
+ // Dezooming. Convert the current zoom into a denominator.
+ float new_zoom = 1.0 / Math::floor(1.0 / zoom_noscale - p_increment_count);
+ if (Math::is_equal_approx(zoom_noscale, new_zoom)) {
+ // New zoom is identical to the old zoom, so try again.
+ // This can happen due to floating-point precision issues.
+ new_zoom = 1.0 / Math::floor(1.0 / zoom_noscale - p_increment_count + 1);
+ }
+ set_zoom(new_zoom * MAX(1, EDSCALE));
+ }
+ }
+ } else {
+ // Base increment factor defined as the twelveth root of two.
+ // This allow a smooth geometric evolution of the zoom, with the advantage of
+ // visiting all integer power of two scale factors.
+ // note: this is analogous to the 'semitones' interval in the music world
+ // In order to avoid numerical imprecisions, we compute and edit a zoom index
+ // with the following relation: zoom = 2 ^ (index / 12)
- // Remove Editor scale from the index computation
- float zoom_noscale = zoom / MAX(1, EDSCALE);
+ if (zoom < CMP_EPSILON || p_increment_count == 0) {
+ return;
+ }
- // zoom = 2**(index/12) => log2(zoom) = index/12
- float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f));
+ // zoom = 2**(index/12) => log2(zoom) = index/12
+ float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f));
- float new_zoom_index = closest_zoom_index + p_increment_count;
- float new_zoom = Math::pow(2.f, new_zoom_index / 12.f);
+ float new_zoom_index = closest_zoom_index + p_increment_count;
+ float new_zoom = Math::pow(2.f, new_zoom_index / 12.f);
- // Restore Editor scale transformation
- new_zoom *= MAX(1, EDSCALE);
+ // Restore Editor scale transformation
+ new_zoom *= MAX(1, EDSCALE);
- set_zoom(new_zoom);
+ set_zoom(new_zoom);
+ }
}
void EditorZoomWidget::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED:
- zoom_minus->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
- zoom_plus->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
+ zoom_minus->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons")));
+ zoom_plus->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
break;
default:
break;
@@ -118,7 +156,7 @@ void EditorZoomWidget::_notification(int p_what) {
void EditorZoomWidget::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &EditorZoomWidget::set_zoom);
ClassDB::bind_method(D_METHOD("get_zoom"), &EditorZoomWidget::get_zoom);
- ClassDB::bind_method(D_METHOD("set_zoom_by_increments", "increment"), &EditorZoomWidget::set_zoom_by_increments);
+ ClassDB::bind_method(D_METHOD("set_zoom_by_increments", "increment", "integer_only"), &EditorZoomWidget::set_zoom_by_increments);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "zoom"), "set_zoom", "get_zoom");
diff --git a/editor/editor_zoom_widget.h b/editor/editor_zoom_widget.h
index 4e95018e52..c35faeefe7 100644
--- a/editor/editor_zoom_widget.h
+++ b/editor/editor_zoom_widget.h
@@ -56,7 +56,7 @@ public:
float get_zoom();
void set_zoom(float p_zoom);
- void set_zoom_by_increments(int p_increment_count);
+ void set_zoom_by_increments(int p_increment_count, bool p_integer_only = false);
};
#endif // EDITOR_ZOOM_WIDGET_H
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index dd4ce74406..699957897f 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -106,8 +106,8 @@ void ExportTemplateManager::_update_template_status() {
TreeItem *ti = installed_table->create_item(installed_root);
ti->set_text(0, version_string);
- ti->add_button(0, get_theme_icon("Folder", "EditorIcons"), OPEN_TEMPLATE_FOLDER, false, TTR("Open the folder containing these templates."));
- ti->add_button(0, get_theme_icon("Remove", "EditorIcons"), UNINSTALL_TEMPLATE, false, TTR("Uninstall these templates."));
+ ti->add_button(0, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), OPEN_TEMPLATE_FOLDER, false, TTR("Open the folder containing these templates."));
+ ti->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), UNINSTALL_TEMPLATE, false, TTR("Uninstall these templates."));
}
}
@@ -352,9 +352,9 @@ void ExportTemplateManager::_set_current_progress_status(const String &p_status,
download_progress_label->set_text(p_status);
if (p_error) {
- download_progress_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ download_progress_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
} else {
- download_progress_label->add_theme_color_override("font_color", get_theme_color("font_color", "Label"));
+ download_progress_label->add_theme_color_override("font_color", get_theme_color(SNAME("font_color"), SNAME("Label")));
}
}
@@ -630,6 +630,12 @@ bool ExportTemplateManager::can_install_android_template() {
}
Error ExportTemplateManager::install_android_template() {
+ const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
+ const String &source_zip = templates_path.plus_file("android_source.zip");
+ ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN);
+ return install_android_template_from_file(source_zip);
+}
+Error ExportTemplateManager::install_android_template_from_file(const String &p_file) {
// To support custom Android builds, we install the Java source code and buildsystem
// from android_source.zip to the project's res://android folder.
@@ -662,14 +668,10 @@ Error ExportTemplateManager::install_android_template() {
// Uncompress source template.
- const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
- const String &source_zip = templates_path.plus_file("android_source.zip");
- ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN);
-
FileAccess *src_f = nullptr;
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
- unzFile pkg = unzOpen2(source_zip.utf8().get_data(), &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.");
int ret = unzGoToFirstFile(pkg);
@@ -737,11 +739,11 @@ void ExportTemplateManager::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- current_value->add_theme_font_override("font", get_theme_font("main", "EditorFonts"));
- current_missing_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
- current_installed_label->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"));
+ current_value->add_theme_font_override("font", get_theme_font(SNAME("main"), SNAME("EditorFonts")));
+ current_missing_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ current_installed_label->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
- mirror_options_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+ mirror_options_button->set_icon(get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -812,6 +814,7 @@ ExportTemplateManager::ExportTemplateManager() {
main_vb->add_child(current_hb);
Label *current_label = memnew(Label);
+ current_label->set_theme_type_variation("HeaderSmall");
current_label->set_text(TTR("Current Version:"));
current_hb->add_child(current_label);
@@ -821,6 +824,8 @@ ExportTemplateManager::ExportTemplateManager() {
// Current version statuses.
// Status: Current version is missing.
current_missing_label = memnew(Label);
+ current_missing_label->set_theme_type_variation("HeaderSmall");
+
current_missing_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
current_missing_label->set_align(Label::ALIGN_RIGHT);
current_missing_label->set_text(TTR("Export templates are missing. Download them or install from a file."));
@@ -828,6 +833,7 @@ ExportTemplateManager::ExportTemplateManager() {
// Status: Current version is installed.
current_installed_label = memnew(Label);
+ current_installed_label->set_theme_type_variation("HeaderSmall");
current_installed_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
current_installed_label->set_align(Label::ALIGN_RIGHT);
current_installed_label->set_text(TTR("Export templates are installed and ready to be used."));
@@ -947,6 +953,7 @@ ExportTemplateManager::ExportTemplateManager() {
HBoxContainer *installed_versions_hb = memnew(HBoxContainer);
main_vb->add_child(installed_versions_hb);
Label *installed_label = memnew(Label);
+ installed_label->set_theme_type_variation("HeaderSmall");
installed_label->set_text(TTR("Other Installed Versions:"));
installed_versions_hb->add_child(installed_label);
diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h
index f145c6c0f5..ebadb88c36 100644
--- a/editor/export_template_manager.h
+++ b/editor/export_template_manager.h
@@ -124,6 +124,8 @@ public:
bool can_install_android_template();
Error install_android_template();
+ Error install_android_template_from_file(const String &p_file);
+
void popup_manager();
ExportTemplateManager();
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index cb89e5c7d0..49c2a84e18 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -50,9 +50,9 @@
Ref<Texture2D> FileSystemDock::_get_tree_item_icon(bool p_is_valid, String p_file_type) {
Ref<Texture2D> file_icon;
if (!p_is_valid) {
- file_icon = get_theme_icon("ImportFail", "EditorIcons");
+ file_icon = get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"));
} else {
- file_icon = (has_theme_icon(p_file_type, "EditorIcons")) ? get_theme_icon(p_file_type, "EditorIcons") : get_theme_icon("File", "EditorIcons");
+ file_icon = (has_theme_icon(p_file_type, SNAME("EditorIcons"))) ? get_theme_icon(p_file_type, SNAME("EditorIcons")) : get_theme_icon(SNAME("File"), SNAME("EditorIcons"));
}
return file_icon;
}
@@ -69,8 +69,8 @@ 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_icon(0, get_theme_icon("Folder", "EditorIcons"));
- subdirectory_item->set_icon_modulate(0, get_theme_color("folder_icon_modulate", "FileDialog"));
+ 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);
String lpath = p_dir->get_path();
subdirectory_item->set_metadata(0, lpath);
@@ -149,7 +149,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
file_item->set_as_cursor(0);
}
if (main_scene == file_metadata) {
- file_item->set_custom_color(0, get_theme_color("accent_color", "Editor"));
+ file_item->set_custom_color(0, get_theme_color(SNAME("accent_color"), SNAME("Editor")));
}
Array udata;
udata.push_back(tree_update_id);
@@ -215,7 +215,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
// Handles the favorites.
TreeItem *favorites = tree->create_item(root);
- favorites->set_icon(0, get_theme_icon("Favorites", "EditorIcons"));
+ favorites->set_icon(0, get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")));
favorites->set_text(0, TTR("Favorites:"));
favorites->set_metadata(0, "Favorites");
favorites->set_collapsed(p_uncollapsed_paths.find("Favorites") < 0);
@@ -227,8 +227,8 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
continue;
}
- Ref<Texture2D> folder_icon = get_theme_icon("Folder", "EditorIcons");
- const Color folder_color = get_theme_color("folder_icon_modulate", "FileDialog");
+ Ref<Texture2D> folder_icon = get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"));
+ const Color folder_color = get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
String text;
Ref<Texture2D> icon;
@@ -248,7 +248,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
if (dir) {
icon = _get_tree_item_icon(dir->get_file_import_is_valid(index), dir->get_file_type(index));
} else {
- icon = get_theme_icon("File", "EditorIcons");
+ icon = get_theme_icon(SNAME("File"), SNAME("EditorIcons"));
}
color = Color(1, 1, 1);
}
@@ -339,28 +339,28 @@ void FileSystemDock::_notification(int p_what) {
String ei = "EditorIcons";
- button_reload->set_icon(get_theme_icon("Reload", ei));
- button_toggle_display_mode->set_icon(get_theme_icon("Panels2", ei));
+ button_reload->set_icon(get_theme_icon(SNAME("Reload"), ei));
+ button_toggle_display_mode->set_icon(get_theme_icon(SNAME("Panels2"), ei));
button_file_list_display_mode->connect("pressed", callable_mp(this, &FileSystemDock::_toggle_file_display));
files->connect("item_activated", callable_mp(this, &FileSystemDock::_file_list_activate_file));
button_hist_next->connect("pressed", callable_mp(this, &FileSystemDock::_fw_history));
button_hist_prev->connect("pressed", callable_mp(this, &FileSystemDock::_bw_history));
- tree_search_box->set_right_icon(get_theme_icon("Search", ei));
+ tree_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
tree_search_box->set_clear_button_enabled(true);
- tree_button_sort->set_icon(get_theme_icon("Sort", ei));
+ tree_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
- file_list_search_box->set_right_icon(get_theme_icon("Search", ei));
+ file_list_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
file_list_search_box->set_clear_button_enabled(true);
- file_list_button_sort->set_icon(get_theme_icon("Sort", ei));
+ file_list_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
if (is_layout_rtl()) {
- button_hist_next->set_icon(get_theme_icon("Back", ei));
- button_hist_prev->set_icon(get_theme_icon("Forward", ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Back"), ei));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Forward"), ei));
} else {
- button_hist_next->set_icon(get_theme_icon("Forward", ei));
- button_hist_prev->set_icon(get_theme_icon("Back", ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Forward"), ei));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Back"), ei));
}
file_list_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_list_rmb_option));
tree_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_tree_rmb_option));
@@ -412,28 +412,28 @@ void FileSystemDock::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
// Update icons.
String ei = "EditorIcons";
- button_reload->set_icon(get_theme_icon("Reload", ei));
- button_toggle_display_mode->set_icon(get_theme_icon("Panels2", ei));
+ button_reload->set_icon(get_theme_icon(SNAME("Reload"), ei));
+ button_toggle_display_mode->set_icon(get_theme_icon(SNAME("Panels2"), ei));
if (is_layout_rtl()) {
- button_hist_next->set_icon(get_theme_icon("Back", ei));
- button_hist_prev->set_icon(get_theme_icon("Forward", ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Back"), ei));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Forward"), ei));
} else {
- button_hist_next->set_icon(get_theme_icon("Forward", ei));
- button_hist_prev->set_icon(get_theme_icon("Back", ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Forward"), ei));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Back"), ei));
}
if (file_list_display_mode == FILE_LIST_DISPLAY_LIST) {
- button_file_list_display_mode->set_icon(get_theme_icon("FileThumbnail", "EditorIcons"));
+ button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
} else {
- button_file_list_display_mode->set_icon(get_theme_icon("FileList", "EditorIcons"));
+ button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
}
- tree_search_box->set_right_icon(get_theme_icon("Search", ei));
+ tree_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
tree_search_box->set_clear_button_enabled(true);
- tree_button_sort->set_icon(get_theme_icon("Sort", ei));
+ tree_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
- file_list_search_box->set_right_icon(get_theme_icon("Search", ei));
+ file_list_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
file_list_search_box->set_clear_button_enabled(true);
- file_list_button_sort->set_icon(get_theme_icon("Sort", ei));
+ file_list_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
// Update always show folders.
bool new_always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
@@ -451,7 +451,7 @@ void FileSystemDock::_notification(int p_what) {
void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_selected) {
// Update the import dock.
import_dock_needs_update = true;
- call_deferred("_update_import_dock");
+ call_deferred(SNAME("_update_import_dock"));
// Return if we don't select something new.
if (!p_selected) {
@@ -581,17 +581,17 @@ void FileSystemDock::_tree_thumbnail_done(const String &p_path, const Ref<Textur
void FileSystemDock::_toggle_file_display() {
_set_file_display(file_list_display_mode != FILE_LIST_DISPLAY_LIST);
- emit_signal("display_mode_changed");
+ emit_signal(SNAME("display_mode_changed"));
}
void FileSystemDock::_set_file_display(bool p_active) {
if (p_active) {
file_list_display_mode = FILE_LIST_DISPLAY_LIST;
- button_file_list_display_mode->set_icon(get_theme_icon("FileThumbnail", "EditorIcons"));
+ button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
button_file_list_display_mode->set_tooltip(TTR("View items as a grid of thumbnails."));
} else {
file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS;
- button_file_list_display_mode->set_icon(get_theme_icon("FileList", "EditorIcons"));
+ button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
button_file_list_display_mode->set_tooltip(TTR("View items as a list."));
}
@@ -733,13 +733,13 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
if (thumbnail_size < 64) {
- folder_thumbnail = get_theme_icon("FolderMediumThumb", ei);
- file_thumbnail = get_theme_icon("FileMediumThumb", ei);
- file_thumbnail_broken = get_theme_icon("FileDeadMediumThumb", ei);
+ folder_thumbnail = get_theme_icon(SNAME("FolderMediumThumb"), ei);
+ file_thumbnail = get_theme_icon(SNAME("FileMediumThumb"), ei);
+ file_thumbnail_broken = get_theme_icon(SNAME("FileDeadMediumThumb"), ei);
} else {
- folder_thumbnail = get_theme_icon("FolderBigThumb", ei);
- file_thumbnail = get_theme_icon("FileBigThumb", ei);
- file_thumbnail_broken = get_theme_icon("FileDeadBigThumb", ei);
+ folder_thumbnail = get_theme_icon(SNAME("FolderBigThumb"), ei);
+ file_thumbnail = get_theme_icon(SNAME("FileBigThumb"), ei);
+ file_thumbnail_broken = get_theme_icon(SNAME("FileDeadBigThumb"), ei);
}
} else {
// No thumbnails.
@@ -750,8 +750,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->set_fixed_icon_size(Size2());
}
- Ref<Texture2D> folder_icon = (use_thumbnails) ? folder_thumbnail : get_theme_icon("folder", "FileDialog");
- const Color folder_color = get_theme_color("folder_icon_modulate", "FileDialog");
+ Ref<Texture2D> folder_icon = (use_thumbnails) ? folder_thumbnail : get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
+ const Color folder_color = get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
// Build the FileInfo list.
List<FileInfo> file_list;
@@ -815,7 +815,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
if (searched_string.length() > 0) {
// Display the search results.
- _search(EditorFileSystem::get_singleton()->get_filesystem(), &file_list, 128);
+ // Limit the number of results displayed to avoid an infinite loop.
+ _search(EditorFileSystem::get_singleton()->get_filesystem(), &file_list, 10000);
} else {
if (display_mode == DISPLAY_MODE_TREE_ONLY || always_show_folders) {
// Display folders in the list.
@@ -884,7 +885,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
type_icon = (has_theme_icon(ftype, ei)) ? get_theme_icon(ftype, ei) : get_theme_icon(oi, ei);
big_icon = file_thumbnail;
} else {
- type_icon = get_theme_icon("ImportFail", ei);
+ type_icon = get_theme_icon(SNAME("ImportFail"), ei);
big_icon = file_thumbnail_broken;
tooltip += "\n" + TTR("Status: Import of file failed. Please fix file and reimport manually.");
}
@@ -904,7 +905,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
}
if (fpath == main_scene) {
- files->set_item_custom_fg_color(item_index, get_theme_color("accent_color", "Editor"));
+ files->set_item_custom_fg_color(item_index, get_theme_color(SNAME("accent_color"), SNAME("Editor")));
}
// Generate the preview.
@@ -1188,11 +1189,11 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
for (int i = 0; i < file_changed_paths.size(); ++i) {
p_file_renames[file_changed_paths[i]] = file_changed_paths[i].replace_first(old_path, new_path);
print_verbose(" Remap: " + file_changed_paths[i] + " -> " + p_file_renames[file_changed_paths[i]]);
- emit_signal("files_moved", file_changed_paths[i], p_file_renames[file_changed_paths[i]]);
+ emit_signal(SNAME("files_moved"), file_changed_paths[i], p_file_renames[file_changed_paths[i]]);
}
for (int i = 0; i < folder_changed_paths.size(); ++i) {
p_folder_renames[folder_changed_paths[i]] = folder_changed_paths[i].replace_first(old_path, new_path);
- emit_signal("folder_moved", folder_changed_paths[i], p_folder_renames[folder_changed_paths[i]].substr(0, p_folder_renames[folder_changed_paths[i]].length() - 1));
+ emit_signal(SNAME("folder_moved"), folder_changed_paths[i], p_folder_renames[folder_changed_paths[i]].substr(0, p_folder_renames[folder_changed_paths[i]].length() - 1));
}
} else {
EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + "\n");
@@ -1441,7 +1442,7 @@ void FileSystemDock::_make_scene_confirm() {
}
void FileSystemDock::_file_removed(String p_file) {
- emit_signal("file_removed", p_file);
+ emit_signal(SNAME("file_removed"), p_file);
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_file.get_base_dir();
@@ -1454,7 +1455,7 @@ void FileSystemDock::_file_removed(String p_file) {
}
void FileSystemDock::_folder_removed(String p_folder) {
- emit_signal("folder_removed", p_folder);
+ emit_signal(SNAME("folder_removed"), p_folder);
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_folder.get_base_dir();
@@ -1761,7 +1762,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
case FILE_INHERIT: {
// Create a new scene inherited from the selected one.
if (p_selected.size() == 1) {
- emit_signal("inherit", p_selected[0]);
+ emit_signal(SNAME("inherit"), p_selected[0]);
}
} break;
@@ -1785,7 +1786,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
}
}
if (!paths.is_empty()) {
- emit_signal("instance", paths);
+ emit_signal(SNAME("instance"), paths);
}
} break;
@@ -1985,20 +1986,6 @@ void FileSystemDock::_resource_created() {
editor->save_resource_as(RES(r), fpath);
}
-void FileSystemDock::_focus_current_search_box() {
- LineEdit *current_search_box = nullptr;
- if (display_mode == DISPLAY_MODE_TREE_ONLY) {
- current_search_box = tree_search_box;
- } else if (display_mode == DISPLAY_MODE_SPLIT) {
- current_search_box = file_list_search_box;
- }
-
- if (current_search_box) {
- current_search_box->grab_focus();
- current_search_box->select_all();
- }
-}
-
void FileSystemDock::_search_changed(const String &p_text, const Control *p_from) {
if (searched_string.length() == 0) {
// Register the uncollapsed paths before they change.
@@ -2032,7 +2019,7 @@ void FileSystemDock::_rescan() {
void FileSystemDock::_toggle_split_mode(bool p_active) {
set_display_mode(p_active ? DISPLAY_MODE_SPLIT : DISPLAY_MODE_TREE_ONLY);
- emit_signal("display_mode_changed");
+ emit_signal(SNAME("display_mode_changed"));
}
void FileSystemDock::fix_dependencies(const String &p_for_file) {
@@ -2040,7 +2027,17 @@ void FileSystemDock::fix_dependencies(const String &p_for_file) {
}
void FileSystemDock::focus_on_filter() {
- file_list_search_box->grab_focus();
+ LineEdit *current_search_box = nullptr;
+ if (display_mode == DISPLAY_MODE_TREE_ONLY) {
+ current_search_box = tree_search_box;
+ } else if (display_mode == DISPLAY_MODE_SPLIT) {
+ current_search_box = file_list_search_box;
+ }
+
+ if (current_search_box) {
+ current_search_box->grab_focus();
+ current_search_box->select_all();
+ }
}
void FileSystemDock::set_file_list_display_mode(FileListDisplayMode p_mode) {
@@ -2407,28 +2404,28 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
if (all_files) {
if (all_files_scenes) {
if (filenames.size() == 1) {
- p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open Scene"), FILE_OPEN);
- p_popup->add_icon_item(get_theme_icon("CreateNewSceneFrom", "EditorIcons"), TTR("New Inherited Scene"), FILE_INHERIT);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open Scene"), FILE_OPEN);
+ p_popup->add_icon_item(get_theme_icon(SNAME("CreateNewSceneFrom"), SNAME("EditorIcons")), TTR("New Inherited Scene"), FILE_INHERIT);
if (ProjectSettings::get_singleton()->get("application/run/main_scene") != filenames[0]) {
- p_popup->add_icon_item(get_theme_icon("PlayScene", "EditorIcons"), TTR("Set As Main Scene"), FILE_MAIN_SCENE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")), TTR("Set As Main Scene"), FILE_MAIN_SCENE);
}
} else {
- p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open Scenes"), FILE_OPEN);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open Scenes"), FILE_OPEN);
}
- p_popup->add_icon_item(get_theme_icon("Instance", "EditorIcons"), TTR("Instance"), FILE_INSTANCE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instance"), FILE_INSTANCE);
p_popup->add_separator();
} else if (filenames.size() == 1) {
- p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open"), FILE_OPEN);
p_popup->add_separator();
}
}
if (p_paths.size() >= 1) {
if (!all_favorites) {
- p_popup->add_icon_item(get_theme_icon("Favorites", "EditorIcons"), TTR("Add to Favorites"), FILE_ADD_FAVORITE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")), TTR("Add to Favorites"), FILE_ADD_FAVORITE);
}
if (!all_not_favorites) {
- p_popup->add_icon_item(get_theme_icon("NonFavorite", "EditorIcons"), TTR("Remove from Favorites"), FILE_REMOVE_FAVORITE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("NonFavorite"), SNAME("EditorIcons")), TTR("Remove from Favorites"), FILE_REMOVE_FAVORITE);
}
p_popup->add_separator();
}
@@ -2441,36 +2438,36 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
}
} else if (all_folders && foldernames.size() > 0) {
- p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open"), FILE_OPEN);
p_popup->add_separator();
}
if (p_paths.size() == 1) {
- p_popup->add_icon_shortcut(get_theme_icon("ActionCopy", "EditorIcons"), ED_GET_SHORTCUT("filesystem_dock/copy_path"), FILE_COPY_PATH);
+ p_popup->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/copy_path"), FILE_COPY_PATH);
if (p_paths[0] != "res://") {
- p_popup->add_icon_shortcut(get_theme_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("filesystem_dock/rename"), FILE_RENAME);
- p_popup->add_icon_shortcut(get_theme_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("filesystem_dock/duplicate"), FILE_DUPLICATE);
+ p_popup->add_icon_shortcut(get_theme_icon(SNAME("Rename"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/rename"), FILE_RENAME);
+ p_popup->add_icon_shortcut(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/duplicate"), FILE_DUPLICATE);
}
}
if (p_paths.size() > 1 || p_paths[0] != "res://") {
- p_popup->add_icon_item(get_theme_icon("MoveUp", "EditorIcons"), TTR("Move To..."), FILE_MOVE);
- p_popup->add_icon_shortcut(get_theme_icon("Remove", "EditorIcons"), ED_GET_SHORTCUT("filesystem_dock/delete"), FILE_REMOVE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")), TTR("Move To..."), FILE_MOVE);
+ p_popup->add_icon_shortcut(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/delete"), FILE_REMOVE);
}
if (p_paths.size() == 1) {
p_popup->add_separator();
if (p_display_path_dependent_options) {
- p_popup->add_icon_item(get_theme_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER);
- p_popup->add_icon_item(get_theme_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE);
- p_popup->add_icon_item(get_theme_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT);
- p_popup->add_icon_item(get_theme_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), TTR("New Folder..."), FILE_NEW_FOLDER);
+ p_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE);
p_popup->add_separator();
}
String fpath = p_paths[0];
String item_text = fpath.ends_with("/") ? TTR("Open in File Manager") : TTR("Show in File Manager");
- p_popup->add_icon_item(get_theme_icon("Filesystem", "EditorIcons"), item_text, FILE_SHOW_IN_EXPLORER);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), item_text, FILE_SHOW_IN_EXPLORER);
}
}
@@ -2481,8 +2478,8 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
tree_popup->clear();
if (paths.size() == 1) {
if (paths[0].ends_with("/")) {
- tree_popup->add_icon_item(get_theme_icon("GuiTreeArrowDown", "EditorIcons"), TTR("Expand All"), FOLDER_EXPAND_ALL);
- tree_popup->add_icon_item(get_theme_icon("GuiTreeArrowRight", "EditorIcons"), TTR("Collapse All"), FOLDER_COLLAPSE_ALL);
+ tree_popup->add_icon_item(get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")), TTR("Expand All"), FOLDER_EXPAND_ALL);
+ tree_popup->add_icon_item(get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")), TTR("Collapse All"), FOLDER_COLLAPSE_ALL);
tree_popup->add_separator();
}
}
@@ -2501,10 +2498,10 @@ void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) {
path = "res://";
tree_popup->clear();
tree_popup->set_size(Size2(1, 1));
- tree_popup->add_icon_item(get_theme_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER);
- tree_popup->add_icon_item(get_theme_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE);
- tree_popup->add_icon_item(get_theme_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT);
- tree_popup->add_icon_item(get_theme_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE);
+ tree_popup->add_icon_item(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), TTR("New Folder..."), FILE_NEW_FOLDER);
+ tree_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE);
+ tree_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT);
+ tree_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE);
tree_popup->set_position(tree->get_global_position() + p_pos);
tree_popup->popup();
}
@@ -2546,12 +2543,12 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) {
file_list_popup->clear();
file_list_popup->set_size(Size2(1, 1));
- file_list_popup->add_icon_item(get_theme_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER);
- file_list_popup->add_icon_item(get_theme_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE);
- file_list_popup->add_icon_item(get_theme_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT);
- file_list_popup->add_icon_item(get_theme_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE);
+ file_list_popup->add_icon_item(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), TTR("New Folder..."), FILE_NEW_FOLDER);
+ file_list_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE);
+ file_list_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT);
+ file_list_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE);
file_list_popup->add_separator();
- file_list_popup->add_icon_item(get_theme_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER);
+ file_list_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER);
file_list_popup->set_position(files->get_global_position() + p_pos);
file_list_popup->popup();
}
@@ -2575,7 +2572,7 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) {
// Update the import dock.
import_dock_needs_update = true;
- call_deferred("_update_import_dock");
+ call_deferred(SNAME("_update_import_dock"));
}
void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
@@ -2590,7 +2587,7 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
} else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) {
_tree_rmb_option(FILE_RENAME);
} else if (ED_IS_SHORTCUT("editor/open_search", p_event)) {
- _focus_current_search_box();
+ focus_on_filter();
} else {
return;
}
@@ -2611,7 +2608,7 @@ void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) {
} else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) {
_file_list_rmb_option(FILE_RENAME);
} else if (ED_IS_SHORTCUT("editor/open_search", p_event)) {
- _focus_current_search_box();
+ focus_on_filter();
} else {
return;
}
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 12c567fb69..21a7abe622 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -253,7 +253,6 @@ private:
void _toggle_split_mode(bool p_active);
- void _focus_current_search_box();
void _search_changed(const String &p_text, const Control *p_from);
MenuButton *_create_file_menu_button();
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index c29b5d5906..87277e79f3 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -116,12 +116,12 @@ void FindInFiles::_notification(int p_notification) {
void FindInFiles::start() {
if (_pattern == "") {
print_verbose("Nothing to search, pattern is empty");
- emit_signal(SIGNAL_FINISHED);
+ emit_signal(SNAME(SIGNAL_FINISHED));
return;
}
if (_extension_filter.size() == 0) {
print_verbose("Nothing to search, filter matches no files");
- emit_signal(SIGNAL_FINISHED);
+ emit_signal(SNAME(SIGNAL_FINISHED));
return;
}
@@ -201,7 +201,7 @@ void FindInFiles::_iterate() {
set_process(false);
_current_dir = "";
_searching = false;
- emit_signal(SIGNAL_FINISHED);
+ emit_signal(SNAME(SIGNAL_FINISHED));
}
}
@@ -267,7 +267,7 @@ void FindInFiles::_scan_file(String fpath) {
String line = f->get_line();
while (find_next(line, _pattern, end, _match_case, _whole_words, begin, end)) {
- emit_signal(SIGNAL_RESULT_FOUND, fpath, line_number, begin, end, line);
+ emit_signal(SNAME(SIGNAL_RESULT_FOUND), fpath, line_number, begin, end, line);
}
}
@@ -457,7 +457,7 @@ void FindInFilesDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (is_visible()) {
// Doesn't work more than once if not deferred...
- _search_text_line_edit->call_deferred("grab_focus");
+ _search_text_line_edit->call_deferred(SNAME("grab_focus"));
_search_text_line_edit->select_all();
// Extensions might have changed in the meantime, we clean them and instance them again.
for (int i = 0; i < _filters_container->get_child_count(); i++) {
@@ -487,10 +487,10 @@ void FindInFilesDialog::custom_action(const String &p_action) {
_filters_preferences[cb->get_text()] = cb->is_pressed();
}
if (p_action == "find") {
- emit_signal(SIGNAL_FIND_REQUESTED);
+ emit_signal(SNAME(SIGNAL_FIND_REQUESTED));
hide();
} else if (p_action == "replace") {
- emit_signal(SIGNAL_REPLACE_REQUESTED);
+ emit_signal(SNAME(SIGNAL_REPLACE_REQUESTED));
hide();
}
}
@@ -565,8 +565,8 @@ FindInFilesPanel::FindInFilesPanel() {
hbc->add_child(find_label);
_search_text_label = memnew(Label);
- _search_text_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts"));
- _search_text_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("source_size", "EditorFonts"));
+ _search_text_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("source"), SNAME("EditorFonts")));
+ _search_text_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")));
hbc->add_child(_search_text_label);
_progress_bar = memnew(ProgressBar);
@@ -594,8 +594,8 @@ FindInFilesPanel::FindInFilesPanel() {
}
_results_display = memnew(Tree);
- _results_display->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts"));
- _results_display->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("source_size", "EditorFonts"));
+ _results_display->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("source"), SNAME("EditorFonts")));
+ _results_display->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")));
_results_display->set_v_size_flags(SIZE_EXPAND_FILL);
_results_display->connect("item_selected", callable_mp(this, &FindInFilesPanel::_on_result_selected));
_results_display->connect("item_edited", callable_mp(this, &FindInFilesPanel::_on_item_edited));
@@ -638,7 +638,7 @@ void FindInFilesPanel::set_with_replace(bool with_replace) {
// Results show checkboxes on their left so they can be opted out
_results_display->set_columns(2);
_results_display->set_column_expand(0, false);
- _results_display->set_column_min_width(0, 48 * EDSCALE);
+ _results_display->set_column_custom_minimum_width(0, 48 * EDSCALE);
} else {
// Results are single-cell items
@@ -688,8 +688,8 @@ void FindInFilesPanel::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
_progress_bar->set_as_ratio(_finder->get_progress());
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
- _search_text_label->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
- _results_display->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
+ _search_text_label->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
+ _results_display->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
}
}
@@ -754,8 +754,8 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
}
Result r = E->value();
String item_text = item->get_text(_with_replace ? 1 : 0);
- Ref<Font> font = _results_display->get_theme_font("font");
- int font_size = _results_display->get_theme_font_size("font_size");
+ Ref<Font> font = _results_display->get_theme_font(SNAME("font"));
+ int font_size = _results_display->get_theme_font_size(SNAME("font_size"));
Rect2 match_rect = rect;
match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed), font_size).x;
@@ -764,7 +764,7 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
match_rect.size.y -= 2 * EDSCALE;
// Use the inverted accent color to help match rectangles stand out even on the currently selected line.
- _results_display->draw_rect(match_rect, get_theme_color("accent_color", "Editor").inverted() * Color(1, 1, 1, 0.5));
+ _results_display->draw_rect(match_rect, get_theme_color(SNAME("accent_color"), SNAME("Editor")).inverted() * Color(1, 1, 1, 0.5));
// Text is drawn by Tree already.
}
@@ -773,11 +773,11 @@ void FindInFilesPanel::_on_item_edited() {
TreeItem *item = _results_display->get_selected();
if (item->is_checked(0)) {
- item->set_custom_color(1, _results_display->get_theme_color("font_color"));
+ item->set_custom_color(1, _results_display->get_theme_color(SNAME("font_color")));
} else {
// Grey out
- Color color = _results_display->get_theme_color("font_color");
+ Color color = _results_display->get_theme_color(SNAME("font_color"));
color.a /= 2.0;
item->set_custom_color(1, color);
}
@@ -823,7 +823,7 @@ void FindInFilesPanel::_on_result_selected() {
TreeItem *file_item = item->get_parent();
String fpath = file_item->get_metadata(0);
- emit_signal(SIGNAL_RESULT_SELECTED, fpath, r.line_number, r.begin, r.end);
+ emit_signal(SNAME(SIGNAL_RESULT_SELECTED), fpath, r.line_number, r.begin, r.end);
}
void FindInFilesPanel::_on_replace_text_changed(String text) {
@@ -860,7 +860,7 @@ void FindInFilesPanel::_on_replace_all_clicked() {
// Hide replace bar so we can't trigger the action twice without doing a new search
_replace_container->hide();
- emit_signal(SIGNAL_FILES_MODIFIED, modified_files);
+ emit_signal(SNAME(SIGNAL_FILES_MODIFIED), modified_files);
}
// Same as get_line, but preserves line ending characters
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 1b11ec4451..0a39768b9a 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -94,7 +94,7 @@ void GroupDialog::_load_nodes(Node *p_current) {
if (!_can_edit(p_current, selected_group)) {
node->set_selectable(0, false);
- node->set_custom_color(0, groups->get_theme_color("disabled_font_color", "Editor"));
+ node->set_custom_color(0, groups->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
}
}
@@ -204,7 +204,7 @@ void GroupDialog::_add_group(String p_name) {
TreeItem *new_group = groups->create_item(groups_root);
new_group->set_text(0, name);
- new_group->add_button(0, groups->get_theme_icon("Remove", "EditorIcons"), 0);
+ new_group->add_button(0, groups->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0);
new_group->set_editable(0, true);
new_group->select(0);
groups->ensure_cursor_is_visible();
@@ -365,16 +365,16 @@ void GroupDialog::_notification(int p_what) {
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_ENTER_TREE: {
if (is_layout_rtl()) {
- add_button->set_icon(groups->get_theme_icon("Back", "EditorIcons"));
- remove_button->set_icon(groups->get_theme_icon("Forward", "EditorIcons"));
+ add_button->set_icon(groups->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
+ remove_button->set_icon(groups->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
} else {
- add_button->set_icon(groups->get_theme_icon("Forward", "EditorIcons"));
- remove_button->set_icon(groups->get_theme_icon("Back", "EditorIcons"));
+ add_button->set_icon(groups->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
+ remove_button->set_icon(groups->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
}
- add_filter->set_right_icon(groups->get_theme_icon("Search", "EditorIcons"));
+ add_filter->set_right_icon(groups->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
add_filter->set_clear_button_enabled(true);
- remove_filter->set_right_icon(groups->get_theme_icon("Search", "EditorIcons"));
+ remove_filter->set_right_icon(groups->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
remove_filter->set_clear_button_enabled(true);
} break;
}
@@ -424,6 +424,8 @@ GroupDialog::GroupDialog() {
vbc_left->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *group_title = memnew(Label);
+ group_title->set_theme_type_variation("HeaderSmall");
+
group_title->set_text(TTR("Groups"));
vbc_left->add_child(group_title);
@@ -458,6 +460,8 @@ GroupDialog::GroupDialog() {
vbc_add->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *out_of_group_title = memnew(Label);
+ out_of_group_title->set_theme_type_variation("HeaderSmall");
+
out_of_group_title->set_text(TTR("Nodes Not in Group"));
vbc_add->add_child(out_of_group_title);
@@ -506,6 +510,8 @@ GroupDialog::GroupDialog() {
vbc_remove->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *in_group_title = memnew(Label);
+ in_group_title->set_theme_type_variation("HeaderSmall");
+
in_group_title->set_text(TTR("Nodes in Group"));
vbc_remove->add_child(in_group_title);
@@ -528,10 +534,12 @@ GroupDialog::GroupDialog() {
remove_filter->connect("text_changed", callable_mp(this, &GroupDialog::_remove_filter_changed));
group_empty = memnew(Label());
+ group_empty->set_theme_type_variation("HeaderSmall");
+
group_empty->set_text(TTR("Empty groups will be automatically removed."));
group_empty->set_valign(Label::VALIGN_CENTER);
group_empty->set_align(Label::ALIGN_CENTER);
- group_empty->set_autowrap(true);
+ group_empty->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
group_empty->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
nodes_to_remove->add_child(group_empty);
group_empty->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
@@ -647,7 +655,7 @@ void GroupsEditor::update_tree() {
TreeItem *item = tree->create_item(root);
item->set_text(0, gi.name);
if (can_be_deleted) {
- item->add_button(0, get_theme_icon("Remove", "EditorIcons"), 0);
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0);
} else {
item->set_selectable(0, false);
}
diff --git a/editor/icons/CenterView.svg b/editor/icons/CenterView.svg
new file mode 100644
index 0000000000..c2a918fe81
--- /dev/null
+++ b/editor/icons/CenterView.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="12" fill="none" r="2"/><g fill="#e0e0e0"><path d="m7.3333333 6c-.7386666 0-1.3333333.5946667-1.3333333 1.3333333v1.3333334c0 .7386663.5946667 1.3333333 1.3333333 1.3333333h1.3333334c.7386666 0 1.3333333-.594667 1.3333333-1.3333333v-1.3333334c0-.7386666-.5946667-1.3333333-1.3333333-1.3333333z" stroke-width=".666667"/><g stroke-width=".830398"><path d="m2.9918978 5.5000002c-.7478701.0001968-1.1170118.9026572-.5810669 1.4205652l.2441488.2424178h-2.15497967v1.6548989h2.15497967l-.2441488.242418c-.8159014.77992.3929613 1.9802119 1.178451 1.1700959l1.6667154-1.6548989c.3253369-.3231472.3253369-.8469488 0-1.170096l-1.6667154-1.6548989c-.1568986-.1601378-.3723426-.2504824-.5973507-.2504937z"/><path d="m13.008102 10.5c.74787-.000197 1.117012-.9026571.581067-1.4205651l-.244149-.242418h2.15498v-1.6548988h-2.15498l.244149-.2424179c.815901-.7799207-.392961-1.9802122-1.178451-1.1700961l-1.666715 1.6548987c-.325337.3231474-.325337.846949 0 1.1700961l1.666715 1.6548991c.156899.160138.372343.250482.597351.250494z"/><path d="m5.5000001 13.008102c.000197.74787.902657 1.117012 1.420565.581067l.242418-.244149v2.15498h1.654899v-2.15498l.242418.244149c.77992.815901 1.9802119-.392961 1.1700959-1.178451l-1.6548989-1.666715c-.323147-.325337-.846949-.325337-1.170096 0l-1.654899 1.666715c-.160138.156899-.250482.372343-.250494.597351z"/><path d="m10.5 2.9918983c-.000197-.7478701-.9026571-1.1170121-1.4205651-.581067l-.242418.244149v-2.1549801h-1.6548989v2.1549801l-.242418-.2441491c-.77992-.815901-1.9802121.3929611-1.170096 1.1784512l1.654899 1.6667148c.3231469.325337.8469489.325337 1.1700959 0l1.6548991-1.6667148c.160138-.156899.250482-.3723431.250494-.597351z"/></g></g></svg>
diff --git a/editor/icons/ImmediateMesh.svg b/editor/icons/ImmediateMesh.svg
new file mode 100644
index 0000000000..9521530876
--- /dev/null
+++ b/editor/icons/ImmediateMesh.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 2v2h5v-2zm5 2v3h2v-3zm2-2v2h5v-2zm-2 7v3h2v-3zm-5 3v2h5v-2zm7 0v2h5v-2z" fill="#ffca5f" transform="scale(.93749994)"/></svg>
diff --git a/editor/icons/ORMMaterial3D.svg b/editor/icons/ORMMaterial3D.svg
index 3d6db6910d..e09208155d 100644
--- a/editor/icons/ORMMaterial3D.svg
+++ b/editor/icons/ORMMaterial3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5.0534707 10.652714q0 .729229-.4538398 1.253141-.4538403.516832-1.0868283.516832h-1.1943162q-.6389592 0-1.1047425-.509753-.47175502-.509751-.47175502-1.26022v-5.5223119q0-.7575473.47175502-1.2672998.4717549-.5097517 1.1047425-.5097517h1.1943162q.6270165 0 1.0868283.516832.4538398.5168313.4538398 1.2602195zm-1.0808559-.233636v-5.0550395q0-.5734707-.3344086-.8141867-.1074887-.0849591-.2567782-.0778788h-.9912826q-.2567779 0-.4120391.2690357-.1552611.2690357-.1552611.6230298v5.0550395q0 .559311.3164938.807108.1074885.08496.2508064.08496h.9912826q.2746925 0 .4359254-.276116.1552614-.276115.1552614-.61595z" fill="#f00"/><path d="m9.9872948 12.451006h-1.0427362l-1.4698137-3.9222572h-.7931457v3.9222572h-1.0094573v-9.076416h2.739956q.5435541 0 .9318066.4601926.3882524.4601933.3882524 1.1540217v2.1239667q0 1.0053443-.6766682 1.3168588-.2107668.099119-.4659043.099119zm-1.2590481-5.64267v-1.5858953q0-.4743524-.2884169-.6867495-.088743-.070798-.2052192-.063719h-1.5530114v2.9452329h1.7194053q.2828702-.00708.3161488-.389394.011093-.1132781.011093-.2194752z" fill="#008000"/><path d="m10.201004 3.7285848q0-.4106342.529158-.3681546.126777.014161.209458.014161v.00708h.115753l1.692202 4.9205216 1.697714-4.9205216h.06063v-.00708h.463013q.198434 0 .297651.212397.03307.063719.03307.1415978v8.694102h-1.01422v-5.6001914l-1.058314 3.2284284h-.953584l-1.058315-2.9310723v5.3028353h-1.014218z" fill="#00f"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.1191406-3.7636719 1.8808594 3.7636719 1.8828125 3.763672-1.8828125z" fill="#80ff45"/><path d="m3 6.6191406v2.3808594 1.382812l1.234375.617188 2.765625 1.382812v-1.382812-2-.3808594l-3.2382812-1.6191406z" fill="#ff4545"/><path d="m13 6.6191406-.761719.3808594-3.238281 1.6191406v3.7636714l2.765625-1.382812 1.234375-.617188v-1.382812z" fill="#45d7ff"/></svg>
diff --git a/editor/icons/RectangleAddRemove.svg b/editor/icons/RectangleAddRemove.svg
deleted file mode 100644
index 87e2155a0d..0000000000
--- a/editor/icons/RectangleAddRemove.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 2c-.5522619.0000552-.9999448.4477381-1 1v10c.0000552.552262.4477381.999945 1 1h6v-2h-5v-8h10v1h2v-2c-.000055-.5522619-.447738-.9999448-1-1zm9.25 4v2.25h-2.25v1.5h2.25v2.25h1.5v-2.25h2.25v-1.5h-2.25v-2.25zm-2.25 7.5v1.5h6v-1.5z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/TileChecked.svg b/editor/icons/TileChecked.svg
new file mode 100644
index 0000000000..33b99a0e4c
--- /dev/null
+++ b/editor/icons/TileChecked.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#808080" stroke-width="1.16667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" fill="#fff" stroke-width="1.06023"/></svg>
diff --git a/editor/icons/TileUnchecked.svg b/editor/icons/TileUnchecked.svg
new file mode 100644
index 0000000000..cd8db4ee19
--- /dev/null
+++ b/editor/icons/TileUnchecked.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#808080" stroke-width="1.16667"/></svg>
diff --git a/editor/icons/TripleBar.svg b/editor/icons/TripleBar.svg
new file mode 100644
index 0000000000..2b521e6c15
--- /dev/null
+++ b/editor/icons/TripleBar.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m1.9375 4h12.062zm0 4h12.062zm0 4h12.062z" fill="none" stroke="#e0e0e0" stroke-opacity=".99608" stroke-width=".92823"/></svg>
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index e845a90259..2db1db9e51 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -78,7 +78,7 @@ void ResourceImporterWAV::get_import_options(List<ImportOption> *r_options, int
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/8_bit"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/mono"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/max_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_EXP_RANGE, "11025,192000,1"), 44100));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_RANGE, "11025,192000,1,exp"), 44100));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/loop"), false));
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index cb9fd1f28e..5dc494d6df 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -105,7 +105,7 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma
MaterialData &material_data = material_map[import_id];
- Ref<Texture2D> icon = get_theme_icon("StandardMaterial3D", "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(SNAME("StandardMaterial3D"), SNAME("EditorIcons"));
TreeItem *item = p_tree->create_item(p_parent);
item->set_text(0, p_material->get_name());
@@ -161,7 +161,7 @@ void SceneImportSettings::_fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, Tree
MeshData &mesh_data = mesh_map[import_id];
- Ref<Texture2D> icon = get_theme_icon("Mesh", "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Mesh"), SNAME("EditorIcons"));
TreeItem *item = p_tree->create_item(p_parent);
item->set_text(0, p_mesh->get_name());
@@ -211,7 +211,7 @@ void SceneImportSettings::_fill_animation(Tree *p_tree, const Ref<Animation> &p_
AnimationData &animation_data = animation_map[p_name];
- Ref<Texture2D> icon = get_theme_icon("Animation", "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Animation"), SNAME("EditorIcons"));
TreeItem *item = p_tree->create_item(p_parent);
item->set_text(0, p_name);
@@ -255,17 +255,17 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
String type = p_node->get_class();
- if (!has_theme_icon(type, "EditorIcons")) {
+ if (!has_theme_icon(type, SNAME("EditorIcons"))) {
type = "Node3D";
}
- Ref<Texture2D> icon = get_theme_icon(type, "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(type, SNAME("EditorIcons"));
TreeItem *item = scene_tree->create_item(p_parent_item);
item->set_text(0, p_node->get_name());
if (p_node == scene) {
- icon = get_theme_icon("PackedScene", "EditorIcons");
+ icon = get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
item->set_text(0, "Scene");
}
@@ -795,11 +795,11 @@ void SceneImportSettings::_save_path_changed(const String &p_path) {
if (FileAccess::exists(p_path)) {
save_path_item->set_text(2, "Warning: File exists");
save_path_item->set_tooltip(2, TTR("Existing file with the same name will be replaced."));
- save_path_item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+ save_path_item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
} else {
save_path_item->set_text(2, "Will create new File");
- save_path_item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ save_path_item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons")));
}
}
@@ -829,7 +829,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
String name = md.material_node->get_text(0);
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- item->set_icon(0, get_theme_icon("StandardMaterial3D", "EditorIcons"));
+ item->set_icon(0, get_theme_icon(SNAME("StandardMaterial3D"), SNAME("EditorIcons")));
item->set_text(0, name);
if (md.has_import_id) {
@@ -851,20 +851,20 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
if (FileAccess::exists(path)) {
item->set_text(2, "Warning: File exists");
item->set_tooltip(2, TTR("Existing file with the same name will be replaced."));
- item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
} else {
item->set_text(2, "Will create new File");
- item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons")));
}
- item->add_button(1, get_theme_icon("Folder", "EditorIcons"));
+ item->add_button(1, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
}
} else {
item->set_text(2, "No import ID");
item->set_tooltip(2, TTR("Material has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID."));
- item->set_icon(2, get_theme_icon("StatusError", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons")));
}
save_path_items.push_back(item);
@@ -882,7 +882,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
String name = md.mesh_node->get_text(0);
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- item->set_icon(0, get_theme_icon("Mesh", "EditorIcons"));
+ item->set_icon(0, get_theme_icon(SNAME("Mesh"), SNAME("EditorIcons")));
item->set_text(0, name);
if (md.has_import_id) {
@@ -904,20 +904,20 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
if (FileAccess::exists(path)) {
item->set_text(2, "Warning: File exists");
item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import."));
- item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
} else {
item->set_text(2, "Will save to new File");
- item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons")));
}
- item->add_button(1, get_theme_icon("Folder", "EditorIcons"));
+ item->add_button(1, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
}
} else {
item->set_text(2, "No import ID");
item->set_tooltip(2, TTR("Mesh has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID."));
- item->set_icon(2, get_theme_icon("StatusError", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons")));
}
save_path_items.push_back(item);
@@ -935,7 +935,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
String name = ad.scene_node->get_text(0);
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- item->set_icon(0, get_theme_icon("Animation", "EditorIcons"));
+ item->set_icon(0, get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")));
item->set_text(0, name);
if (ad.settings.has("save_to_file/enabled") && bool(ad.settings["save_to_file/enabled"])) {
@@ -956,14 +956,14 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
if (FileAccess::exists(path)) {
item->set_text(2, "Warning: File exists");
item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import."));
- item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
} else {
item->set_text(2, "Will save to new File");
- item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons")));
}
- item->add_button(1, get_theme_icon("Folder", "EditorIcons"));
+ item->add_button(1, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
}
save_path_items.push_back(item);
@@ -1163,13 +1163,13 @@ SceneImportSettings::SceneImportSettings() {
external_path_tree->set_columns(3);
external_path_tree->set_column_titles_visible(true);
external_path_tree->set_column_expand(0, true);
- external_path_tree->set_column_min_width(0, 100 * EDSCALE);
+ external_path_tree->set_column_custom_minimum_width(0, 100 * EDSCALE);
external_path_tree->set_column_title(0, TTR("Resource"));
external_path_tree->set_column_expand(1, true);
- external_path_tree->set_column_min_width(1, 100 * EDSCALE);
+ external_path_tree->set_column_custom_minimum_width(1, 100 * EDSCALE);
external_path_tree->set_column_title(1, TTR("Path"));
external_path_tree->set_column_expand(2, false);
- external_path_tree->set_column_min_width(2, 200 * EDSCALE);
+ external_path_tree->set_column_custom_minimum_width(2, 200 * EDSCALE);
external_path_tree->set_column_title(2, TTR("Status"));
save_path = memnew(EditorFileDialog);
save_path->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp
index ce78166d1e..f8e93df382 100644
--- a/editor/import/scene_importer_mesh.cpp
+++ b/editor/import/scene_importer_mesh.cpp
@@ -506,7 +506,7 @@ Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const {
const Vector<Face3> faces = get_faces();
- Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces);
+ Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces, -1);
Vector<Ref<Shape3D>> ret;
diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp
index 43b97eb910..8c506e938d 100644
--- a/editor/import_defaults_editor.cpp
+++ b/editor/import_defaults_editor.cpp
@@ -98,7 +98,7 @@ void ImportDefaultsEditor::_save() {
ProjectSettings::get_singleton()->set("importer_defaults/" + settings->importer->get_importer_name(), Variant());
}
- emit_signal("project_settings_changed");
+ emit_signal(SNAME("project_settings_changed"));
}
}
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 6fa9864830..4110912ff3 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -526,18 +526,18 @@ void ImportDock::_reimport() {
}
EditorFileSystem::get_singleton()->reimport_files(params->paths);
- EditorFileSystem::get_singleton()->emit_signal("filesystem_changed"); //it changed, so force emitting the signal
+ EditorFileSystem::get_singleton()->emit_signal(SNAME("filesystem_changed")); //it changed, so force emitting the signal
}
void ImportDock::_notification(int p_what) {
switch (p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- imported->add_theme_style_override("normal", get_theme_stylebox("normal", "LineEdit"));
+ imported->add_theme_style_override("normal", get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")));
} break;
case NOTIFICATION_ENTER_TREE: {
import_opts->edit(params);
- label_warning->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"));
+ label_warning->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
} break;
}
}
@@ -563,7 +563,7 @@ void ImportDock::initialize_import_options() const {
ImportDock::ImportDock() {
set_name("Import");
imported = memnew(Label);
- imported->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("normal", "LineEdit"));
+ imported->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")));
imported->set_clip_text(true);
add_child(imported);
HBoxContainer *hb = memnew(HBoxContainer);
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index e8c01d0e0c..ab307500e7 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -63,7 +63,7 @@ void InspectorDock::_menu_option(int p_option) {
case OBJECT_REQUEST_HELP: {
if (current) {
editor->set_visible_editor(EditorNode::EDITOR_SCRIPT);
- emit_signal("request_help", current->get_class());
+ emit_signal(SNAME("request_help"), current->get_class());
}
} break;
@@ -216,7 +216,7 @@ void InspectorDock::_prepare_history() {
history_menu->get_popup()->clear();
- Ref<Texture2D> base_icon = get_theme_icon("Object", "EditorIcons");
+ Ref<Texture2D> base_icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
Set<ObjectID> already;
for (int i = editor_history->get_history_len() - 1; i >= history_to; i--) {
ObjectID id = editor_history->get_history_obj(i);
@@ -337,27 +337,27 @@ void InspectorDock::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
set_theme(editor->get_gui_base()->get_theme());
- resource_new_button->set_icon(get_theme_icon("New", "EditorIcons"));
- resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons"));
- resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons"));
- resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+ resource_new_button->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons")));
+ resource_load_button->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")));
+ resource_save_button->set_icon(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")));
+ resource_extra_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
PopupMenu *resource_extra_popup = resource_extra_button->get_popup();
- resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_EDIT_CLIPBOARD), get_theme_icon("ActionPaste", "EditorIcons"));
- resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_COPY), get_theme_icon("ActionCopy", "EditorIcons"));
+ resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_EDIT_CLIPBOARD), get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")));
+ resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_COPY), get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
- backward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
- forward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
+ backward_button->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
+ forward_button->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
} else {
- backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
- forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
+ backward_button->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
+ forward_button->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
}
- history_menu->set_icon(get_theme_icon("History", "EditorIcons"));
- object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
- warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
- warning->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"));
+ history_menu->set_icon(get_theme_icon(SNAME("History"), SNAME("EditorIcons")));
+ object_menu->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
+ warning->set_icon(get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")));
+ warning->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
} break;
}
}
@@ -433,8 +433,8 @@ void InspectorDock::update(Object *p_object) {
PopupMenu *p = object_menu->get_popup();
p->clear();
- p->add_icon_shortcut(get_theme_icon("GuiTreeArrowDown", "EditorIcons"), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL);
- p->add_icon_shortcut(get_theme_icon("GuiTreeArrowRight", "EditorIcons"), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL);
+ p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL);
+ p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL);
p->add_separator();
p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Properties")), OBJECT_COPY_PARAMS);
@@ -499,7 +499,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
resource_new_button = memnew(Button);
resource_new_button->set_flat(true);
resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it."));
- resource_new_button->set_icon(get_theme_icon("New", "EditorIcons"));
+ resource_new_button->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons")));
general_options_hb->add_child(resource_new_button);
resource_new_button->connect("pressed", callable_mp(this, &InspectorDock::_new_resource));
resource_new_button->set_focus_mode(Control::FOCUS_NONE);
@@ -507,14 +507,14 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
resource_load_button = memnew(Button);
resource_load_button->set_flat(true);
resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it."));
- resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons"));
+ resource_load_button->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")));
general_options_hb->add_child(resource_load_button);
resource_load_button->connect("pressed", callable_mp(this, &InspectorDock::_open_resource_selector));
resource_load_button->set_focus_mode(Control::FOCUS_NONE);
resource_save_button = memnew(MenuButton);
resource_save_button->set_tooltip(TTR("Save the currently edited resource."));
- resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons"));
+ resource_save_button->set_icon(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")));
general_options_hb->add_child(resource_save_button);
resource_save_button->get_popup()->add_item(TTR("Save"), RESOURCE_SAVE);
resource_save_button->get_popup()->add_item(TTR("Save As..."), RESOURCE_SAVE_AS);
@@ -523,10 +523,11 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
resource_save_button->set_disabled(true);
resource_extra_button = memnew(MenuButton);
- resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+ resource_extra_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ resource_extra_button->set_tooltip(TTR("Extra resource options."));
general_options_hb->add_child(resource_extra_button);
- resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionPaste", "EditorIcons"), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD);
- resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionCopy", "EditorIcons"), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
+ resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD);
+ resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
resource_extra_button->get_popup()->set_item_disabled(1, true);
resource_extra_button->get_popup()->add_separator();
resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Resource Built-In")), RESOURCE_MAKE_BUILT_IN);
@@ -539,9 +540,9 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
backward_button->set_flat(true);
general_options_hb->add_child(backward_button);
if (is_layout_rtl()) {
- backward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
+ backward_button->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
} else {
- backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
+ backward_button->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
}
backward_button->set_tooltip(TTR("Go to the previous edited object in history."));
backward_button->set_disabled(true);
@@ -551,9 +552,9 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
forward_button->set_flat(true);
general_options_hb->add_child(forward_button);
if (is_layout_rtl()) {
- forward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
+ forward_button->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
} else {
- forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
+ forward_button->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
}
forward_button->set_tooltip(TTR("Go to the next edited object in history."));
forward_button->set_disabled(true);
@@ -561,7 +562,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
history_menu = memnew(MenuButton);
history_menu->set_tooltip(TTR("History of recently edited objects."));
- history_menu->set_icon(get_theme_icon("History", "EditorIcons"));
+ history_menu->set_icon(get_theme_icon(SNAME("History"), SNAME("EditorIcons")));
general_options_hb->add_child(history_menu);
history_menu->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_history));
history_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_select_history));
@@ -576,7 +577,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
open_docs_button->set_flat(true);
open_docs_button->set_visible(false);
open_docs_button->set_tooltip(TTR("Open documentation for this object."));
- open_docs_button->set_icon(get_theme_icon("HelpSearch", "EditorIcons"));
+ open_docs_button->set_icon(get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")));
open_docs_button->set_shortcut(ED_SHORTCUT("property_editor/open_help", TTR("Open Documentation")));
subresource_hb->add_child(open_docs_button);
open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option), varray(OBJECT_REQUEST_HELP));
@@ -592,13 +593,13 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
search = memnew(LineEdit);
search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search->set_placeholder(TTR("Filter properties"));
- search->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ search->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search->set_clear_button_enabled(true);
property_tools_hb->add_child(search);
object_menu = memnew(MenuButton);
object_menu->set_shortcut_context(this);
- object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
+ object_menu->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
property_tools_hb->add_child(object_menu);
object_menu->set_tooltip(TTR("Manage object properties."));
object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option));
@@ -606,8 +607,8 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
warning = memnew(Button);
add_child(warning);
warning->set_text(TTR("Changes may be lost!"));
- warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
- warning->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"));
+ warning->set_icon(get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")));
+ warning->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
warning->set_clip_text(true);
warning->hide();
warning->connect("pressed", callable_mp(this, &InspectorDock::_warning_pressed));
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index 161f1dde0d..f51decd9dc 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -176,7 +176,7 @@ void LocalizationEditor::_translation_res_select() {
return;
}
- call_deferred("update_translations");
+ call_deferred(SNAME("update_translations"));
}
void LocalizationEditor::_translation_res_option_changed() {
@@ -453,7 +453,7 @@ void LocalizationEditor::update_translations() {
t->set_text(0, translations[i].replace_first("res://", ""));
t->set_tooltip(0, translations[i]);
t->set_metadata(0, i);
- t->add_button(0, get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
+ t->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove"));
}
}
@@ -571,7 +571,7 @@ void LocalizationEditor::update_translations() {
t->set_text(0, keys[i].replace_first("res://", ""));
t->set_tooltip(0, keys[i]);
t->set_metadata(0, keys[i]);
- t->add_button(0, get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
+ t->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove"));
if (keys[i] == remap_selected) {
t->select(0);
translation_res_option_add_button->set_disabled(false);
@@ -588,7 +588,7 @@ void LocalizationEditor::update_translations() {
t2->set_text(0, path.replace_first("res://", ""));
t2->set_tooltip(0, path);
t2->set_metadata(0, j);
- t2->add_button(0, get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
+ t2->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove"));
t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
t2->set_text(1, langnames);
t2->set_editable(1, true);
@@ -621,7 +621,7 @@ void LocalizationEditor::update_translations() {
t->set_text(0, pot_translations[i].replace_first("res://", ""));
t->set_tooltip(0, pot_translations[i]);
t->set_metadata(0, i);
- t->add_button(0, get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
+ t->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove"));
}
}
@@ -656,7 +656,9 @@ LocalizationEditor::LocalizationEditor() {
translations->add_child(tvb);
HBoxContainer *thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Translations:"))));
+ Label *l = memnew(Label(TTR("Translations:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
@@ -684,7 +686,9 @@ LocalizationEditor::LocalizationEditor() {
translations->add_child(tvb);
HBoxContainer *thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Resources:"))));
+ Label *l = memnew(Label(TTR("Resources:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
@@ -708,7 +712,9 @@ LocalizationEditor::LocalizationEditor() {
add_child(translation_res_file_open_dialog);
thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Remaps by Locale:"))));
+ l = memnew(Label(TTR("Remaps by Locale:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
@@ -728,8 +734,10 @@ LocalizationEditor::LocalizationEditor() {
translation_remap_options->set_column_title(1, TTR("Locale"));
translation_remap_options->set_column_titles_visible(true);
translation_remap_options->set_column_expand(0, true);
+ translation_remap_options->set_column_clip_content(0, true);
translation_remap_options->set_column_expand(1, false);
- translation_remap_options->set_column_min_width(1, 200);
+ translation_remap_options->set_column_clip_content(1, true);
+ translation_remap_options->set_column_custom_minimum_width(1, 200);
translation_remap_options->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_changed));
translation_remap_options->connect("button_pressed", callable_mp(this, &LocalizationEditor::_translation_res_option_delete));
tmc->add_child(translation_remap_options);
@@ -756,7 +764,9 @@ LocalizationEditor::LocalizationEditor() {
translation_locale_filter_mode->connect("item_selected", callable_mp(this, &LocalizationEditor::_translation_filter_mode_changed));
tmc->add_margin_child(TTR("Filter mode:"), translation_locale_filter_mode);
- tmc->add_child(memnew(Label(TTR("Locales:"))));
+ Label *l = memnew(Label(TTR("Locales:")));
+ l->set_theme_type_variation("HeaderSmall");
+ tmc->add_child(l);
translation_filter = memnew(Tree);
translation_filter->set_v_size_flags(Control::SIZE_EXPAND_FILL);
translation_filter->set_columns(1);
@@ -770,7 +780,9 @@ LocalizationEditor::LocalizationEditor() {
translations->add_child(tvb);
HBoxContainer *thb = memnew(HBoxContainer);
- thb->add_child(memnew(Label(TTR("Files with translation strings:"))));
+ Label *l = memnew(Label(TTR("Files with translation strings:")));
+ l->set_theme_type_variation("HeaderSmall");
+ thb->add_child(l);
thb->add_spacer();
tvb->add_child(thb);
diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp
index 2a399f4b03..74fb38b66b 100644
--- a/editor/node_3d_editor_gizmos.cpp
+++ b/editor/node_3d_editor_gizmos.cpp
@@ -562,7 +562,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
if (selectable_icon_size > 0.0f) {
Transform3D t = spatial_node->get_global_transform();
Vector3 camera_position = p_camera->get_camera_transform().origin;
- if (camera_position.distance_squared_to(t.origin) > 0.01) {
+ if (!camera_position.is_equal_approx(t.origin)) {
t.set_look_at(t.origin, camera_position);
}
@@ -578,7 +578,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
Transform3D orig_camera_transform = p_camera->get_camera_transform();
- if (orig_camera_transform.origin.distance_squared_to(t.origin) > 0.01 &&
+ if (!orig_camera_transform.origin.is_equal_approx(t.origin) &&
ABS(orig_camera_transform.basis.get_axis(Vector3::AXIS_Z).dot(Vector3(0, 1, 0))) < 0.99) {
p_camera->look_at(t.origin);
}
@@ -782,9 +782,9 @@ Light3DGizmoPlugin::Light3DGizmoPlugin() {
create_material("lines_secondary", Color(1, 1, 1, 0.35), false, false, true);
create_material("lines_billboard", Color(1, 1, 1), true, false, true);
- create_icon_material("light_directional_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoDirectionalLight", "EditorIcons"));
- create_icon_material("light_omni_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoLight", "EditorIcons"));
- create_icon_material("light_spot_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoSpotLight", "EditorIcons"));
+ create_icon_material("light_directional_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoDirectionalLight"), SNAME("EditorIcons")));
+ create_icon_material("light_omni_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoLight"), SNAME("EditorIcons")));
+ create_icon_material("light_spot_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoSpotLight"), SNAME("EditorIcons")));
create_handle_material("handles");
create_handle_material("handles_billboard", true);
@@ -1050,7 +1050,7 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
AudioStreamPlayer3DGizmoPlugin::AudioStreamPlayer3DGizmoPlugin() {
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/stream_player_3d", Color(0.4, 0.8, 1));
- create_icon_material("stream_player_3d_icon", Node3DEditor::get_singleton()->get_theme_icon("Gizmo3DSamplePlayer", "EditorIcons"));
+ create_icon_material("stream_player_3d_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("Gizmo3DSamplePlayer"), SNAME("EditorIcons")));
create_material("stream_player_3d_material_primary", gizmo_color);
create_material("stream_player_3d_material_secondary", gizmo_color * Color(1, 1, 1, 0.35));
create_handle_material("handles");
@@ -1558,7 +1558,7 @@ Position3DGizmoPlugin::Position3DGizmoPlugin() {
// Use a darkened axis color for the negative axis.
// This makes it possible to see in which direction the Position3D node is rotated
// (which can be important depending on how it's used).
- const Color color_x = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor");
+ const Color color_x = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("axis_x_color"), SNAME("Editor"));
cursor_colors.push_back(color_x);
cursor_colors.push_back(color_x);
// FIXME: Use less strong darkening factor once GH-48573 is fixed.
@@ -1566,13 +1566,13 @@ Position3DGizmoPlugin::Position3DGizmoPlugin() {
cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75));
cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75));
- const Color color_y = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor");
+ const Color color_y = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("axis_y_color"), SNAME("Editor"));
cursor_colors.push_back(color_y);
cursor_colors.push_back(color_y);
cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75));
cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75));
- const Color color_z = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor");
+ const Color color_z = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("axis_z_color"), SNAME("Editor"));
cursor_colors.push_back(color_z);
cursor_colors.push_back(color_z);
cursor_colors.push_back(color_z.lerp(Color(0, 0, 0), 0.75));
@@ -2284,7 +2284,7 @@ void VisibleOnScreenNotifier3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
CPUParticles3DGizmoPlugin::CPUParticles3DGizmoPlugin() {
- create_icon_material("particles_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoCPUParticles3D", "EditorIcons"));
+ create_icon_material("particles_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoCPUParticles3D"), SNAME("EditorIcons")));
}
bool CPUParticles3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
@@ -2315,7 +2315,7 @@ GPUParticles3DGizmoPlugin::GPUParticles3DGizmoPlugin() {
create_material("particles_material", gizmo_color);
gizmo_color.a = 0.1;
create_material("particles_solid_material", gizmo_color);
- create_icon_material("particles_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoGPUParticles3D", "EditorIcons"));
+ create_icon_material("particles_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoGPUParticles3D"), SNAME("EditorIcons")));
create_handle_material("handles");
}
@@ -2746,7 +2746,7 @@ ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() {
gizmo_color.a = 0.1;
create_material("reflection_probe_solid_material", gizmo_color);
- create_icon_material("reflection_probe_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoReflectionProbe", "EditorIcons"));
+ create_icon_material("reflection_probe_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoReflectionProbe"), SNAME("EditorIcons")));
create_handle_material("handles");
}
@@ -3072,7 +3072,7 @@ VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() {
gizmo_color.a = 0.05;
create_material("voxel_gi_solid_material", gizmo_color);
- create_icon_material("voxel_gi_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoVoxelGI", "EditorIcons"));
+ create_icon_material("voxel_gi_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoVoxelGI"), SNAME("EditorIcons")));
create_handle_material("handles");
}
@@ -3254,7 +3254,7 @@ LightmapGIGizmoPlugin::LightmapGIGizmoPlugin() {
add_material("lightmap_probe_material", mat);
- create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoLightmapGI", "EditorIcons"));
+ create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoLightmapGI"), SNAME("EditorIcons")));
}
String LightmapGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
@@ -4589,7 +4589,7 @@ Joint3DGizmoPlugin::Joint3DGizmoPlugin() {
update_timer->set_wait_time(1.0 / 120.0);
update_timer->connect("timeout", callable_mp(this, &Joint3DGizmoPlugin::incremental_update_gizmos));
update_timer->set_autostart(true);
- EditorNode::get_singleton()->call_deferred("add_child", update_timer);
+ EditorNode::get_singleton()->call_deferred(SNAME("add_child"), update_timer);
}
void Joint3DGizmoPlugin::incremental_update_gizmos() {
diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp
index 43c9cabe01..532413897b 100644
--- a/editor/node_dock.cpp
+++ b/editor/node_dock.cpp
@@ -52,8 +52,8 @@ void NodeDock::_bind_methods() {
void NodeDock::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- connections_button->set_icon(get_theme_icon("Signals", "EditorIcons"));
- groups_button->set_icon(get_theme_icon("Groups", "EditorIcons"));
+ connections_button->set_icon(get_theme_icon(SNAME("Signals"), SNAME("EditorIcons")));
+ groups_button->set_icon(get_theme_icon(SNAME("Groups"), SNAME("EditorIcons")));
}
}
@@ -130,6 +130,6 @@ NodeDock::NodeDock() {
select_a_node->set_v_size_flags(SIZE_EXPAND_FILL);
select_a_node->set_valign(Label::VALIGN_CENTER);
select_a_node->set_align(Label::ALIGN_CENTER);
- select_a_node->set_autowrap(true);
+ select_a_node->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
add_child(select_a_node);
}
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index f55d77d782..35b27b25aa 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "plugin_config_dialog.h"
+
#include "core/io/config_file.h"
#include "core/io/dir_access.h"
#include "editor/editor_node.h"
@@ -112,7 +113,7 @@ void PluginConfigDialog::_on_confirmed() {
}
#endif
- emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? _to_absolute_plugin_path(subfolder_edit->get_text()) : "");
+ emit_signal(SNAME("plugin_ready"), script.operator->(), active_edit->is_pressed() ? _to_absolute_plugin_path(subfolder_edit->get_text()) : "");
} else {
EditorNode::get_singleton()->get_project_settings()->update_plugins();
}
@@ -126,7 +127,51 @@ void PluginConfigDialog::_on_cancelled() {
void PluginConfigDialog::_on_required_text_changed(const String &) {
int lang_idx = script_option_edit->get_selected();
String ext = ScriptServer::get_language(lang_idx)->get_extension();
- get_ok_button()->set_disabled(script_edit->get_text().get_basename().is_empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().is_empty());
+
+ Ref<Texture2D> valid_icon = get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons"));
+ Ref<Texture2D> invalid_icon = get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"));
+
+ // Set variables to assume all is valid
+ bool is_valid = true;
+ name_validation->set_texture(valid_icon);
+ subfolder_validation->set_texture(valid_icon);
+ script_validation->set_texture(valid_icon);
+ name_validation->set_tooltip("");
+ subfolder_validation->set_tooltip("");
+ script_validation->set_tooltip("");
+
+ // Change valid status to invalid depending on conditions.
+ Vector<String> errors;
+ if (name_edit->get_text().is_empty()) {
+ is_valid = false;
+ name_validation->set_texture(invalid_icon);
+ name_validation->set_tooltip(TTR("Plugin name cannot not be blank."));
+ }
+ if (script_edit->get_text().get_extension() != ext) {
+ is_valid = false;
+ script_validation->set_texture(invalid_icon);
+ script_validation->set_tooltip(vformat(TTR("Script extension must match chosen langauge extension (.%s)."), ext));
+ }
+ if (script_edit->get_text().get_basename().is_empty()) {
+ is_valid = false;
+ script_validation->set_texture(invalid_icon);
+ script_validation->set_tooltip(TTR("Script name cannot not be blank."));
+ }
+ if (subfolder_edit->get_text().is_empty()) {
+ is_valid = false;
+ subfolder_validation->set_texture(invalid_icon);
+ subfolder_validation->set_tooltip(TTR("Subfolder cannot be blank."));
+ } else {
+ DirAccessRef 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;
+ subfolder_validation->set_texture(invalid_icon);
+ subfolder_validation->set_tooltip(TTR("Subfolder cannot be one which already exists."));
+ }
+ }
+
+ get_ok_button()->set_disabled(!is_valid);
}
String PluginConfigDialog::_to_absolute_plugin_path(const String &p_plugin_name) {
@@ -162,19 +207,22 @@ void PluginConfigDialog::config(const String &p_config_path) {
_edit_mode = true;
active_edit->hide();
- Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->hide();
+ Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 2))->hide();
subfolder_edit->hide();
- Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->hide();
+ Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 2))->hide();
set_title(TTR("Edit a Plugin"));
} else {
_clear_fields();
_edit_mode = false;
active_edit->show();
- Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->show();
+ Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 2))->show();
subfolder_edit->show();
- Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->show();
+ Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 2))->show();
set_title(TTR("Create a Plugin"));
}
+ // Simulate text changing so the errors populate.
+ _on_required_text_changed("");
+
get_ok_button()->set_disabled(!_edit_mode);
get_ok_button()->set_text(_edit_mode ? TTR("Update") : TTR("Create"));
}
@@ -187,56 +235,88 @@ PluginConfigDialog::PluginConfigDialog() {
get_ok_button()->set_disabled(true);
set_hide_on_ok(true);
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(vbox);
+
GridContainer *grid = memnew(GridContainer);
- grid->set_columns(2);
- add_child(grid);
+ grid->set_columns(3);
+ vbox->add_child(grid);
+ // Plugin Name
Label *name_lb = memnew(Label);
name_lb->set_text(TTR("Plugin Name:"));
grid->add_child(name_lb);
+ name_validation = memnew(TextureRect);
+ name_validation->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ grid->add_child(name_validation);
+
name_edit = memnew(LineEdit);
name_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
name_edit->set_placeholder("MyPlugin");
grid->add_child(name_edit);
+ // Subfolder
Label *subfolder_lb = memnew(Label);
subfolder_lb->set_text(TTR("Subfolder:"));
grid->add_child(subfolder_lb);
+ subfolder_validation = memnew(TextureRect);
+ subfolder_validation->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ grid->add_child(subfolder_validation);
+
subfolder_edit = memnew(LineEdit);
subfolder_edit->set_placeholder("\"my_plugin\" -> res://addons/my_plugin");
+ subfolder_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
grid->add_child(subfolder_edit);
+ // Description
Label *desc_lb = memnew(Label);
desc_lb->set_text(TTR("Description:"));
grid->add_child(desc_lb);
+ Control *desc_spacer = memnew(Control);
+ grid->add_child(desc_spacer);
+
desc_edit = memnew(TextEdit);
desc_edit->set_custom_minimum_size(Size2(400, 80) * EDSCALE);
desc_edit->set_wrap_enabled(true);
grid->add_child(desc_edit);
+ // Author
Label *author_lb = memnew(Label);
author_lb->set_text(TTR("Author:"));
grid->add_child(author_lb);
+ Control *author_spacer = memnew(Control);
+ grid->add_child(author_spacer);
+
author_edit = memnew(LineEdit);
author_edit->set_placeholder("Godette");
grid->add_child(author_edit);
+ // Version
Label *version_lb = memnew(Label);
version_lb->set_text(TTR("Version:"));
grid->add_child(version_lb);
+ Control *version_spacer = memnew(Control);
+ grid->add_child(version_spacer);
+
version_edit = memnew(LineEdit);
version_edit->set_placeholder("1.0");
grid->add_child(version_edit);
+ // Language dropdown
Label *script_option_lb = memnew(Label);
script_option_lb->set_text(TTR("Language:"));
grid->add_child(script_option_lb);
+ Control *script_opt_spacer = memnew(Control);
+ grid->add_child(script_opt_spacer);
+
script_option_edit = memnew(OptionButton);
int default_lang = 0;
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
@@ -251,20 +331,29 @@ PluginConfigDialog::PluginConfigDialog() {
script_option_edit->select(default_lang);
grid->add_child(script_option_edit);
+ // Plugin Script Name
Label *script_lb = memnew(Label);
script_lb->set_text(TTR("Script Name:"));
grid->add_child(script_lb);
+ script_validation = memnew(TextureRect);
+ script_validation->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ grid->add_child(script_validation);
+
script_edit = memnew(LineEdit);
script_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
script_edit->set_placeholder("\"plugin.gd\" -> res://addons/my_plugin/plugin.gd");
grid->add_child(script_edit);
+ // Activate now checkbox
// TODO Make this option work better with languages like C#. Right now, it does not work because the C# project must be compiled first.
Label *active_lb = memnew(Label);
active_lb->set_text(TTR("Activate now?"));
grid->add_child(active_lb);
+ Control *active_spacer = memnew(Control);
+ grid->add_child(active_spacer);
+
active_edit = memnew(CheckBox);
active_edit->set_pressed(true);
grid->add_child(active_edit);
diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h
index f49f14c881..ad5b96735f 100644
--- a/editor/plugin_config_dialog.h
+++ b/editor/plugin_config_dialog.h
@@ -36,6 +36,7 @@
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
#include "scene/gui/text_edit.h"
+#include "scene/gui/texture_rect.h"
class PluginConfigDialog : public ConfirmationDialog {
GDCLASS(PluginConfigDialog, ConfirmationDialog);
@@ -49,6 +50,10 @@ class PluginConfigDialog : public ConfirmationDialog {
LineEdit *script_edit;
CheckBox *active_edit;
+ TextureRect *name_validation;
+ TextureRect *subfolder_validation;
+ TextureRect *script_validation;
+
bool _edit_mode;
void _clear_fields();
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index e6f7ec1fbf..df01ecd1be 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -150,9 +150,9 @@ void AbstractPolygon2DEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
disable_polygon_editing(false, String());
- button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons"));
- button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons"));
- button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons"));
+ button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveCreate"), SNAME("EditorIcons")));
+ button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons")));
+ button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveDelete"), SNAME("EditorIcons")));
button_edit->set_pressed(true);
get_tree()->connect("node_removed", callable_mp(this, &AbstractPolygon2DEditor::_node_removed));
@@ -477,7 +477,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl
Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
// All polygon points are sharp, so use the sharp handle icon
- const Ref<Texture2D> handle = get_theme_icon("EditorPathSharpHandle", "EditorIcons");
+ const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons"));
const Vertex active_point = get_active_point();
const int n_polygons = _get_polygon_count();
@@ -550,8 +550,8 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl
p_overlay->draw_texture(handle, point - handle->get_size() * 0.5, modulate);
if (vertex == hover_point) {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
String num = String::num(vertex.vertex);
Size2 num_size = font->get_string_size(num, font_size);
p_overlay->draw_string(font, point - num_size * 0.5, num, HALIGN_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
@@ -560,7 +560,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl
}
if (edge_point.valid()) {
- Ref<Texture2D> add_handle = get_theme_icon("EditorHandleAdd", "EditorIcons");
+ Ref<Texture2D> add_handle = get_theme_icon(SNAME("EditorHandleAdd"), SNAME("EditorIcons"));
p_overlay->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5);
}
}
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index b6dd9474d3..9e58332e41 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -73,7 +73,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
ap->get_animation_list(&names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- animations_menu->add_icon_item(get_theme_icon("Animation", "EditorIcons"), E->get());
+ animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E->get());
animations_to_add.push_back(E->get());
}
}
@@ -196,19 +196,19 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
}
void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
- Color linecolor = get_theme_color("font_color", "Label");
+ Color linecolor = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color linecolor_soft = linecolor;
linecolor_soft.a *= 0.5;
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- Ref<Texture2D> icon = get_theme_icon("KeyValue", "EditorIcons");
- Ref<Texture2D> icon_selected = get_theme_icon("KeySelected", "EditorIcons");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Ref<Texture2D> icon = get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons"));
+ Ref<Texture2D> icon_selected = get_theme_icon(SNAME("KeySelected"), SNAME("EditorIcons"));
Size2 s = blend_space_draw->get_size();
if (blend_space_draw->has_focus()) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
blend_space_draw->draw_rect(Rect2(Point2(), s), color, false);
}
@@ -279,7 +279,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
{
Color color;
if (tool_blend->is_pressed()) {
- color = get_theme_color("accent_color", "Editor");
+ color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
} else {
color = linecolor;
color.a *= 0.5;
@@ -529,15 +529,15 @@ void AnimationNodeBlendSpace1DEditor::_open_editor() {
void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
- panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- tool_blend->set_icon(get_theme_icon("EditPivot", "EditorIcons"));
- tool_select->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- tool_create->set_icon(get_theme_icon("EditKey", "EditorIcons"));
- tool_erase->set_icon(get_theme_icon("Remove", "EditorIcons"));
- snap->set_icon(get_theme_icon("SnapGrid", "EditorIcons"));
- open_editor->set_icon(get_theme_icon("Edit", "EditorIcons"));
+ error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ tool_blend->set_icon(get_theme_icon(SNAME("EditPivot"), SNAME("EditorIcons")));
+ tool_select->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ tool_create->set_icon(get_theme_icon(SNAME("EditKey"), SNAME("EditorIcons")));
+ tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ snap->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons")));
+ open_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
}
if (p_what == NOTIFICATION_PROCESS) {
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 359df95bce..bbf88bbd8f 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -97,7 +97,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
List<StringName> names;
ap->get_animation_list(&names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- animations_menu->add_icon_item(get_theme_icon("Animation", "EditorIcons"), E->get());
+ animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E->get());
animations_to_add.push_back(E->get());
}
}
@@ -392,18 +392,18 @@ void AnimationNodeBlendSpace2DEditor::_tool_switch(int p_tool) {
}
void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
- Color linecolor = get_theme_color("font_color", "Label");
+ Color linecolor = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color linecolor_soft = linecolor;
linecolor_soft.a *= 0.5;
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
- Ref<Texture2D> icon = get_theme_icon("KeyValue", "EditorIcons");
- Ref<Texture2D> icon_selected = get_theme_icon("KeySelected", "EditorIcons");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Ref<Texture2D> icon = get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons"));
+ Ref<Texture2D> icon_selected = get_theme_icon(SNAME("KeySelected"), SNAME("EditorIcons"));
Size2 s = blend_space_draw->get_size();
if (blend_space_draw->has_focus()) {
- Color color = get_theme_color("accent_color", "Editor");
+ Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
blend_space_draw->draw_rect(Rect2(Point2(), s), color, false);
}
blend_space_draw->draw_line(Point2(1, 0), Point2(1, s.height - 1), linecolor);
@@ -483,7 +483,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
Color color;
if (i == selected_triangle) {
- color = get_theme_color("accent_color", "Editor");
+ color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
color.a *= 0.5;
} else {
color = linecolor;
@@ -543,7 +543,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
{
Color color;
if (tool_blend->is_pressed()) {
- color = get_theme_color("accent_color", "Editor");
+ color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
} else {
color = linecolor;
color.a *= 0.5;
@@ -733,21 +733,21 @@ void AnimationNodeBlendSpace2DEditor::_edit_point_pos(double) {
void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
- panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- tool_blend->set_icon(get_theme_icon("EditPivot", "EditorIcons"));
- tool_select->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- tool_create->set_icon(get_theme_icon("EditKey", "EditorIcons"));
- tool_triangle->set_icon(get_theme_icon("ToolTriangle", "EditorIcons"));
- tool_erase->set_icon(get_theme_icon("Remove", "EditorIcons"));
- snap->set_icon(get_theme_icon("SnapGrid", "EditorIcons"));
- open_editor->set_icon(get_theme_icon("Edit", "EditorIcons"));
- auto_triangles->set_icon(get_theme_icon("AutoTriangle", "EditorIcons"));
+ error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ tool_blend->set_icon(get_theme_icon(SNAME("EditPivot"), SNAME("EditorIcons")));
+ tool_select->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ tool_create->set_icon(get_theme_icon(SNAME("EditKey"), SNAME("EditorIcons")));
+ tool_triangle->set_icon(get_theme_icon(SNAME("ToolTriangle"), SNAME("EditorIcons")));
+ tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ snap->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons")));
+ open_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ auto_triangles->set_icon(get_theme_icon(SNAME("AutoTriangle"), SNAME("EditorIcons")));
interpolation->clear();
- interpolation->add_icon_item(get_theme_icon("TrackContinuous", "EditorIcons"), "", 0);
- interpolation->add_icon_item(get_theme_icon("TrackDiscrete", "EditorIcons"), "", 1);
- interpolation->add_icon_item(get_theme_icon("TrackCapture", "EditorIcons"), "", 2);
+ interpolation->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), "", 0);
+ interpolation->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), "", 1);
+ interpolation->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), "", 2);
}
if (p_what == NOTIFICATION_PROCESS) {
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index dcde89f177..7930bc1e1c 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -138,7 +138,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
name->set_text(E->get());
name->set_expand_to_text_length_enabled(true);
node->add_child(name);
- node->set_slot(0, false, 0, Color(), true, 0, get_theme_color("font_color", "Label"));
+ node->set_slot(0, false, 0, Color(), true, 0, get_theme_color(SNAME("font_color"), SNAME("Label")));
name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode), CONNECT_DEFERRED);
name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out), varray(name, agnode), CONNECT_DEFERRED);
base = 1;
@@ -150,7 +150,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
Label *in_name = memnew(Label);
node->add_child(in_name);
in_name->set_text(agnode->get_input_name(i));
- node->set_slot(base + i, true, 0, get_theme_color("font_color", "Label"), false, 0, Color());
+ node->set_slot(base + i, true, 0, get_theme_color(SNAME("font_color"), SNAME("Label")), false, 0, Color());
}
List<PropertyInfo> pinfo;
@@ -177,7 +177,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
node->add_child(memnew(HSeparator));
Button *open_in_editor = memnew(Button);
open_in_editor->set_text(TTR("Open Editor"));
- open_in_editor->set_icon(get_theme_icon("Edit", "EditorIcons"));
+ open_in_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
node->add_child(open_in_editor);
open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor), varray(E->get()), CONNECT_DEFERRED);
open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER);
@@ -187,7 +187,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
node->add_child(memnew(HSeparator));
Button *edit_filters = memnew(Button);
edit_filters->set_text(TTR("Edit Filters"));
- edit_filters->set_icon(get_theme_icon("AnimationFilter", "EditorIcons"));
+ edit_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons")));
node->add_child(edit_filters);
edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters), varray(E->get()), CONNECT_DEFERRED);
edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER);
@@ -197,7 +197,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
if (anim.is_valid()) {
MenuButton *mb = memnew(MenuButton);
mb->set_text(anim->get_animation());
- mb->set_icon(get_theme_icon("Animation", "EditorIcons"));
+ mb->set_icon(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")));
Array options;
node->add_child(memnew(HSeparator));
@@ -231,7 +231,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected), varray(options, E->get()), CONNECT_DEFERRED);
}
- Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode");
+ Ref<StyleBoxFlat> sb = node->get_theme_stylebox(SNAME("frame"), SNAME("GraphNode"));
Color c = sb->get_border_color();
Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0);
mono_color.a = 0.85;
@@ -617,7 +617,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
ti->set_text(0, F->get());
ti->set_selectable(0, false);
ti->set_editable(0, false);
- ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons"));
+ ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
} else {
ti = parenthood[accum];
}
@@ -628,7 +628,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
ti->set_text(0, concat);
ti->set_checked(0, anode->is_path_filtered(path));
- ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons"));
+ ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
ti->set_metadata(0, path);
} else {
@@ -690,8 +690,8 @@ void AnimationNodeBlendTreeEditor::_removed_from_graph() {
void AnimationNodeBlendTreeEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree()) {
_update_graph();
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index e31c98db92..cbce5bb3f5 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -99,23 +99,23 @@ void AnimationPlayerEditor::_notification(int p_what) {
get_tree()->connect("node_removed", callable_mp(this, &AnimationPlayerEditor::_node_removed));
- add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("panel", "Panel"));
+ add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox(SNAME("panel"), SNAME("Panel")));
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("panel", "Panel"));
+ add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox(SNAME("panel"), SNAME("Panel")));
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
- autoplay->set_icon(get_theme_icon("AutoPlay", "EditorIcons"));
+ autoplay->set_icon(get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons")));
- play->set_icon(get_theme_icon("PlayStart", "EditorIcons"));
- play_from->set_icon(get_theme_icon("Play", "EditorIcons"));
- play_bw->set_icon(get_theme_icon("PlayStartBackwards", "EditorIcons"));
- play_bw_from->set_icon(get_theme_icon("PlayBackwards", "EditorIcons"));
+ play->set_icon(get_theme_icon(SNAME("PlayStart"), SNAME("EditorIcons")));
+ play_from->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ play_bw->set_icon(get_theme_icon(SNAME("PlayStartBackwards"), SNAME("EditorIcons")));
+ play_bw_from->set_icon(get_theme_icon(SNAME("PlayBackwards"), SNAME("EditorIcons")));
- autoplay_icon = get_theme_icon("AutoPlay", "EditorIcons");
- reset_icon = get_theme_icon("Reload", "EditorIcons");
+ autoplay_icon = get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons"));
+ reset_icon = get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"));
{
Ref<Image> autoplay_img = autoplay_icon->get_image();
Ref<Image> reset_img = reset_icon->get_image();
@@ -128,17 +128,17 @@ void AnimationPlayerEditor::_notification(int p_what) {
autoplay_reset_icon.instantiate();
autoplay_reset_icon->create_from_image(autoplay_reset_img);
}
- stop->set_icon(get_theme_icon("Stop", "EditorIcons"));
+ stop->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
- onion_toggle->set_icon(get_theme_icon("Onion", "EditorIcons"));
- onion_skinning->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
+ onion_toggle->set_icon(get_theme_icon(SNAME("Onion"), SNAME("EditorIcons")));
+ onion_skinning->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- pin->set_icon(get_theme_icon("Pin", "EditorIcons"));
+ pin->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
- tool_anim->add_theme_style_override("normal", get_theme_stylebox("normal", "Button"));
- track_editor->get_edit_menu()->add_theme_style_override("normal", get_theme_stylebox("normal", "Button"));
+ tool_anim->add_theme_style_override("normal", get_theme_stylebox(SNAME("normal"), SNAME("Button")));
+ track_editor->get_edit_menu()->add_theme_style_override("normal", get_theme_stylebox(SNAME("normal"), SNAME("Button")));
-#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(m_icon, "EditorIcons"))
+#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");
@@ -373,7 +373,7 @@ void AnimationPlayerEditor::_animation_save_in_path(const Ref<Resource> &p_resou
}
((Resource *)p_resource.ptr())->set_path(path);
- editor->emit_signal("resource_saved", p_resource);
+ editor->emit_signal(SNAME("resource_saved"), p_resource);
}
void AnimationPlayerEditor::_animation_save(const Ref<Resource> &p_resource) {
@@ -569,8 +569,10 @@ void AnimationPlayerEditor::_animation_blend() {
blend_editor.dialog->popup_centered(Size2(400, 400) * EDSCALE);
blend_editor.tree->set_hide_root(true);
- blend_editor.tree->set_column_min_width(0, 10);
- blend_editor.tree->set_column_min_width(1, 3);
+ blend_editor.tree->set_column_expand_ratio(0, 10);
+ blend_editor.tree->set_column_clip_content(0, true);
+ blend_editor.tree->set_column_expand_ratio(1, 3);
+ blend_editor.tree->set_column_clip_content(1, true);
List<StringName> anims;
player->get_animation_list(&anims);
@@ -1322,11 +1324,11 @@ void AnimationPlayerEditor::_prepare_onion_layers_1() {
}
// And go to next step afterwards.
- call_deferred("_prepare_onion_layers_2");
+ call_deferred(SNAME("_prepare_onion_layers_2"));
}
void AnimationPlayerEditor::_prepare_onion_layers_1_deferred() {
- call_deferred("_prepare_onion_layers_1");
+ call_deferred(SNAME("_prepare_onion_layers_1"));
}
void AnimationPlayerEditor::_prepare_onion_layers_2() {
@@ -1731,27 +1733,27 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
onion.capture.material = Ref<ShaderMaterial>(memnew(ShaderMaterial));
onion.capture.shader = Ref<Shader>(memnew(Shader));
- onion.capture.shader->set_code(" \
- shader_type canvas_item; \
- \
- uniform vec4 bkg_color; \
- uniform vec4 dir_color; \
- uniform bool differences_only; \
- uniform sampler2D present; \
- \
- float zero_if_equal(vec4 a, vec4 b) { \
- return smoothstep(0.0, 0.005, length(a.rgb - b.rgb) / sqrt(3.0)); \
- } \
- \
- void fragment() { \
- vec4 capture_samp = texture(TEXTURE, UV); \
- vec4 present_samp = texture(present, UV); \
- float bkg_mask = zero_if_equal(capture_samp, bkg_color); \
- float diff_mask = 1.0 - zero_if_equal(present_samp, bkg_color); \
- diff_mask = min(1.0, diff_mask + float(!differences_only)); \
- COLOR = vec4(capture_samp.rgb * dir_color.rgb, bkg_mask * diff_mask); \
- } \
- ");
+ onion.capture.shader->set_code(R"(
+shader_type canvas_item;
+
+uniform vec4 bkg_color;
+uniform vec4 dir_color;
+uniform bool differences_only;
+uniform sampler2D present;
+
+float zero_if_equal(vec4 a, vec4 b) {
+ return smoothstep(0.0, 0.005, length(a.rgb - b.rgb) / sqrt(3.0));
+}
+
+void fragment() {
+ vec4 capture_samp = texture(TEXTURE, UV);
+ vec4 present_samp = texture(present, UV);
+ float bkg_mask = zero_if_equal(capture_samp, bkg_color);
+ float diff_mask = 1.0 - zero_if_equal(present_samp, bkg_color);
+ diff_mask = min(1.0, diff_mask + float(!differences_only));
+ COLOR = vec4(capture_samp.rgb * dir_color.rgb, bkg_mask * diff_mask);
+}
+)");
RS::get_singleton()->material_set_shader(onion.capture.material->get_rid(), onion.capture.shader->get_rid());
}
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 94e526922d..8abe20c3c9 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -94,7 +94,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
List<StringName> names;
ap->get_animation_list(&names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- animations_menu->add_icon_item(get_theme_icon("Animation", "EditorIcons"), E->get());
+ animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E->get());
animations_to_add.push_back(E->get());
}
}
@@ -145,7 +145,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
if (node_rects[i].name.has_point(mb->get_position())) { //edit name
- Ref<StyleBox> line_sb = get_theme_stylebox("normal", "LineEdit");
+ Ref<StyleBox> line_sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"));
Rect2 edit_rect = node_rects[i].name;
edit_rect.position -= line_sb->get_offset();
@@ -163,7 +163,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
if (node_rects[i].edit.has_point(mb->get_position())) { //edit name
- call_deferred("_open_editor", node_rects[i].node_name);
+ call_deferred(SNAME("_open_editor"), node_rects[i].node_name);
return;
}
@@ -487,9 +487,9 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) {
}
void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, const Vector2 &p_to, AnimationNodeStateMachineTransition::SwitchMode p_mode, bool p_enabled, bool p_selected, bool p_travel, bool p_auto_advance) {
- Color linecolor = get_theme_color("font_color", "Label");
+ Color linecolor = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color icon_color(1, 1, 1);
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
if (!p_enabled) {
linecolor.a *= 0.2;
@@ -498,12 +498,12 @@ void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, co
}
Ref<Texture2D> icons[6] = {
- get_theme_icon("TransitionImmediateBig", "EditorIcons"),
- get_theme_icon("TransitionSyncBig", "EditorIcons"),
- get_theme_icon("TransitionEndBig", "EditorIcons"),
- get_theme_icon("TransitionImmediateAutoBig", "EditorIcons"),
- get_theme_icon("TransitionSyncAutoBig", "EditorIcons"),
- get_theme_icon("TransitionEndAutoBig", "EditorIcons")
+ get_theme_icon(SNAME("TransitionImmediateBig"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TransitionSyncBig"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TransitionEndBig"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TransitionImmediateAutoBig"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TransitionSyncAutoBig"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("TransitionEndAutoBig"), SNAME("EditorIcons"))
};
if (p_selected) {
@@ -555,19 +555,19 @@ void AnimationNodeStateMachineEditor::_clip_dst_line_to_rect(Vector2 &r_from, Ve
void AnimationNodeStateMachineEditor::_state_machine_draw() {
Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
- Ref<StyleBox> style = get_theme_stylebox("state_machine_frame", "GraphNode");
- Ref<StyleBox> style_selected = get_theme_stylebox("state_machine_selectedframe", "GraphNode");
-
- Ref<Font> font = get_theme_font("title_font", "GraphNode");
- int font_size = get_theme_font_size("title_font_size", "GraphNode");
- Color font_color = get_theme_color("title_color", "GraphNode");
- Ref<Texture2D> play = get_theme_icon("Play", "EditorIcons");
- Ref<Texture2D> auto_play = get_theme_icon("AutoPlay", "EditorIcons");
- Ref<Texture2D> edit = get_theme_icon("Edit", "EditorIcons");
- Color accent = get_theme_color("accent_color", "Editor");
- Color linecolor = get_theme_color("font_color", "Label");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("state_machine_frame"), SNAME("GraphNode"));
+ Ref<StyleBox> style_selected = get_theme_stylebox(SNAME("state_machine_selectedframe"), SNAME("GraphNode"));
+
+ Ref<Font> font = get_theme_font(SNAME("title_font"), SNAME("GraphNode"));
+ int font_size = get_theme_font_size(SNAME("title_font_size"), SNAME("GraphNode"));
+ Color font_color = get_theme_color(SNAME("title_color"), SNAME("GraphNode"));
+ Ref<Texture2D> play = get_theme_icon(SNAME("Play"), SNAME("EditorIcons"));
+ Ref<Texture2D> auto_play = get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons"));
+ Ref<Texture2D> edit = get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"));
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ Color linecolor = get_theme_color(SNAME("font_color"), SNAME("Label"));
linecolor.a *= 0.3;
- Ref<StyleBox> playing_overlay = get_theme_stylebox("position", "GraphNode");
+ Ref<StyleBox> playing_overlay = get_theme_stylebox(SNAME("position"), SNAME("GraphNode"));
bool playing = false;
StringName current;
@@ -667,7 +667,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
_connection_draw(from, to, AnimationNodeStateMachineTransition::SwitchMode(transition_mode->get_selected()), true, false, false, false);
}
- Ref<Texture2D> tr_reference_icon = get_theme_icon("TransitionImmediateBig", "EditorIcons");
+ Ref<Texture2D> tr_reference_icon = get_theme_icon(SNAME("TransitionImmediateBig"), SNAME("EditorIcons"));
float tr_bidi_offset = int(tr_reference_icon->get_height() * 0.8);
//draw transition lines
@@ -857,7 +857,7 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
float pos = CLAMP(play_pos, 0, len);
float c = pos / len;
- Color fg = get_theme_color("font_color", "Label");
+ Color fg = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color bg = fg;
bg.a *= 0.3;
@@ -882,26 +882,26 @@ void AnimationNodeStateMachineEditor::_update_graph() {
void AnimationNodeStateMachineEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
- error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
- panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
+ error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
- tool_select->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- tool_create->set_icon(get_theme_icon("ToolAddNode", "EditorIcons"));
- tool_connect->set_icon(get_theme_icon("ToolConnect", "EditorIcons"));
+ tool_select->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ tool_create->set_icon(get_theme_icon(SNAME("ToolAddNode"), SNAME("EditorIcons")));
+ tool_connect->set_icon(get_theme_icon(SNAME("ToolConnect"), SNAME("EditorIcons")));
transition_mode->clear();
- transition_mode->add_icon_item(get_theme_icon("TransitionImmediate", "EditorIcons"), TTR("Immediate"));
- transition_mode->add_icon_item(get_theme_icon("TransitionSync", "EditorIcons"), TTR("Sync"));
- transition_mode->add_icon_item(get_theme_icon("TransitionEnd", "EditorIcons"), TTR("At End"));
+ transition_mode->add_icon_item(get_theme_icon(SNAME("TransitionImmediate"), SNAME("EditorIcons")), TTR("Immediate"));
+ transition_mode->add_icon_item(get_theme_icon(SNAME("TransitionSync"), SNAME("EditorIcons")), TTR("Sync"));
+ transition_mode->add_icon_item(get_theme_icon(SNAME("TransitionEnd"), SNAME("EditorIcons")), TTR("At End"));
- tool_erase->set_icon(get_theme_icon("Remove", "EditorIcons"));
- tool_autoplay->set_icon(get_theme_icon("AutoPlay", "EditorIcons"));
- tool_end->set_icon(get_theme_icon("AutoEnd", "EditorIcons"));
+ tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ tool_autoplay->set_icon(get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons")));
+ tool_end->set_icon(get_theme_icon(SNAME("AutoEnd"), SNAME("EditorIcons")));
play_mode->clear();
- play_mode->add_icon_item(get_theme_icon("PlayTravel", "EditorIcons"), TTR("Travel"));
- play_mode->add_icon_item(get_theme_icon("Play", "EditorIcons"), TTR("Immediate"));
+ play_mode->add_icon_item(get_theme_icon(SNAME("PlayTravel"), SNAME("EditorIcons")), TTR("Travel"));
+ play_mode->add_icon_item(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")), TTR("Immediate"));
}
if (p_what == NOTIFICATION_PROCESS) {
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index e90665f84d..9c28e023dd 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -79,7 +79,7 @@ void AnimationTreeEditor::_update_path() {
group.instantiate();
Button *b = memnew(Button);
- b->set_text("Root");
+ b->set_text(TTR("Root"));
b->set_toggle_mode(true);
b->set_button_group(group);
b->set_pressed(true);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index cd61ebd418..bbc8107cf6 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -58,7 +58,7 @@ void EditorAssetLibraryItem::set_image(int p_type, int p_index, const Ref<Textur
void EditorAssetLibraryItem::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- icon->set_normal_texture(get_theme_icon("ProjectIconLoading", "EditorIcons"));
+ icon->set_normal_texture(get_theme_icon(SNAME("ProjectIconLoading"), SNAME("EditorIcons")));
category->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
author->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
price->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
@@ -66,15 +66,15 @@ void EditorAssetLibraryItem::_notification(int p_what) {
}
void EditorAssetLibraryItem::_asset_clicked() {
- emit_signal("asset_selected", asset_id);
+ emit_signal(SNAME("asset_selected"), asset_id);
}
void EditorAssetLibraryItem::_category_clicked() {
- emit_signal("category_selected", category_id);
+ emit_signal(SNAME("category_selected"), category_id);
}
void EditorAssetLibraryItem::_author_clicked() {
- emit_signal("author_selected", author_id);
+ emit_signal(SNAME("author_selected"), author_id);
}
void EditorAssetLibraryItem::_bind_methods() {
@@ -144,7 +144,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const
for (int i = 0; i < preview_images.size(); i++) {
if (preview_images[i].id == p_index) {
if (preview_images[i].is_video) {
- Ref<Image> overlay = previews->get_theme_icon("PlayOverlay", "EditorIcons")->get_image();
+ Ref<Image> overlay = previews->get_theme_icon(SNAME("PlayOverlay"), SNAME("EditorIcons"))->get_image();
Ref<Image> thumbnail = p_image->get_image();
thumbnail = thumbnail->duplicate();
Point2 overlay_pos = Point2((thumbnail->get_width() - overlay->get_width()) / 2, (thumbnail->get_height() - overlay->get_height()) / 2);
@@ -185,7 +185,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const
void EditorAssetLibraryItemDescription::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- previews_bg->add_theme_style_override("panel", previews->get_theme_stylebox("normal", "TextEdit"));
+ previews_bg->add_theme_style_override("panel", previews->get_theme_stylebox(SNAME("normal"), SNAME("TextEdit")));
} break;
}
}
@@ -240,12 +240,12 @@ void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video, cons
preview.video_link = p_url;
preview.is_video = p_video;
preview.button = memnew(Button);
- preview.button->set_icon(previews->get_theme_icon("ThumbnailWait", "EditorIcons"));
+ preview.button->set_icon(previews->get_theme_icon(SNAME("ThumbnailWait"), SNAME("EditorIcons")));
preview.button->set_toggle_mode(true);
preview.button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click), varray(p_id));
preview_hb->add_child(preview.button);
if (!p_video) {
- preview.image = previews->get_theme_icon("ThumbnailWait", "EditorIcons");
+ preview.image = previews->get_theme_icon(SNAME("ThumbnailWait"), SNAME("EditorIcons"));
}
preview_images.push_back(preview);
if (preview_images.size() == 1 && !p_video) {
@@ -369,6 +369,9 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int
progress->set_modulate(Color(0, 0, 0, 0));
set_process(false);
+
+ // Automatically prompt for installation once the download is completed.
+ _install();
}
void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asset_id, const Ref<Texture2D> &p_preview, const String &p_download_url, const String &p_sha256_hash) {
@@ -376,7 +379,7 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse
icon->set_texture(p_preview);
asset_id = p_asset_id;
if (!p_preview.is_valid()) {
- icon->set_texture(get_theme_icon("FileBrokenBigThumb", "EditorIcons"));
+ icon->set_texture(get_theme_icon(SNAME("FileBrokenBigThumb"), SNAME("EditorIcons")));
}
host = p_download_url;
sha256 = p_sha256_hash;
@@ -387,8 +390,8 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) {
switch (p_what) {
// FIXME: The editor crashes if 'NOTICATION_THEME_CHANGED' is used.
case NOTIFICATION_ENTER_TREE: {
- add_theme_style_override("panel", get_theme_stylebox("panel", "TabContainer"));
- dismiss->set_normal_texture(get_theme_icon("Close", "EditorIcons"));
+ add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
+ dismiss->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_PROCESS: {
// Make the progress bar visible again when retrying the download.
@@ -452,10 +455,11 @@ void EditorAssetLibraryItemDownload::_install() {
String file = download->get_download_file();
if (external_install) {
- emit_signal("install_asset", file, title->get_text());
+ emit_signal(SNAME("install_asset"), file, title->get_text());
return;
}
+ asset_installer->set_asset_name(title->get_text());
asset_installer->open(file, 1);
}
@@ -549,8 +553,8 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() {
void EditorAssetLibrary::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- error_tr->set_texture(get_theme_icon("Error", "EditorIcons"));
- filter->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ error_tr->set_texture(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
filter->set_clear_button_enabled(true);
error_label->raise();
@@ -584,10 +588,10 @@ void EditorAssetLibrary::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- library_scroll_bg->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- downloads_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
- error_tr->set_texture(get_theme_icon("Error", "EditorIcons"));
- filter->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ library_scroll_bg->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ downloads_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ error_tr->set_texture(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
filter->set_clear_button_enabled(true);
} break;
@@ -769,7 +773,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
}
if (!image_set && final) {
- obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_theme_icon("FileBrokenBigThumb", "EditorIcons"));
+ obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_theme_icon(SNAME("FileBrokenBigThumb"), SNAME("EditorIcons")));
}
}
}
@@ -812,7 +816,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
WARN_PRINT("Error getting image file from URL: " + image_queue[p_queue_id].image_url);
Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
if (obj) {
- obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_theme_icon("FileBrokenBigThumb", "EditorIcons"));
+ obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_theme_icon(SNAME("FileBrokenBigThumb"), SNAME("EditorIcons")));
}
}
@@ -1296,6 +1300,7 @@ void EditorAssetLibrary::_asset_file_selected(const String &p_file) {
}
asset_installer = memnew(EditorAssetInstaller);
+ asset_installer->set_asset_name(p_file.get_basename());
add_child(asset_installer);
asset_installer->open(p_file);
}
@@ -1310,7 +1315,7 @@ void EditorAssetLibrary::_manage_plugins() {
}
void EditorAssetLibrary::_install_external_asset(String p_zip_path, String p_title) {
- emit_signal("install_asset", p_zip_path, p_title);
+ emit_signal(SNAME("install_asset"), p_zip_path, p_title);
}
void EditorAssetLibrary::disable_community_support() {
@@ -1485,7 +1490,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
error_hb = memnew(HBoxContainer);
library_main->add_child(error_hb);
error_label = memnew(Label);
- error_label->add_theme_color_override("color", get_theme_color("error_color", "Editor"));
+ error_label->add_theme_color_override("color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
error_hb->add_child(error_label);
error_tr = memnew(TextureRect);
error_tr->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index 3b54b30b54..482c08f50a 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -43,10 +43,10 @@ void AudioStreamEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) {
- _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons"));
- _stop_button->set_icon(get_theme_icon("Stop", "EditorIcons"));
- _preview->set_color(get_theme_color("dark_color_2", "Editor"));
- set_color(get_theme_color("dark_color_1", "Editor"));
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ _stop_button->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+ _preview->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor")));
+ set_color(get_theme_color(SNAME("dark_color_1"), SNAME("Editor")));
_indicator->update();
_preview->update();
@@ -86,7 +86,7 @@ void AudioStreamEditor::_draw_preview() {
}
Vector<Color> color;
- color.push_back(get_theme_color("contrast_color_2", "Editor"));
+ color.push_back(get_theme_color(SNAME("contrast_color_2"), SNAME("Editor")));
RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color);
}
@@ -109,25 +109,25 @@ void AudioStreamEditor::_play() {
// '_pausing' variable indicates that we want to pause the audio player, not stop it. See '_on_finished()'.
_pausing = true;
_player->stop();
- _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons"));
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
set_process(false);
} else {
_player->play(_current);
- _play_button->set_icon(get_theme_icon("Pause", "EditorIcons"));
+ _play_button->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
set_process(true);
}
}
void AudioStreamEditor::_stop() {
_player->stop();
- _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons"));
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
_current = 0;
_indicator->update();
set_process(false);
}
void AudioStreamEditor::_on_finished() {
- _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons"));
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
if (!_pausing) {
_current = 0;
_indicator->update();
@@ -145,11 +145,11 @@ void AudioStreamEditor::_draw_indicator() {
Rect2 rect = _preview->get_rect();
float len = stream->get_length();
float ofs_x = _current / len * rect.size.width;
- const Color color = get_theme_color("accent_color", "Editor");
+ const Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
_indicator->draw_line(Point2(ofs_x, 0), Point2(ofs_x, rect.size.height), color, Math::round(2 * EDSCALE));
_indicator->draw_texture(
- get_theme_icon("TimelineIndicator", "EditorIcons"),
- Point2(ofs_x - get_theme_icon("TimelineIndicator", "EditorIcons")->get_width() * 0.5, 0),
+ get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons")),
+ Point2(ofs_x - get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"))->get_width() * 0.5, 0),
color);
_current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /");
@@ -243,14 +243,14 @@ AudioStreamEditor::AudioStreamEditor() {
_current_label = memnew(Label);
_current_label->set_align(Label::ALIGN_RIGHT);
_current_label->set_h_size_flags(SIZE_EXPAND_FILL);
- _current_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
- _current_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
+ _current_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ _current_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
_current_label->set_modulate(Color(1, 1, 1, 0.5));
hbox->add_child(_current_label);
_duration_label = memnew(Label);
- _duration_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
- _duration_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
+ _duration_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ _duration_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
hbox->add_child(_duration_label);
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 29012d1180..d5ef13e426 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -903,7 +903,7 @@ void CanvasItemEditor::_node_created(Node *p_node) {
c->_edit_set_position(xform.xform(node_create_position));
}
- call_deferred("_reset_create_position"); // Defer the call in case more than one node is added.
+ call_deferred(SNAME("_reset_create_position")); // Defer the call in case more than one node is added.
}
void CanvasItemEditor::_reset_create_position() {
@@ -1149,8 +1149,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
update_viewport();
} else {
- zoom_widget->set_zoom_by_increments(-1);
- if (b->get_factor() != 1.f) {
+ zoom_widget->set_zoom_by_increments(-1, Input::get_singleton()->is_key_pressed(KEY_ALT));
+ if (!Math::is_equal_approx(b->get_factor(), 1.0f)) {
+ // Handle high-precision (analog) scrolling.
zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f));
}
_zoom_on_position(zoom_widget->get_zoom(), b->get_position());
@@ -1164,8 +1165,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
update_viewport();
} else {
- zoom_widget->set_zoom_by_increments(1);
- if (b->get_factor() != 1.f) {
+ zoom_widget->set_zoom_by_increments(1, Input::get_singleton()->is_key_pressed(KEY_ALT));
+ if (!Math::is_equal_approx(b->get_factor(), 1.0f)) {
+ // Handle high-precision (analog) scrolling.
zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f));
}
_zoom_on_position(zoom_widget->get_zoom(), b->get_position());
@@ -1194,6 +1196,30 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
+ if (k->is_pressed()) {
+ if (ED_GET_SHORTCUT("canvas_item_editor/zoom_3.125_percent")->is_shortcut(p_event)) {
+ _update_zoom((1.0 / 32.0) * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_6.25_percent")->is_shortcut(p_event)) {
+ _update_zoom((1.0 / 16.0) * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_12.5_percent")->is_shortcut(p_event)) {
+ _update_zoom((1.0 / 8.0) * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_25_percent")->is_shortcut(p_event)) {
+ _update_zoom((1.0 / 4.0) * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_50_percent")->is_shortcut(p_event)) {
+ _update_zoom((1.0 / 2.0) * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_100_percent")->is_shortcut(p_event)) {
+ _update_zoom(1.0 * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_200_percent")->is_shortcut(p_event)) {
+ _update_zoom(2.0 * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_400_percent")->is_shortcut(p_event)) {
+ _update_zoom(4.0 * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_800_percent")->is_shortcut(p_event)) {
+ _update_zoom(8.0 * MAX(1, EDSCALE));
+ } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_1600_percent")->is_shortcut(p_event)) {
+ _update_zoom(16.0 * MAX(1, EDSCALE));
+ }
+ }
+
bool is_pan_key = pan_view_shortcut.is_valid() && pan_view_shortcut->is_shortcut(p_event);
if (is_pan_key && (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || drag_type != DRAG_NONE)) {
@@ -1241,7 +1267,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid() && !p_already_accepted) {
- // If control key pressed, then zoom instead of pan
+ // If ctrl key pressed, then zoom instead of pan.
if (pan_gesture->is_ctrl_pressed()) {
const float factor = pan_gesture->get_delta().y;
@@ -2189,7 +2215,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
// Popup the selection menu list
Point2 click = transform.affine_inverse().xform(b->get_position());
- _get_canvas_items_at_pos(click, selection_results, b->is_alt_pressed() && tool != TOOL_LIST_SELECT);
+ _get_canvas_items_at_pos(click, selection_results, b->is_alt_pressed() && tool == TOOL_SELECT);
if (selection_results.size() == 1) {
CanvasItem *item = selection_results[0].item;
@@ -2308,7 +2334,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
if (m.is_valid()) {
Point2 click = transform.affine_inverse().xform(m->get_position());
- bool movement_threshold_passed = drag_start_origin.distance_to(click) > 10 * EDSCALE;
+ bool movement_threshold_passed = drag_start_origin.distance_to(click) > (8 * MAX(1, EDSCALE)) / zoom;
if (m.is_valid() && movement_threshold_passed) {
List<CanvasItem *> selection2 = _get_edited_canvas_items();
@@ -2513,7 +2539,7 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
// Grab focus
if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
- viewport->call_deferred("grab_focus");
+ viewport->call_deferred(SNAME("grab_focus"));
}
}
@@ -2601,10 +2627,10 @@ void CanvasItemEditor::_update_cursor() {
}
void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Side p_side) {
- Color color = get_theme_color("font_color", "Editor");
+ Color color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
color.a = 0.8;
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Size2 text_size = font->get_string_size(p_string, font_size);
switch (p_side) {
case SIDE_LEFT:
@@ -2640,7 +2666,7 @@ void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_posi
void CanvasItemEditor::_draw_focus() {
// Draw the focus around the base viewport
if (viewport->has_focus()) {
- get_theme_stylebox("Focus", "EditorStyles")->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size()));
+ get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles"))->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size()));
}
}
@@ -2672,21 +2698,21 @@ void CanvasItemEditor::_draw_guides() {
}
// Dragged guide
- Color text_color = get_theme_color("font_color", "Editor");
+ Color text_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
Color outline_color = text_color.inverted();
const float outline_size = 2;
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x)));
- Ref<Font> font = get_theme_font("bold", "EditorFonts");
- int font_size = get_theme_font_size("bold_size", "EditorFonts");
+ Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
Size2 text_size = font->get_string_size(str, font_size);
viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HALIGN_LEFT, -1, font_size, text_color, outline_size, outline_color);
viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
}
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y)));
- Ref<Font> font = get_theme_font("bold", "EditorFonts");
- int font_size = get_theme_font_size("bold_size", "EditorFonts");
+ Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
Size2 text_size = font->get_string_size(str, font_size);
viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HALIGN_LEFT, -1, font_size, text_color, outline_size, outline_color);
viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE));
@@ -2708,12 +2734,12 @@ void CanvasItemEditor::_draw_smart_snapping() {
}
void CanvasItemEditor::_draw_rulers() {
- Color bg_color = get_theme_color("dark_color_2", "Editor");
- Color graduation_color = get_theme_color("font_color", "Editor").lerp(bg_color, 0.5);
- Color font_color = get_theme_color("font_color", "Editor");
+ Color bg_color = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
+ Color graduation_color = get_theme_color(SNAME("font_color"), SNAME("Editor")).lerp(bg_color, 0.5);
+ Color font_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
font_color.a = 0.8;
- Ref<Font> font = get_theme_font("rulers", "EditorFonts");
- int font_size = get_theme_font_size("rulers_size", "EditorFonts");
+ Ref<Font> font = get_theme_font(SNAME("rulers"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("rulers_size"), SNAME("EditorFonts"));
// The rule transform
Transform2D ruler_transform = Transform2D();
@@ -2874,7 +2900,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
}
if (ruler_tool_active) {
- Color ruler_primary_color = get_theme_color("accent_color", "Editor");
+ Color ruler_primary_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
Color ruler_secondary_color = ruler_primary_color;
ruler_secondary_color.a = 0.5;
@@ -2891,9 +2917,9 @@ void CanvasItemEditor::_draw_ruler_tool() {
viewport->draw_line(corner, end, ruler_secondary_color, Math::round(EDSCALE));
}
- Ref<Font> font = get_theme_font("bold", "EditorFonts");
- int font_size = get_theme_font_size("bold_size", "EditorFonts");
- Color font_color = get_theme_color("font_color", "Editor");
+ Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
+ Color font_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
Color font_secondary_color = font_color;
font_secondary_color.set_v(font_secondary_color.get_v() > 0.5 ? 0.7 : 0.3);
Color outline_color = font_color.inverted();
@@ -2994,8 +3020,8 @@ void CanvasItemEditor::_draw_ruler_tool() {
}
} else {
if (grid_snap_active) {
- Ref<Texture2D> position_icon = get_theme_icon("EditorPosition", "EditorIcons");
- viewport->draw_texture(get_theme_icon("EditorPosition", "EditorIcons"), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2);
+ Ref<Texture2D> position_icon = get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
+ viewport->draw_texture(get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons")), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2);
}
}
}
@@ -3213,9 +3239,9 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
}
void CanvasItemEditor::_draw_selection() {
- Ref<Texture2D> pivot_icon = get_theme_icon("EditorPivot", "EditorIcons");
- Ref<Texture2D> position_icon = get_theme_icon("EditorPosition", "EditorIcons");
- Ref<Texture2D> previous_position_icon = get_theme_icon("EditorPositionPrevious", "EditorIcons");
+ Ref<Texture2D> pivot_icon = get_theme_icon(SNAME("EditorPivot"), SNAME("EditorIcons"));
+ Ref<Texture2D> position_icon = get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
+ Ref<Texture2D> previous_position_icon = get_theme_icon(SNAME("EditorPositionPrevious"), SNAME("EditorIcons"));
RID ci = viewport->get_canvas_item();
@@ -3341,16 +3367,16 @@ void CanvasItemEditor::_draw_selection() {
points.push_back(Vector2(move_factor.x * EDSCALE, -5 * EDSCALE));
points.push_back(Vector2((move_factor.x + 10) * EDSCALE, 0));
- viewport->draw_colored_polygon(points, get_theme_color("axis_x_color", "Editor"));
- viewport->draw_line(Point2(), Point2(move_factor.x * EDSCALE, 0), get_theme_color("axis_x_color", "Editor"), Math::round(EDSCALE));
+ viewport->draw_colored_polygon(points, get_theme_color(SNAME("axis_x_color"), SNAME("Editor")));
+ viewport->draw_line(Point2(), Point2(move_factor.x * EDSCALE, 0), get_theme_color(SNAME("axis_x_color"), SNAME("Editor")), Math::round(EDSCALE));
points.clear();
points.push_back(Vector2(5 * EDSCALE, move_factor.y * EDSCALE));
points.push_back(Vector2(-5 * EDSCALE, move_factor.y * EDSCALE));
points.push_back(Vector2(0, (move_factor.y + 10) * EDSCALE));
- viewport->draw_colored_polygon(points, get_theme_color("axis_y_color", "Editor"));
- viewport->draw_line(Point2(), Point2(0, move_factor.y * EDSCALE), get_theme_color("axis_y_color", "Editor"), Math::round(EDSCALE));
+ viewport->draw_colored_polygon(points, get_theme_color(SNAME("axis_y_color"), SNAME("Editor")));
+ viewport->draw_line(Point2(), Point2(0, move_factor.y * EDSCALE), get_theme_color(SNAME("axis_y_color"), SNAME("Editor")), Math::round(EDSCALE));
viewport->draw_set_transform_matrix(viewport->get_transform());
}
@@ -3380,12 +3406,12 @@ void CanvasItemEditor::_draw_selection() {
viewport->draw_set_transform_matrix(simple_xform);
Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
- viewport->draw_rect(x_handle_rect, get_theme_color("axis_x_color", "Editor"));
- viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_theme_color("axis_x_color", "Editor"), Math::round(EDSCALE));
+ viewport->draw_rect(x_handle_rect, get_theme_color(SNAME("axis_x_color"), SNAME("Editor")));
+ viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_theme_color(SNAME("axis_x_color"), SNAME("Editor")), Math::round(EDSCALE));
Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
- viewport->draw_rect(y_handle_rect, get_theme_color("axis_y_color", "Editor"));
- viewport->draw_line(Point2(), Point2(0, scale_factor.y * EDSCALE), get_theme_color("axis_y_color", "Editor"), Math::round(EDSCALE));
+ viewport->draw_rect(y_handle_rect, get_theme_color(SNAME("axis_y_color"), SNAME("Editor")));
+ viewport->draw_line(Point2(), Point2(0, scale_factor.y * EDSCALE), get_theme_color(SNAME("axis_y_color"), SNAME("Editor")), Math::round(EDSCALE));
viewport->draw_set_transform_matrix(viewport->get_transform());
}
@@ -3400,11 +3426,11 @@ void CanvasItemEditor::_draw_selection() {
viewport->draw_rect(
Rect2(bsfrom, bsto - bsfrom),
- get_theme_color("box_selection_fill_color", "Editor"));
+ get_theme_color(SNAME("box_selection_fill_color"), SNAME("Editor")));
viewport->draw_rect(
Rect2(bsfrom, bsto - bsfrom),
- get_theme_color("box_selection_stroke_color", "Editor"),
+ get_theme_color(SNAME("box_selection_stroke_color"), SNAME("Editor")),
false,
Math::round(EDSCALE));
}
@@ -3414,7 +3440,7 @@ void CanvasItemEditor::_draw_selection() {
viewport->draw_line(
transform.xform(drag_rotation_center),
transform.xform(drag_to),
- get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.6),
+ get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.6),
Math::round(2 * EDSCALE));
}
}
@@ -3462,8 +3488,8 @@ void CanvasItemEditor::_draw_straight_line(Point2 p_from, Point2 p_to, Color p_c
void CanvasItemEditor::_draw_axis() {
if (show_origin) {
- _draw_straight_line(Point2(), Point2(1, 0), get_theme_color("axis_x_color", "Editor") * Color(1, 1, 1, 0.75));
- _draw_straight_line(Point2(), Point2(0, 1), get_theme_color("axis_y_color", "Editor") * Color(1, 1, 1, 0.75));
+ _draw_straight_line(Point2(), Point2(1, 0), get_theme_color(SNAME("axis_x_color"), SNAME("Editor")) * Color(1, 1, 1, 0.75));
+ _draw_straight_line(Point2(), Point2(0, 1), get_theme_color(SNAME("axis_y_color"), SNAME("Editor")) * Color(1, 1, 1, 0.75));
}
if (show_viewport) {
@@ -3517,7 +3543,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans
Transform2D xform = transform * canvas_xform * parent_xform;
// Draw the node's position
- Ref<Texture2D> position_icon = get_theme_icon("EditorPositionUnselected", "EditorIcons");
+ Ref<Texture2D> position_icon = get_theme_icon(SNAME("EditorPositionUnselected"), SNAME("EditorIcons"));
Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
viewport->draw_set_transform_matrix(simple_xform);
@@ -3533,8 +3559,8 @@ void CanvasItemEditor::_draw_hover() {
Ref<Texture2D> node_icon = hovering_results[i].icon;
String node_name = hovering_results[i].name;
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Size2 node_name_size = font->get_string_size(node_name);
Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3));
@@ -3587,13 +3613,13 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p
if (canvas_item) {
float offset = 0;
- Ref<Texture2D> lock = get_theme_icon("LockViewport", "EditorIcons");
+ Ref<Texture2D> lock = get_theme_icon(SNAME("LockViewport"), SNAME("EditorIcons"));
if (p_node->has_meta("_edit_lock_") && show_edit_locks) {
lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
offset += lock->get_size().x;
}
- Ref<Texture2D> group = get_theme_icon("GroupViewport", "EditorIcons");
+ Ref<Texture2D> group = get_theme_icon(SNAME("GroupViewport"), SNAME("EditorIcons"));
if (canvas_item->has_meta("_edit_group_") && show_edit_locks) {
group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
//offset += group->get_size().x;
@@ -3793,7 +3819,7 @@ void CanvasItemEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_ENTER_TREE) {
- select_sb->set_texture(get_theme_icon("EditorRect2D", "EditorIcons"));
+ select_sb->set_texture(get_theme_icon(SNAME("EditorRect2D"), SNAME("EditorIcons")));
for (int i = 0; i < 4; i++) {
select_sb->set_margin_size(Side(i), 4);
select_sb->set_default_margin(Side(i), 4);
@@ -3803,92 +3829,92 @@ void CanvasItemEditor::_notification(int p_what) {
_keying_changed();
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- select_sb->set_texture(get_theme_icon("EditorRect2D", "EditorIcons"));
+ select_sb->set_texture(get_theme_icon(SNAME("EditorRect2D"), SNAME("EditorIcons")));
}
if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- select_button->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- list_select_button->set_icon(get_theme_icon("ListSelect", "EditorIcons"));
- move_button->set_icon(get_theme_icon("ToolMove", "EditorIcons"));
- scale_button->set_icon(get_theme_icon("ToolScale", "EditorIcons"));
- rotate_button->set_icon(get_theme_icon("ToolRotate", "EditorIcons"));
- smart_snap_button->set_icon(get_theme_icon("Snap", "EditorIcons"));
- grid_snap_button->set_icon(get_theme_icon("SnapGrid", "EditorIcons"));
- snap_config_menu->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
- skeleton_menu->set_icon(get_theme_icon("Bone", "EditorIcons"));
- override_camera_button->set_icon(get_theme_icon("Camera2D", "EditorIcons"));
- pan_button->set_icon(get_theme_icon("ToolPan", "EditorIcons"));
- ruler_button->set_icon(get_theme_icon("Ruler", "EditorIcons"));
- pivot_button->set_icon(get_theme_icon("EditPivot", "EditorIcons"));
- select_handle = get_theme_icon("EditorHandle", "EditorIcons");
- anchor_handle = get_theme_icon("EditorControlAnchor", "EditorIcons");
- lock_button->set_icon(get_theme_icon("Lock", "EditorIcons"));
- unlock_button->set_icon(get_theme_icon("Unlock", "EditorIcons"));
- group_button->set_icon(get_theme_icon("Group", "EditorIcons"));
- ungroup_button->set_icon(get_theme_icon("Ungroup", "EditorIcons"));
- key_loc_button->set_icon(get_theme_icon("KeyPosition", "EditorIcons"));
- key_rot_button->set_icon(get_theme_icon("KeyRotation", "EditorIcons"));
- key_scale_button->set_icon(get_theme_icon("KeyScale", "EditorIcons"));
- key_insert_button->set_icon(get_theme_icon("Key", "EditorIcons"));
- key_auto_insert_button->set_icon(get_theme_icon("AutoKey", "EditorIcons"));
+ select_button->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ list_select_button->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons")));
+ move_button->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons")));
+ scale_button->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons")));
+ rotate_button->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons")));
+ smart_snap_button->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
+ grid_snap_button->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons")));
+ snap_config_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ skeleton_menu->set_icon(get_theme_icon(SNAME("Bone"), SNAME("EditorIcons")));
+ override_camera_button->set_icon(get_theme_icon(SNAME("Camera2D"), SNAME("EditorIcons")));
+ pan_button->set_icon(get_theme_icon(SNAME("ToolPan"), SNAME("EditorIcons")));
+ ruler_button->set_icon(get_theme_icon(SNAME("Ruler"), SNAME("EditorIcons")));
+ pivot_button->set_icon(get_theme_icon(SNAME("EditPivot"), SNAME("EditorIcons")));
+ select_handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
+ anchor_handle = get_theme_icon(SNAME("EditorControlAnchor"), SNAME("EditorIcons"));
+ lock_button->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")));
+ unlock_button->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons")));
+ group_button->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons")));
+ ungroup_button->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons")));
+ key_loc_button->set_icon(get_theme_icon(SNAME("KeyPosition"), SNAME("EditorIcons")));
+ key_rot_button->set_icon(get_theme_icon(SNAME("KeyRotation"), SNAME("EditorIcons")));
+ key_scale_button->set_icon(get_theme_icon(SNAME("KeyScale"), SNAME("EditorIcons")));
+ key_insert_button->set_icon(get_theme_icon(SNAME("Key"), SNAME("EditorIcons")));
+ key_auto_insert_button->set_icon(get_theme_icon(SNAME("AutoKey"), SNAME("EditorIcons")));
// Use a different color for the active autokey icon to make them easier
// to distinguish from the other key icons at the top. On a light theme,
// the icon will be dark, so we need to lighten it before blending it
// with the red color.
const Color key_auto_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25);
key_auto_insert_button->add_theme_color_override("icon_pressed_color", key_auto_color.lerp(Color(1, 0, 0), 0.55));
- animation_menu->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
+ animation_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- presets_menu->set_icon(get_theme_icon("ControlLayout", "EditorIcons"));
+ presets_menu->set_icon(get_theme_icon(SNAME("ControlLayout"), SNAME("EditorIcons")));
PopupMenu *p = presets_menu->get_popup();
p->clear();
- p->add_icon_item(get_theme_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT);
- p->add_icon_item(get_theme_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT);
- p->add_icon_item(get_theme_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT);
- p->add_icon_item(get_theme_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignTopLeft"), SNAME("EditorIcons")), TTR("Top Left"), ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignTopRight"), SNAME("EditorIcons")), TTR("Top Right"), ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomRight"), SNAME("EditorIcons")), TTR("Bottom Right"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomLeft"), SNAME("EditorIcons")), TTR("Bottom Left"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT);
p->add_separator();
- p->add_icon_item(get_theme_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT);
- p->add_icon_item(get_theme_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP);
- p->add_icon_item(get_theme_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT);
- p->add_icon_item(get_theme_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM);
- p->add_icon_item(get_theme_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_AND_OFFSETS_PRESET_CENTER);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignLeftCenter"), SNAME("EditorIcons")), TTR("Center Left"), ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignTopCenter"), SNAME("EditorIcons")), TTR("Center Top"), ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignRightCenter"), SNAME("EditorIcons")), TTR("Center Right"), ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomCenter"), SNAME("EditorIcons")), TTR("Center Bottom"), ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")), TTR("Center"), ANCHORS_AND_OFFSETS_PRESET_CENTER);
p->add_separator();
- p->add_icon_item(get_theme_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE);
- p->add_icon_item(get_theme_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE);
- p->add_icon_item(get_theme_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE);
- p->add_icon_item(get_theme_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE);
- p->add_icon_item(get_theme_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE);
- p->add_icon_item(get_theme_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignLeftWide"), SNAME("EditorIcons")), TTR("Left Wide"), ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignTopWide"), SNAME("EditorIcons")), TTR("Top Wide"), ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignRightWide"), SNAME("EditorIcons")), TTR("Right Wide"), ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomWide"), SNAME("EditorIcons")), TTR("Bottom Wide"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("ControlVcenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("ControlHcenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE);
p->add_separator();
- p->add_icon_item(get_theme_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_WIDE);
- p->add_icon_item(get_theme_icon("Anchor", "EditorIcons"), TTR("Keep Ratio"), ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")), TTR("Keep Ratio"), ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO);
p->add_separator();
p->add_submenu_item(TTR("Anchors only"), "Anchors");
- p->set_item_icon(21, get_theme_icon("Anchor", "EditorIcons"));
+ p->set_item_icon(21, get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")));
anchors_popup->clear();
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_PRESET_TOP_LEFT);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_PRESET_TOP_RIGHT);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_PRESET_BOTTOM_RIGHT);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_PRESET_BOTTOM_LEFT);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignTopLeft"), SNAME("EditorIcons")), TTR("Top Left"), ANCHORS_PRESET_TOP_LEFT);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignTopRight"), SNAME("EditorIcons")), TTR("Top Right"), ANCHORS_PRESET_TOP_RIGHT);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomRight"), SNAME("EditorIcons")), TTR("Bottom Right"), ANCHORS_PRESET_BOTTOM_RIGHT);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomLeft"), SNAME("EditorIcons")), TTR("Bottom Left"), ANCHORS_PRESET_BOTTOM_LEFT);
anchors_popup->add_separator();
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_PRESET_CENTER_LEFT);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_PRESET_CENTER_TOP);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_PRESET_CENTER_RIGHT);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_PRESET_CENTER_BOTTOM);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_PRESET_CENTER);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignLeftCenter"), SNAME("EditorIcons")), TTR("Center Left"), ANCHORS_PRESET_CENTER_LEFT);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignTopCenter"), SNAME("EditorIcons")), TTR("Center Top"), ANCHORS_PRESET_CENTER_TOP);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignRightCenter"), SNAME("EditorIcons")), TTR("Center Right"), ANCHORS_PRESET_CENTER_RIGHT);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomCenter"), SNAME("EditorIcons")), TTR("Center Bottom"), ANCHORS_PRESET_CENTER_BOTTOM);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")), TTR("Center"), ANCHORS_PRESET_CENTER);
anchors_popup->add_separator();
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_PRESET_LEFT_WIDE);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_PRESET_TOP_WIDE);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_PRESET_RIGHT_WIDE);
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_PRESET_BOTTOM_WIDE);
- anchors_popup->add_icon_item(get_theme_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE);
- anchors_popup->add_icon_item(get_theme_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignLeftWide"), SNAME("EditorIcons")), TTR("Left Wide"), ANCHORS_PRESET_LEFT_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignTopWide"), SNAME("EditorIcons")), TTR("Top Wide"), ANCHORS_PRESET_TOP_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignRightWide"), SNAME("EditorIcons")), TTR("Right Wide"), ANCHORS_PRESET_RIGHT_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomWide"), SNAME("EditorIcons")), TTR("Bottom Wide"), ANCHORS_PRESET_BOTTOM_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlVcenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlHcenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE);
anchors_popup->add_separator();
- anchors_popup->add_icon_item(get_theme_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_PRESET_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_WIDE);
- anchor_mode_button->set_icon(get_theme_icon("Anchor", "EditorIcons"));
+ anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")));
}
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
@@ -4242,7 +4268,7 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), p_on_existing);
}
if (key_rot && p_rotation) {
- AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "rotation_degrees", Math::rad2deg(n2d->get_rotation()), p_on_existing);
+ AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "rotation", n2d->get_rotation(), p_on_existing);
}
if (key_scale && p_scale) {
AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), p_on_existing);
@@ -4274,7 +4300,7 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), p_on_existing);
}
if (key_rot) {
- AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "rotation_degrees", Math::rad2deg(F->get()->get_rotation()), p_on_existing);
+ AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "rotation", F->get()->get_rotation(), p_on_existing);
}
if (key_scale) {
AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), p_on_existing);
@@ -4290,7 +4316,7 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing);
}
if (key_rot) {
- AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_degrees(), p_on_existing);
+ AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation(), p_on_existing);
}
if (key_scale) {
AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing);
@@ -4317,11 +4343,11 @@ void CanvasItemEditor::_button_toggle_anchor_mode(bool p_status) {
void CanvasItemEditor::_update_override_camera_button(bool p_game_running) {
if (p_game_running) {
override_camera_button->set_disabled(false);
- override_camera_button->set_tooltip(TTR("Game Camera Override\nOverrides game camera with editor viewport camera."));
+ override_camera_button->set_tooltip(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera."));
} else {
override_camera_button->set_disabled(true);
override_camera_button->set_pressed(false);
- override_camera_button->set_tooltip(TTR("Game Camera Override\nNo game instance running."));
+ override_camera_button->set_tooltip(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature."));
}
}
@@ -4873,7 +4899,7 @@ void CanvasItemEditor::_focus_selection(int p_op) {
zoom *= 0.90;
viewport->update();
zoom_widget->set_zoom(zoom);
- call_deferred("_popup_callback", VIEW_CENTER_TO_SELECTION);
+ call_deferred(SNAME("_popup_callback"), VIEW_CENTER_TO_SELECTION);
}
}
}
@@ -5199,8 +5225,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
editor->get_scene_tree_dock()->connect("node_created", callable_mp(this, &CanvasItemEditor::_node_created));
editor->get_scene_tree_dock()->connect("add_node_used", callable_mp(this, &CanvasItemEditor::_reset_create_position));
- editor->call_deferred("connect", "play_pressed", Callable(this, "_update_override_camera_button"), make_binds(true));
- editor->call_deferred("connect", "stop_pressed", Callable(this, "_update_override_camera_button"), make_binds(false));
+ editor->call_deferred(SNAME("connect"), "play_pressed", Callable(this, "_update_override_camera_button"), make_binds(true));
+ editor->call_deferred(SNAME("connect"), "stop_pressed", Callable(this, "_update_override_camera_button"), make_binds(false));
hb = memnew(HBoxContainer);
add_child(hb);
@@ -5260,9 +5286,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
warning_child_of_container = memnew(Label);
warning_child_of_container->hide();
warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent."));
- warning_child_of_container->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor"));
- warning_child_of_container->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
- warning_child_of_container->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
+ warning_child_of_container->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ warning_child_of_container->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts")));
+ warning_child_of_container->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")));
add_control_to_info_overlay(warning_child_of_container);
h_scroll = memnew(HScrollBar);
@@ -5299,7 +5325,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
select_button->set_pressed(true);
select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q));
select_button->set_shortcut_context(this);
- select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection"));
+ select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
hb->add_child(memnew(VSeparator));
@@ -5337,7 +5363,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(list_select_button);
list_select_button->set_toggle_mode(true);
list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_LIST_SELECT));
- list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
+ list_select_button->set_tooltip(TTR("Show list of selectable nodes at position clicked."));
pivot_button = memnew(Button);
pivot_button->set_flat(true);
@@ -5422,25 +5448,33 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(lock_button);
lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(LOCK_SELECTED));
- lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved)."));
+ lock_button->set_tooltip(TTR("Lock selected node, preventing selection and movement."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L));
unlock_button = memnew(Button);
unlock_button->set_flat(true);
hb->add_child(unlock_button);
unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNLOCK_SELECTED));
- unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved)."));
+ unlock_button->set_tooltip(TTR("Unlock selected node, allowing selection and movement."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L));
group_button = memnew(Button);
group_button->set_flat(true);
hb->add_child(group_button);
group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(GROUP_SELECTED));
group_button->set_tooltip(TTR("Makes sure the object's children are not selectable."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G));
ungroup_button = memnew(Button);
ungroup_button->set_flat(true);
hb->add_child(ungroup_button);
ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNGROUP_SELECTED));
ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G));
hb->add_child(memnew(VSeparator));
@@ -5478,7 +5512,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p = view_menu->get_popup();
p->set_hide_on_checkable_item_selection(false);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_MASK_CTRL | KEY_G), SHOW_GRID);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_NUMBERSIGN), SHOW_GRID);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES);
@@ -5591,8 +5625,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
add_node_menu = memnew(PopupMenu);
add_child(add_node_menu);
- add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon("Add", "EditorIcons"), TTR("Add Node Here"));
- add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon("Instance", "EditorIcons"), TTR("Instance Scene Here"));
+ add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), TTR("Add Node Here"));
+ add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instance Scene Here"));
add_node_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_add_node_pressed));
multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
@@ -5602,10 +5636,25 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true);
singleton = this;
+ // To ensure that scripts can parse the list of shortcuts correctly, we have to define
+ // those shortcuts one by one.
+ // Resetting zoom to 100% is a duplicate shortcut of `canvas_item_editor/reset_zoom`,
+ // but it ensures both 1 and Ctrl + 0 can be used to reset zoom.
+ ED_SHORTCUT("canvas_item_editor/zoom_3.125_percent", TTR("Zoom to 3.125%"), KEY_MASK_SHIFT | KEY_5);
+ ED_SHORTCUT("canvas_item_editor/zoom_6.25_percent", TTR("Zoom to 6.25%"), KEY_MASK_SHIFT | KEY_4);
+ ED_SHORTCUT("canvas_item_editor/zoom_12.5_percent", TTR("Zoom to 12.5%"), KEY_MASK_SHIFT | KEY_3);
+ ED_SHORTCUT("canvas_item_editor/zoom_25_percent", TTR("Zoom to 25%"), KEY_MASK_SHIFT | KEY_2);
+ ED_SHORTCUT("canvas_item_editor/zoom_50_percent", TTR("Zoom to 50%"), KEY_MASK_SHIFT | KEY_1);
+ ED_SHORTCUT("canvas_item_editor/zoom_100_percent", TTR("Zoom to 100%"), KEY_1);
+ ED_SHORTCUT("canvas_item_editor/zoom_200_percent", TTR("Zoom to 200%"), KEY_2);
+ ED_SHORTCUT("canvas_item_editor/zoom_400_percent", TTR("Zoom to 400%"), KEY_3);
+ ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom to 800%"), KEY_4);
+ ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom to 1600%"), KEY_5);
+
set_process_unhandled_key_input(true);
// Update the menus' checkboxes
- call_deferred("set_state", get_state());
+ call_deferred(SNAME("set_state"), get_state());
}
CanvasItemEditor *CanvasItemEditor::singleton = nullptr;
@@ -5623,12 +5672,12 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
canvas_item_editor->show();
canvas_item_editor->set_physics_process(true);
- RenderingServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false);
+ RenderingServer::get_singleton()->viewport_set_disable_2d(editor->get_scene_root()->get_viewport_rid(), false);
} else {
canvas_item_editor->hide();
canvas_item_editor->set_physics_process(false);
- RenderingServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), true);
+ RenderingServer::get_singleton()->viewport_set_disable_2d(editor->get_scene_root()->get_viewport_rid(), true);
}
}
@@ -6041,7 +6090,7 @@ void CanvasItemEditorViewport::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
connect("mouse_exited", callable_mp(this, &CanvasItemEditorViewport::_on_mouse_exit));
- label->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"));
+ label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
} break;
case NOTIFICATION_EXIT_TREE: {
disconnect("mouse_exited", callable_mp(this, &CanvasItemEditorViewport::_on_mouse_exit));
diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp
index 7873c1b136..5d5f78e0dc 100644
--- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp
@@ -42,8 +42,8 @@
void CollisionPolygon3DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- button_create->set_icon(get_theme_icon("Edit", "EditorIcons"));
- button_edit->set_icon(get_theme_icon("MovePoint", "EditorIcons"));
+ button_create->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ button_edit->set_icon(get_theme_icon(SNAME("MovePoint"), SNAME("EditorIcons")));
button_edit->set_pressed(true);
get_tree()->connect("node_removed", callable_mp(this, &CollisionPolygon3DEditor::_node_removed));
@@ -358,9 +358,9 @@ void CollisionPolygon3DEditor::_polygon_draw() {
float depth = _get_depth() * 0.5;
- imgeom->clear();
+ imesh->clear_surfaces();
imgeom->set_material_override(line_material);
- imgeom->begin(Mesh::PRIMITIVE_LINES, Ref<Texture2D>());
+ imesh->surface_begin(Mesh::PRIMITIVE_LINES);
Rect2 rect;
@@ -382,10 +382,10 @@ void CollisionPolygon3DEditor::_polygon_draw() {
Vector3 point = Vector3(p.x, p.y, depth);
Vector3 next_point = Vector3(p2.x, p2.y, depth);
- imgeom->set_color(Color(1, 0.3, 0.1, 0.8));
- imgeom->add_vertex(point);
- imgeom->set_color(Color(1, 0.3, 0.1, 0.8));
- imgeom->add_vertex(next_point);
+ imesh->surface_set_color(Color(1, 0.3, 0.1, 0.8));
+ imesh->surface_add_vertex(point);
+ imesh->surface_set_color(Color(1, 0.3, 0.1, 0.8));
+ imesh->surface_add_vertex(next_point);
//Color col=Color(1,0.3,0.1,0.8);
//vpc->draw_line(point,next_point,col,2);
@@ -402,45 +402,43 @@ void CollisionPolygon3DEditor::_polygon_draw() {
r.size.y = rect.size.y;
r.size.z = 0;
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position);
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(0.3, 0, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position);
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(0.0, 0.3, 0));
-
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0));
-
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0));
-
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + r.size);
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + r.size - Vector3(0.3, 0, 0));
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + r.size);
- imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2));
- imgeom->add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0));
-
- imgeom->end();
-
- m->clear_surfaces();
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position);
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(0.3, 0, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position);
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(0.0, 0.3, 0));
+
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0));
+
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0));
+
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + r.size);
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + r.size - Vector3(0.3, 0, 0));
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + r.size);
+ imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
+ imesh->surface_add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0));
+
+ imesh->surface_end();
if (poly.size() == 0) {
return;
@@ -515,7 +513,9 @@ CollisionPolygon3DEditor::CollisionPolygon3DEditor(EditorNode *p_editor) {
mode = MODE_EDIT;
wip_active = false;
- imgeom = memnew(ImmediateGeometry3D);
+ imgeom = memnew(MeshInstance3D);
+ imesh.instantiate();
+ imgeom->set_mesh(imesh);
imgeom->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
@@ -531,7 +531,7 @@ CollisionPolygon3DEditor::CollisionPolygon3DEditor(EditorNode *p_editor) {
handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- Ref<Texture2D> handle = editor->get_gui_base()->get_theme_icon("Editor3DHandle", "EditorIcons");
+ Ref<Texture2D> handle = editor->get_gui_base()->get_theme_icon(SNAME("Editor3DHandle"), SNAME("EditorIcons"));
handle_material->set_point_size(handle->get_width());
handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle);
diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.h b/editor/plugins/collision_polygon_3d_editor_plugin.h
index c66518e3e5..5db0f7308a 100644
--- a/editor/plugins/collision_polygon_3d_editor_plugin.h
+++ b/editor/plugins/collision_polygon_3d_editor_plugin.h
@@ -34,8 +34,8 @@
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "scene/3d/collision_polygon_3d.h"
-#include "scene/3d/immediate_geometry_3d.h"
#include "scene/3d/mesh_instance_3d.h"
+#include "scene/resources/immediate_mesh.h"
class CanvasItemEditor;
@@ -60,7 +60,8 @@ class CollisionPolygon3DEditor : public HBoxContainer {
EditorNode *editor;
Panel *panel;
Node3D *node;
- ImmediateGeometry3D *imgeom;
+ Ref<ImmediateMesh> imesh;
+ MeshInstance3D *imgeom;
MeshInstance3D *pointsm;
Ref<ArrayMesh> m;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index c38458c37f..45adbe29de 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -430,7 +430,7 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla
Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture2D> h = get_theme_icon("EditorHandle", "EditorIcons");
+ Ref<Texture2D> h = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
Vector2 size = h->get_size() * 0.5;
handles.clear();
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index 6a56cd31d1..c4deb296fb 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -224,7 +224,7 @@ void CPUParticles2DEditorPlugin::_generate_emission_mask() {
void CPUParticles2DEditorPlugin::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
menu->get_popup()->connect("id_pressed", callable_mp(this, &CPUParticles2DEditorPlugin::_menu_callback));
- menu->set_icon(epoints->get_theme_icon("CPUParticles2D", "EditorIcons"));
+ menu->set_icon(epoints->get_theme_icon(SNAME("CPUParticles2D"), SNAME("EditorIcons")));
file->connect("file_selected", callable_mp(this, &CPUParticles2DEditorPlugin::_file_selected));
}
}
diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.cpp b/editor/plugins/cpu_particles_3d_editor_plugin.cpp
index f41ccfa86b..fc52cd0f99 100644
--- a/editor/plugins/cpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_3d_editor_plugin.cpp
@@ -41,7 +41,7 @@ void CPUParticles3DEditor::_node_removed(Node *p_node) {
void CPUParticles3DEditor::_notification(int p_notification) {
if (p_notification == NOTIFICATION_ENTER_TREE) {
- options->set_icon(get_theme_icon("CPUParticles3D", "EditorIcons"));
+ options->set_icon(get_theme_icon(SNAME("CPUParticles3D"), SNAME("EditorIcons")));
}
}
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 706243fe25..07ff0eb346 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -393,7 +393,8 @@ int CurveEditor::get_point_at(Vector2 pos) const {
}
const Curve &curve = **_curve_ref;
- const float r = _hover_radius * _hover_radius;
+ const float true_hover_radius = Math::round(_hover_radius * EDSCALE);
+ const float r = true_hover_radius * true_hover_radius;
for (int i = 0; i < curve.get_point_count(); ++i) {
Vector2 p = get_view_pos(curve.get_point_position(i));
@@ -519,8 +520,8 @@ void CurveEditor::set_hover_point_index(int index) {
}
void CurveEditor::update_view_transform() {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
const real_t margin = font->get_height(font_size) + 2 * EDSCALE;
@@ -558,7 +559,7 @@ Vector2 CurveEditor::get_tangent_view_pos(int i, TangentIndex tangent) const {
Vector2 point_pos = get_view_pos(_curve_ref->get_point_position(i));
Vector2 control_pos = get_view_pos(_curve_ref->get_point_position(i) + dir);
- return point_pos + _tangents_length * (control_pos - point_pos).normalized();
+ return point_pos + Math::round(_tangents_length * EDSCALE) * (control_pos - point_pos).normalized();
}
Vector2 CurveEditor::get_view_pos(Vector2 world_pos) const {
@@ -635,7 +636,7 @@ void CurveEditor::_draw() {
// Background
Vector2 view_size = get_rect().size;
- draw_style_box(get_theme_stylebox("bg", "Tree"), Rect2(Point2(), view_size));
+ draw_style_box(get_theme_stylebox(SNAME("bg"), SNAME("Tree")), Rect2(Point2(), view_size));
// Grid
@@ -644,8 +645,8 @@ void CurveEditor::_draw() {
Vector2 min_edge = get_world_pos(Vector2(0, view_size.y));
Vector2 max_edge = get_world_pos(Vector2(view_size.x, 0));
- const Color grid_color0 = get_theme_color("mono_color", "Editor") * Color(1, 1, 1, 0.15);
- const Color grid_color1 = get_theme_color("mono_color", "Editor") * Color(1, 1, 1, 0.07);
+ const Color grid_color0 = get_theme_color(SNAME("mono_color"), SNAME("Editor")) * Color(1, 1, 1, 0.15);
+ const Color grid_color1 = get_theme_color(SNAME("mono_color"), SNAME("Editor")) * Color(1, 1, 1, 0.07);
draw_line(Vector2(min_edge.x, curve.get_min_value()), Vector2(max_edge.x, curve.get_min_value()), grid_color0);
draw_line(Vector2(max_edge.x, curve.get_max_value()), Vector2(min_edge.x, curve.get_max_value()), grid_color0);
draw_line(Vector2(0, min_edge.y), Vector2(0, max_edge.y), grid_color0);
@@ -665,10 +666,10 @@ void CurveEditor::_draw() {
draw_set_transform_matrix(Transform2D());
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
float font_height = font->get_height(font_size);
- Color text_color = get_theme_color("font_color", "Editor");
+ Color text_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
{
// X axis
@@ -695,7 +696,7 @@ void CurveEditor::_draw() {
// Draw tangents for current point
if (_selected_point >= 0) {
- const Color tangent_color = get_theme_color("accent_color", "Editor");
+ const Color tangent_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
int i = _selected_point;
Vector2 pos = curve.get_point_position(i);
@@ -703,13 +704,13 @@ void CurveEditor::_draw() {
if (i != 0) {
Vector2 control_pos = get_tangent_view_pos(i, TANGENT_LEFT);
draw_line(get_view_pos(pos), control_pos, tangent_color, Math::round(EDSCALE));
- draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color);
+ draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(Math::round(2 * EDSCALE)), tangent_color);
}
if (i != curve.get_point_count() - 1) {
Vector2 control_pos = get_tangent_view_pos(i, TANGENT_RIGHT);
draw_line(get_view_pos(pos), control_pos, tangent_color, Math::round(EDSCALE));
- draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color);
+ draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(Math::round(2 * EDSCALE)), tangent_color);
}
}
@@ -717,8 +718,8 @@ void CurveEditor::_draw() {
draw_set_transform_matrix(_world_to_view);
- const Color line_color = get_theme_color("font_color", "Editor");
- const Color edge_line_color = get_theme_color("highlight_color", "Editor");
+ const Color line_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
+ const Color edge_line_color = get_theme_color(SNAME("highlight_color"), SNAME("Editor"));
CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color);
plot_curve_accurate(curve, 4.f / view_size.x, plot_func);
@@ -727,12 +728,12 @@ void CurveEditor::_draw() {
draw_set_transform_matrix(Transform2D());
- const Color point_color = get_theme_color("font_color", "Editor");
- const Color selected_point_color = get_theme_color("accent_color", "Editor");
+ const Color point_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
+ const Color selected_point_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (int i = 0; i < curve.get_point_count(); ++i) {
Vector2 pos = curve.get_point_position(i);
- draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(3), i == _selected_point ? selected_point_color : point_color);
+ draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(Math::round(3 * EDSCALE)), i == _selected_point ? selected_point_color : point_color);
// TODO Circles are prettier. Needs a fix! Or a texture
//draw_circle(pos, 2, point_color);
}
@@ -742,7 +743,7 @@ void CurveEditor::_draw() {
if (_hover_point != -1) {
const Color hover_color = line_color;
Vector2 pos = curve.get_point_position(_hover_point);
- draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(_hover_radius), hover_color, false, Math::round(EDSCALE));
+ draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(Math::round(_hover_radius * EDSCALE)), hover_color, false, Math::round(EDSCALE));
}
// Help text
diff --git a/editor/plugins/editor_debugger_plugin.cpp b/editor/plugins/editor_debugger_plugin.cpp
index 85114d88ae..89073b7189 100644
--- a/editor/plugins/editor_debugger_plugin.cpp
+++ b/editor/plugins/editor_debugger_plugin.cpp
@@ -34,18 +34,18 @@
void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug) {
if (p_really_did) {
- emit_signal("breaked", p_can_debug);
+ emit_signal(SNAME("breaked"), p_can_debug);
} else {
- emit_signal("continued");
+ emit_signal(SNAME("continued"));
}
}
void EditorDebuggerPlugin::_started() {
- emit_signal("started");
+ emit_signal(SNAME("started"));
}
void EditorDebuggerPlugin::_stopped() {
- emit_signal("stopped");
+ emit_signal(SNAME("stopped"));
}
void EditorDebuggerPlugin::_bind_methods() {
diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp
index 9b0af37abb..22c9cc9ab1 100644
--- a/editor/plugins/font_editor_plugin.cpp
+++ b/editor/plugins/font_editor_plugin.cpp
@@ -34,7 +34,7 @@
void FontDataPreview::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Color text_color = get_theme_color("font_color", "Label");
+ Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color line_color = text_color;
line_color.a *= 0.6;
Vector2 pos = (get_size() - line->get_size()) / 2;
@@ -127,7 +127,7 @@ FontDataPreview::FontDataPreview() {
void FontDataEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_SORT_CHILDREN) {
int split_width = get_name_split_ratio() * get_size().width;
- button->set_size(Size2(get_theme_icon("Add", "EditorIcons")->get_width(), get_size().height));
+ button->set_size(Size2(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))->get_width(), get_size().height));
if (is_layout_rtl()) {
if (le != nullptr) {
fit_child_in_rect(le, Rect2(Vector2(split_width, 0), Size2(split_width, get_size().height)));
@@ -145,7 +145,7 @@ void FontDataEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_DRAW) {
int split_width = get_name_split_ratio() * get_size().width;
- Color dark_color = get_theme_color("dark_color_2", "Editor");
+ Color dark_color = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
if (is_layout_rtl()) {
draw_rect(Rect2(Vector2(0, 0), Size2(split_width, get_size().height)), dark_color);
} else {
@@ -154,9 +154,9 @@ void FontDataEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_THEME_CHANGED) {
if (le != nullptr) {
- button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} else {
- button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
}
queue_sort();
}
@@ -187,12 +187,12 @@ void FontDataEditor::init_lang_add() {
le->set_editable(true);
add_child(le);
- button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
button->connect("pressed", callable_mp(this, &FontDataEditor::add_lang));
}
void FontDataEditor::init_lang_edit() {
- button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
button->connect("pressed", callable_mp(this, &FontDataEditor::remove_lang));
chk->connect("toggled", callable_mp(this, &FontDataEditor::toggle_lang));
}
@@ -204,12 +204,12 @@ void FontDataEditor::init_script_add() {
le->set_editable(true);
add_child(le);
- button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
button->connect("pressed", callable_mp(this, &FontDataEditor::add_script));
}
void FontDataEditor::init_script_edit() {
- button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
button->connect("pressed", callable_mp(this, &FontDataEditor::remove_script));
chk->connect("toggled", callable_mp(this, &FontDataEditor::toggle_script));
}
@@ -290,7 +290,7 @@ void EditorInspectorPluginFont::parse_begin(Object *p_object) {
add_custom_control(editor);
}
-bool EditorInspectorPluginFont::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+bool EditorInspectorPluginFont::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) {
if (p_path.begins_with("language_support_override/") && p_object->is_class("FontData")) {
String lang = p_path.replace("language_support_override/", "");
diff --git a/editor/plugins/font_editor_plugin.h b/editor/plugins/font_editor_plugin.h
index 04e6c1dac7..71464003a0 100644
--- a/editor/plugins/font_editor_plugin.h
+++ b/editor/plugins/font_editor_plugin.h
@@ -94,7 +94,7 @@ class EditorInspectorPluginFont : public EditorInspectorPlugin {
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
- virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) override;
+ virtual bool 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 = false) override;
};
/*************************************************************************/
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 37f900280b..cc5793a1f9 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -329,7 +329,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() {
void GPUParticles2DEditorPlugin::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
menu->get_popup()->connect("id_pressed", callable_mp(this, &GPUParticles2DEditorPlugin::_menu_callback));
- menu->set_icon(menu->get_theme_icon("GPUParticles2D", "EditorIcons"));
+ menu->set_icon(menu->get_theme_icon(SNAME("GPUParticles2D"), SNAME("EditorIcons")));
file->connect("file_selected", callable_mp(this, &GPUParticles2DEditorPlugin::_file_selected));
}
}
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 571bcf9c4a..8576082597 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -230,7 +230,7 @@ void GPUParticles3DEditor::_node_removed(Node *p_node) {
void GPUParticles3DEditor::_notification(int p_notification) {
if (p_notification == NOTIFICATION_ENTER_TREE) {
- options->set_icon(options->get_popup()->get_theme_icon("GPUParticles3D", "EditorIcons"));
+ options->set_icon(options->get_popup()->get_theme_icon(SNAME("GPUParticles3D"), SNAME("EditorIcons")));
get_tree()->connect("node_removed", callable_mp(this, &GPUParticles3DEditor::_node_removed));
}
}
diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
index a2dee4a1dc..a4436525fb 100644
--- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
@@ -83,13 +83,13 @@ void GPUParticlesCollisionSDFEditorPlugin::_notification(int p_what) {
Color color;
if (size_mb <= 16.0 + CMP_EPSILON) {
// Fast.
- color = bake_info->get_theme_color("success_color", "Editor");
+ color = bake_info->get_theme_color(SNAME("success_color"), SNAME("Editor"));
} else if (size_mb <= 64.0 + CMP_EPSILON) {
// Medium.
- color = bake_info->get_theme_color("warning_color", "Editor");
+ color = bake_info->get_theme_color(SNAME("warning_color"), SNAME("Editor"));
} else {
// Slow.
- color = bake_info->get_theme_color("error_color", "Editor");
+ color = bake_info->get_theme_color(SNAME("error_color"), SNAME("Editor"));
}
bake_info->add_theme_color_override("font_color", color);
@@ -131,7 +131,7 @@ void GPUParticlesCollisionSDFEditorPlugin::_sdf_save_path_and_bake(const String
if (col_sdf) {
Ref<Image> bake_img = col_sdf->bake();
if (bake_img.is_null()) {
- EditorNode::get_singleton()->show_warning("Bake Error.");
+ EditorNode::get_singleton()->show_warning(TTR("Bake Error."));
return;
}
@@ -174,7 +174,7 @@ GPUParticlesCollisionSDFEditorPlugin::GPUParticlesCollisionSDFEditorPlugin(Edito
bake_hb->hide();
bake = memnew(Button);
bake->set_flat(true);
- bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
+ bake->set_icon(editor->get_gui_base()->get_theme_icon(SNAME("Bake"), SNAME("EditorIcons")));
bake->set_text(TTR("Bake SDF"));
bake->connect("pressed", callable_mp(this, &GPUParticlesCollisionSDFEditorPlugin::_bake));
bake_hb->add_child(bake);
diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp
new file mode 100644
index 0000000000..d3d2de92f5
--- /dev/null
+++ b/editor/plugins/input_event_editor_plugin.cpp
@@ -0,0 +1,122 @@
+/*************************************************************************/
+/* input_event_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "input_event_editor_plugin.h"
+
+void InputEventConfigContainer::_bind_methods() {
+}
+
+void InputEventConfigContainer::_configure_pressed() {
+ config_dialog->popup_and_configure(input_event);
+}
+
+void InputEventConfigContainer::_event_changed() {
+ input_event_text->set_text(input_event->as_text());
+}
+
+void InputEventConfigContainer::_config_dialog_confirmed() {
+ Ref<InputEvent> ie = config_dialog->get_event();
+ input_event->copy_from(ie);
+ _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;
+ Ref<InputEventJoypadButton> jb = p_event;
+ Ref<InputEventJoypadMotion> jm = p_event;
+
+ if (k.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_KEY);
+ } else if (m.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_MOUSE_BUTTON);
+ } else if (jb.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_JOY_BUTTON);
+ } else if (jm.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_JOY_MOTION);
+ }
+
+ input_event = p_event;
+ _event_changed();
+ input_event->connect("changed", callable_mp(this, &InputEventConfigContainer::_event_changed));
+}
+
+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);
+
+ 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);
+
+ input_event_text = memnew(Label);
+ hb->add_child(input_event_text);
+
+ 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);
+ Ref<InputEventJoypadButton> jb = Ref<InputEventJoypadButton>(p_object);
+ Ref<InputEventJoypadMotion> jm = Ref<InputEventJoypadMotion>(p_object);
+
+ return k.is_valid() || m.is_valid() || jb.is_valid() || jm.is_valid();
+}
+
+void EditorInspectorPluginInputEvent::parse_begin(Object *p_object) {
+ Ref<InputEvent> ie = Ref<InputEvent>(p_object);
+
+ InputEventConfigContainer *picker_controls = memnew(InputEventConfigContainer);
+ picker_controls->set_event(ie);
+ add_custom_control(picker_controls);
+}
+
+InputEventEditorPlugin::InputEventEditorPlugin(EditorNode *p_node) {
+ Ref<EditorInspectorPluginInputEvent> plugin;
+ plugin.instantiate();
+ add_inspector_plugin(plugin);
+}
diff --git a/editor/plugins/input_event_editor_plugin.h b/editor/plugins/input_event_editor_plugin.h
new file mode 100644
index 0000000000..bc8293c9e5
--- /dev/null
+++ b/editor/plugins/input_event_editor_plugin.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* input_event_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef INPUT_EVENT_EDITOR_PLUGIN_H
+#define INPUT_EVENT_EDITOR_PLUGIN_H
+
+#include "editor/action_map_editor.h"
+#include "editor/editor_inspector.h"
+#include "editor/editor_node.h"
+
+class InputEventConfigContainer : public HBoxContainer {
+ GDCLASS(InputEventConfigContainer, HBoxContainer);
+
+ Label *input_event_text;
+ Button *open_config_button;
+
+ Ref<InputEvent> input_event;
+ InputEventConfigurationDialog *config_dialog;
+
+ void _config_dialog_confirmed();
+ void _configure_pressed();
+
+ void _event_changed();
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Size2 get_minimum_size() const override;
+ void set_event(const Ref<InputEvent> &p_event);
+
+ InputEventConfigContainer();
+};
+
+class EditorInspectorPluginInputEvent : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginInputEvent, EditorInspectorPlugin);
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class InputEventEditorPlugin : public EditorPlugin {
+ GDCLASS(InputEventEditorPlugin, EditorPlugin);
+
+public:
+ virtual String get_name() const override { return "InputEvent"; }
+
+ InputEventEditorPlugin(EditorNode *p_node);
+};
+
+#endif // INPUT_EVENT_EDITOR_PLUGIN_H
diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp
index 1ea6630622..3207a989bd 100644
--- a/editor/plugins/item_list_editor_plugin.cpp
+++ b/editor/plugins/item_list_editor_plugin.cpp
@@ -243,8 +243,8 @@ void ItemListEditor::_node_removed(Node *p_node) {
void ItemListEditor::_notification(int p_notification) {
if (p_notification == NOTIFICATION_ENTER_TREE || p_notification == NOTIFICATION_THEME_CHANGED) {
- add_button->set_icon(get_theme_icon("Add", "EditorIcons"));
- del_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ del_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
} else if (p_notification == NOTIFICATION_READY) {
get_tree()->connect("node_removed", callable_mp(this, &ItemListEditor::_node_removed));
}
diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp
index 484fdabfe1..b4a70cd31d 100644
--- a/editor/plugins/lightmap_gi_editor_plugin.cpp
+++ b/editor/plugins/lightmap_gi_editor_plugin.cpp
@@ -119,7 +119,7 @@ LightmapGIEditorPlugin::LightmapGIEditorPlugin(EditorNode *p_node) {
editor = p_node;
bake = memnew(Button);
bake->set_flat(true);
- bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
+ bake->set_icon(editor->get_gui_base()->get_theme_icon(SNAME("Bake"), SNAME("EditorIcons")));
bake->set_text(TTR("Bake Lightmaps"));
bake->hide();
bake->connect("pressed", Callable(this, "_bake"));
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 17a634ee14..7105d351b0 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -42,22 +42,22 @@ void MaterialEditor::_notification(int p_what) {
if (first_enter) {
//it's in propertyeditor so.. could be moved around
- light_1_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight1", "EditorIcons"));
- light_1_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight1Off", "EditorIcons"));
- light_2_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight2", "EditorIcons"));
- light_2_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight2Off", "EditorIcons"));
+ light_1_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight1"), SNAME("EditorIcons")));
+ light_1_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight1Off"), SNAME("EditorIcons")));
+ light_2_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight2"), SNAME("EditorIcons")));
+ light_2_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight2Off"), SNAME("EditorIcons")));
- sphere_switch->set_normal_texture(get_theme_icon("MaterialPreviewSphereOff", "EditorIcons"));
- sphere_switch->set_pressed_texture(get_theme_icon("MaterialPreviewSphere", "EditorIcons"));
- box_switch->set_normal_texture(get_theme_icon("MaterialPreviewCubeOff", "EditorIcons"));
- box_switch->set_pressed_texture(get_theme_icon("MaterialPreviewCube", "EditorIcons"));
+ sphere_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewSphereOff"), SNAME("EditorIcons")));
+ sphere_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewSphere"), SNAME("EditorIcons")));
+ box_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewCubeOff"), SNAME("EditorIcons")));
+ box_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewCube"), SNAME("EditorIcons")));
first_enter = false;
}
}
if (p_what == NOTIFICATION_DRAW) {
- Ref<Texture2D> checkerboard = get_theme_icon("Checkerboard", "EditorIcons");
+ Ref<Texture2D> checkerboard = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
Size2 size = get_size();
draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index fcc6b84efb..39ab3215ff 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -55,10 +55,10 @@ void MeshEditor::_notification(int p_what) {
if (first_enter) {
//it's in propertyeditor so. could be moved around
- light_1_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight1", "EditorIcons"));
- light_1_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight1Off", "EditorIcons"));
- light_2_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight2", "EditorIcons"));
- light_2_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight2Off", "EditorIcons"));
+ light_1_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight1"), SNAME("EditorIcons")));
+ light_1_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight1Off"), SNAME("EditorIcons")));
+ light_2_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight2"), SNAME("EditorIcons")));
+ light_2_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight2Off"), SNAME("EditorIcons")));
first_enter = false;
}
}
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 0d2b2ea2f5..91415f4883 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -153,14 +153,18 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
ur->commit_action();
} break;
- case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE: {
+
+ case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE:
+ case MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE: {
if (node == get_tree()->get_edited_scene_root()) {
err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root."));
err_dialog->popup_centered();
return;
}
- Ref<Shape3D> shape = mesh->create_convex_shape();
+ bool simplify = (p_option == MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
+
+ Ref<Shape3D> shape = mesh->create_convex_shape(true, simplify);
if (shape.is_null()) {
err_dialog->set_text(TTR("Couldn't create a single convex collision shape."));
@@ -169,7 +173,11 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Create Single Convex Shape"));
+ if (simplify) {
+ ur->create_action(TTR("Create Simplified Convex Shape"));
+ } else {
+ ur->create_action(TTR("Create Single Convex Shape"));
+ }
CollisionShape3D *cshape = memnew(CollisionShape3D);
cshape->set_shape(shape);
@@ -186,6 +194,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->commit_action();
} break;
+
case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: {
if (node == get_tree()->get_edited_scene_root()) {
err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root."));
@@ -432,7 +441,7 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
Node3DEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text(TTR("Mesh"));
- options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MeshInstance3D", "EditorIcons"));
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("MeshInstance3D"), SNAME("EditorIcons")));
options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a StaticBody3D and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection."));
@@ -441,8 +450,10 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
+ options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
+ options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy."));
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
- options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options."));
+ options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision."));
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
options->get_popup()->add_separator();
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 69f494de7f..98b667c978 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -43,6 +43,7 @@ class MeshInstance3DEditor : public Control {
MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE,
+ MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE,
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
MENU_OPTION_CREATE_NAVMESH,
MENU_OPTION_CREATE_OUTLINE_MESH,
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 5d1d29cbc8..15b6a0f3a0 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -254,7 +254,7 @@ MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) {
Node3DEditor::get_singleton()->add_control_to_menu_panel(menu);
menu->set_position(Point2(1, 1));
menu->set_text(TTR("Mesh Library"));
- menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MeshLibrary", "EditorIcons"));
+ menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("MeshLibrary"), SNAME("EditorIcons")));
menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM);
menu->get_popup()->add_item(TTR("Remove Selected Item"), MENU_OPTION_REMOVE_ITEM);
menu->get_popup()->add_separator();
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index 48b885930f..5514bccabb 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -268,7 +268,7 @@ MultiMeshEditor::MultiMeshEditor() {
Node3DEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text("MultiMesh");
- options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MultiMeshInstance3D", "EditorIcons"));
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("MultiMeshInstance3D"), SNAME("EditorIcons")));
options->get_popup()->add_item(TTR("Populate Surface"));
options->get_popup()->connect("id_pressed", callable_mp(this, &MultiMeshEditor::_menu_option));
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 14087801f5..7290a39463 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -92,9 +92,9 @@ void ViewportRotationControl::_notification(int p_what) {
axis_menu_options.push_back(Node3DEditorViewport::VIEW_FRONT);
axis_colors.clear();
- axis_colors.push_back(get_theme_color("axis_x_color", "Editor"));
- axis_colors.push_back(get_theme_color("axis_y_color", "Editor"));
- axis_colors.push_back(get_theme_color("axis_z_color", "Editor"));
+ axis_colors.push_back(get_theme_color(SNAME("axis_x_color"), SNAME("Editor")));
+ axis_colors.push_back(get_theme_color(SNAME("axis_y_color"), SNAME("Editor")));
+ axis_colors.push_back(get_theme_color(SNAME("axis_z_color"), SNAME("Editor")));
update();
if (!is_connected("mouse_exited", callable_mp(this, &ViewportRotationControl::_on_mouse_exited))) {
@@ -143,7 +143,7 @@ void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) {
if (front) {
String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z");
draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c);
- draw_char(get_theme_font("rotation_control", "EditorFonts"), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", get_theme_font_size("rotation_control_size", "EditorFonts"), Color(0.3, 0.3, 0.3));
+ draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.3, 0.3, 0.3));
} else {
draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS * (0.55 + (0.2 * (1.0 + p_axis.z_axis))), c);
}
@@ -467,22 +467,31 @@ void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_
}
void Node3DEditorViewport::_select(Node *p_node, bool p_append, bool p_single) {
- if (!p_append) {
- editor_selection->clear();
- }
-
- if (editor_selection->is_selected(p_node)) {
- //erase
- editor_selection->remove_node(p_node);
+ // Add or remove a single node from the selection
+ if (p_append && p_single) {
+ if (editor_selection->is_selected(p_node)) {
+ // Already in the selection, remove it from the selected nodes
+ editor_selection->remove_node(p_node);
+ } else {
+ // Add the item to the selection
+ editor_selection->add_node(p_node);
+ }
+ } else if (p_append && !p_single) {
+ // Add the item to the selection
+ editor_selection->add_node(p_node);
} else {
+ // No append; single select
+ editor_selection->clear();
editor_selection->add_node(p_node);
- }
-
- if (p_single) {
+ // Reselect
if (Engine::get_singleton()->is_editor_hint()) {
editor->call("edit_node", p_node);
}
}
+
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ editor->push_item(editor_selection->get_selected_node_list()[0]);
+ }
}
ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) {
@@ -562,7 +571,7 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
return closest;
}
-void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select) {
+void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select, bool p_include_locked_nodes) {
Vector3 ray = _get_ray(p_pos);
Vector3 pos = _get_ray_pos(p_pos);
@@ -605,6 +614,10 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_inclu
continue;
}
+ if (!p_include_locked_nodes && _is_node_locked(spat)) {
+ continue;
+ }
+
if (editor_selection->is_selected(spat)) {
r_includes_current = true;
}
@@ -1025,7 +1038,7 @@ bool Node3DEditorViewport ::_is_node_locked(const Node *p_node) {
}
void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
- _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->is_shift_pressed());
+ _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->is_shift_pressed(), spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
Node *scene = editor->get_edited_scene();
@@ -1045,7 +1058,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
selection_results.clear();
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != Node3DEditor::TOOL_MODE_LIST_SELECT);
+ _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
clicked = ObjectID();
}
@@ -1122,7 +1135,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
- emit_signal("clicked", this);
+ emit_signal(SNAME("clicked"), this);
float zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor();
switch (b->get_button_index()) {
@@ -1454,7 +1467,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
} else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed()) {
nav_mode = NAVIGATION_ORBIT;
} else {
- bool movement_threshold_passed = _edit.original_mouse_pos.distance_to(_edit.mouse_pos) > 10 * EDSCALE;
+ const bool movement_threshold_passed = _edit.original_mouse_pos.distance_to(_edit.mouse_pos) > 8 * EDSCALE;
if (clicked.is_valid() && movement_threshold_passed) {
if (!clicked_includes_current) {
_select_clicked(clicked_wants_append, true);
@@ -1967,6 +1980,13 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
return;
}
+ if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_numpad")) {
+ const uint32_t code = k->get_keycode();
+ if (code >= KEY_0 && code <= KEY_9) {
+ k->set_keycode(code - KEY_0 + KEY_KP_0);
+ }
+ }
+
if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) {
if (_edit.mode != TRANSFORM_NONE) {
_edit.snap = !_edit.snap;
@@ -2025,7 +2045,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- spatial_editor->emit_signal("transform_key_request", sp, "", sp->get_transform());
+ spatial_editor->emit_signal(SNAME("transform_key_request"), sp, "", sp->get_transform());
}
set_message(TTR("Animation Key Inserted."));
@@ -2041,7 +2061,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (k->get_keycode() == KEY_SPACE) {
if (!k->is_pressed()) {
- emit_signal("toggle_maximize_view", this);
+ emit_signal(SNAME("toggle_maximize_view"), this);
}
}
}
@@ -2395,12 +2415,12 @@ void Node3DEditorViewport::_notification(int p_what) {
} else {
set_freelook_active(false);
}
- call_deferred("update_transform_gizmo_view");
+ call_deferred(SNAME("update_transform_gizmo_view"));
rotation_control->set_visible(EditorSettings::get_singleton()->get("editors/3d/navigation/show_viewport_rotation_gizmo"));
}
if (p_what == NOTIFICATION_RESIZED) {
- call_deferred("update_transform_gizmo_view");
+ call_deferred(SNAME("update_transform_gizmo_view"));
}
if (p_what == NOTIFICATION_PROCESS) {
@@ -2418,7 +2438,7 @@ void Node3DEditorViewport::_notification(int p_what) {
Node *scene_root = editor->get_scene_tree_dock()->get_editor_data()->get_edited_scene_root();
if (previewing_cinema && scene_root != nullptr) {
- Camera3D *cam = scene_root->get_viewport()->get_camera();
+ Camera3D *cam = scene_root->get_viewport()->get_camera_3d();
if (cam != nullptr && cam != previewing) {
//then switch the viewport's camera to the scene's viewport camera
if (previewing != nullptr) {
@@ -2504,25 +2524,21 @@ void Node3DEditorViewport::_notification(int p_what) {
}
if (show_info) {
+ const String viewport_size = vformat(String::utf8("%d × %d"), viewport->get_size().x, viewport->get_size().y);
String text;
- text += "X: " + rtos(current_camera->get_position().x).pad_decimals(1) + "\n";
- text += "Y: " + rtos(current_camera->get_position().y).pad_decimals(1) + "\n";
- text += "Z: " + rtos(current_camera->get_position().z).pad_decimals(1) + "\n";
- text += TTR("Pitch") + ": " + itos(Math::round(current_camera->get_rotation_degrees().x)) + "\n";
- text += TTR("Yaw") + ": " + itos(Math::round(current_camera->get_rotation_degrees().y)) + "\n\n";
-
- text += TTR("Size") +
- vformat(
- ": %dx%d (%.1fMP)\n",
- viewport->get_size().x,
- viewport->get_size().y,
- viewport->get_size().x * viewport->get_size().y * 0.000'001);
- text += TTR("Objects Drawn") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_OBJECTS_IN_FRAME)) + "\n";
- text += TTR("Material Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_MATERIAL_CHANGES_IN_FRAME)) + "\n";
- text += TTR("Shader Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_SHADER_CHANGES_IN_FRAME)) + "\n";
- text += TTR("Surface Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_SURFACE_CHANGES_IN_FRAME)) + "\n";
- text += TTR("Draw Calls") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_DRAW_CALLS_IN_FRAME)) + "\n";
- text += TTR("Vertices") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_VERTICES_IN_FRAME));
+ text += vformat(TTR("X: %s\n"), rtos(current_camera->get_position().x).pad_decimals(1));
+ text += vformat(TTR("Y: %s\n"), rtos(current_camera->get_position().y).pad_decimals(1));
+ text += vformat(TTR("Z: %s\n"), rtos(current_camera->get_position().z).pad_decimals(1));
+ text += "\n";
+ text += vformat(
+ TTR("Size: %s (%.1fMP)\n"),
+ viewport_size,
+ viewport->get_size().x * viewport->get_size().y * 0.000001);
+
+ text += "\n";
+ text += vformat(TTR("Objects: %d\n"), viewport->get_render_info(Viewport::RENDER_INFO_TYPE_VISIBLE, Viewport::RENDER_INFO_OBJECTS_IN_FRAME));
+ text += vformat(TTR("Primitives: %d\n"), viewport->get_render_info(Viewport::RENDER_INFO_TYPE_VISIBLE, Viewport::RENDER_INFO_PRIMITIVES_IN_FRAME));
+ text += vformat(TTR("Draw Calls: %d"), viewport->get_render_info(Viewport::RENDER_INFO_TYPE_VISIBLE, Viewport::RENDER_INFO_DRAW_CALLS_IN_FRAME));
info_label->set_text(text);
}
@@ -2617,31 +2633,31 @@ void Node3DEditorViewport::_notification(int p_what) {
}
if (p_what == NOTIFICATION_THEME_CHANGED) {
- view_menu->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
- preview_camera->set_icon(get_theme_icon("Camera3D", "EditorIcons"));
+ view_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ preview_camera->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons")));
- view_menu->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- view_menu->add_theme_style_override("hover", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- view_menu->add_theme_style_override("pressed", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- view_menu->add_theme_style_override("focus", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- view_menu->add_theme_style_override("disabled", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
+ view_menu->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ view_menu->add_theme_style_override("hover", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ view_menu->add_theme_style_override("pressed", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ view_menu->add_theme_style_override("focus", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ view_menu->add_theme_style_override("disabled", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
- preview_camera->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- preview_camera->add_theme_style_override("hover", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- preview_camera->add_theme_style_override("pressed", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- preview_camera->add_theme_style_override("focus", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- preview_camera->add_theme_style_override("disabled", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
+ preview_camera->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ preview_camera->add_theme_style_override("hover", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ preview_camera->add_theme_style_override("pressed", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ preview_camera->add_theme_style_override("focus", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ preview_camera->add_theme_style_override("disabled", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
- frame_time_gradient->set_color(0, get_theme_color("success_color", "Editor"));
- frame_time_gradient->set_color(1, get_theme_color("warning_color", "Editor"));
- frame_time_gradient->set_color(2, get_theme_color("error_color", "Editor"));
+ frame_time_gradient->set_color(0, get_theme_color(SNAME("success_color"), SNAME("Editor")));
+ frame_time_gradient->set_color(1, get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ frame_time_gradient->set_color(2, get_theme_color(SNAME("error_color"), SNAME("Editor")));
- info_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- cpu_time_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- gpu_time_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- fps_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- cinema_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
- locked_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles"));
+ info_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ cpu_time_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ gpu_time_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ fps_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ cinema_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
+ locked_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
}
}
@@ -2682,7 +2698,7 @@ void Node3DEditorViewport::_draw() {
if (surface->has_focus()) {
Size2 size = surface->get_size();
Rect2 r = Rect2(Point2(), size);
- get_theme_stylebox("Focus", "EditorStyles")->draw(surface->get_canvas_item(), r);
+ get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles"))->draw(surface->get_canvas_item(), r);
}
if (cursor.region_select) {
@@ -2690,11 +2706,11 @@ void Node3DEditorViewport::_draw() {
surface->draw_rect(
selection_rect,
- get_theme_color("box_selection_fill_color", "Editor"));
+ get_theme_color(SNAME("box_selection_fill_color"), SNAME("Editor")));
surface->draw_rect(
selection_rect,
- get_theme_color("box_selection_stroke_color", "Editor"),
+ get_theme_color(SNAME("box_selection_stroke_color"), SNAME("Editor")),
false,
Math::round(EDSCALE));
}
@@ -2702,8 +2718,8 @@ void Node3DEditorViewport::_draw() {
RID ci = surface->get_canvas_item();
if (message_time > 0) {
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Point2 msgpos = Point2(5, get_size().y - 20);
font->draw_string(ci, msgpos + Point2(1, 1), message, HALIGN_LEFT, -1, font_size, Color(0, 0, 0, 0.8));
font->draw_string(ci, msgpos + Point2(-1, -1), message, HALIGN_LEFT, -1, font_size, Color(0, 0, 0, 0.8));
@@ -2716,16 +2732,16 @@ void Node3DEditorViewport::_draw() {
Color handle_color;
switch (_edit.plane) {
case TRANSFORM_X_AXIS:
- handle_color = get_theme_color("axis_x_color", "Editor");
+ handle_color = get_theme_color(SNAME("axis_x_color"), SNAME("Editor"));
break;
case TRANSFORM_Y_AXIS:
- handle_color = get_theme_color("axis_y_color", "Editor");
+ handle_color = get_theme_color(SNAME("axis_y_color"), SNAME("Editor"));
break;
case TRANSFORM_Z_AXIS:
- handle_color = get_theme_color("axis_z_color", "Editor");
+ handle_color = get_theme_color(SNAME("axis_z_color"), SNAME("Editor"));
break;
default:
- handle_color = get_theme_color("accent_color", "Editor");
+ handle_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
break;
}
handle_color.a = 1.0;
@@ -2782,9 +2798,9 @@ void Node3DEditorViewport::_draw() {
draw_indicator_bar(
*surface,
1.0 - logscale_t,
- get_theme_icon("ViewportSpeed", "EditorIcons"),
- get_theme_font("font", "Label"),
- get_theme_font_size("font_size", "Label"),
+ get_theme_icon(SNAME("ViewportSpeed"), SNAME("EditorIcons")),
+ get_theme_font(SNAME("font"), SNAME("Label")),
+ get_theme_font_size(SNAME("font_size"), SNAME("Label")),
vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision)));
}
@@ -2804,9 +2820,9 @@ void Node3DEditorViewport::_draw() {
draw_indicator_bar(
*surface,
logscale_t,
- get_theme_icon("ViewportZoom", "EditorIcons"),
- get_theme_font("font", "Label"),
- get_theme_font_size("font_size", "Label"),
+ get_theme_icon(SNAME("ViewportZoom"), SNAME("EditorIcons")),
+ get_theme_font(SNAME("font"), SNAME("Label")),
+ get_theme_font_size(SNAME("font_size"), SNAME("Label")),
vformat("%s u", String::num(cursor.distance).pad_decimals(precision)));
}
}
@@ -2960,7 +2976,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false);
orthogonal = false;
auto_orthogonal = false;
- call_deferred("update_transform_gizmo_view");
+ call_deferred(SNAME("update_transform_gizmo_view"));
_update_name();
} break;
@@ -2969,7 +2985,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true);
orthogonal = true;
auto_orthogonal = false;
- call_deferred("update_transform_gizmo_view");
+ call_deferred(SNAME("update_transform_gizmo_view"));
_update_name();
} break;
@@ -3254,14 +3270,12 @@ void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) {
if (!preview) {
preview_camera->hide();
}
- view_menu->set_disabled(false);
surface->update();
} else {
previewing = preview;
previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene));
RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), preview->get_camera()); //replace
- view_menu->set_disabled(true);
surface->update();
}
}
@@ -3296,7 +3310,7 @@ void Node3DEditorViewport::_selection_result_pressed(int p_result) {
clicked = selection_results[p_result].item->get_instance_id();
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != Node3DEditor::TOOL_MODE_LIST_SELECT);
+ _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
clicked = ObjectID();
}
}
@@ -3324,7 +3338,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
Transform3D camera_xform = camera->get_transform();
- if (xform.origin.distance_squared_to(camera_xform.origin) < 0.01) {
+ if (xform.origin.is_equal_approx(camera_xform.origin)) {
for (int i = 0; i < 3; i++) {
RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], false);
RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], false);
@@ -3508,7 +3522,6 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) {
previewing = Object::cast_to<Camera3D>(pv);
previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene));
RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), previewing->get_camera()); //replace
- view_menu->set_disabled(true);
surface->update();
preview_camera->set_pressed(true);
preview_camera->show();
@@ -4238,8 +4251,8 @@ void Node3DEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->is_pressed()) {
Vector2 size = get_size();
- int h_sep = get_theme_constant("separation", "HSplitContainer");
- int v_sep = get_theme_constant("separation", "VSplitContainer");
+ int h_sep = get_theme_constant(SNAME("separation"), SNAME("HSplitContainer"));
+ int v_sep = get_theme_constant(SNAME("separation"), SNAME("VSplitContainer"));
int mid_w = size.width * ratio_h;
int mid_h = size.height * ratio_v;
@@ -4284,8 +4297,8 @@ void Node3DEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (view == VIEW_USE_3_VIEWPORTS || view == VIEW_USE_3_VIEWPORTS_ALT || view == VIEW_USE_4_VIEWPORTS) {
Vector2 size = get_size();
- int h_sep = get_theme_constant("separation", "HSplitContainer");
- int v_sep = get_theme_constant("separation", "VSplitContainer");
+ int h_sep = get_theme_constant(SNAME("separation"), SNAME("HSplitContainer"));
+ int v_sep = get_theme_constant(SNAME("separation"), SNAME("VSplitContainer"));
int mid_w = size.width * ratio_h;
int mid_h = size.height * ratio_v;
@@ -4324,18 +4337,18 @@ void Node3DEditorViewportContainer::_notification(int p_what) {
}
if (p_what == NOTIFICATION_DRAW && mouseover) {
- Ref<Texture2D> h_grabber = get_theme_icon("grabber", "HSplitContainer");
- Ref<Texture2D> v_grabber = get_theme_icon("grabber", "VSplitContainer");
+ Ref<Texture2D> h_grabber = get_theme_icon(SNAME("grabber"), SNAME("HSplitContainer"));
+ Ref<Texture2D> v_grabber = get_theme_icon(SNAME("grabber"), SNAME("VSplitContainer"));
- Ref<Texture2D> hdiag_grabber = get_theme_icon("GuiViewportHdiagsplitter", "EditorIcons");
- Ref<Texture2D> vdiag_grabber = get_theme_icon("GuiViewportVdiagsplitter", "EditorIcons");
- Ref<Texture2D> vh_grabber = get_theme_icon("GuiViewportVhsplitter", "EditorIcons");
+ Ref<Texture2D> hdiag_grabber = get_theme_icon(SNAME("GuiViewportHdiagsplitter"), SNAME("EditorIcons"));
+ Ref<Texture2D> vdiag_grabber = get_theme_icon(SNAME("GuiViewportVdiagsplitter"), SNAME("EditorIcons"));
+ Ref<Texture2D> vh_grabber = get_theme_icon(SNAME("GuiViewportVhsplitter"), SNAME("EditorIcons"));
Vector2 size = get_size();
- int h_sep = get_theme_constant("separation", "HSplitContainer");
+ int h_sep = get_theme_constant(SNAME("separation"), SNAME("HSplitContainer"));
- int v_sep = get_theme_constant("separation", "VSplitContainer");
+ int v_sep = get_theme_constant(SNAME("separation"), SNAME("VSplitContainer"));
int mid_w = size.width * ratio_h;
int mid_h = size.height * ratio_v;
@@ -4421,9 +4434,9 @@ void Node3DEditorViewportContainer::_notification(int p_what) {
}
return;
}
- int h_sep = get_theme_constant("separation", "HSplitContainer");
+ int h_sep = get_theme_constant(SNAME("separation"), SNAME("HSplitContainer"));
- int v_sep = get_theme_constant("separation", "VSplitContainer");
+ int v_sep = get_theme_constant(SNAME("separation"), SNAME("VSplitContainer"));
int mid_w = size.width * ratio_h;
int mid_h = size.height * ratio_v;
@@ -5041,13 +5054,13 @@ void Node3DEditor::_menu_gizmo_toggled(int p_option) {
const int state = gizmos_menu->get_item_state(idx);
switch (state) {
case EditorNode3DGizmoPlugin::VISIBLE:
- gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_visible"));
+ gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon(SNAME("visibility_visible")));
break;
case EditorNode3DGizmoPlugin::ON_TOP:
- gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_xray"));
+ gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon(SNAME("visibility_xray")));
break;
case EditorNode3DGizmoPlugin::HIDDEN:
- gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_hidden"));
+ gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon(SNAME("visibility_hidden")));
break;
}
@@ -5334,13 +5347,13 @@ void Node3DEditor::_init_indicators() {
Color origin_color;
switch (i) {
case 0:
- origin_color = get_theme_color("axis_x_color", "Editor");
+ origin_color = get_theme_color(SNAME("axis_x_color"), SNAME("Editor"));
break;
case 1:
- origin_color = get_theme_color("axis_y_color", "Editor");
+ origin_color = get_theme_color(SNAME("axis_y_color"), SNAME("Editor"));
break;
case 2:
- origin_color = get_theme_color("axis_z_color", "Editor");
+ origin_color = get_theme_color(SNAME("axis_z_color"), SNAME("Editor"));
break;
default:
origin_color = Color();
@@ -5368,35 +5381,37 @@ void Node3DEditor::_init_indicators() {
}
Ref<Shader> grid_shader = memnew(Shader);
- grid_shader->set_code(
- "\n"
- "shader_type spatial; \n"
- "render_mode unshaded; \n"
- "uniform bool orthogonal; \n"
- "uniform float grid_size; \n"
- "\n"
- "void vertex() { \n"
- " // From FLAG_SRGB_VERTEX_COLOR \n"
- " if (!OUTPUT_IS_SRGB) { \n"
- " COLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045))); \n"
- " } \n"
- "} \n"
- "\n"
- "void fragment() { \n"
- " ALBEDO = COLOR.rgb; \n"
- " vec3 dir = orthogonal ? -vec3(0, 0, 1) : VIEW; \n"
- " float angle_fade = abs(dot(dir, NORMAL)); \n"
- " angle_fade = smoothstep(0.05, 0.2, angle_fade); \n"
- " \n"
- " vec3 world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz; \n"
- " vec3 world_normal = (CAMERA_MATRIX * vec4(NORMAL, 0.0)).xyz; \n"
- " vec3 camera_world_pos = CAMERA_MATRIX[3].xyz; \n"
- " vec3 camera_world_pos_on_plane = camera_world_pos * (1.0 - world_normal); \n"
- " float dist_fade = 1.0 - (distance(world_pos, camera_world_pos_on_plane) / grid_size); \n"
- " dist_fade = smoothstep(0.02, 0.3, dist_fade); \n"
- " \n"
- " ALPHA = COLOR.a * dist_fade * angle_fade; \n"
- "}");
+ grid_shader->set_code(R"(
+shader_type spatial;
+
+render_mode unshaded;
+
+uniform bool orthogonal;
+uniform float grid_size;
+
+void vertex() {
+ // From FLAG_SRGB_VERTEX_COLOR.
+ if (!OUTPUT_IS_SRGB) {
+ COLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045)));
+ }
+}
+
+void fragment() {
+ ALBEDO = COLOR.rgb;
+ vec3 dir = orthogonal ? -vec3(0, 0, 1) : VIEW;
+ float angle_fade = abs(dot(dir, NORMAL));
+ angle_fade = smoothstep(0.05, 0.2, angle_fade);
+
+ vec3 world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
+ vec3 world_normal = (CAMERA_MATRIX * vec4(NORMAL, 0.0)).xyz;
+ vec3 camera_world_pos = CAMERA_MATRIX[3].xyz;
+ vec3 camera_world_pos_on_plane = camera_world_pos * (1.0 - world_normal);
+ float dist_fade = 1.0 - (distance(world_pos, camera_world_pos_on_plane) / grid_size);
+ dist_fade = smoothstep(0.02, 0.3, dist_fade);
+
+ ALPHA = COLOR.a * dist_fade * angle_fade;
+}
+)");
for (int i = 0; i < 3; i++) {
grid_mat[i].instantiate();
@@ -5435,13 +5450,13 @@ void Node3DEditor::_init_indicators() {
Color col;
switch (i) {
case 0:
- col = get_theme_color("axis_x_color", "Editor");
+ col = get_theme_color(SNAME("axis_x_color"), SNAME("Editor"));
break;
case 1:
- col = get_theme_color("axis_y_color", "Editor");
+ col = get_theme_color(SNAME("axis_y_color"), SNAME("Editor"));
break;
case 2:
- col = get_theme_color("axis_z_color", "Editor");
+ col = get_theme_color(SNAME("axis_z_color"), SNAME("Editor"));
break;
default:
col = Color();
@@ -5608,33 +5623,35 @@ void Node3DEditor::_init_indicators() {
Ref<Shader> rotate_shader = memnew(Shader);
- rotate_shader->set_code(
- "\n"
- "shader_type spatial; \n"
- "render_mode unshaded, depth_test_disabled; \n"
- "uniform vec4 albedo; \n"
- "\n"
- "mat3 orthonormalize(mat3 m) { \n"
- " vec3 x = normalize(m[0]); \n"
- " vec3 y = normalize(m[1] - x * dot(x, m[1])); \n"
- " vec3 z = m[2] - x * dot(x, m[2]); \n"
- " z = normalize(z - y * (dot(y,m[2]))); \n"
- " return mat3(x,y,z); \n"
- "} \n"
- "\n"
- "void vertex() { \n"
- " mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n"
- " vec3 n = mv * VERTEX; \n"
- " float orientation = dot(vec3(0,0,-1),n); \n"
- " if (orientation <= 0.005) { \n"
- " VERTEX += NORMAL*0.02; \n"
- " } \n"
- "} \n"
- "\n"
- "void fragment() { \n"
- " ALBEDO = albedo.rgb; \n"
- " ALPHA = albedo.a; \n"
- "}");
+ rotate_shader->set_code(R"(
+shader_type spatial;
+
+render_mode unshaded, depth_test_disabled;
+
+uniform vec4 albedo;
+
+mat3 orthonormalize(mat3 m) {
+ vec3 x = normalize(m[0]);
+ vec3 y = normalize(m[1] - x * dot(x, m[1]));
+ vec3 z = m[2] - x * dot(x, m[2]);
+ z = normalize(z - y * (dot(y,m[2])));
+ return mat3(x,y,z);
+}
+
+void vertex() {
+ mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX));
+ vec3 n = mv * VERTEX;
+ float orientation = dot(vec3(0, 0, -1), n);
+ if (orientation <= 0.005) {
+ VERTEX += NORMAL * 0.02;
+ }
+}
+
+void fragment() {
+ ALBEDO = albedo.rgb;
+ ALPHA = albedo.a;
+}
+)");
Ref<ShaderMaterial> rotate_mat = memnew(ShaderMaterial);
rotate_mat->set_render_priority(Material::RENDER_PRIORITY_MAX);
@@ -5654,34 +5671,36 @@ void Node3DEditor::_init_indicators() {
Ref<ShaderMaterial> border_mat = rotate_mat->duplicate();
Ref<Shader> border_shader = memnew(Shader);
- border_shader->set_code(
- "\n"
- "shader_type spatial; \n"
- "render_mode unshaded, depth_test_disabled; \n"
- "uniform vec4 albedo; \n"
- "\n"
- "mat3 orthonormalize(mat3 m) { \n"
- " vec3 x = normalize(m[0]); \n"
- " vec3 y = normalize(m[1] - x * dot(x, m[1])); \n"
- " vec3 z = m[2] - x * dot(x, m[2]); \n"
- " z = normalize(z - y * (dot(y,m[2]))); \n"
- " return mat3(x,y,z); \n"
- "} \n"
- "\n"
- "void vertex() { \n"
- " mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n"
- " mv = inverse(mv); \n"
- " VERTEX += NORMAL*0.008; \n"
- " vec3 camera_dir_local = mv * vec3(0,0,1); \n"
- " vec3 camera_up_local = mv * vec3(0,1,0); \n"
- " mat3 rotation_matrix = mat3(cross(camera_dir_local, camera_up_local), camera_up_local, camera_dir_local); \n"
- " VERTEX = rotation_matrix * VERTEX; \n"
- "} \n"
- "\n"
- "void fragment() { \n"
- " ALBEDO = albedo.rgb; \n"
- " ALPHA = albedo.a; \n"
- "}");
+ border_shader->set_code(R"(
+shader_type spatial;
+
+render_mode unshaded, depth_test_disabled;
+
+uniform vec4 albedo;
+
+mat3 orthonormalize(mat3 m) {
+ vec3 x = normalize(m[0]);
+ vec3 y = normalize(m[1] - x * dot(x, m[1]));
+ vec3 z = m[2] - x * dot(x, m[2]);
+ z = normalize(z - y * (dot(y,m[2])));
+ return mat3(x,y,z);
+}
+
+void vertex() {
+ mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX));
+ mv = inverse(mv);
+ VERTEX += NORMAL*0.008;
+ vec3 camera_dir_local = mv * vec3(0,0,1);
+ vec3 camera_up_local = mv * vec3(0,1,0);
+ mat3 rotation_matrix = mat3(cross(camera_dir_local, camera_up_local), camera_up_local, camera_dir_local);
+ VERTEX = rotation_matrix * VERTEX;
+}
+
+void fragment() {
+ ALBEDO = albedo.rgb;
+ ALPHA = albedo.a;
+}
+)");
border_mat->set_shader(border_shader);
border_mat->set_shader_param("albedo", Color(0.75, 0.75, 0.75, col.a / 3.0));
@@ -5801,13 +5820,13 @@ void Node3DEditor::_update_gizmos_menu() {
TTR("Click to toggle between visibility states.\n\nOpen eye: Gizmo is visible.\nClosed eye: Gizmo is hidden.\nHalf-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")."));
switch (plugin_state) {
case EditorNode3DGizmoPlugin::VISIBLE:
- gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible"));
+ gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon(SNAME("visibility_visible")));
break;
case EditorNode3DGizmoPlugin::ON_TOP:
- gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_xray"));
+ gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon(SNAME("visibility_xray")));
break;
case EditorNode3DGizmoPlugin::HIDDEN:
- gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_hidden"));
+ gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon(SNAME("visibility_hidden")));
break;
}
}
@@ -5822,13 +5841,13 @@ void Node3DEditor::_update_gizmos_menu_theme() {
const int idx = gizmos_menu->get_item_index(i);
switch (plugin_state) {
case EditorNode3DGizmoPlugin::VISIBLE:
- gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible"));
+ gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon(SNAME("visibility_visible")));
break;
case EditorNode3DGizmoPlugin::ON_TOP:
- gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_xray"));
+ gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon(SNAME("visibility_xray")));
break;
case EditorNode3DGizmoPlugin::HIDDEN:
- gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_hidden"));
+ gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon(SNAME("visibility_hidden")));
break;
}
}
@@ -6172,7 +6191,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() {
}
if (snapped_to_floor) {
- undo_redo->create_action(TTR("Snap Nodes To Floor"));
+ undo_redo->create_action(TTR("Snap Nodes to Floor"));
// Perform snapping if at least one node can be snapped
for (int i = 0; i < keys.size(); i++) {
@@ -6218,39 +6237,58 @@ void Node3DEditor::_sun_environ_settings_pressed() {
sun_environ_popup->popup();
}
-void Node3DEditor::_add_sun_to_scene() {
+void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) {
sun_environ_popup->hide();
+ if (!p_already_added_environment && world_env_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ // Prevent infinite feedback loop between the sun and environment methods.
+ _add_environment_to_scene(true);
+ }
+
Node *base = get_tree()->get_edited_scene_root();
if (!base) {
- EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
- return;
+ // Create a root node so we can add child nodes to it.
+ EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D));
+ base = get_tree()->get_edited_scene_root();
}
ERR_FAIL_COND(!base);
Node *new_sun = preview_sun->duplicate();
- undo_redo->create_action("Add Preview Sun to Scene");
+ undo_redo->create_action(TTR("Add Preview Sun to Scene"));
undo_redo->add_do_method(base, "add_child", new_sun);
+ // Move to the beginning of the scene tree since more "global" nodes
+ // generally look better when placed at the top.
+ undo_redo->add_do_method(base, "move_child", new_sun, 0);
undo_redo->add_do_method(new_sun, "set_owner", base);
undo_redo->add_undo_method(base, "remove_child", new_sun);
undo_redo->add_do_reference(new_sun);
undo_redo->commit_action();
}
-void Node3DEditor::_add_environment_to_scene() {
+
+void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) {
sun_environ_popup->hide();
+ if (!p_already_added_sun && directional_light_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ // Prevent infinite feedback loop between the sun and environment methods.
+ _add_sun_to_scene(true);
+ }
+
Node *base = get_tree()->get_edited_scene_root();
if (!base) {
- EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
- return;
+ // Create a root node so we can add child nodes to it.
+ EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D));
+ base = get_tree()->get_edited_scene_root();
}
ERR_FAIL_COND(!base);
WorldEnvironment *new_env = memnew(WorldEnvironment);
new_env->set_environment(preview_environment->get_environment()->duplicate(true));
- undo_redo->create_action("Add Preview Environment to Scene");
+ undo_redo->create_action(TTR("Add Preview Environment to Scene"));
undo_redo->add_do_method(base, "add_child", new_env);
+ // Move to the beginning of the scene tree since more "global" nodes
+ // generally look better when placed at the top.
+ undo_redo->add_do_method(base, "move_child", new_env, 0);
undo_redo->add_do_method(new_env, "set_owner", base);
undo_redo->add_undo_method(base, "remove_child", new_env);
undo_redo->add_do_reference(new_env);
@@ -6259,26 +6297,26 @@ void Node3DEditor::_add_environment_to_scene() {
void Node3DEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
- tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons"));
-
- tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons"));
- tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons"));
- tool_option_button[Node3DEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon("Camera3D", "EditorIcons"));
-
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon("Panels1", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon("Panels2", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon("Panels2Alt", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon("Panels3", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon("Panels3Alt", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon("Panels4", "EditorIcons"));
+ tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons")));
+
+ tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")));
+ tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
+ tool_option_button[Node3DEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons")));
+
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels2Alt"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon(SNAME("Panels3"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons")));
_menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
@@ -6292,13 +6330,13 @@ void Node3DEditor::_notification(int p_what) {
editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false));
editor->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true));
- sun_button->set_icon(get_theme_icon("DirectionalLight3D", "EditorIcons"));
- environ_button->set_icon(get_theme_icon("WorldEnvironment", "EditorIcons"));
- sun_environ_settings->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
+ sun_button->set_icon(get_theme_icon(SNAME("DirectionalLight3D"), SNAME("EditorIcons")));
+ environ_button->set_icon(get_theme_icon(SNAME("WorldEnvironment"), SNAME("EditorIcons")));
+ sun_environ_settings->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
_update_preview_environment();
- sun_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
- environ_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+ sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
+ environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
sun_state->set_custom_minimum_size(sun_vb->get_combined_minimum_size());
environ_state->set_custom_minimum_size(environ_vb->get_combined_minimum_size());
@@ -6308,30 +6346,30 @@ void Node3DEditor::_notification(int p_what) {
_init_indicators();
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
_update_gizmos_menu_theme();
- sun_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
- environ_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+ sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
+ environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
} else if (p_what == NOTIFICATION_EXIT_TREE) {
_finish_indicators();
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons"));
- tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons"));
-
- tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons"));
- tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons"));
-
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon("Panels1", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon("Panels2", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon("Panels2Alt", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon("Panels3", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon("Panels3Alt", "EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon("Panels4", "EditorIcons"));
+ tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons")));
+
+ tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")));
+ tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
+
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels2Alt"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon(SNAME("Panels3"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons")));
// Update grid color by rebuilding grid.
_finish_grid();
@@ -6373,7 +6411,7 @@ void Node3DEditor::_request_gizmo(Object *p_obj) {
if (!sp) {
return;
}
- if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_a_parent_of(sp)))) {
+ if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_ancestor_of(sp)))) {
Ref<EditorNode3DGizmo> seg;
for (int i = 0; i < gizmo_plugins_by_priority.size(); ++i) {
@@ -6447,7 +6485,7 @@ void Node3DEditor::_toggle_maximize_view(Object *p_viewport) {
}
void Node3DEditor::_node_added(Node *p_node) {
- if (EditorNode::get_singleton()->get_scene_root()->is_a_parent_of(p_node)) {
+ if (EditorNode::get_singleton()->get_scene_root()->is_ancestor_of(p_node)) {
if (Object::cast_to<WorldEnvironment>(p_node)) {
world_env_count++;
if (world_env_count == 1) {
@@ -6463,7 +6501,7 @@ void Node3DEditor::_node_added(Node *p_node) {
}
void Node3DEditor::_node_removed(Node *p_node) {
- if (EditorNode::get_singleton()->get_scene_root()->is_a_parent_of(p_node)) {
+ if (EditorNode::get_singleton()->get_scene_root()->is_ancestor_of(p_node)) {
if (Object::cast_to<WorldEnvironment>(p_node)) {
world_env_count--;
if (world_env_count == 0) {
@@ -6731,7 +6769,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), KEY_Q));
tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this);
- tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection"));
+ tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Show list of all nodes at position clicked, including locked."));
hbc_menu->add_child(memnew(VSeparator));
@@ -6770,21 +6808,25 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true);
button_binds.write[0] = MENU_TOOL_LIST_SELECT;
tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
- tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
+ tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show list of selectable nodes at position clicked."));
tool_button[TOOL_LOCK_SELECTED] = memnew(Button);
hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]);
tool_button[TOOL_LOCK_SELECTED]->set_flat(true);
button_binds.write[0] = MENU_LOCK_SELECTED;
tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
- tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved)."));
+ tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock selected node, preventing selection and movement."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L));
tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button);
hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]);
tool_button[TOOL_UNLOCK_SELECTED]->set_flat(true);
button_binds.write[0] = MENU_UNLOCK_SELECTED;
tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
- tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved)."));
+ tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock selected node, allowing selection and movement."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L));
tool_button[TOOL_GROUP_SELECTED] = memnew(Button);
hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]);
@@ -6792,6 +6834,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
button_binds.write[0] = MENU_GROUP_SELECTED;
tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G));
tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button);
hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]);
@@ -6799,6 +6843,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
button_binds.write[0] = MENU_UNGROUP_SELECTED;
tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected."));
+ // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
+ tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G));
hbc_menu->add_child(memnew(VSeparator));
@@ -6917,7 +6963,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid")), MENU_VIEW_GRID);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), KEY_NUMBERSIGN), MENU_VIEW_GRID);
p->add_separator();
p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings...")), MENU_VIEW_CAMERA_SETTINGS);
@@ -7073,8 +7119,6 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
xform_dialog->connect("confirmed", callable_mp(this, &Node3DEditor::_xform_dialog_action));
- scenario_debug = RenderingServer::SCENARIO_DEBUG_DISABLED;
-
selected = nullptr;
set_process_unhandled_key_input(true);
@@ -7103,6 +7147,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
sun_vb->hide();
sun_title = memnew(Label);
+ sun_title->set_theme_type_variation("HeaderSmall");
sun_vb->add_child(sun_title);
sun_title->set_text(TTR("Preview Sun"));
sun_title->set_align(Label::ALIGN_CENTER);
@@ -7116,9 +7161,21 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
sun_direction->connect("draw", callable_mp(this, &Node3DEditor::_sun_direction_draw));
sun_direction->set_default_cursor_shape(CURSOR_MOVE);
- String sun_dir_shader_code = "shader_type canvas_item; uniform vec3 sun_direction; uniform vec3 sun_color; void fragment() { vec3 n; n.xy = UV * 2.0 - 1.0; n.z = sqrt(max(0.0, 1.0 - dot(n.xy, n.xy))); COLOR.rgb = dot(n,sun_direction) * sun_color; COLOR.a = 1.0 - smoothstep(0.99,1.0,length(n.xy)); }";
sun_direction_shader.instantiate();
- sun_direction_shader->set_code(sun_dir_shader_code);
+ sun_direction_shader->set_code(R"(
+shader_type canvas_item;
+
+uniform vec3 sun_direction;
+uniform vec3 sun_color;
+
+void fragment() {
+ vec3 n;
+ n.xy = UV * 2.0 - 1.0;
+ n.z = sqrt(max(0.0, 1.0 - dot(n.xy, n.xy)));
+ COLOR.rgb = dot(n, sun_direction) * sun_color;
+ COLOR.a = 1.0 - smoothstep(0.99, 1.0, length(n.xy));
+}
+)");
sun_direction_material.instantiate();
sun_direction_material->set_shader(sun_direction_shader);
sun_direction_material->set_shader_param("sun_direction", Vector3(0, 0, 1));
@@ -7172,7 +7229,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
sun_add_to_scene = memnew(Button);
sun_add_to_scene->set_text(TTR("Add Sun to Scene"));
- sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene));
+ sun_add_to_scene->set_tooltip(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene."));
+ sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene), varray(false));
sun_vb->add_spacer();
sun_vb->add_child(sun_add_to_scene);
@@ -7193,6 +7251,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
environ_vb->hide();
environ_title = memnew(Label);
+ environ_title->set_theme_type_variation("HeaderSmall");
+
environ_vb->add_child(environ_title);
environ_title->set_text(TTR("Preview Environment"));
environ_title->set_align(Label::ALIGN_CENTER);
@@ -7236,7 +7296,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
environ_add_to_scene = memnew(Button);
environ_add_to_scene->set_text(TTR("Add Environment to Scene"));
- environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene));
+ environ_add_to_scene->set_tooltip(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene."));
+ environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene), varray(false));
environ_vb->add_spacer();
environ_vb->add_child(environ_add_to_scene);
@@ -7471,7 +7532,7 @@ void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool
handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true);
- Ref<Texture2D> handle_t = p_icon != nullptr ? p_icon : Node3DEditor::get_singleton()->get_theme_icon("Editor3DHandle", "EditorIcons");
+ Ref<Texture2D> handle_t = p_icon != nullptr ? p_icon : Node3DEditor::get_singleton()->get_theme_icon(SNAME("Editor3DHandle"), SNAME("EditorIcons"));
handle_material->set_point_size(handle_t->get_width());
handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t);
handle_material->set_albedo(Color(1, 1, 1));
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index fa432a5868..cc65cb53ca 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -34,7 +34,6 @@
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/editor_scale.h"
-#include "scene/3d/immediate_geometry_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/visual_instance_3d.h"
#include "scene/3d/world_environment.h"
@@ -318,7 +317,7 @@ private:
void _select_clicked(bool p_append, bool p_single, bool p_allow_locked = false);
void _select(Node *p_node, bool p_append, bool p_single);
ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = nullptr, bool p_alt_select = false);
- void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false);
+ void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false, bool p_include_locked_nodes = false);
Vector3 _get_ray_pos(const Vector2 &p_pos) const;
Vector3 _get_ray(const Vector2 &p_pos) const;
Point2 _point_to_screen(const Vector3 &p_point);
@@ -495,7 +494,7 @@ public:
AcceptDialog *p_accept);
SubViewport *get_viewport_node() { return viewport; }
- Camera3D *get_camera() { return camera; } // return the default camera object.
+ Camera3D *get_camera_3d() { return camera; } // return the default camera object.
Node3DEditorViewport(Node3DEditor *p_spatial_editor, EditorNode *p_editor, int p_index);
~Node3DEditorViewport();
@@ -601,8 +600,6 @@ private:
ToolMode tool_mode;
- RenderingServer::ScenarioDebugMode scenario_debug;
-
RID origin;
RID origin_instance;
bool origin_enabled;
@@ -808,8 +805,8 @@ private:
void _preview_settings_changed();
void _sun_environ_settings_pressed();
- void _add_sun_to_scene();
- void _add_environment_to_scene();
+ void _add_sun_to_scene(bool p_already_added_environment = false);
+ void _add_environment_to_scene(bool p_already_added_sun = false);
protected:
void _notification(int p_what);
diff --git a/editor/plugins/occluder_instance_3d_editor_plugin.cpp b/editor/plugins/occluder_instance_3d_editor_plugin.cpp
index b0cafd83be..ab88b9f00d 100644
--- a/editor/plugins/occluder_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/occluder_instance_3d_editor_plugin.cpp
@@ -98,7 +98,7 @@ OccluderInstance3DEditorPlugin::OccluderInstance3DEditorPlugin(EditorNode *p_nod
editor = p_node;
bake = memnew(Button);
bake->set_flat(true);
- bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
+ bake->set_icon(editor->get_gui_base()->get_theme_icon(SNAME("Bake"), SNAME("EditorIcons")));
bake->set_text(TTR("Bake Occluders"));
bake->hide();
bake->connect("pressed", Callable(this, "_bake"));
diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp
index baab9bc438..fd42bce06e 100644
--- a/editor/plugins/ot_features_plugin.cpp
+++ b/editor/plugins/ot_features_plugin.cpp
@@ -49,10 +49,10 @@ void OpenTypeFeaturesEditor::update_property() {
void OpenTypeFeaturesEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Color base = get_theme_color("accent_color", "Editor");
+ Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
- button->set_icon(get_theme_icon("Remove", "EditorIcons"));
- button->set_size(get_theme_icon("Remove", "EditorIcons")->get_size());
+ button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ button->set_size(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))->get_size());
spin->set_custom_label_color(true, base);
}
}
@@ -106,7 +106,7 @@ void OpenTypeFeaturesAdd::update_property() {
bool have_ss = false;
bool have_cv = false;
bool have_cu = false;
- Dictionary features = Object::cast_to<Control>(get_edited_object())->get_theme_font("font")->get_feature_list();
+ Dictionary features = Object::cast_to<Control>(get_edited_object())->get_theme_font(SNAME("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_")) {
@@ -142,8 +142,8 @@ void OpenTypeFeaturesAdd::_features_menu() {
void OpenTypeFeaturesAdd::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) {
set_label("");
- button->set_icon(get_theme_icon("Add", "EditorIcons"));
- button->set_size(get_theme_icon("Add", "EditorIcons")->get_size());
+ button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ button->set_size(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))->get_size());
}
}
@@ -191,7 +191,7 @@ void EditorInspectorPluginOpenTypeFeatures::parse_begin(Object *p_object) {
void EditorInspectorPluginOpenTypeFeatures::parse_category(Object *p_object, const String &p_parse_category) {
}
-bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+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) {
if (p_path == "opentype_features/_new") {
OpenTypeFeaturesAdd *editor = memnew(OpenTypeFeaturesAdd);
add_property_editor(p_path, editor);
diff --git a/editor/plugins/ot_features_plugin.h b/editor/plugins/ot_features_plugin.h
index 9559a6c0c3..dbafa3bbf6 100644
--- a/editor/plugins/ot_features_plugin.h
+++ b/editor/plugins/ot_features_plugin.h
@@ -88,7 +88,7 @@ public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
virtual void parse_category(Object *p_object, const String &p_parse_category) override;
- virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) override;
+ virtual bool 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 = false) override;
};
/*************************************************************************/
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 838e67b5e7..8866e8c53e 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -364,12 +364,12 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- const Ref<Texture2D> path_sharp_handle = get_theme_icon("EditorPathSharpHandle", "EditorIcons");
- const Ref<Texture2D> path_smooth_handle = get_theme_icon("EditorPathSmoothHandle", "EditorIcons");
+ const Ref<Texture2D> path_sharp_handle = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons"));
+ const Ref<Texture2D> path_smooth_handle = get_theme_icon(SNAME("EditorPathSmoothHandle"), SNAME("EditorIcons"));
// Both handle icons must be of the same size
const Size2 handle_size = path_sharp_handle->get_size();
- const Ref<Texture2D> curve_handle = get_theme_icon("EditorCurveHandle", "EditorIcons");
+ const Ref<Texture2D> curve_handle = get_theme_icon(SNAME("EditorCurveHandle"), SNAME("EditorIcons"));
const Size2 curve_handle_size = curve_handle->get_size();
Ref<Curve2D> curve = node->get_curve();
@@ -411,7 +411,7 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
}
if (on_edge) {
- Ref<Texture2D> add_handle = get_theme_icon("EditorHandleAdd", "EditorIcons");
+ Ref<Texture2D> add_handle = get_theme_icon(SNAME("EditorHandleAdd"), SNAME("EditorIcons"));
p_overlay->draw_texture(add_handle, edge_point - add_handle->get_size() * 0.5);
}
}
@@ -481,7 +481,7 @@ void Path2DEditor::_mode_selected(int p_mode) {
Vector2 begin = node->get_curve()->get_point_position(0);
Vector2 end = node->get_curve()->get_point_position(node->get_curve()->get_point_count() - 1);
- if (begin.distance_to(end) < CMP_EPSILON) {
+ if (begin.is_equal_approx(end)) {
return;
}
@@ -534,7 +534,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
base_hb->add_child(sep);
curve_edit = memnew(Button);
curve_edit->set_flat(true);
- curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons"));
+ curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons")));
curve_edit->set_toggle_mode(true);
curve_edit->set_focus_mode(Control::FOCUS_NONE);
curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point"));
@@ -542,7 +542,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
base_hb->add_child(curve_edit);
curve_edit_curve = memnew(Button);
curve_edit_curve->set_flat(true);
- curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCurve", "EditorIcons"));
+ curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveCurve"), SNAME("EditorIcons")));
curve_edit_curve->set_toggle_mode(true);
curve_edit_curve->set_focus_mode(Control::FOCUS_NONE);
curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)"));
@@ -550,7 +550,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
base_hb->add_child(curve_edit_curve);
curve_create = memnew(Button);
curve_create->set_flat(true);
- curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons"));
+ curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveCreate"), SNAME("EditorIcons")));
curve_create->set_toggle_mode(true);
curve_create->set_focus_mode(Control::FOCUS_NONE);
curve_create->set_tooltip(TTR("Add Point (in empty space)"));
@@ -558,7 +558,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
base_hb->add_child(curve_create);
curve_del = memnew(Button);
curve_del->set_flat(true);
- curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons"));
+ curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveDelete"), SNAME("EditorIcons")));
curve_del->set_toggle_mode(true);
curve_del->set_focus_mode(Control::FOCUS_NONE);
curve_del->set_tooltip(TTR("Delete Point"));
@@ -566,7 +566,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
base_hb->add_child(curve_del);
curve_close = memnew(Button);
curve_close->set_flat(true);
- curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons"));
+ curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveClose"), SNAME("EditorIcons")));
curve_close->set_focus_mode(Control::FOCUS_NONE);
curve_close->set_tooltip(TTR("Close Curve"));
curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(ACTION_CLOSE));
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 82b51f8a06..0a95986fe2 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -453,14 +453,14 @@ void Path3DEditorPlugin::edit(Object *p_object) {
path = Object::cast_to<Path3D>(p_object);
if (path) {
if (path->get_curve().is_valid()) {
- path->get_curve()->emit_signal("changed");
+ path->get_curve()->emit_signal(SNAME("changed"));
}
}
} else {
Path3D *pre = path;
path = nullptr;
if (pre) {
- pre->get_curve()->emit_signal("changed");
+ pre->get_curve()->emit_signal(SNAME("changed"));
}
}
//collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
@@ -490,7 +490,7 @@ void Path3DEditorPlugin::make_visible(bool p_visible) {
Path3D *pre = path;
path = nullptr;
if (pre && pre->get_curve().is_valid()) {
- pre->get_curve()->emit_signal("changed");
+ pre->get_curve()->emit_signal(SNAME("changed"));
}
}
}
@@ -562,7 +562,7 @@ Path3DEditorPlugin::Path3DEditorPlugin(EditorNode *p_node) {
Node3DEditor::get_singleton()->add_control_to_menu_panel(sep);
curve_edit = memnew(Button);
curve_edit->set_flat(true);
- curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons"));
+ curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons")));
curve_edit->set_toggle_mode(true);
curve_edit->hide();
curve_edit->set_focus_mode(Control::FOCUS_NONE);
@@ -570,7 +570,7 @@ Path3DEditorPlugin::Path3DEditorPlugin(EditorNode *p_node) {
Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_edit);
curve_create = memnew(Button);
curve_create->set_flat(true);
- curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons"));
+ curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveCreate"), SNAME("EditorIcons")));
curve_create->set_toggle_mode(true);
curve_create->hide();
curve_create->set_focus_mode(Control::FOCUS_NONE);
@@ -578,7 +578,7 @@ Path3DEditorPlugin::Path3DEditorPlugin(EditorNode *p_node) {
Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_create);
curve_del = memnew(Button);
curve_del->set_flat(true);
- curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons"));
+ curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveDelete"), SNAME("EditorIcons")));
curve_del->set_toggle_mode(true);
curve_del->hide();
curve_del->set_focus_mode(Control::FOCUS_NONE);
@@ -586,7 +586,7 @@ Path3DEditorPlugin::Path3DEditorPlugin(EditorNode *p_node) {
Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_del);
curve_close = memnew(Button);
curve_close->set_flat(true);
- curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons"));
+ curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveClose"), SNAME("EditorIcons")));
curve_close->hide();
curve_close->set_focus_mode(Control::FOCUS_NONE);
curve_close->set_tooltip(TTR("Close Curve"));
@@ -644,6 +644,6 @@ Path3DGizmoPlugin::Path3DGizmoPlugin() {
Color path_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/path", Color(0.5, 0.5, 1.0, 0.8));
create_material("path_material", path_color);
create_material("path_thin_material", Color(0.5, 0.5, 0.5));
- create_handle_material("handles", false, Node3DEditor::get_singleton()->get_theme_icon("EditorPathSmoothHandle", "EditorIcons"));
- create_handle_material("sec_handles", false, Node3DEditor::get_singleton()->get_theme_icon("EditorCurveHandle", "EditorIcons"));
+ create_handle_material("handles", false, Node3DEditor::get_singleton()->get_theme_icon(SNAME("EditorPathSmoothHandle"), SNAME("EditorIcons")));
+ create_handle_material("sec_handles", false, Node3DEditor::get_singleton()->get_theme_icon(SNAME("EditorCurveHandle"), SNAME("EditorIcons")));
}
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp
index 4b52512933..f92f50f826 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.cpp
+++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp
@@ -60,7 +60,7 @@ PhysicalBone3DEditor::PhysicalBone3DEditor(EditorNode *p_editor) :
spatial_editor_hb->add_child(button_transform_joint);
button_transform_joint->set_text(TTR("Move Joint"));
- button_transform_joint->set_icon(Node3DEditor::get_singleton()->get_theme_icon("PhysicalBone3D", "EditorIcons"));
+ button_transform_joint->set_icon(Node3DEditor::get_singleton()->get_theme_icon(SNAME("PhysicalBone3D"), SNAME("EditorIcons")));
button_transform_joint->set_toggle_mode(true);
button_transform_joint->connect("toggled", callable_mp(this, &PhysicalBone3DEditor::_on_toggle_button_transform_joint));
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 1a13a028c8..b420372eff 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -64,27 +64,27 @@ void Polygon2DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- bone_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ bone_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
} break;
case NOTIFICATION_READY: {
- button_uv->set_icon(get_theme_icon("Uv", "EditorIcons"));
-
- uv_button[UV_MODE_CREATE]->set_icon(get_theme_icon("Edit", "EditorIcons"));
- uv_button[UV_MODE_CREATE_INTERNAL]->set_icon(get_theme_icon("EditInternal", "EditorIcons"));
- uv_button[UV_MODE_REMOVE_INTERNAL]->set_icon(get_theme_icon("RemoveInternal", "EditorIcons"));
- uv_button[UV_MODE_EDIT_POINT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- uv_button[UV_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons"));
- uv_button[UV_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons"));
- uv_button[UV_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons"));
- uv_button[UV_MODE_ADD_POLYGON]->set_icon(get_theme_icon("Edit", "EditorIcons"));
- uv_button[UV_MODE_REMOVE_POLYGON]->set_icon(get_theme_icon("Close", "EditorIcons"));
- uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_theme_icon("Bucket", "EditorIcons"));
- uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_theme_icon("Clear", "EditorIcons"));
-
- b_snap_grid->set_icon(get_theme_icon("Grid", "EditorIcons"));
- b_snap_enable->set_icon(get_theme_icon("SnapGrid", "EditorIcons"));
- uv_icon_zoom->set_texture(get_theme_icon("Zoom", "EditorIcons"));
+ button_uv->set_icon(get_theme_icon(SNAME("Uv"), SNAME("EditorIcons")));
+
+ uv_button[UV_MODE_CREATE]->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_CREATE_INTERNAL]->set_icon(get_theme_icon(SNAME("EditInternal"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_REMOVE_INTERNAL]->set_icon(get_theme_icon(SNAME("RemoveInternal"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_EDIT_POINT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_ADD_POLYGON]->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_REMOVE_POLYGON]->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons")));
+ uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
+
+ b_snap_grid->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
+ b_snap_enable->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons")));
+ uv_icon_zoom->set_texture(get_theme_icon(SNAME("Zoom"), SNAME("EditorIcons")));
uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
@@ -1015,7 +1015,7 @@ void Polygon2DEditor::_uv_draw() {
}
// All UV points are sharp, so use the sharp handle icon
- Ref<Texture2D> handle = get_theme_icon("EditorPathSharpHandle", "EditorIcons");
+ Ref<Texture2D> handle = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons"));
Color poly_line_color = Color(0.9, 0.5, 0.5);
if (polygons.size() || polygon_create.size()) {
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index b8b2c6d343..e099c8b5fd 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -40,7 +40,7 @@ void ResourcePreloaderEditor::_gui_input(Ref<InputEvent> p_event) {
void ResourcePreloaderEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- load->set_icon(get_theme_icon("Folder", "EditorIcons"));
+ load->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
}
if (p_what == NOTIFICATION_READY) {
@@ -208,11 +208,11 @@ void ResourcePreloaderEditor::_update_library() {
ti->set_selectable(1, false);
if (type == "PackedScene") {
- ti->add_button(1, get_theme_icon("InstanceOptions", "EditorIcons"), BUTTON_OPEN_SCENE, false, TTR("Open in Editor"));
+ ti->add_button(1, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")), BUTTON_OPEN_SCENE, false, TTR("Open in Editor"));
} else {
- ti->add_button(1, get_theme_icon("Load", "EditorIcons"), BUTTON_EDIT_RESOURCE, false, TTR("Open in Editor"));
+ ti->add_button(1, get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), BUTTON_EDIT_RESOURCE, false, TTR("Open in Editor"));
}
- ti->add_button(1, get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE, false, TTR("Remove"));
+ ti->add_button(1, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE, false, TTR("Remove"));
}
//player->add_resource("default",resource);
@@ -367,8 +367,10 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() {
tree = memnew(Tree);
tree->connect("button_pressed", callable_mp(this, &ResourcePreloaderEditor::_cell_button_pressed));
tree->set_columns(2);
- tree->set_column_min_width(0, 2);
- tree->set_column_min_width(1, 3);
+ tree->set_column_expand_ratio(0, 2);
+ tree->set_column_clip_content(0, true);
+ tree->set_column_expand_ratio(1, 3);
+ tree->set_column_clip_content(1, true);
tree->set_column_expand(0, true);
tree->set_column_expand(1, true);
tree->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp
index 1e6237ced1..cea76f5233 100644
--- a/editor/plugins/root_motion_editor_plugin.cpp
+++ b/editor/plugins/root_motion_editor_plugin.cpp
@@ -149,7 +149,7 @@ void EditorPropertyRootMotion::_node_assign() {
ti->set_text(0, F->get());
ti->set_selectable(0, true);
ti->set_editable(0, false);
- ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons"));
+ ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
ti->set_metadata(0, accum);
} else {
ti = parenthood[accum];
@@ -158,7 +158,7 @@ void EditorPropertyRootMotion::_node_assign() {
ti->set_selectable(0, true);
ti->set_text(0, concat);
- ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons"));
+ ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
ti->set_metadata(0, path);
if (path == current) {
ti->select(0);
@@ -234,7 +234,7 @@ void EditorPropertyRootMotion::setup(const NodePath &p_base_hint) {
void EditorPropertyRootMotion::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- Ref<Texture2D> t = get_theme_icon("Clear", "EditorIcons");
+ Ref<Texture2D> t = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"));
clear->set_icon(t);
}
}
@@ -278,7 +278,7 @@ void EditorInspectorRootMotionPlugin::parse_begin(Object *p_object) {
//do none
}
-bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+bool EditorInspectorRootMotionPlugin::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) {
if (p_path == "root_motion_track" && p_object->is_class("AnimationTree") && p_type == Variant::NODE_PATH) {
EditorPropertyRootMotion *editor = memnew(EditorPropertyRootMotion);
if (p_hint == PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && p_hint_text != String()) {
diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h
index c70fff7db7..1484af62e8 100644
--- a/editor/plugins/root_motion_editor_plugin.h
+++ b/editor/plugins/root_motion_editor_plugin.h
@@ -65,7 +65,7 @@ class EditorInspectorRootMotionPlugin : public EditorInspectorPlugin {
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
- virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false) override;
+ virtual bool 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 = false) override;
virtual void parse_end() override;
};
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 498d5b0711..1851ffdc34 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -355,7 +355,7 @@ void ScriptEditorQuickOpen::_confirmed() {
}
int line = ti->get_text(0).get_slice(":", 1).to_int();
- emit_signal("goto_line", line - 1);
+ emit_signal(SNAME("goto_line"), line - 1);
hide();
}
@@ -368,7 +368,7 @@ void ScriptEditorQuickOpen::_notification(int p_what) {
[[fallthrough]];
}
case NOTIFICATION_VISIBILITY_CHANGED: {
- search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(search_options->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_EXIT_TREE: {
disconnect("confirmed", callable_mp(this, &ScriptEditorQuickOpen::_confirmed));
@@ -577,7 +577,7 @@ void ScriptEditor::_go_to_tab(int p_idx) {
}
if (Object::cast_to<EditorHelp>(c)) {
script_name_label->set_text(Object::cast_to<EditorHelp>(c)->get_class());
- script_icon->set_texture(get_theme_icon("Help", "EditorIcons"));
+ script_icon->set_texture(get_theme_icon(SNAME("Help"), SNAME("EditorIcons")));
if (is_visible_in_tree()) {
Object::cast_to<EditorHelp>(c)->set_focused();
}
@@ -631,7 +631,7 @@ void ScriptEditor::_open_recent_script(int p_idx) {
// clear button
if (p_idx == recent_scripts->get_item_count() - 1) {
EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", Array());
- call_deferred("_update_recent_scripts");
+ call_deferred(SNAME("_update_recent_scripts"));
return;
}
@@ -946,7 +946,7 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource> &p_res) {
_update_script_names();
if (!pending_auto_reload && auto_reload_running_scripts) {
- call_deferred("_live_auto_reload_running_scripts");
+ call_deferred(SNAME("_live_auto_reload_running_scripts"));
pending_auto_reload = true;
}
}
@@ -997,7 +997,7 @@ bool ScriptEditor::_test_script_times_on_disk(RES p_for_script) {
script_editor->_reload_scripts();
need_reload = false;
} else {
- disk_changed->call_deferred("popup_centered_ratio", 0.5);
+ disk_changed->call_deferred(SNAME("popup_centered_ratio"), 0.5);
}
}
@@ -1155,7 +1155,7 @@ void ScriptEditor::_menu_option(int p_option) {
if (ResourceLoader::get_resource_type(res_path) == "PackedScene") {
if (!EditorNode::get_singleton()->is_scene_open(res_path)) {
EditorNode::get_singleton()->load_scene(res_path);
- script_editor->call_deferred("_menu_option", p_option);
+ script_editor->call_deferred(SNAME("_menu_option"), p_option);
previous_scripts.push_back(path); //repeat the operation
return;
}
@@ -1486,23 +1486,23 @@ void ScriptEditor::_notification(int p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
- help_search->set_icon(get_theme_icon("HelpSearch", "EditorIcons"));
- site_search->set_icon(get_theme_icon("Instance", "EditorIcons"));
+ help_search->set_icon(get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")));
+ site_search->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
- script_forward->set_icon(get_theme_icon("Back", "EditorIcons"));
- script_back->set_icon(get_theme_icon("Forward", "EditorIcons"));
+ script_forward->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
+ script_back->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
} else {
- script_forward->set_icon(get_theme_icon("Forward", "EditorIcons"));
- script_back->set_icon(get_theme_icon("Back", "EditorIcons"));
+ script_forward->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
+ script_back->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
}
- members_overview_alphabeta_sort_button->set_icon(get_theme_icon("Sort", "EditorIcons"));
+ members_overview_alphabeta_sort_button->set_icon(get_theme_icon(SNAME("Sort"), SNAME("EditorIcons")));
- filter_scripts->set_right_icon(get_theme_icon("Search", "EditorIcons"));
- filter_methods->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ filter_scripts->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
+ filter_methods->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
- filename->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("normal", "LineEdit"));
+ filename->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")));
recent_scripts->set_as_minsize();
@@ -1576,11 +1576,11 @@ void ScriptEditor::edited_scene_changed() {
}
void ScriptEditor::notify_script_close(const Ref<Script> &p_script) {
- emit_signal("script_close", p_script);
+ emit_signal(SNAME("script_close"), p_script);
}
void ScriptEditor::notify_script_changed(const Ref<Script> &p_script) {
- emit_signal("editor_script_changed", p_script);
+ emit_signal(SNAME("editor_script_changed"), p_script);
}
void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
@@ -1796,8 +1796,8 @@ void ScriptEditor::_update_script_colors() {
bool script_temperature_enabled = EditorSettings::get_singleton()->get("text_editor/script_list/script_temperature_enabled");
int hist_size = EditorSettings::get_singleton()->get("text_editor/script_list/script_temperature_history_size");
- Color hot_color = get_theme_color("accent_color", "Editor");
- Color cold_color = get_theme_color("font_color", "Editor");
+ Color hot_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ Color cold_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
for (int i = 0; i < script_list->get_item_count(); i++) {
int c = script_list->get_item_metadata(i);
@@ -1946,7 +1946,7 @@ void ScriptEditor::_update_script_names() {
EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(i));
if (eh) {
String name = eh->get_class();
- Ref<Texture2D> icon = get_theme_icon("Help", "EditorIcons");
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Help"), SNAME("EditorIcons"));
String tooltip = vformat(TTR("%s Class Reference"), name);
_ScriptEditorItemData sd;
@@ -2554,8 +2554,8 @@ void ScriptEditor::_tree_changed() {
}
waiting_update_names = true;
- call_deferred("_update_script_names");
- call_deferred("_update_script_connections");
+ call_deferred(SNAME("_update_script_names"));
+ call_deferred(SNAME("_update_script_connections"));
}
void ScriptEditor::_script_split_dragged(float) {
@@ -2581,7 +2581,7 @@ Variant ScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
EditorHelp *eh = Object::cast_to<EditorHelp>(cur_node);
if (eh) {
preview_name = eh->get_class();
- preview_icon = get_theme_icon("Help", "EditorIcons");
+ preview_icon = get_theme_icon(SNAME("Help"), SNAME("EditorIcons"));
}
if (!preview_icon.is_null()) {
@@ -3362,7 +3362,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
filename = memnew(Label);
filename->set_clip_text(true);
filename->set_h_size_flags(SIZE_EXPAND_FILL);
- filename->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("normal", "LineEdit"));
+ filename->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")));
buttons_hbox->add_child(filename);
members_overview_alphabeta_sort_button = memnew(Button);
@@ -3612,8 +3612,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
ScriptServer::edit_request_func = _open_script_request;
- add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("ScriptEditorPanel", "EditorStyles"));
- tab_container->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("ScriptEditor", "EditorStyles"));
+ add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox(SNAME("ScriptEditorPanel"), SNAME("EditorStyles")));
+ tab_container->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox(SNAME("ScriptEditor"), SNAME("EditorStyles")));
}
ScriptEditor::~ScriptEditor() {
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 5fc1f74089..1a6dfa273e 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -66,7 +66,7 @@ void ConnectionInfoDialog::popup_connections(String p_method, Vector<Node *> p_n
node_item->set_text(1, connection.signal.get_name());
Control *p = Object::cast_to<Control>(get_parent());
- node_item->set_icon(1, p->get_theme_icon("Slot", "EditorIcons"));
+ node_item->set_icon(1, p->get_theme_icon(SNAME("Slot"), SNAME("EditorIcons")));
node_item->set_selectable(1, false);
node_item->set_editable(1, false);
@@ -147,7 +147,7 @@ void ScriptTextEditor::set_edited_resource(const RES &p_res) {
code_editor->get_text_editor()->clear_undo_history();
code_editor->get_text_editor()->tag_saved_version();
- emit_signal("name_changed");
+ emit_signal(SNAME("name_changed"));
code_editor->update_line_and_column();
}
@@ -440,7 +440,7 @@ void ScriptTextEditor::_validate_script() {
String target_path = base == connection.callable.get_object() ? base_path : base_path + "/" + base->get_path_to(Object::cast_to<Node>(connection.callable.get_object()));
warnings_panel->push_cell();
- warnings_panel->push_color(warnings_panel->get_theme_color("warning_color", "Editor"));
+ warnings_panel->push_color(warnings_panel->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
warnings_panel->add_text(vformat(TTR("Missing connected method '%s' for signal '%s' from node '%s' to node '%s'."), connection.callable.get_method(), connection.signal.get_name(), source_path, target_path));
warnings_panel->pop(); // Color.
warnings_panel->pop(); // Cell.
@@ -465,7 +465,7 @@ void ScriptTextEditor::_validate_script() {
warnings_panel->push_cell();
warnings_panel->push_meta(ignore_meta);
warnings_panel->push_color(
- warnings_panel->get_theme_color("accent_color", "Editor").lerp(warnings_panel->get_theme_color("mono_color", "Editor"), 0.5));
+ warnings_panel->get_theme_color(SNAME("accent_color"), SNAME("Editor")).lerp(warnings_panel->get_theme_color(SNAME("mono_color"), SNAME("Editor")), 0.5));
warnings_panel->add_text(TTR("[Ignore]"));
warnings_panel->pop(); // Color.
warnings_panel->pop(); // Meta ignore.
@@ -473,7 +473,7 @@ void ScriptTextEditor::_validate_script() {
warnings_panel->push_cell();
warnings_panel->push_meta(w.start_line - 1);
- warnings_panel->push_color(warnings_panel->get_theme_color("warning_color", "Editor"));
+ warnings_panel->push_color(warnings_panel->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
warnings_panel->add_text(TTR("Line") + " " + itos(w.start_line));
warnings_panel->add_text(" (" + w.string_code + "):");
warnings_panel->pop(); // Color.
@@ -493,7 +493,7 @@ void ScriptTextEditor::_validate_script() {
errors_panel->push_cell();
errors_panel->push_meta(err.line - 1);
- errors_panel->push_color(warnings_panel->get_theme_color("error_color", "Editor"));
+ errors_panel->push_color(warnings_panel->get_theme_color(SNAME("error_color"), SNAME("Editor")));
errors_panel->add_text(TTR("Line") + " " + itos(err.line) + ":");
errors_panel->pop(); // Color.
errors_panel->pop(); // Meta goto.
@@ -535,8 +535,8 @@ void ScriptTextEditor::_validate_script() {
}
}
- emit_signal("name_changed");
- emit_signal("edited_script_changed");
+ emit_signal(SNAME("name_changed"));
+ emit_signal(SNAME("edited_script_changed"));
}
void ScriptTextEditor::_update_bookmark_list() {
@@ -725,7 +725,7 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) {
_edit_option(breakpoints_menu->get_item_id(p_idx));
} else {
code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx));
- code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred().
+ code_editor->get_text_editor()->call_deferred(SNAME("center_viewport_to_cursor")); //Need to be deferred, because goto uses call_deferred().
}
}
@@ -760,14 +760,14 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
switch (result.type) {
case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: {
if (result.script.is_valid()) {
- emit_signal("request_open_script_at_line", result.script, result.location - 1);
+ emit_signal(SNAME("request_open_script_at_line"), result.script, result.location - 1);
} else {
- emit_signal("request_save_history");
+ emit_signal(SNAME("request_save_history"));
goto_line_centered(result.location - 1);
}
} break;
case ScriptLanguage::LookupResult::RESULT_CLASS: {
- emit_signal("go_to_help", "class_name:" + result.class_name);
+ emit_signal(SNAME("go_to_help"), "class_name:" + result.class_name);
} break;
case ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT: {
StringName cname = result.class_name;
@@ -782,11 +782,11 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
}
}
- emit_signal("go_to_help", "class_constant:" + result.class_name + ":" + result.class_member);
+ emit_signal(SNAME("go_to_help"), "class_constant:" + result.class_name + ":" + result.class_member);
} break;
case ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY: {
- emit_signal("go_to_help", "class_property:" + result.class_name + ":" + result.class_member);
+ emit_signal(SNAME("go_to_help"), "class_property:" + result.class_name + ":" + result.class_member);
} break;
case ScriptLanguage::LookupResult::RESULT_CLASS_METHOD: {
@@ -801,7 +801,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
}
}
- emit_signal("go_to_help", "class_method:" + result.class_name + ":" + result.class_member);
+ emit_signal(SNAME("go_to_help"), "class_method:" + result.class_name + ":" + result.class_member);
} break;
case ScriptLanguage::LookupResult::RESULT_CLASS_ENUM: {
@@ -817,11 +817,11 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
}
}
- emit_signal("go_to_help", "class_enum:" + result.class_name + ":" + result.class_member);
+ emit_signal(SNAME("go_to_help"), "class_enum:" + result.class_name + ":" + result.class_member);
} break;
case ScriptLanguage::LookupResult::RESULT_CLASS_TBD_GLOBALSCOPE: {
- emit_signal("go_to_help", "class_global:" + result.class_name + ":" + result.class_member);
+ emit_signal(SNAME("go_to_help"), "class_global:" + result.class_name + ":" + result.class_member);
} break;
}
} else if (ProjectSettings::get_singleton()->has_autoload(p_symbol)) {
@@ -934,7 +934,7 @@ void ScriptTextEditor::_update_connected_methods() {
if (name == connection.callable.get_method()) {
line = functions[j].get_slice(":", 1).to_int() - 1;
text_edit->set_line_gutter_metadata(line, connection_gutter, connection.callable.get_method());
- text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon("Slot", "EditorIcons"));
+ text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon(SNAME("Slot"), SNAME("EditorIcons")));
text_edit->set_line_gutter_clickable(line, connection_gutter, true);
methods_found.insert(connection.callable.get_method());
break;
@@ -1004,27 +1004,27 @@ void ScriptTextEditor::_edit_option(int p_op) {
switch (p_op) {
case EDIT_UNDO: {
tx->undo();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_REDO: {
tx->redo();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_CUT: {
tx->cut();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_COPY: {
tx->copy();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_PASTE: {
tx->paste();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_SELECT_ALL: {
tx->select_all();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_MOVE_LINE_UP: {
code_editor->move_lines_up();
@@ -1051,8 +1051,8 @@ void ScriptTextEditor::_edit_option(int p_op) {
case EDIT_DELETE_LINE: {
code_editor->delete_lines();
} break;
- case EDIT_CLONE_DOWN: {
- code_editor->clone_lines_down();
+ case EDIT_DUPLICATE_SELECTION: {
+ code_editor->duplicate_selection();
} break;
case EDIT_TOGGLE_FOLD_LINE: {
tx->toggle_foldable_line(tx->cursor_get_line());
@@ -1163,12 +1163,12 @@ void ScriptTextEditor::_edit_option(int p_op) {
// Yep, because it doesn't make sense to instance this dialog for every single script open...
// So this will be delegated to the ScriptEditor.
- emit_signal("search_in_files_requested", selected_text);
+ emit_signal(SNAME("search_in_files_requested"), selected_text);
} break;
case REPLACE_IN_FILES: {
String selected_text = code_editor->get_text_editor()->get_selection_text();
- emit_signal("replace_in_files_requested", selected_text);
+ emit_signal(SNAME("replace_in_files_requested"), selected_text);
} break;
case SEARCH_LOCATE_FUNCTION: {
quick_open->popup_dialog(get_functions());
@@ -1262,7 +1262,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
text = tx->get_word_under_cursor();
}
if (text != "") {
- emit_signal("request_help", text);
+ emit_signal(SNAME("request_help"), text);
}
} break;
case LOOKUP_SYMBOL: {
@@ -1444,6 +1444,7 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
}
if (d.has("type") && (String(d["type"]) == "files" || String(d["type"]) == "files_and_dirs")) {
+ const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
Array files = d["files"];
String text_to_drop;
@@ -1454,9 +1455,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
}
if (preload) {
- text_to_drop += "preload(\"" + String(files[i]).c_escape() + "\")";
+ text_to_drop += "preload(" + String(files[i]).c_escape().quote(quote_style) + ")";
} else {
- text_to_drop += "\"" + String(files[i]).c_escape() + "\"";
+ text_to_drop += String(files[i]).c_escape().quote(quote_style);
}
}
@@ -1685,16 +1686,16 @@ void ScriptTextEditor::_enable_code_editor() {
editor_box->add_child(warnings_panel);
warnings_panel->add_theme_font_override(
- "normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
+ "normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts")));
warnings_panel->add_theme_font_size_override(
- "normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
+ "normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")));
warnings_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_warning_clicked));
editor_box->add_child(errors_panel);
errors_panel->add_theme_font_override(
- "normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
+ "normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts")));
errors_panel->add_theme_font_size_override(
- "normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
+ "normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")));
errors_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_error_clicked));
add_child(context_menu);
@@ -1759,7 +1760,7 @@ void ScriptTextEditor::_enable_code_editor() {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_all_lines"), EDIT_FOLD_ALL_LINES);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/evaluate_selection"), EDIT_EVALUATE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE);
@@ -1818,7 +1819,7 @@ ScriptTextEditor::ScriptTextEditor() {
code_editor->get_text_editor()->set_gutter_name(connection_gutter, "connection_gutter");
code_editor->get_text_editor()->set_gutter_draw(connection_gutter, false);
code_editor->get_text_editor()->set_gutter_overwritable(connection_gutter, true);
- code_editor->get_text_editor()->set_gutter_type(connection_gutter, TextEdit::GUTTER_TPYE_ICON);
+ code_editor->get_text_editor()->set_gutter_type(connection_gutter, TextEdit::GUTTER_TYPE_ICON);
warnings_panel = memnew(RichTextLabel);
warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
@@ -1933,9 +1934,9 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), 0);
ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0);
#ifdef OSX_ENABLED
- ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C);
+ ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C);
#else
- ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D);
+ ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D);
#endif
ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E);
ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T);
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 8a8e9aa737..e4a13951e4 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -117,7 +117,7 @@ class ScriptTextEditor : public ScriptEditorBase {
EDIT_INDENT_RIGHT,
EDIT_INDENT_LEFT,
EDIT_DELETE_LINE,
- EDIT_CLONE_DOWN,
+ EDIT_DUPLICATE_SELECTION,
EDIT_PICK_COLOR,
EDIT_TO_UPPERCASE,
EDIT_TO_LOWERCASE,
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 173f1dd7fb..0d65dec87b 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -63,8 +63,8 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) {
get_text_editor()->set_text(p_shader->get_code());
get_text_editor()->clear_undo_history();
- get_text_editor()->call_deferred("set_h_scroll", 0);
- get_text_editor()->call_deferred("set_v_scroll", 0);
+ get_text_editor()->call_deferred(SNAME("set_h_scroll"), 0);
+ get_text_editor()->call_deferred(SNAME("set_v_scroll"), 0);
_validate_script();
_line_col_changed();
@@ -160,8 +160,8 @@ void ShaderTextEditor::_load_theme_settings() {
if (warnings_panel) {
// Warnings panel
- warnings_panel->add_theme_font_override("normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
- warnings_panel->add_theme_font_size_override("normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
+ warnings_panel->add_theme_font_override("normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts")));
+ warnings_panel->add_theme_font_size_override("normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")));
}
}
@@ -242,7 +242,7 @@ void ShaderTextEditor::_validate_script() {
} else {
set_warning_count(0);
}
- emit_signal("script_changed");
+ emit_signal(SNAME("script_changed"));
}
void ShaderTextEditor::_update_warning_panel() {
@@ -266,7 +266,7 @@ void ShaderTextEditor::_update_warning_panel() {
// First cell.
warnings_panel->push_cell();
warnings_panel->push_meta(w.get_line() - 1);
- warnings_panel->push_color(warnings_panel->get_theme_color("warning_color", "Editor"));
+ warnings_panel->push_color(warnings_panel->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
warnings_panel->add_text(TTR("Line") + " " + itos(w.get_line()));
warnings_panel->add_text(" (" + w.get_name() + "):");
warnings_panel->pop(); // Color.
@@ -334,8 +334,8 @@ void ShaderEditor::_menu_option(int p_option) {
case EDIT_DELETE_LINE: {
shader_editor->delete_lines();
} break;
- case EDIT_CLONE_DOWN: {
- shader_editor->clone_lines_down();
+ case EDIT_DUPLICATE_SELECTION: {
+ shader_editor->duplicate_selection();
} break;
case EDIT_TOGGLE_COMMENT: {
if (shader.is_null()) {
@@ -380,7 +380,7 @@ void ShaderEditor::_menu_option(int p_option) {
} break;
}
if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
- shader_editor->get_text_editor()->call_deferred("grab_focus");
+ shader_editor->get_text_editor()->call_deferred(SNAME("grab_focus"));
}
}
@@ -484,7 +484,7 @@ void ShaderEditor::_check_for_external_edit() {
if (use_autoreload) {
_reload_shader_from_disk();
} else {
- disk_changed->call_deferred("popup_centered");
+ disk_changed->call_deferred(SNAME("popup_centered"));
}
}
}
@@ -692,7 +692,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE);
edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditor::_menu_option));
@@ -728,7 +728,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
help_menu = memnew(MenuButton);
help_menu->set_text(TTR("Help"));
help_menu->set_switch_on_hover(true);
- help_menu->get_popup()->add_icon_item(p_node->get_gui_base()->get_theme_icon("Instance", "EditorIcons"), TTR("Online Docs"), HELP_DOCS);
+ help_menu->get_popup()->add_icon_item(p_node->get_gui_base()->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Online Docs"), HELP_DOCS);
help_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditor::_menu_option));
add_child(main_container);
@@ -737,7 +737,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
hbc->add_child(edit_menu);
hbc->add_child(goto_menu);
hbc->add_child(help_menu);
- hbc->add_theme_style_override("panel", p_node->get_gui_base()->get_theme_stylebox("ScriptEditorPanel", "EditorStyles"));
+ hbc->add_theme_style_override("panel", p_node->get_gui_base()->get_theme_stylebox(SNAME("ScriptEditorPanel"), SNAME("EditorStyles")));
VSplitContainer *editor_box = memnew(VSplitContainer);
main_container->add_child(editor_box);
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index d7da73f2ae..77579754d3 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -91,7 +91,7 @@ class ShaderEditor : public PanelContainer {
EDIT_INDENT_LEFT,
EDIT_INDENT_RIGHT,
EDIT_DELETE_LINE,
- EDIT_CLONE_DOWN,
+ EDIT_DUPLICATE_SELECTION,
EDIT_TOGGLE_COMMENT,
EDIT_COMPLETE,
SEARCH_FIND,
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index 85ccc5b798..66d2b36be1 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -66,9 +66,9 @@ void ShaderFileEditor::_version_selected(int p_option) {
Ref<Texture2D> icon;
if (bytecode->get_stage_compile_error(RD::ShaderStage(i)) != String()) {
- icon = get_theme_icon("ImportFail", "EditorIcons");
+ icon = get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"));
} else {
- icon = get_theme_icon("ImportCheck", "EditorIcons");
+ icon = get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons"));
}
stages[i]->set_icon(icon);
@@ -95,7 +95,7 @@ void ShaderFileEditor::_version_selected(int p_option) {
String error = bytecode->get_stage_compile_error(stage);
- error_text->push_font(get_theme_font("source", "EditorFonts"));
+ error_text->push_font(get_theme_font(SNAME("source"), SNAME("EditorFonts")));
if (error == String()) {
error_text->add_text(TTR("Shader stage compiled without errors."));
@@ -111,7 +111,7 @@ void ShaderFileEditor::_update_options() {
stage_hb->hide();
versions->hide();
error_text->clear();
- error_text->push_font(get_theme_font("source", "EditorFonts"));
+ error_text->push_font(get_theme_font(SNAME("source"), SNAME("EditorFonts")));
error_text->add_text(vformat(TTR("File structure for '%s' contains unrecoverable errors:\n\n"), shader_file->get_path().get_file()));
error_text->add_text(shader_file->get_base_error());
return;
@@ -154,9 +154,9 @@ void ShaderFileEditor::_update_options() {
}
if (failed) {
- icon = get_theme_icon("ImportFail", "EditorIcons");
+ icon = get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"));
} else {
- icon = get_theme_icon("ImportCheck", "EditorIcons");
+ icon = get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons"));
}
versions->add_item(title, icon);
diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp
index 44916e1d46..7ef680d7ef 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_2d_editor_plugin.cpp
@@ -96,7 +96,7 @@ Skeleton2DEditor::Skeleton2DEditor() {
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text(TTR("Skeleton2D"));
- options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Skeleton2D", "EditorIcons"));
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton2D"), SNAME("EditorIcons")));
options->get_popup()->add_item(TTR("Make Rest Pose (From Bones)"), MENU_OPTION_MAKE_REST);
options->get_popup()->add_separator();
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 0b04c2e50e..4202d8b611 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -44,7 +44,7 @@
#include "scene/resources/sphere_shape_3d.h"
void BoneTransformEditor::create_editors() {
- const Color section_color = get_theme_color("prop_subsection", "Editor");
+ const Color section_color = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
section = memnew(EditorInspectorSection);
section->setup("trf_properties", label, this, section_color, true);
@@ -53,7 +53,7 @@ void BoneTransformEditor::create_editors() {
key_button = memnew(Button);
key_button->set_text(TTR("Key Transform"));
key_button->set_visible(keyable);
- key_button->set_icon(get_theme_icon("Key", "EditorIcons"));
+ key_button->set_icon(get_theme_icon(SNAME("Key"), SNAME("EditorIcons")));
key_button->set_flat(true);
section->get_vbox()->add_child(key_button);
@@ -113,19 +113,19 @@ void BoneTransformEditor::_notification(int p_what) {
[[fallthrough]];
}
case NOTIFICATION_SORT_CHILDREN: {
- const Ref<Font> font = get_theme_font("font", "Tree");
- int font_size = get_theme_font_size("font_size", "Tree");
+ const Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
Point2 buffer;
- buffer.x += get_theme_constant("inspector_margin", "Editor");
+ buffer.x += get_theme_constant(SNAME("inspector_margin"), SNAME("Editor"));
buffer.y += font->get_height(font_size);
- buffer.y += get_theme_constant("vseparation", "Tree");
+ buffer.y += get_theme_constant(SNAME("vseparation"), SNAME("Tree"));
const float vector_height = translation_property->get_size().y;
const float transform_height = transform_property->get_size().y;
const float button_height = key_button->get_size().y;
- const float width = get_size().x - get_theme_constant("inspector_margin", "Editor");
+ const float width = get_size().x - get_theme_constant(SNAME("inspector_margin"), SNAME("Editor"));
Vector<Rect2> input_rects;
if (keyable && section->get_vbox()->is_visible()) {
input_rects.push_back(Rect2(key_button->get_position() + buffer, Size2(width, button_height)));
@@ -155,7 +155,7 @@ void BoneTransformEditor::_notification(int p_what) {
break;
}
case NOTIFICATION_DRAW: {
- const Color dark_color = get_theme_color("dark_color_2", "Editor");
+ const Color dark_color = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
for (int i = 0; i < 5; ++i) {
draw_rect(background_rects[i], dark_color);
@@ -552,7 +552,7 @@ void Skeleton3DEditor::update_joint_tree() {
items.insert(-1, root);
const Vector<int> &joint_porder = skeleton->get_bone_process_orders();
- Ref<Texture> bone_icon = get_theme_icon("BoneAttachment3D", "EditorIcons");
+ Ref<Texture> bone_icon = get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons"));
for (int i = 0; i < joint_porder.size(); ++i) {
const int b_idx = joint_porder[i];
@@ -584,13 +584,13 @@ void Skeleton3DEditor::create_editors() {
Node3DEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text(TTR("Skeleton3D"));
- options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Skeleton3D", "EditorIcons"));
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons")));
options->get_popup()->add_item(TTR("Create physical skeleton"), MENU_OPTION_CREATE_PHYSICAL_SKELETON);
options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_option));
- const Color section_color = get_theme_color("prop_subsection", "Editor");
+ const Color section_color = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
EditorInspectorSection *bones_section = memnew(EditorInspectorSection);
bones_section->setup("bones", "Bones", skeleton, section_color, true);
diff --git a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp
index 2da49c1c0b..85632cf481 100644
--- a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp
@@ -83,7 +83,7 @@ void SkeletonIK3DEditorPlugin::_bind_methods() {
SkeletonIK3DEditorPlugin::SkeletonIK3DEditorPlugin(EditorNode *p_node) {
editor = p_node;
play_btn = memnew(Button);
- play_btn->set_icon(editor->get_gui_base()->get_theme_icon("Play", "EditorIcons"));
+ play_btn->set_icon(editor->get_gui_base()->get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
play_btn->set_text(TTR("Play IK"));
play_btn->set_toggle_mode(true);
play_btn->hide();
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index ef328bcfe2..0f889ce33d 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -506,7 +506,7 @@ Sprite2DEditor::Sprite2DEditor() {
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text(TTR("Sprite2D"));
- options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Sprite2D", "EditorIcons"));
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Sprite2D"), SNAME("EditorIcons")));
options->get_popup()->add_item(TTR("Convert to Mesh2D"), MENU_OPTION_CONVERT_TO_MESH_2D);
options->get_popup()->add_item(TTR("Convert to Polygon2D"), MENU_OPTION_CONVERT_TO_POLYGON_2D);
@@ -521,7 +521,7 @@ Sprite2DEditor::Sprite2DEditor() {
debug_uv_dialog = memnew(ConfirmationDialog);
debug_uv_dialog->get_ok_button()->set_text(TTR("Create Mesh2D"));
- debug_uv_dialog->set_title("Mesh 2D Preview");
+ debug_uv_dialog->set_title(TTR("Mesh 2D Preview"));
VBoxContainer *vb = memnew(VBoxContainer);
debug_uv_dialog->add_child(vb);
ScrollContainer *scroll = memnew(ScrollContainer);
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 70c7b3072b..9bb8fbacbb 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -65,13 +65,11 @@ void SpriteFramesEditor::_sheet_preview_draw() {
int x = i * width;
split_sheet_preview->draw_line(Point2(x, 0), Point2(x, size.height), Color(1, 1, 1, a));
split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, size.height), Color(0, 0, 0, a));
-
- for (int j = 1; j < v; j++) {
- int y = j * height;
-
- split_sheet_preview->draw_line(Point2(0, y), Point2(size.width, y), Color(1, 1, 1, a));
- split_sheet_preview->draw_line(Point2(0, y + 1), Point2(size.width, y + 1), Color(0, 0, 0, a));
- }
+ }
+ for (int i = 1; i < v; i++) {
+ int y = i * height;
+ split_sheet_preview->draw_line(Point2(0, y), Point2(size.width, y), Color(1, 1, 1, a));
+ split_sheet_preview->draw_line(Point2(0, y + 1), Point2(size.width, y + 1), Color(0, 0, 0, a));
}
if (frames_selected.size() == 0) {
@@ -80,7 +78,7 @@ void SpriteFramesEditor::_sheet_preview_draw() {
return;
}
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
int idx = E->get();
@@ -308,27 +306,27 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
void SpriteFramesEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- load->set_icon(get_theme_icon("Load", "EditorIcons"));
- load_sheet->set_icon(get_theme_icon("SpriteSheet", "EditorIcons"));
- copy->set_icon(get_theme_icon("ActionCopy", "EditorIcons"));
- paste->set_icon(get_theme_icon("ActionPaste", "EditorIcons"));
- empty->set_icon(get_theme_icon("InsertBefore", "EditorIcons"));
- empty2->set_icon(get_theme_icon("InsertAfter", "EditorIcons"));
- move_up->set_icon(get_theme_icon("MoveLeft", "EditorIcons"));
- move_down->set_icon(get_theme_icon("MoveRight", "EditorIcons"));
- _delete->set_icon(get_theme_icon("Remove", "EditorIcons"));
- zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
- zoom_reset->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
- zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
- new_anim->set_icon(get_theme_icon("New", "EditorIcons"));
- remove_anim->set_icon(get_theme_icon("Remove", "EditorIcons"));
- split_sheet_zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
- split_sheet_zoom_reset->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
- split_sheet_zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
+ load->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")));
+ load_sheet->set_icon(get_theme_icon(SNAME("SpriteSheet"), SNAME("EditorIcons")));
+ copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
+ paste->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")));
+ empty->set_icon(get_theme_icon(SNAME("InsertBefore"), SNAME("EditorIcons")));
+ empty2->set_icon(get_theme_icon(SNAME("InsertAfter"), SNAME("EditorIcons")));
+ move_up->set_icon(get_theme_icon(SNAME("MoveLeft"), SNAME("EditorIcons")));
+ move_down->set_icon(get_theme_icon(SNAME("MoveRight"), SNAME("EditorIcons")));
+ _delete->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons")));
+ zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons")));
+ zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
+ new_anim->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons")));
+ remove_anim->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ split_sheet_zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons")));
+ split_sheet_zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons")));
+ split_sheet_zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
- split_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ split_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
} break;
case NOTIFICATION_READY: {
add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index 6954cacac6..91c5e96f08 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -44,7 +44,7 @@ void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) {
add_custom_control(preview);
}
-bool EditorInspectorPluginStyleBox::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+bool EditorInspectorPluginStyleBox::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, bool p_wide) {
return false; //do not want
}
diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h
index d4a235cd10..8ca348bd80 100644
--- a/editor/plugins/style_box_editor_plugin.h
+++ b/editor/plugins/style_box_editor_plugin.h
@@ -61,7 +61,7 @@ class EditorInspectorPluginStyleBox : public EditorInspectorPlugin {
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
- virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false) override;
+ virtual bool 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 = false) override;
virtual void parse_end() override;
};
diff --git a/editor/plugins/sub_viewport_preview_editor_plugin.cpp b/editor/plugins/sub_viewport_preview_editor_plugin.cpp
new file mode 100644
index 0000000000..75c47bda2e
--- /dev/null
+++ b/editor/plugins/sub_viewport_preview_editor_plugin.cpp
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* sub_viewport_preview_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "sub_viewport_preview_editor_plugin.h"
+
+bool EditorInspectorPluginSubViewportPreview::can_handle(Object *p_object) {
+ return Object::cast_to<SubViewport>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginSubViewportPreview::parse_begin(Object *p_object) {
+ SubViewport *sub_viewport = Object::cast_to<SubViewport>(p_object);
+
+ TexturePreview *sub_viewport_preview = memnew(TexturePreview(sub_viewport->get_texture(), false));
+ // Otherwise `sub_viewport_preview`'s `texture_display` doesn't update properly when `sub_viewport`'s size changes.
+ sub_viewport->connect("size_changed", callable_mp((CanvasItem *)sub_viewport_preview->get_texture_display(), &CanvasItem::update));
+ add_custom_control(sub_viewport_preview);
+}
+
+SubViewportPreviewEditorPlugin::SubViewportPreviewEditorPlugin(EditorNode *p_node) {
+ Ref<EditorInspectorPluginSubViewportPreview> plugin;
+ plugin.instantiate();
+ add_inspector_plugin(plugin);
+}
diff --git a/editor/plugins/sub_viewport_preview_editor_plugin.h b/editor/plugins/sub_viewport_preview_editor_plugin.h
new file mode 100644
index 0000000000..03b8b678d1
--- /dev/null
+++ b/editor/plugins/sub_viewport_preview_editor_plugin.h
@@ -0,0 +1,56 @@
+/*************************************************************************/
+/* sub_viewport_preview_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SUB_VIEWPORT_PREVIEW_EDITOR_PLUGIN_H
+#define SUB_VIEWPORT_PREVIEW_EDITOR_PLUGIN_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "editor/plugins/texture_editor_plugin.h"
+#include "scene/main/viewport.h"
+
+class EditorInspectorPluginSubViewportPreview : public EditorInspectorPluginTexture {
+ GDCLASS(EditorInspectorPluginSubViewportPreview, EditorInspectorPluginTexture);
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class SubViewportPreviewEditorPlugin : public EditorPlugin {
+ GDCLASS(SubViewportPreviewEditorPlugin, EditorPlugin);
+
+public:
+ virtual String get_name() const override { return "SubViewportPreview"; }
+
+ SubViewportPreviewEditorPlugin(EditorNode *p_node);
+};
+
+#endif // SUB_VIEWPORT_PREVIEW_EDITOR_PLUGIN_H
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index d62be993af..faf287b9bd 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -100,7 +100,7 @@ void TextEditor::set_edited_resource(const RES &p_res) {
code_editor->get_text_editor()->clear_undo_history();
code_editor->get_text_editor()->tag_saved_version();
- emit_signal("name_changed");
+ emit_signal(SNAME("name_changed"));
code_editor->update_line_and_column();
}
@@ -149,8 +149,8 @@ void TextEditor::reload_text() {
}
void TextEditor::_validate_script() {
- emit_signal("name_changed");
- emit_signal("edited_script_changed");
+ emit_signal(SNAME("name_changed"));
+ emit_signal(SNAME("edited_script_changed"));
}
void TextEditor::_update_bookmark_list() {
@@ -291,27 +291,27 @@ void TextEditor::_edit_option(int p_op) {
switch (p_op) {
case EDIT_UNDO: {
tx->undo();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_REDO: {
tx->redo();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_CUT: {
tx->cut();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_COPY: {
tx->copy();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_PASTE: {
tx->paste();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_SELECT_ALL: {
tx->select_all();
- tx->call_deferred("grab_focus");
+ tx->call_deferred(SNAME("grab_focus"));
} break;
case EDIT_MOVE_LINE_UP: {
code_editor->move_lines_up();
@@ -328,8 +328,8 @@ void TextEditor::_edit_option(int p_op) {
case EDIT_DELETE_LINE: {
code_editor->delete_lines();
} break;
- case EDIT_CLONE_DOWN: {
- code_editor->clone_lines_down();
+ case EDIT_DUPLICATE_SELECTION: {
+ code_editor->duplicate_selection();
} break;
case EDIT_TOGGLE_FOLD_LINE: {
tx->toggle_foldable_line(tx->cursor_get_line());
@@ -378,12 +378,12 @@ void TextEditor::_edit_option(int p_op) {
// Yep, because it doesn't make sense to instance this dialog for every single script open...
// So this will be delegated to the ScriptEditor.
- emit_signal("search_in_files_requested", selected_text);
+ emit_signal(SNAME("search_in_files_requested"), selected_text);
} break;
case REPLACE_IN_FILES: {
String selected_text = code_editor->get_text_editor()->get_selection_text();
- emit_signal("replace_in_files_requested", selected_text);
+ emit_signal(SNAME("replace_in_files_requested"), selected_text);
} break;
case SEARCH_GOTO_LINE: {
goto_line_dialog->popup_find_line(tx);
@@ -559,7 +559,7 @@ TextEditor::TextEditor() {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_all_lines"), EDIT_FOLD_ALL_LINES);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_indent_to_spaces"), EDIT_CONVERT_INDENT_TO_SPACES);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_indent_to_tabs"), EDIT_CONVERT_INDENT_TO_TABS);
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index 4e667dc676..86a4910ac0 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -66,7 +66,7 @@ private:
EDIT_INDENT_RIGHT,
EDIT_INDENT_LEFT,
EDIT_DELETE_LINE,
- EDIT_CLONE_DOWN,
+ EDIT_DUPLICATE_SELECTION,
EDIT_TO_UPPERCASE,
EDIT_TO_LOWERCASE,
EDIT_CAPITALIZE,
diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp
index 696aa88e23..3987cdd6a0 100644
--- a/editor/plugins/texture_3d_editor_plugin.cpp
+++ b/editor/plugins/texture_3d_editor_plugin.cpp
@@ -50,7 +50,7 @@ void Texture3DEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_DRAW) {
- Ref<Texture2D> checkerboard = get_theme_icon("Checkerboard", "EditorIcons");
+ Ref<Texture2D> checkerboard = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
Size2 size = get_size();
draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
@@ -77,16 +77,17 @@ void Texture3DEditor::_update_material() {
}
void Texture3DEditor::_make_shaders() {
- String shader_3d = ""
- "shader_type canvas_item;\n"
- "uniform sampler3D tex;\n"
- "uniform float layer;\n"
- "void fragment() {\n"
- " COLOR = textureLod(tex,vec3(UV,layer),0.0);\n"
- "}";
-
shader.instantiate();
- shader->set_code(shader_3d);
+ shader->set_code(R"(
+shader_type canvas_item;
+
+uniform sampler3D tex;
+uniform float layer;
+
+void fragment() {
+ COLOR = textureLod(tex, vec3(UV, layer), 0.0);
+}
+)");
material.instantiate();
material->set_shader(shader);
}
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 10b942d9ee..4029d6785c 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -30,132 +30,67 @@
#include "texture_editor_plugin.h"
-#include "core/config/project_settings.h"
-#include "core/io/resource_loader.h"
-#include "editor/editor_settings.h"
+#include "editor/editor_scale.h"
-void TextureEditor::_gui_input(Ref<InputEvent> p_event) {
+TextureRect *TexturePreview::get_texture_display() {
+ return texture_display;
}
-void TextureEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_READY) {
- //get_scene()->connect("node_removed",this,"_node_removed");
- }
-
- if (p_what == NOTIFICATION_DRAW) {
- Ref<Texture2D> checkerboard = get_theme_icon("Checkerboard", "EditorIcons");
- Size2 size = get_size();
-
- draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
-
- int tex_width = texture->get_width() * size.height / texture->get_height();
- int tex_height = size.height;
-
- if (tex_width > size.width) {
- tex_width = size.width;
- tex_height = texture->get_height() * tex_width / texture->get_width();
- }
-
- // Prevent the texture from being unpreviewable after the rescale, so that we can still see something
- if (tex_height <= 0) {
- tex_height = 1;
- }
- if (tex_width <= 0) {
- tex_width = 1;
- }
+TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
+ TextureRect *checkerboard = memnew(TextureRect);
+ checkerboard->set_texture(get_theme_icon("Checkerboard", "EditorIcons"));
+ checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
+ checkerboard->set_texture_repeat(CanvasItem::TEXTURE_REPEAT_ENABLED);
+ checkerboard->set_custom_minimum_size(Size2(0.0, 256.0) * EDSCALE);
+ add_child(checkerboard);
- int ofs_x = (size.width - tex_width) / 2;
- int ofs_y = (size.height - tex_height) / 2;
-
- if (Object::cast_to<CurveTexture>(*texture)) {
- // In the case of CurveTextures we know they are 1 in height, so fill the preview to see the gradient
- ofs_y = 0;
- tex_height = size.height;
- } else if (Object::cast_to<GradientTexture>(*texture)) {
- ofs_y = size.height / 4.0;
- tex_height = size.height / 2.0;
- }
+ texture_display = memnew(TextureRect);
+ texture_display->set_texture(p_texture);
+ texture_display->set_anchors_preset(TextureRect::PRESET_WIDE);
+ texture_display->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
+ texture_display->set_expand(true);
+ add_child(texture_display);
- draw_texture_rect(texture, Rect2(ofs_x, ofs_y, tex_width, tex_height));
-
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ if (p_show_metadata) {
+ Label *metadata_label = memnew(Label);
String format;
- if (Object::cast_to<ImageTexture>(*texture)) {
- format = Image::get_format_name(Object::cast_to<ImageTexture>(*texture)->get_format());
- } else if (Object::cast_to<StreamTexture2D>(*texture)) {
- format = Image::get_format_name(Object::cast_to<StreamTexture2D>(*texture)->get_format());
+ if (Object::cast_to<ImageTexture>(*p_texture)) {
+ format = Image::get_format_name(Object::cast_to<ImageTexture>(*p_texture)->get_format());
+ } else if (Object::cast_to<StreamTexture2D>(*p_texture)) {
+ format = Image::get_format_name(Object::cast_to<StreamTexture2D>(*p_texture)->get_format());
} else {
- format = texture->get_class();
- }
- String text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format;
-
- Size2 rect = font->get_string_size(text, font_size);
-
- Vector2 draw_from = size - rect + Size2(-2, font->get_ascent(font_size) - 2);
- if (draw_from.x < 0) {
- draw_from.x = 0;
+ format = p_texture->get_class();
}
- draw_string(font, draw_from + Vector2(2, 2), text, HALIGN_LEFT, size.width, font_size, Color(0, 0, 0, 0.5));
- draw_string(font, draw_from - Vector2(2, 2), text, HALIGN_LEFT, size.width, font_size, Color(0, 0, 0, 0.5));
- draw_string(font, draw_from, text, HALIGN_LEFT, size.width, font_size, Color(1, 1, 1, 1));
- }
-}
-
-void TextureEditor::_texture_changed() {
- if (!is_visible()) {
- return;
- }
- update();
-}
-
-void TextureEditor::edit(Ref<Texture2D> p_texture) {
- if (!texture.is_null()) {
- texture->disconnect("changed", callable_mp(this, &TextureEditor::_texture_changed));
- }
+ metadata_label->set_text(itos(p_texture->get_width()) + "x" + itos(p_texture->get_height()) + " " + format);
- texture = p_texture;
+ metadata_label->add_theme_font_size_override("font_size", 16 * EDSCALE);
+ metadata_label->add_theme_color_override("font_outline_color", Color::named("black"));
+ metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE);
+ Ref<Font> metadata_label_font = get_theme_font("expression", "EditorFonts");
+ metadata_label->add_theme_font_override("font", metadata_label_font);
- if (!texture.is_null()) {
- texture->connect("changed", callable_mp(this, &TextureEditor::_texture_changed));
- update();
- } else {
- hide();
- }
-}
+ // It's okay that these colors are static since the grid color is static too.
+ metadata_label->add_theme_color_override("font_color", Color::named("white"));
+ metadata_label->add_theme_color_override("font_color_shadow", Color::named("black"));
-void TextureEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_gui_input"), &TextureEditor::_gui_input);
-}
+ metadata_label->add_theme_constant_override("shadow_as_outline", 1);
+ metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END);
+ metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END);
-TextureEditor::TextureEditor() {
- set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED);
- set_custom_minimum_size(Size2(1, 150));
-}
-
-TextureEditor::~TextureEditor() {
- if (!texture.is_null()) {
- texture->disconnect("changed", callable_mp(this, &TextureEditor::_texture_changed));
+ add_child(metadata_label);
}
}
-//
bool EditorInspectorPluginTexture::can_handle(Object *p_object) {
return Object::cast_to<ImageTexture>(p_object) != nullptr || Object::cast_to<AtlasTexture>(p_object) != nullptr || Object::cast_to<StreamTexture2D>(p_object) != nullptr || Object::cast_to<AnimatedTexture>(p_object) != nullptr;
}
void EditorInspectorPluginTexture::parse_begin(Object *p_object) {
- Texture2D *texture = Object::cast_to<Texture2D>(p_object);
- if (!texture) {
- return;
- }
- Ref<Texture2D> m(texture);
+ Ref<Texture> texture(Object::cast_to<Texture>(p_object));
- TextureEditor *editor = memnew(TextureEditor);
- editor->edit(m);
- add_custom_control(editor);
+ add_custom_control(memnew(TexturePreview(texture, true)));
}
TextureEditorPlugin::TextureEditorPlugin(EditorNode *p_node) {
diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h
index ebe8882194..165090be93 100644
--- a/editor/plugins/texture_editor_plugin.h
+++ b/editor/plugins/texture_editor_plugin.h
@@ -35,21 +35,15 @@
#include "editor/editor_plugin.h"
#include "scene/resources/texture.h"
-class TextureEditor : public Control {
- GDCLASS(TextureEditor, Control);
+class TexturePreview : public MarginContainer {
+ GDCLASS(TexturePreview, MarginContainer);
- Ref<Texture2D> texture;
-
-protected:
- void _notification(int p_what);
- void _gui_input(Ref<InputEvent> p_event);
- void _texture_changed();
- static void _bind_methods();
+private:
+ TextureRect *texture_display;
public:
- void edit(Ref<Texture2D> p_texture);
- TextureEditor();
- ~TextureEditor();
+ TextureRect *get_texture_display();
+ TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata);
};
class EditorInspectorPluginTexture : public EditorInspectorPlugin {
diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp
index 3f46cd64a2..80359452ac 100644
--- a/editor/plugins/texture_layered_editor_plugin.cpp
+++ b/editor/plugins/texture_layered_editor_plugin.cpp
@@ -58,7 +58,7 @@ void TextureLayeredEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_DRAW) {
- Ref<Texture2D> checkerboard = get_theme_icon("Checkerboard", "EditorIcons");
+ Ref<Texture2D> checkerboard = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
Size2 size = get_size();
draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
@@ -104,43 +104,46 @@ void TextureLayeredEditor::_update_material() {
}
void TextureLayeredEditor::_make_shaders() {
- String shader_2d_array = ""
- "shader_type canvas_item;\n"
- "uniform sampler2DArray tex;\n"
- "uniform float layer;\n"
- "void fragment() {\n"
- " COLOR = textureLod(tex,vec3(UV,layer),0.0);\n"
- "}";
-
shaders[0].instantiate();
- shaders[0]->set_code(shader_2d_array);
-
- String shader_cube = ""
- "shader_type canvas_item;\n"
- "uniform samplerCube tex;\n"
- "uniform vec3 normal;\n"
- "uniform mat3 rot;\n"
- "void fragment() {\n"
- " vec3 n = rot * normalize(vec3(normal.xy*(UV * 2.0 - 1.0),normal.z));\n"
- " COLOR = textureLod(tex,n,0.0);\n"
- "}";
+ shaders[0]->set_code(R"(
+shader_type canvas_item;
+
+uniform sampler2DArray tex;
+uniform float layer;
+
+void fragment() {
+ COLOR = textureLod(tex, vec3(UV, layer), 0.0);
+}
+)");
shaders[1].instantiate();
- shaders[1]->set_code(shader_cube);
-
- String shader_cube_array = ""
- "shader_type canvas_item;\n"
- "uniform samplerCubeArray tex;\n"
- "uniform vec3 normal;\n"
- "uniform mat3 rot;\n"
- "uniform float layer;\n"
- "void fragment() {\n"
- " vec3 n = rot * normalize(vec3(normal.xy*(UV * 2.0 - 1.0),normal.z));\n"
- " COLOR = textureLod(tex,vec4(n,layer),0.0);\n"
- "}";
+ shaders[1]->set_code(R"(
+shader_type canvas_item;
+
+uniform samplerCube tex;
+uniform vec3 normal;
+uniform mat3 rot;
+
+void fragment() {
+ vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z));
+ COLOR = textureLod(tex, n, 0.0);
+}
+)");
shaders[2].instantiate();
- shaders[2]->set_code(shader_cube_array);
+ shaders[2]->set_code(R"(
+shader_type canvas_item;
+
+uniform samplerCubeArray tex;
+uniform vec3 normal;
+uniform mat3 rot;
+uniform float layer;
+
+void fragment() {
+ vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z));
+ COLOR = textureLod(tex, vec4(n, layer), 0.0);
+}
+)");
for (int i = 0; i < 3; i++) {
materials[i].instantiate();
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index d0ba68138b..e323f1571d 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -47,14 +47,14 @@ void draw_margin_line(Control *edit_draw, Vector2 from, Vector2 to) {
edit_draw->draw_line(
from,
to,
- EditorNode::get_singleton()->get_theme_base()->get_theme_color("mono_color", "Editor").inverted() * Color(1, 1, 1, 0.5),
+ EditorNode::get_singleton()->get_theme_base()->get_theme_color(SNAME("mono_color"), SNAME("Editor")).inverted() * Color(1, 1, 1, 0.5),
Math::round(2 * EDSCALE));
while ((to - from).length_squared() > 200) {
edit_draw->draw_line(
from,
from + line,
- EditorNode::get_singleton()->get_theme_base()->get_theme_color("mono_color", "Editor"),
+ EditorNode::get_singleton()->get_theme_base()->get_theme_color(SNAME("mono_color"), SNAME("Editor")),
Math::round(2 * EDSCALE));
from += line * 2;
@@ -159,7 +159,7 @@ void TextureRegionEditor::_region_draw() {
}
}
- Ref<Texture2D> select_handle = get_theme_icon("EditorHandle", "EditorIcons");
+ Ref<Texture2D> select_handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
Rect2 scroll_rect(Point2(), base_tex->get_size());
@@ -175,7 +175,7 @@ void TextureRegionEditor::_region_draw() {
mtx.basis_xform(raw_endpoints[2]),
mtx.basis_xform(raw_endpoints[3])
};
- Color color = get_theme_color("mono_color", "Editor");
+ Color color = get_theme_color(SNAME("mono_color"), SNAME("Editor"));
for (int i = 0; i < 4; i++) {
int prev = (i + 3) % 4;
int next = (i + 1) % 4;
@@ -799,12 +799,12 @@ void TextureRegionEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- edit_draw->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
+ edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
} break;
case NOTIFICATION_READY: {
- zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
- zoom_reset->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
- zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
+ zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons")));
+ zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons")));
+ zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 4ab5887cd7..9338ea6ddd 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -127,7 +127,7 @@ void ThemeItemImportTree::_update_items_tree() {
switch (dt) {
case Theme::DATA_TYPE_COLOR:
- data_type_node->set_icon(0, get_theme_icon("Color", "EditorIcons"));
+ data_type_node->set_icon(0, get_theme_icon(SNAME("Color"), SNAME("EditorIcons")));
data_type_node->set_text(0, TTR("Colors"));
item_list = &tree_color_items;
@@ -135,7 +135,7 @@ void ThemeItemImportTree::_update_items_tree() {
break;
case Theme::DATA_TYPE_CONSTANT:
- data_type_node->set_icon(0, get_theme_icon("MemberConstant", "EditorIcons"));
+ data_type_node->set_icon(0, get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons")));
data_type_node->set_text(0, TTR("Constants"));
item_list = &tree_constant_items;
@@ -143,7 +143,7 @@ void ThemeItemImportTree::_update_items_tree() {
break;
case Theme::DATA_TYPE_FONT:
- data_type_node->set_icon(0, get_theme_icon("Font", "EditorIcons"));
+ data_type_node->set_icon(0, get_theme_icon(SNAME("Font"), SNAME("EditorIcons")));
data_type_node->set_text(0, TTR("Fonts"));
item_list = &tree_font_items;
@@ -151,7 +151,7 @@ void ThemeItemImportTree::_update_items_tree() {
break;
case Theme::DATA_TYPE_FONT_SIZE:
- data_type_node->set_icon(0, get_theme_icon("FontSize", "EditorIcons"));
+ data_type_node->set_icon(0, get_theme_icon(SNAME("FontSize"), SNAME("EditorIcons")));
data_type_node->set_text(0, TTR("Font Sizes"));
item_list = &tree_font_size_items;
@@ -159,7 +159,7 @@ void ThemeItemImportTree::_update_items_tree() {
break;
case Theme::DATA_TYPE_ICON:
- data_type_node->set_icon(0, get_theme_icon("ImageTexture", "EditorIcons"));
+ data_type_node->set_icon(0, get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")));
data_type_node->set_text(0, TTR("Icons"));
item_list = &tree_icon_items;
@@ -167,7 +167,7 @@ void ThemeItemImportTree::_update_items_tree() {
break;
case Theme::DATA_TYPE_STYLEBOX:
- data_type_node->set_icon(0, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ data_type_node->set_icon(0, get_theme_icon(SNAME("StyleBoxFlat"), SNAME("EditorIcons")));
data_type_node->set_text(0, TTR("Styleboxes"));
item_list = &tree_stylebox_items;
@@ -821,7 +821,7 @@ void ThemeItemImportTree::_import_selected() {
ProgressDialog::get_singleton()->task_step("import_theme_items", TTR("Finalizing"), idx++);
ProgressDialog::get_singleton()->end_task("import_theme_items");
- emit_signal("items_imported");
+ emit_signal(SNAME("items_imported"));
}
void ThemeItemImportTree::set_edited_theme(const Ref<Theme> &p_theme) {
@@ -854,47 +854,47 @@ void ThemeItemImportTree::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- select_icons_warning_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons"));
- select_icons_warning->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"));
+ select_icons_warning_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
+ select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
// Bottom panel buttons.
- import_collapse_types_button->set_icon(get_theme_icon("CollapseTree", "EditorIcons"));
- import_expand_types_button->set_icon(get_theme_icon("ExpandTree", "EditorIcons"));
+ import_collapse_types_button->set_icon(get_theme_icon(SNAME("CollapseTree"), SNAME("EditorIcons")));
+ import_expand_types_button->set_icon(get_theme_icon(SNAME("ExpandTree"), SNAME("EditorIcons")));
- import_select_all_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
- import_select_full_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
- import_deselect_all_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ import_select_all_button->set_icon(get_theme_icon(SNAME("ThemeSelectAll"), SNAME("EditorIcons")));
+ import_select_full_button->set_icon(get_theme_icon(SNAME("ThemeSelectFull"), SNAME("EditorIcons")));
+ import_deselect_all_button->set_icon(get_theme_icon(SNAME("ThemeDeselectAll"), SNAME("EditorIcons")));
// Side panel buttons.
- select_colors_icon->set_texture(get_theme_icon("Color", "EditorIcons"));
- deselect_all_colors_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
- select_all_colors_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
- select_full_colors_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
-
- select_constants_icon->set_texture(get_theme_icon("MemberConstant", "EditorIcons"));
- deselect_all_constants_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
- select_all_constants_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
- select_full_constants_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
-
- select_fonts_icon->set_texture(get_theme_icon("Font", "EditorIcons"));
- deselect_all_fonts_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
- select_all_fonts_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
- select_full_fonts_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
-
- select_font_sizes_icon->set_texture(get_theme_icon("FontSize", "EditorIcons"));
- deselect_all_font_sizes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
- select_all_font_sizes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
- select_full_font_sizes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
-
- select_icons_icon->set_texture(get_theme_icon("ImageTexture", "EditorIcons"));
- deselect_all_icons_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
- select_all_icons_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
- select_full_icons_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
-
- select_styleboxes_icon->set_texture(get_theme_icon("StyleBoxFlat", "EditorIcons"));
- deselect_all_styleboxes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
- select_all_styleboxes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
- select_full_styleboxes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+ select_colors_icon->set_texture(get_theme_icon(SNAME("Color"), SNAME("EditorIcons")));
+ deselect_all_colors_button->set_icon(get_theme_icon(SNAME("ThemeDeselectAll"), SNAME("EditorIcons")));
+ select_all_colors_button->set_icon(get_theme_icon(SNAME("ThemeSelectAll"), SNAME("EditorIcons")));
+ select_full_colors_button->set_icon(get_theme_icon(SNAME("ThemeSelectFull"), SNAME("EditorIcons")));
+
+ select_constants_icon->set_texture(get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons")));
+ deselect_all_constants_button->set_icon(get_theme_icon(SNAME("ThemeDeselectAll"), SNAME("EditorIcons")));
+ select_all_constants_button->set_icon(get_theme_icon(SNAME("ThemeSelectAll"), SNAME("EditorIcons")));
+ select_full_constants_button->set_icon(get_theme_icon(SNAME("ThemeSelectFull"), SNAME("EditorIcons")));
+
+ select_fonts_icon->set_texture(get_theme_icon(SNAME("Font"), SNAME("EditorIcons")));
+ deselect_all_fonts_button->set_icon(get_theme_icon(SNAME("ThemeDeselectAll"), SNAME("EditorIcons")));
+ select_all_fonts_button->set_icon(get_theme_icon(SNAME("ThemeSelectAll"), SNAME("EditorIcons")));
+ select_full_fonts_button->set_icon(get_theme_icon(SNAME("ThemeSelectFull"), SNAME("EditorIcons")));
+
+ select_font_sizes_icon->set_texture(get_theme_icon(SNAME("FontSize"), SNAME("EditorIcons")));
+ deselect_all_font_sizes_button->set_icon(get_theme_icon(SNAME("ThemeDeselectAll"), SNAME("EditorIcons")));
+ select_all_font_sizes_button->set_icon(get_theme_icon(SNAME("ThemeSelectAll"), SNAME("EditorIcons")));
+ select_full_font_sizes_button->set_icon(get_theme_icon(SNAME("ThemeSelectFull"), SNAME("EditorIcons")));
+
+ select_icons_icon->set_texture(get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")));
+ deselect_all_icons_button->set_icon(get_theme_icon(SNAME("ThemeDeselectAll"), SNAME("EditorIcons")));
+ select_all_icons_button->set_icon(get_theme_icon(SNAME("ThemeSelectAll"), SNAME("EditorIcons")));
+ select_full_icons_button->set_icon(get_theme_icon(SNAME("ThemeSelectFull"), SNAME("EditorIcons")));
+
+ select_styleboxes_icon->set_texture(get_theme_icon(SNAME("StyleBoxFlat"), SNAME("EditorIcons")));
+ deselect_all_styleboxes_button->set_icon(get_theme_icon(SNAME("ThemeDeselectAll"), SNAME("EditorIcons")));
+ select_all_styleboxes_button->set_icon(get_theme_icon(SNAME("ThemeSelectAll"), SNAME("EditorIcons")));
+ select_full_styleboxes_button->set_icon(get_theme_icon(SNAME("ThemeSelectFull"), SNAME("EditorIcons")));
} break;
}
}
@@ -930,11 +930,14 @@ ThemeItemImportTree::ThemeItemImportTree() {
import_items_tree->set_column_title(IMPORT_ITEM, TTR("Import"));
import_items_tree->set_column_title(IMPORT_ITEM_DATA, TTR("With Data"));
import_items_tree->set_column_expand(0, true);
+ import_items_tree->set_column_clip_content(0, true);
import_items_tree->set_column_expand(IMPORT_ITEM, false);
import_items_tree->set_column_expand(IMPORT_ITEM_DATA, false);
- import_items_tree->set_column_min_width(0, 160 * EDSCALE);
- import_items_tree->set_column_min_width(IMPORT_ITEM, 80 * EDSCALE);
- import_items_tree->set_column_min_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
+ import_items_tree->set_column_custom_minimum_width(0, 160 * EDSCALE);
+ import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM, 80 * EDSCALE);
+ import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
+ import_items_tree->set_column_clip_content(1, true);
+ import_items_tree->set_column_clip_content(2, true);
ScrollContainer *import_bulk_sc = memnew(ScrollContainer);
import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE);
@@ -1141,7 +1144,7 @@ ThemeItemImportTree::ThemeItemImportTree() {
select_icons_warning = memnew(Label);
select_icons_warning->set_text(TTR("Caution: Adding icon data may considerably increase the size of your Theme resource."));
- select_icons_warning->set_autowrap(true);
+ select_icons_warning->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
select_icons_warning->set_h_size_flags(Control::SIZE_EXPAND_FILL);
select_icons_warning_hb->add_child(select_icons_warning);
}
@@ -1236,7 +1239,7 @@ void ThemeItemEditorDialog::_update_edit_types() {
for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) {
Ref<Texture2D> item_icon;
if (E->get() == "") {
- item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
+ item_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons"));
} else {
item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
}
@@ -1310,16 +1313,16 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
if (names.size() > 0) {
TreeItem *color_root = edit_items_tree->create_item(root);
color_root->set_metadata(0, Theme::DATA_TYPE_COLOR);
- color_root->set_icon(0, get_theme_icon("Color", "EditorIcons"));
+ color_root->set_icon(0, get_theme_icon(SNAME("Color"), SNAME("EditorIcons")));
color_root->set_text(0, TTR("Colors"));
- color_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Color Items"));
+ color_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Color Items"));
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
TreeItem *item = edit_items_tree->create_item(color_root);
item->set_text(0, E->get());
- item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
- item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
}
}
@@ -1331,16 +1334,16 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
if (names.size() > 0) {
TreeItem *constant_root = edit_items_tree->create_item(root);
constant_root->set_metadata(0, Theme::DATA_TYPE_CONSTANT);
- constant_root->set_icon(0, get_theme_icon("MemberConstant", "EditorIcons"));
+ constant_root->set_icon(0, get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons")));
constant_root->set_text(0, TTR("Constants"));
- constant_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Constant Items"));
+ constant_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Constant Items"));
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
TreeItem *item = edit_items_tree->create_item(constant_root);
item->set_text(0, E->get());
- item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
- item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
}
}
@@ -1352,16 +1355,16 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
if (names.size() > 0) {
TreeItem *font_root = edit_items_tree->create_item(root);
font_root->set_metadata(0, Theme::DATA_TYPE_FONT);
- font_root->set_icon(0, get_theme_icon("Font", "EditorIcons"));
+ font_root->set_icon(0, get_theme_icon(SNAME("Font"), SNAME("EditorIcons")));
font_root->set_text(0, TTR("Fonts"));
- font_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Items"));
+ font_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Items"));
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
TreeItem *item = edit_items_tree->create_item(font_root);
item->set_text(0, E->get());
- item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
- item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
}
}
@@ -1373,16 +1376,16 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
if (names.size() > 0) {
TreeItem *font_size_root = edit_items_tree->create_item(root);
font_size_root->set_metadata(0, Theme::DATA_TYPE_FONT_SIZE);
- font_size_root->set_icon(0, get_theme_icon("FontSize", "EditorIcons"));
+ font_size_root->set_icon(0, get_theme_icon(SNAME("FontSize"), SNAME("EditorIcons")));
font_size_root->set_text(0, TTR("Font Sizes"));
- font_size_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Size Items"));
+ font_size_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Size Items"));
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
TreeItem *item = edit_items_tree->create_item(font_size_root);
item->set_text(0, E->get());
- item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
- item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
}
}
@@ -1394,16 +1397,16 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
if (names.size() > 0) {
TreeItem *icon_root = edit_items_tree->create_item(root);
icon_root->set_metadata(0, Theme::DATA_TYPE_ICON);
- icon_root->set_icon(0, get_theme_icon("ImageTexture", "EditorIcons"));
+ icon_root->set_icon(0, get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")));
icon_root->set_text(0, TTR("Icons"));
- icon_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Icon Items"));
+ icon_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Icon Items"));
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
TreeItem *item = edit_items_tree->create_item(icon_root);
item->set_text(0, E->get());
- item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
- item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
}
}
@@ -1415,16 +1418,16 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
if (names.size() > 0) {
TreeItem *stylebox_root = edit_items_tree->create_item(root);
stylebox_root->set_metadata(0, Theme::DATA_TYPE_STYLEBOX);
- stylebox_root->set_icon(0, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ stylebox_root->set_icon(0, get_theme_icon(SNAME("StyleBoxFlat"), SNAME("EditorIcons")));
stylebox_root->set_text(0, TTR("Styleboxes"));
- stylebox_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All StyleBox Items"));
+ stylebox_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All StyleBox Items"));
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
TreeItem *item = edit_items_tree->create_item(stylebox_root);
item->set_text(0, E->get());
- item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
- item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
}
}
@@ -1456,13 +1459,16 @@ void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_colu
_update_edit_item_tree(edited_item_type);
}
-void ThemeItemEditorDialog::_add_theme_type() {
- edited_theme->add_icon_type(edit_add_type_value->get_text());
- edited_theme->add_stylebox_type(edit_add_type_value->get_text());
- edited_theme->add_font_type(edit_add_type_value->get_text());
- edited_theme->add_font_size_type(edit_add_type_value->get_text());
- edited_theme->add_color_type(edit_add_type_value->get_text());
- edited_theme->add_constant_type(edit_add_type_value->get_text());
+void ThemeItemEditorDialog::_add_theme_type(const String &p_new_text) {
+ const String new_type = edit_add_type_value->get_text().strip_edges();
+ edit_add_type_value->clear();
+
+ edited_theme->add_icon_type(new_type);
+ edited_theme->add_stylebox_type(new_type);
+ edited_theme->add_font_type(new_type);
+ edited_theme->add_font_size_type(new_type);
+ edited_theme->add_color_type(new_type);
+ edited_theme->add_constant_type(new_type);
_update_edit_types();
// Force emit a change so that other parts of the editor can update.
@@ -1715,21 +1721,21 @@ void ThemeItemEditorDialog::_notification(int p_what) {
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
- edit_items_add_color->set_icon(get_theme_icon("Color", "EditorIcons"));
- edit_items_add_constant->set_icon(get_theme_icon("MemberConstant", "EditorIcons"));
- edit_items_add_font->set_icon(get_theme_icon("Font", "EditorIcons"));
- edit_items_add_font_size->set_icon(get_theme_icon("FontSize", "EditorIcons"));
- edit_items_add_icon->set_icon(get_theme_icon("ImageTexture", "EditorIcons"));
- edit_items_add_stylebox->set_icon(get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ edit_items_add_color->set_icon(get_theme_icon(SNAME("Color"), SNAME("EditorIcons")));
+ edit_items_add_constant->set_icon(get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons")));
+ edit_items_add_font->set_icon(get_theme_icon(SNAME("Font"), SNAME("EditorIcons")));
+ edit_items_add_font_size->set_icon(get_theme_icon(SNAME("FontSize"), SNAME("EditorIcons")));
+ edit_items_add_icon->set_icon(get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")));
+ edit_items_add_stylebox->set_icon(get_theme_icon(SNAME("StyleBoxFlat"), SNAME("EditorIcons")));
- edit_items_remove_class->set_icon(get_theme_icon("Control", "EditorIcons"));
- edit_items_remove_custom->set_icon(get_theme_icon("ThemeRemoveCustomItems", "EditorIcons"));
- edit_items_remove_all->set_icon(get_theme_icon("ThemeRemoveAllItems", "EditorIcons"));
+ edit_items_remove_class->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons")));
+ edit_items_remove_custom->set_icon(get_theme_icon(SNAME("ThemeRemoveCustomItems"), SNAME("EditorIcons")));
+ edit_items_remove_all->set_icon(get_theme_icon(SNAME("ThemeRemoveAllItems"), SNAME("EditorIcons")));
- import_another_theme_button->set_icon(get_theme_icon("Folder", "EditorIcons"));
+ import_another_theme_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
- tc->add_theme_style_override("tab_selected", get_theme_stylebox("tab_selected_odd", "TabContainer"));
- tc->add_theme_style_override("panel", get_theme_stylebox("panel_odd", "TabContainer"));
+ tc->add_theme_style_override("tab_selected", get_theme_stylebox(SNAME("tab_selected_odd"), SNAME("TabContainer")));
+ tc->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel_odd"), SNAME("TabContainer")));
} break;
}
}
@@ -1773,11 +1779,12 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_dialog_side_vb->add_child(edit_add_type_hb);
edit_add_type_value = memnew(LineEdit);
edit_add_type_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ edit_add_type_value->connect("text_submitted", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type));
edit_add_type_hb->add_child(edit_add_type_value);
Button *edit_add_type_button = memnew(Button);
edit_add_type_button->set_text(TTR("Add"));
edit_add_type_hb->add_child(edit_add_type_button);
- edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type));
+ edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type), varray(""));
VBoxContainer *edit_items_vb = memnew(VBoxContainer);
edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -1940,6 +1947,123 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog));
}
+void ThemeTypeDialog::_dialog_about_to_show() {
+ add_type_filter->set_text("");
+ add_type_filter->grab_focus();
+
+ _update_add_type_options();
+}
+
+void ThemeTypeDialog::ok_pressed() {
+ emit_signal(SNAME("type_selected"), add_type_filter->get_text().strip_edges());
+}
+
+void ThemeTypeDialog::_update_add_type_options(const String &p_filter) {
+ add_type_options->clear();
+
+ List<StringName> names;
+ Theme::get_default()->get_type_list(&names);
+ if (include_own_types) {
+ edited_theme->get_type_list(&names);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+
+ Vector<StringName> unique_names;
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ // Filter out undesired values.
+ if (!p_filter.is_subsequence_ofi(String(E->get()))) {
+ continue;
+ }
+
+ // Skip duplicate values.
+ if (unique_names.has(E->get())) {
+ continue;
+ }
+ unique_names.append(E->get());
+
+ Ref<Texture2D> item_icon;
+ if (E->get() == "") {
+ item_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons"));
+ } else {
+ item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ }
+
+ add_type_options->add_item(E->get(), item_icon);
+ }
+}
+
+void ThemeTypeDialog::_add_type_filter_cbk(const String &p_value) {
+ _update_add_type_options(p_value);
+}
+
+void ThemeTypeDialog::_add_type_options_cbk(int p_index) {
+ add_type_filter->set_text(add_type_options->get_item_text(p_index));
+}
+
+void ThemeTypeDialog::_add_type_dialog_entered(const String &p_value) {
+ emit_signal(SNAME("type_selected"), p_value.strip_edges());
+ hide();
+}
+
+void ThemeTypeDialog::_add_type_dialog_activated(int p_index) {
+ emit_signal(SNAME("type_selected"), add_type_options->get_item_text(p_index));
+ hide();
+}
+
+void ThemeTypeDialog::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ connect("about_to_popup", callable_mp(this, &ThemeTypeDialog::_dialog_about_to_show));
+ [[fallthrough]];
+ }
+ case NOTIFICATION_THEME_CHANGED: {
+ _update_add_type_options();
+ } break;
+
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (is_visible()) {
+ add_type_filter->grab_focus();
+ }
+ } break;
+ }
+}
+
+void ThemeTypeDialog::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("type_selected", PropertyInfo(Variant::STRING, "type_name")));
+}
+
+void ThemeTypeDialog::set_edited_theme(const Ref<Theme> &p_theme) {
+ edited_theme = p_theme;
+}
+
+void ThemeTypeDialog::set_include_own_types(bool p_enable) {
+ include_own_types = p_enable;
+}
+
+ThemeTypeDialog::ThemeTypeDialog() {
+ VBoxContainer *add_type_vb = memnew(VBoxContainer);
+ add_child(add_type_vb);
+
+ Label *add_type_filter_label = memnew(Label);
+ add_type_filter_label->set_text(TTR("Name:"));
+ add_type_vb->add_child(add_type_filter_label);
+
+ add_type_filter = memnew(LineEdit);
+ add_type_vb->add_child(add_type_filter);
+ add_type_filter->connect("text_changed", callable_mp(this, &ThemeTypeDialog::_add_type_filter_cbk));
+ add_type_filter->connect("text_submitted", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_entered));
+
+ Label *add_type_options_label = memnew(Label);
+ add_type_options_label->set_text(TTR("Node Types:"));
+ add_type_vb->add_child(add_type_options_label);
+
+ add_type_options = memnew(ItemList);
+ add_type_options->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_type_vb->add_child(add_type_options);
+ add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeDialog::_add_type_options_cbk));
+ add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_activated));
+}
+
VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
VBoxContainer *items_tab = memnew(VBoxContainer);
items_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
@@ -2011,7 +2135,7 @@ void ThemeTypeEditor::_update_type_list() {
for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) {
Ref<Texture2D> item_icon;
if (E->get() == "") {
- item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
+ item_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons"));
} else {
item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
}
@@ -2045,36 +2169,18 @@ void ThemeTypeEditor::_update_type_list_debounced() {
update_debounce_timer->start();
}
-void ThemeTypeEditor::_update_add_type_options(const String &p_filter) {
- add_type_options->clear();
-
- List<StringName> names;
- Theme::get_default()->get_type_list(&names);
- names.sort_custom<StringName::AlphCompare>();
-
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!p_filter.is_subsequence_ofi(String(E->get()))) {
- continue;
- }
-
- Ref<Texture2D> item_icon;
- if (E->get() == "") {
- item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
- } else {
- item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
- }
-
- add_type_options->add_item(E->get(), item_icon);
- }
-}
-
OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) {
OrderedHashMap<StringName, bool> items;
List<StringName> names;
if (include_default) {
names.clear();
- (Theme::get_default().operator->()->*get_list_func)(p_type_name, &names);
+ String default_type = p_type_name;
+ if (edited_theme->get_type_variation_base(p_type_name) != StringName()) {
+ default_type = edited_theme->get_type_variation_base(p_type_name);
+ }
+
+ (Theme::get_default().operator->()->*get_list_func)(default_type, &names);
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
items[E->get()] = false;
@@ -2128,21 +2234,21 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_
item_name_edit->hide();
Button *item_rename_button = memnew(Button);
- item_rename_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
+ item_rename_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
item_rename_button->set_tooltip(TTR("Rename Item"));
item_rename_button->set_flat(true);
item_name_container->add_child(item_rename_button);
item_rename_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_cbk), varray(p_data_type, p_item_name, item_name_container));
Button *item_remove_button = memnew(Button);
- item_remove_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ item_remove_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
item_remove_button->set_tooltip(TTR("Remove Item"));
item_remove_button->set_flat(true);
item_name_container->add_child(item_remove_button);
item_remove_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_remove_cbk), varray(p_data_type, p_item_name));
Button *item_rename_confirm_button = memnew(Button);
- item_rename_confirm_button->set_icon(get_theme_icon("ImportCheck", "EditorIcons"));
+ item_rename_confirm_button->set_icon(get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons")));
item_rename_confirm_button->set_tooltip(TTR("Confirm Item Rename"));
item_rename_confirm_button->set_flat(true);
item_name_container->add_child(item_rename_confirm_button);
@@ -2150,17 +2256,17 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_
item_rename_confirm_button->hide();
Button *item_rename_cancel_button = memnew(Button);
- item_rename_cancel_button->set_icon(get_theme_icon("ImportFail", "EditorIcons"));
+ item_rename_cancel_button->set_icon(get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons")));
item_rename_cancel_button->set_tooltip(TTR("Cancel Item Rename"));
item_rename_cancel_button->set_flat(true);
item_name_container->add_child(item_rename_cancel_button);
item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled), varray(p_data_type, p_item_name, item_name_container));
item_rename_cancel_button->hide();
} else {
- item_name->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"));
+ item_name->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
Button *item_override_button = memnew(Button);
- item_override_button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ item_override_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
item_override_button->set_tooltip(TTR("Override Item"));
item_override_button->set_flat(true);
item_name_container->add_child(item_override_button);
@@ -2369,7 +2475,7 @@ void ThemeTypeEditor::_update_type_items() {
pin_leader_button->set_flat(true);
pin_leader_button->set_toggle_mode(true);
pin_leader_button->set_pressed(true);
- pin_leader_button->set_icon(get_theme_icon("Pin", "EditorIcons"));
+ pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
pin_leader_button->set_tooltip(TTR("Unpin this StyleBox as a main style."));
item_control->add_child(pin_leader_button);
pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_unpin_leading_stylebox));
@@ -2414,7 +2520,7 @@ void ThemeTypeEditor::_update_type_items() {
Button *pin_leader_button = memnew(Button);
pin_leader_button->set_flat(true);
pin_leader_button->set_toggle_mode(true);
- pin_leader_button->set_icon(get_theme_icon("Pin", "EditorIcons"));
+ pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type."));
item_control->add_child(pin_leader_button);
pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_pin_leading_stylebox), varray(item_editor, E.key()));
@@ -2432,6 +2538,20 @@ void ThemeTypeEditor::_update_type_items() {
stylebox_items_list->add_child(item_control);
}
}
+
+ // Various type settings.
+ if (ClassDB::class_exists(edited_type)) {
+ type_variation_edit->set_editable(false);
+ type_variation_edit->set_tooltip(TTR("A type associated with a built-in class cannot be marked as a variation of another type."));
+ type_variation_edit->set_text("");
+ type_variation_button->hide();
+ } else {
+ type_variation_edit->set_editable(true);
+ type_variation_edit->set_tooltip("");
+ type_variation_edit->set_text(edited_theme->get_type_variation_base(edited_type));
+ _add_focusable(type_variation_edit);
+ type_variation_button->show();
+ }
}
void ThemeTypeEditor::_list_type_selected(int p_index) {
@@ -2440,34 +2560,18 @@ void ThemeTypeEditor::_list_type_selected(int p_index) {
}
void ThemeTypeEditor::_add_type_button_cbk() {
+ add_type_mode = ADD_THEME_TYPE;
+ add_type_dialog->set_title(TTR("Add Item Type"));
+ add_type_dialog->set_include_own_types(false);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
- add_type_filter->grab_focus();
-}
-
-void ThemeTypeEditor::_add_type_filter_cbk(const String &p_value) {
- _update_add_type_options(p_value);
-}
-
-void ThemeTypeEditor::_add_type_options_cbk(int p_index) {
- add_type_filter->set_text(add_type_options->get_item_text(p_index));
-}
-
-void ThemeTypeEditor::_add_type_dialog_confirmed() {
- select_type(add_type_filter->get_text().strip_edges());
-}
-
-void ThemeTypeEditor::_add_type_dialog_entered(const String &p_value) {
- select_type(p_value.strip_edges());
- add_type_dialog->hide();
-}
-
-void ThemeTypeEditor::_add_type_dialog_activated(int p_index) {
- select_type(add_type_options->get_item_text(p_index));
- add_type_dialog->hide();
}
void ThemeTypeEditor::_add_default_type_items() {
List<StringName> names;
+ String default_type = edited_type;
+ if (edited_theme->get_type_variation_base(edited_type) != StringName()) {
+ default_type = edited_theme->get_type_variation_base(edited_type);
+ }
updating = true;
// Prevent changes from immediatelly being reported while the operation is still ongoing.
@@ -2475,7 +2579,7 @@ void ThemeTypeEditor::_add_default_type_items() {
{
names.clear();
- Theme::get_default()->get_icon_list(edited_type, &names);
+ Theme::get_default()->get_icon_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_icon(E->get(), edited_type)) {
edited_theme->set_icon(E->get(), edited_type, Ref<Texture2D>());
@@ -2484,7 +2588,7 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
- Theme::get_default()->get_stylebox_list(edited_type, &names);
+ Theme::get_default()->get_stylebox_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_stylebox(E->get(), edited_type)) {
edited_theme->set_stylebox(E->get(), edited_type, Ref<StyleBox>());
@@ -2493,7 +2597,7 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
- Theme::get_default()->get_font_list(edited_type, &names);
+ Theme::get_default()->get_font_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_font(E->get(), edited_type)) {
edited_theme->set_font(E->get(), edited_type, Ref<Font>());
@@ -2502,28 +2606,28 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
- Theme::get_default()->get_font_size_list(edited_type, &names);
+ Theme::get_default()->get_font_size_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_font_size(E->get(), edited_type)) {
- edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), edited_type));
+ edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), default_type));
}
}
}
{
names.clear();
- Theme::get_default()->get_color_list(edited_type, &names);
+ Theme::get_default()->get_color_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_color(E->get(), edited_type)) {
- edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), edited_type));
+ edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), default_type));
}
}
}
{
names.clear();
- Theme::get_default()->get_constant_list(edited_type, &names);
+ Theme::get_default()->get_constant_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_constant(E->get(), edited_type)) {
- edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), edited_type));
+ edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), default_type));
}
}
}
@@ -2814,23 +2918,48 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
edited_theme->_unfreeze_and_propagate_changes();
}
+void ThemeTypeEditor::_type_variation_changed(const String p_value) {
+ if (p_value.is_empty()) {
+ edited_theme->clear_type_variation(edited_type);
+ } else {
+ edited_theme->set_type_variation(edited_type, StringName(p_value));
+ }
+}
+
+void ThemeTypeEditor::_add_type_variation_cbk() {
+ add_type_mode = ADD_VARIATION_BASE;
+ add_type_dialog->set_title(TTR("Add Variation Base Type"));
+ add_type_dialog->set_include_own_types(true);
+ add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
+}
+
+void ThemeTypeEditor::_add_type_dialog_selected(const String p_type_name) {
+ if (add_type_mode == ADD_THEME_TYPE) {
+ select_type(p_type_name);
+ } else if (add_type_mode == ADD_VARIATION_BASE) {
+ _type_variation_changed(p_type_name);
+ _update_type_items();
+ }
+}
+
void ThemeTypeEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- add_type_button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ add_type_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- data_type_tabs->set_tab_icon(0, get_theme_icon("Color", "EditorIcons"));
- data_type_tabs->set_tab_icon(1, get_theme_icon("MemberConstant", "EditorIcons"));
- data_type_tabs->set_tab_icon(2, get_theme_icon("Font", "EditorIcons"));
- data_type_tabs->set_tab_icon(3, get_theme_icon("FontSize", "EditorIcons"));
- data_type_tabs->set_tab_icon(4, get_theme_icon("ImageTexture", "EditorIcons"));
- data_type_tabs->set_tab_icon(5, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ data_type_tabs->set_tab_icon(0, get_theme_icon(SNAME("Color"), SNAME("EditorIcons")));
+ data_type_tabs->set_tab_icon(1, get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons")));
+ data_type_tabs->set_tab_icon(2, get_theme_icon(SNAME("Font"), SNAME("EditorIcons")));
+ data_type_tabs->set_tab_icon(3, get_theme_icon(SNAME("FontSize"), SNAME("EditorIcons")));
+ data_type_tabs->set_tab_icon(4, get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")));
+ data_type_tabs->set_tab_icon(5, get_theme_icon(SNAME("StyleBoxFlat"), SNAME("EditorIcons")));
+ data_type_tabs->set_tab_icon(6, get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
- data_type_tabs->add_theme_style_override("tab_selected", get_theme_stylebox("tab_selected_odd", "TabContainer"));
- data_type_tabs->add_theme_style_override("panel", get_theme_stylebox("panel_odd", "TabContainer"));
+ data_type_tabs->add_theme_style_override("tab_selected", get_theme_stylebox(SNAME("tab_selected_odd"), SNAME("TabContainer")));
+ data_type_tabs->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel_odd"), SNAME("TabContainer")));
- _update_add_type_options();
+ type_variation_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
}
}
@@ -2843,6 +2972,8 @@ void ThemeTypeEditor::set_edited_theme(const Ref<Theme> &p_theme) {
edited_theme = p_theme;
edited_theme->connect("changed", callable_mp(this, &ThemeTypeEditor::_update_type_list_debounced));
_update_type_list();
+
+ add_type_dialog->set_edited_theme(edited_theme);
}
void ThemeTypeEditor::select_type(String p_type_name) {
@@ -2889,34 +3020,10 @@ ThemeTypeEditor::ThemeTypeEditor() {
theme_type_list->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_list_type_selected));
add_type_button = memnew(Button);
- add_type_button->set_tooltip(TTR("Add Type"));
+ add_type_button->set_tooltip(TTR("Add a type from a list of available types or create a new one."));
type_list_hb->add_child(add_type_button);
add_type_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_button_cbk));
- add_type_dialog = memnew(ConfirmationDialog);
- add_type_dialog->set_title(TTR("Add Item Type"));
- type_list_hb->add_child(add_type_dialog);
- add_type_dialog->connect("confirmed", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_confirmed));
-
- VBoxContainer *add_type_vb = memnew(VBoxContainer);
- add_type_dialog->add_child(add_type_vb);
-
- Label *add_type_filter_label = memnew(Label);
- add_type_filter_label->set_text(TTR("Name:"));
- add_type_vb->add_child(add_type_filter_label);
- add_type_filter = memnew(LineEdit);
- add_type_vb->add_child(add_type_filter);
- add_type_filter->connect("text_changed", callable_mp(this, &ThemeTypeEditor::_add_type_filter_cbk));
- add_type_filter->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_entered));
- Label *add_type_options_label = memnew(Label);
- add_type_options_label->set_text(TTR("Node Types:"));
- add_type_vb->add_child(add_type_options_label);
- add_type_options = memnew(ItemList);
- add_type_options->set_v_size_flags(SIZE_EXPAND_FILL);
- add_type_vb->add_child(add_type_options);
- add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_add_type_options_cbk));
- add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_activated));
-
HBoxContainer *type_controls = memnew(HBoxContainer);
main_vb->add_child(type_controls);
@@ -2947,6 +3054,39 @@ ThemeTypeEditor::ThemeTypeEditor() {
icon_items_list = _create_item_list(Theme::DATA_TYPE_ICON);
stylebox_items_list = _create_item_list(Theme::DATA_TYPE_STYLEBOX);
+ VBoxContainer *type_settings_tab = memnew(VBoxContainer);
+ type_settings_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
+ data_type_tabs->add_child(type_settings_tab);
+ data_type_tabs->set_tab_title(data_type_tabs->get_tab_count() - 1, "");
+
+ ScrollContainer *type_settings_sc = memnew(ScrollContainer);
+ type_settings_sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ type_settings_sc->set_enable_h_scroll(false);
+ type_settings_tab->add_child(type_settings_sc);
+ VBoxContainer *type_settings_list = memnew(VBoxContainer);
+ type_settings_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ type_settings_sc->add_child(type_settings_list);
+
+ HBoxContainer *type_variation_hb = memnew(HBoxContainer);
+ type_settings_list->add_child(type_variation_hb);
+ Label *type_variation_label = memnew(Label);
+ type_variation_hb->add_child(type_variation_label);
+ type_variation_label->set_text(TTR("Base Type"));
+ type_variation_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ type_variation_edit = memnew(LineEdit);
+ type_variation_hb->add_child(type_variation_edit);
+ type_variation_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ type_variation_edit->connect("text_changed", callable_mp(this, &ThemeTypeEditor::_type_variation_changed));
+ type_variation_edit->connect("focus_exited", callable_mp(this, &ThemeTypeEditor::_update_type_items));
+ type_variation_button = memnew(Button);
+ type_variation_hb->add_child(type_variation_button);
+ type_variation_button->set_tooltip(TTR("Select the variation base type from a list of available types."));
+ type_variation_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_variation_cbk));
+
+ add_type_dialog = memnew(ThemeTypeDialog);
+ add_child(add_type_dialog);
+ add_type_dialog->connect("type_selected", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_selected));
+
update_debounce_timer = memnew(Timer);
update_debounce_timer->set_one_shot(true);
update_debounce_timer->set_wait_time(0.5);
@@ -3003,7 +3143,7 @@ void ThemeEditor::_preview_scene_dialog_cbk(const String &p_path) {
return;
}
- _add_preview_tab(preview_tab, p_path.get_file(), get_theme_icon("PackedScene", "EditorIcons"));
+ _add_preview_tab(preview_tab, p_path.get_file(), get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")));
preview_tab->connect("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid), varray(preview_tab));
preview_tab->connect("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab), varray(preview_tab));
}
@@ -3013,7 +3153,7 @@ void ThemeEditor::_add_preview_tab(ThemeEditorPreview *p_preview_tab, const Stri
preview_tabs->add_tab(p_preview_name, p_icon);
preview_tabs_content->add_child(p_preview_tab);
- preview_tabs->set_tab_right_button(preview_tabs->get_tab_count() - 1, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("close", "Tabs"));
+ preview_tabs->set_tab_right_button(preview_tabs->get_tab_count() - 1, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("close"), SNAME("Tabs")));
p_preview_tab->connect("control_picked", callable_mp(this, &ThemeEditor::_preview_control_picked));
preview_tabs->set_current_tab(preview_tabs->get_tab_count() - 1);
@@ -3076,11 +3216,11 @@ void ThemeEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- preview_tabs->add_theme_style_override("tab_selected", get_theme_stylebox("ThemeEditorPreviewFG", "EditorStyles"));
- preview_tabs->add_theme_style_override("tab_unselected", get_theme_stylebox("ThemeEditorPreviewBG", "EditorStyles"));
- preview_tabs_content->add_theme_style_override("panel", get_theme_stylebox("panel_odd", "TabContainer"));
+ preview_tabs->add_theme_style_override("tab_selected", get_theme_stylebox(SNAME("ThemeEditorPreviewFG"), SNAME("EditorStyles")));
+ preview_tabs->add_theme_style_override("tab_unselected", get_theme_stylebox(SNAME("ThemeEditorPreviewBG"), SNAME("EditorStyles")));
+ preview_tabs_content->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel_odd"), SNAME("TabContainer")));
- add_preview_button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ add_preview_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
}
}
@@ -3091,6 +3231,7 @@ ThemeEditor::ThemeEditor() {
theme_name = memnew(Label);
theme_name->set_text(TTR("Theme") + ": ");
+ theme_name->set_theme_type_variation("HeaderSmall");
top_menu->add_child(theme_name);
top_menu->add_spacer(false);
@@ -3168,7 +3309,7 @@ ThemeEditor::ThemeEditor() {
theme_type_editor = memnew(ThemeTypeEditor);
main_hs->add_child(theme_type_editor);
- theme_type_editor->set_custom_minimum_size(Size2(360, 0) * EDSCALE);
+ theme_type_editor->set_custom_minimum_size(Size2(280, 0) * EDSCALE);
}
void ThemeEditorPlugin::edit(Object *p_node) {
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index cdedbbec8d..e78b244a42 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -239,7 +239,7 @@ class ThemeItemEditorDialog : public AcceptDialog {
void _update_edit_item_tree(String p_item_type);
void _item_tree_button_pressed(Object *p_item, int p_column, int p_id);
- void _add_theme_type();
+ void _add_theme_type(const String &p_new_text);
void _add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type);
void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type);
void _remove_class_items();
@@ -263,6 +263,36 @@ public:
ThemeItemEditorDialog();
};
+class ThemeTypeDialog : public ConfirmationDialog {
+ GDCLASS(ThemeTypeDialog, ConfirmationDialog);
+
+ Ref<Theme> edited_theme;
+ bool include_own_types = false;
+
+ LineEdit *add_type_filter;
+ ItemList *add_type_options;
+
+ void _dialog_about_to_show();
+ void ok_pressed() override;
+
+ void _update_add_type_options(const String &p_filter = "");
+
+ void _add_type_filter_cbk(const String &p_value);
+ void _add_type_options_cbk(int p_index);
+ void _add_type_dialog_entered(const String &p_value);
+ void _add_type_dialog_activated(int p_index);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_edited_theme(const Ref<Theme> &p_theme);
+ void set_include_own_types(bool p_enable);
+
+ ThemeTypeDialog();
+};
+
class ThemeTypeEditor : public MarginContainer {
GDCLASS(ThemeTypeEditor, MarginContainer);
@@ -281,9 +311,6 @@ class ThemeTypeEditor : public MarginContainer {
OptionButton *theme_type_list;
Button *add_type_button;
- ConfirmationDialog *add_type_dialog;
- LineEdit *add_type_filter;
- ItemList *add_type_options;
CheckButton *show_default_items_button;
@@ -295,13 +322,23 @@ class ThemeTypeEditor : public MarginContainer {
VBoxContainer *icon_items_list;
VBoxContainer *stylebox_items_list;
+ LineEdit *type_variation_edit;
+ Button *type_variation_button;
+
+ enum TypeDialogMode {
+ ADD_THEME_TYPE,
+ ADD_VARIATION_BASE,
+ };
+
+ TypeDialogMode add_type_mode = ADD_THEME_TYPE;
+ ThemeTypeDialog *add_type_dialog;
+
Vector<Control *> focusables;
Timer *update_debounce_timer;
VBoxContainer *_create_item_list(Theme::DataType p_data_type);
void _update_type_list();
void _update_type_list_debounced();
- void _update_add_type_options(const String &p_filter = "");
OrderedHashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default);
HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable);
void _add_focusable(Control *p_control);
@@ -310,11 +347,6 @@ class ThemeTypeEditor : public MarginContainer {
void _list_type_selected(int p_index);
void _select_type(String p_type_name);
void _add_type_button_cbk();
- void _add_type_filter_cbk(const String &p_value);
- void _add_type_options_cbk(int p_index);
- void _add_type_dialog_confirmed();
- void _add_type_dialog_entered(const String &p_value);
- void _add_type_dialog_activated(int p_index);
void _add_default_type_items();
void _item_add_cbk(int p_data_type, Control *p_control);
@@ -337,6 +369,11 @@ class ThemeTypeEditor : public MarginContainer {
void _unpin_leading_stylebox();
void _update_stylebox_from_leading();
+ void _type_variation_changed(const String p_value);
+ void _add_type_variation_cbk();
+
+ void _add_type_dialog_selected(const String p_type_name);
+
protected:
void _notification(int p_what);
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index 0b02150444..801ee0eac2 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -76,7 +76,7 @@ void ThemeEditorPreview::_picker_button_cbk() {
Control *ThemeEditorPreview::_find_hovered_control(Control *p_parent, Vector2 p_mouse_position) {
Control *found = nullptr;
- for (int i = 0; i < p_parent->get_child_count(); i++) {
+ for (int i = p_parent->get_child_count() - 1; i >= 0; i--) {
Control *cc = Object::cast_to<Control>(p_parent->get_child(i));
if (!cc || !cc->is_visible()) {
continue;
@@ -105,12 +105,35 @@ void ThemeEditorPreview::_draw_picker_overlay() {
return;
}
- picker_overlay->draw_rect(Rect2(Vector2(0.0, 0.0), picker_overlay->get_size()), get_theme_color("preview_picker_overlay_color", "ThemeEditor"));
+ picker_overlay->draw_rect(Rect2(Vector2(0.0, 0.0), picker_overlay->get_size()), theme_cache.preview_picker_overlay_color);
if (hovered_control) {
Rect2 highlight_rect = hovered_control->get_global_rect();
highlight_rect.position = picker_overlay->get_global_transform().affine_inverse().xform(highlight_rect.position);
+ picker_overlay->draw_style_box(theme_cache.preview_picker_overlay, highlight_rect);
- picker_overlay->draw_style_box(get_theme_stylebox("preview_picker_overlay", "ThemeEditor"), highlight_rect);
+ String highlight_name = hovered_control->get_theme_type_variation();
+ if (highlight_name == StringName()) {
+ highlight_name = hovered_control->get_class_name();
+ }
+
+ Rect2 highlight_label_rect = highlight_rect;
+ highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name);
+
+ int margin_top = theme_cache.preview_picker_label->get_margin(SIDE_TOP);
+ int margin_left = theme_cache.preview_picker_label->get_margin(SIDE_LEFT);
+ int margin_bottom = theme_cache.preview_picker_label->get_margin(SIDE_BOTTOM);
+ int margin_right = theme_cache.preview_picker_label->get_margin(SIDE_RIGHT);
+ highlight_label_rect.size.x += margin_left + margin_right;
+ highlight_label_rect.size.y += margin_top + margin_bottom;
+
+ highlight_label_rect.position.x = CLAMP(highlight_label_rect.position.x, 0.0, picker_overlay->get_size().width);
+ highlight_label_rect.position.y = CLAMP(highlight_label_rect.position.y, 0.0, picker_overlay->get_size().height);
+ picker_overlay->draw_style_box(theme_cache.preview_picker_label, highlight_label_rect);
+
+ Point2 label_pos = highlight_label_rect.position;
+ label_pos.y += highlight_label_rect.size.y - margin_bottom;
+ label_pos.x += margin_left;
+ picker_overlay->draw_string(theme_cache.preview_picker_font, label_pos, highlight_name);
}
}
@@ -123,12 +146,12 @@ void ThemeEditorPreview::_gui_input_picker_overlay(const Ref<InputEvent> &p_even
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (hovered_control) {
- StringName theme_type = hovered_control->get_theme_custom_type();
+ StringName theme_type = hovered_control->get_theme_type_variation();
if (theme_type == StringName()) {
theme_type = hovered_control->get_class_name();
}
- emit_signal("control_picked", theme_type);
+ emit_signal(SNAME("control_picked"), theme_type);
picker_button->set_pressed(false);
picker_overlay->set_visible(false);
}
@@ -143,6 +166,11 @@ void ThemeEditorPreview::_gui_input_picker_overlay(const Ref<InputEvent> &p_even
}
}
+void ThemeEditorPreview::_reset_picker_overlay() {
+ hovered_control = nullptr;
+ picker_overlay->update();
+}
+
void ThemeEditorPreview::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -154,7 +182,12 @@ void ThemeEditorPreview::_notification(int p_what) {
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
- picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
+ picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
+
+ theme_cache.preview_picker_overlay = get_theme_stylebox(SNAME("preview_picker_overlay"), SNAME("ThemeEditor"));
+ theme_cache.preview_picker_overlay_color = get_theme_color(SNAME("preview_picker_overlay_color"), SNAME("ThemeEditor"));
+ theme_cache.preview_picker_label = get_theme_stylebox(SNAME("preview_picker_label"), SNAME("ThemeEditor"));
+ theme_cache.preview_picker_font = get_theme_font(SNAME("status_source"), SNAME("EditorFonts"));
} break;
case NOTIFICATION_PROCESS: {
time_left -= get_process_delta_time();
@@ -213,12 +246,14 @@ ThemeEditorPreview::ThemeEditorPreview() {
preview_overlay = memnew(MarginContainer);
preview_overlay->set_mouse_filter(MOUSE_FILTER_IGNORE);
+ preview_overlay->set_clip_contents(true);
preview_body->add_child(preview_overlay);
picker_overlay = memnew(Control);
add_preview_overlay(picker_overlay);
picker_overlay->connect("draw", callable_mp(this, &ThemeEditorPreview::_draw_picker_overlay));
picker_overlay->connect("gui_input", callable_mp(this, &ThemeEditorPreview::_gui_input_picker_overlay));
+ picker_overlay->connect("mouse_exited", callable_mp(this, &ThemeEditorPreview::_reset_picker_overlay));
}
DefaultThemeEditorPreview::DefaultThemeEditorPreview() {
@@ -393,7 +428,7 @@ void SceneThemeEditorPreview::_reload_scene() {
if (loaded_scene->get_path().is_empty() || !ResourceLoader::exists(loaded_scene->get_path())) {
EditorNode::get_singleton()->show_warning(TTR("Invalid path, the PackedScene resource was probably moved or removed."));
- emit_signal("scene_invalidated");
+ emit_signal(SNAME("scene_invalidated"));
return;
}
@@ -406,19 +441,19 @@ void SceneThemeEditorPreview::_reload_scene() {
Node *instance = loaded_scene->instantiate();
if (!instance || !Object::cast_to<Control>(instance)) {
EditorNode::get_singleton()->show_warning(TTR("Invalid PackedScene resource, must have a Control node at its root."));
- emit_signal("scene_invalidated");
+ emit_signal(SNAME("scene_invalidated"));
return;
}
preview_content->add_child(instance);
- emit_signal("scene_reloaded");
+ emit_signal(SNAME("scene_reloaded"));
}
void SceneThemeEditorPreview::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- reload_scene_button->set_icon(get_theme_icon("Reload", "EditorIcons"));
+ reload_scene_button->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
} break;
}
}
diff --git a/editor/plugins/theme_editor_preview.h b/editor/plugins/theme_editor_preview.h
index efb7e424d4..4e1b149e70 100644
--- a/editor/plugins/theme_editor_preview.h
+++ b/editor/plugins/theme_editor_preview.h
@@ -60,6 +60,13 @@ class ThemeEditorPreview : public VBoxContainer {
Control *picker_overlay;
Control *hovered_control = nullptr;
+ struct ThemeCache {
+ Ref<StyleBox> preview_picker_overlay;
+ Color preview_picker_overlay_color;
+ Ref<StyleBox> preview_picker_label;
+ Ref<Font> preview_picker_font;
+ } theme_cache;
+
double time_left = 0;
void _propagate_redraw(Control *p_at);
@@ -71,6 +78,7 @@ class ThemeEditorPreview : public VBoxContainer {
void _draw_picker_overlay();
void _gui_input_picker_overlay(const Ref<InputEvent> &p_event);
+ void _reset_picker_overlay();
protected:
HBoxContainer *preview_toolbar;
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index 78f181e321..84e40e2ffa 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -33,7 +33,6 @@
#include "core/input/input.h"
#include "core/os/keyboard.h"
#include "scene/gui/box_container.h"
-#include "scene/gui/center_container.h"
#include "scene/gui/label.h"
#include "scene/gui/panel.h"
#include "scene/gui/texture_rect.h"
@@ -42,23 +41,49 @@
#include "editor/editor_settings.h"
void TileAtlasView::_gui_input(const Ref<InputEvent> &p_event) {
- bool ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL);
-
- Ref<InputEventMouseButton> b = p_event;
- if (b.is_valid()) {
- if (ctrl && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
- // Zoom out
- zoom_widget->set_zoom_by_increments(-2);
- emit_signal("transform_changed", zoom_widget->get_zoom(), Vector2(scroll_container->get_h_scroll(), scroll_container->get_v_scroll()));
- _update_zoom(zoom_widget->get_zoom(), true);
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ drag_type = DRAG_TYPE_NONE;
+
+ Vector2i scroll_vec = Vector2((mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT) - (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT), (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) - (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN));
+ if (scroll_vec != Vector2()) {
+ if (mb->is_ctrl_pressed()) {
+ if (mb->is_shift_pressed()) {
+ panning.x += 32 * mb->get_factor() * scroll_vec.y;
+ panning.y += 32 * mb->get_factor() * scroll_vec.x;
+ } else {
+ panning.y += 32 * mb->get_factor() * scroll_vec.y;
+ panning.x += 32 * mb->get_factor() * scroll_vec.x;
+ }
+
+ emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
+ _update_zoom_and_panning(true);
+ accept_event();
+
+ } else if (!mb->is_shift_pressed()) {
+ zoom_widget->set_zoom_by_increments(scroll_vec.y * 2);
+ emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
+ _update_zoom_and_panning(true);
+ accept_event();
+ }
+ }
+
+ if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE || mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
+ if (mb->is_pressed()) {
+ drag_type = DRAG_TYPE_PAN;
+ } else {
+ drag_type = DRAG_TYPE_NONE;
+ }
accept_event();
}
+ }
- if (ctrl && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
- // Zoom in
- zoom_widget->set_zoom_by_increments(2);
- emit_signal("transform_changed", zoom_widget->get_zoom(), Vector2(scroll_container->get_h_scroll(), scroll_container->get_v_scroll()));
- _update_zoom(zoom_widget->get_zoom(), true);
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (drag_type == DRAG_TYPE_PAN) {
+ panning += mm->get_relative();
+ _update_zoom_and_panning();
+ emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
accept_event();
}
}
@@ -103,25 +128,27 @@ Size2i TileAtlasView::_compute_alternative_tiles_control_size() {
return size;
}
-void TileAtlasView::_update_zoom(float p_zoom, bool p_zoom_on_mouse_pos, Vector2i p_scroll) {
+void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos) {
+ float zoom = zoom_widget->get_zoom();
+
// Compute the minimum sizes.
Size2i base_tiles_control_size = _compute_base_tiles_control_size();
- base_tiles_root_control->set_custom_minimum_size(Vector2(base_tiles_control_size) * p_zoom);
+ base_tiles_root_control->set_custom_minimum_size(Vector2(base_tiles_control_size) * zoom);
Size2i alternative_tiles_control_size = _compute_alternative_tiles_control_size();
- alternative_tiles_root_control->set_custom_minimum_size(Vector2(alternative_tiles_control_size) * p_zoom);
+ alternative_tiles_root_control->set_custom_minimum_size(Vector2(alternative_tiles_control_size) * zoom);
// Set the texture for the base tiles.
Ref<Texture2D> texture = tile_set_atlas_source->get_texture();
// Set the scales.
if (base_tiles_control_size.x > 0 && base_tiles_control_size.y > 0) {
- base_tiles_drawing_root->set_scale(Vector2(p_zoom, p_zoom));
+ base_tiles_drawing_root->set_scale(Vector2(zoom, zoom));
} else {
base_tiles_drawing_root->set_scale(Vector2(1, 1));
}
if (alternative_tiles_control_size.x > 0 && alternative_tiles_control_size.y > 0) {
- alternative_tiles_drawing_root->set_scale(Vector2(p_zoom, p_zoom));
+ alternative_tiles_drawing_root->set_scale(Vector2(zoom, zoom));
} else {
alternative_tiles_drawing_root->set_scale(Vector2(1, 1));
}
@@ -129,64 +156,40 @@ void TileAtlasView::_update_zoom(float p_zoom, bool p_zoom_on_mouse_pos, Vector2
// Update the margin container's margins.
const char *constants[] = { "margin_left", "margin_top", "margin_right", "margin_bottom" };
for (int i = 0; i < 4; i++) {
- margin_container->add_theme_constant_override(constants[i], margin_container_paddings[i] * p_zoom);
+ margin_container->add_theme_constant_override(constants[i], margin_container_paddings[i] * zoom);
}
// Update the backgrounds.
background_left->update();
background_right->update();
- if (p_scroll != Vector2i(-1, -1)) {
- scroll_container->set_h_scroll(p_scroll.x);
- scroll_container->set_v_scroll(p_scroll.y);
- }
-
// Zoom on the position.
- if (previous_zoom != p_zoom) {
- // TODO: solve this.
- // There is however an issue with scrollcainter preventing this, as it seems
- // that the scrollbars are not updated right aways after its children update.
-
- // Compute point on previous area.
- /*Vector2 max = Vector2(scroll_container->get_h_scrollbar()->get_max(), scroll_container->get_v_scrollbar()->get_max());
- Vector2 min = Vector2(scroll_container->get_h_scrollbar()->get_min(), scroll_container->get_v_scrollbar()->get_min());
- Vector2 value = Vector2(scroll_container->get_h_scrollbar()->get_value(), scroll_container->get_v_scrollbar()->get_value());
-
- Vector2 old_max = max * previous_zoom / p_zoom;
-
- Vector2 max_pixel_change = max - old_max;
- Vector2 ratio = ((value + scroll_container->get_local_mouse_position()) / old_max).max(Vector2()).min(Vector2(1,1));
- Vector2 offset = max_pixel_change * ratio;
-
- print_line("--- ZOOMED ---");
- print_line(vformat("max: %s", max));
- print_line(vformat("min: %s", min));
- print_line(vformat("value: %s", value));
- print_line(vformat("size: %s", scroll_container->get_size()));
- print_line(vformat("mouse_pos: %s", scroll_container->get_local_mouse_position()));
-
- print_line(vformat("ratio: %s", ratio));
- print_line(vformat("max_pixel_change: %s", max_pixel_change));
- print_line(vformat("offset: %s", offset));
-
+ if (p_zoom_on_mouse_pos) {
+ // Offset the panning relative to the center of panel.
+ Vector2 relative_mpos = get_local_mouse_position() - get_size() / 2;
+ panning = (panning - relative_mpos) * zoom / previous_zoom + relative_mpos;
+ } else {
+ // Center of panel.
+ panning = panning * zoom / previous_zoom;
+ }
+ button_center_view->set_disabled(panning.is_equal_approx(Vector2()));
- print_line(vformat("value before: %s", Vector2(scroll_container->get_h_scroll(), scroll_container->get_v_scroll())));
- scroll_container->set_h_scroll(10000);//scroll_container->get_h_scroll()+offset.x);
- scroll_container->set_v_scroll(10000);//scroll_container->get_v_scroll()+offset.y);
- print_line(vformat("value after: %s", Vector2(scroll_container->get_h_scroll(), scroll_container->get_v_scroll())));
- */
+ previous_zoom = zoom;
- previous_zoom = p_zoom;
- }
+ center_container->set_begin(panning - center_container->get_minimum_size() / 2);
+ center_container->set_size(center_container->get_minimum_size());
}
-void TileAtlasView::_scroll_changed() {
- emit_signal("transform_changed", zoom_widget->get_zoom(), Vector2(scroll_container->get_h_scroll(), scroll_container->get_v_scroll()));
+void TileAtlasView::_zoom_widget_changed() {
+ _update_zoom_and_panning();
+ emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
}
-void TileAtlasView::_zoom_widget_changed() {
- _update_zoom(zoom_widget->get_zoom());
- emit_signal("transform_changed", zoom_widget->get_zoom(), Vector2(scroll_container->get_h_scroll(), scroll_container->get_v_scroll()));
+void TileAtlasView::_center_view() {
+ panning = Vector2();
+ button_center_view->set_disabled(true);
+ _update_zoom_and_panning();
+ emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
}
void TileAtlasView::_base_tiles_root_control_gui_input(const Ref<InputEvent> &p_event) {
@@ -385,13 +388,13 @@ void TileAtlasView::_draw_alternatives() {
}
void TileAtlasView::_draw_background_left() {
- Ref<Texture2D> texture = get_theme_icon("Checkerboard", "EditorIcons");
+ Ref<Texture2D> texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
background_left->set_size(base_tiles_root_control->get_custom_minimum_size());
background_left->draw_texture_rect(texture, Rect2(Vector2(), background_left->get_size()), true);
}
void TileAtlasView::_draw_background_right() {
- Ref<Texture2D> texture = get_theme_icon("Checkerboard", "EditorIcons");
+ Ref<Texture2D> texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
background_right->set_size(alternative_tiles_root_control->get_custom_minimum_size());
background_right->draw_texture_rect(texture, Rect2(Vector2(), background_right->get_size()), true);
}
@@ -415,7 +418,7 @@ void TileAtlasView::set_atlas_source(TileSet *p_tile_set, TileSetAtlasSource *p_
_update_alternative_tiles_rect_cache();
// Update everything.
- _update_zoom(zoom_widget->get_zoom());
+ _update_zoom_and_panning();
// Change children control size.
Size2i base_tiles_control_size = _compute_base_tiles_control_size();
@@ -448,9 +451,10 @@ float TileAtlasView::get_zoom() const {
return zoom_widget->get_zoom();
};
-void TileAtlasView::set_transform(float p_zoom, Vector2i p_scroll) {
+void TileAtlasView::set_transform(float p_zoom, Vector2i p_panning) {
zoom_widget->set_zoom(p_zoom);
- _update_zoom(zoom_widget->get_zoom(), false, p_scroll);
+ panning = p_panning;
+ _update_zoom_and_panning();
};
void TileAtlasView::set_padding(Side p_side, int p_padding) {
@@ -525,7 +529,7 @@ Rect2i TileAtlasView::get_alternative_tile_rect(const Vector2i p_coords, int p_a
}
void TileAtlasView::update() {
- scroll_container->update();
+ base_tiles_draw->update();
base_tiles_texture_grid->update();
base_tiles_shape_grid->update();
base_tiles_dark->update();
@@ -534,124 +538,150 @@ void TileAtlasView::update() {
background_right->update();
}
+void TileAtlasView::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY:
+ button_center_view->set_icon(get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons")));
+ break;
+ }
+}
+
void TileAtlasView::_bind_methods() {
+ ClassDB::bind_method("_gui_input", &TileAtlasView::_gui_input);
+
ADD_SIGNAL(MethodInfo("transform_changed", PropertyInfo(Variant::FLOAT, "zoom"), PropertyInfo(Variant::VECTOR2, "scroll")));
}
TileAtlasView::TileAtlasView() {
- Panel *panel_container = memnew(Panel);
- panel_container->set_h_size_flags(SIZE_EXPAND_FILL);
- panel_container->set_v_size_flags(SIZE_EXPAND_FILL);
- panel_container->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
- add_child(panel_container);
-
- //Scrolling
- scroll_container = memnew(ScrollContainer);
- scroll_container->get_h_scrollbar()->connect("value_changed", callable_mp(this, &TileAtlasView::_scroll_changed).unbind(1));
- scroll_container->get_v_scrollbar()->connect("value_changed", callable_mp(this, &TileAtlasView::_scroll_changed).unbind(1));
- panel_container->add_child(scroll_container);
- scroll_container->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+
+ Panel *panel = memnew(Panel);
+ panel->set_clip_contents(true);
+ panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ panel->set_h_size_flags(SIZE_EXPAND_FILL);
+ panel->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(panel);
+ // Scrollingsc
zoom_widget = memnew(EditorZoomWidget);
add_child(zoom_widget);
zoom_widget->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT, Control::PRESET_MODE_MINSIZE, 2 * EDSCALE);
zoom_widget->connect("zoom_changed", callable_mp(this, &TileAtlasView::_zoom_widget_changed).unbind(1));
- CenterContainer *center_container = memnew(CenterContainer);
- center_container->set_h_size_flags(SIZE_EXPAND_FILL);
- center_container->set_v_size_flags(SIZE_EXPAND_FILL);
+ button_center_view = memnew(Button);
+ button_center_view->set_icon(get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons")));
+ button_center_view->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT, Control::PRESET_MODE_MINSIZE, 5);
+ button_center_view->connect("pressed", callable_mp(this, &TileAtlasView::_center_view));
+ button_center_view->set_flat(true);
+ button_center_view->set_disabled(true);
+ button_center_view->set_tooltip(TTR("Center View"));
+ add_child(button_center_view);
+
+ center_container = memnew(CenterContainer);
+ center_container->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ center_container->set_anchors_preset(Control::PRESET_CENTER);
center_container->connect("gui_input", callable_mp(this, &TileAtlasView::_gui_input));
- scroll_container->add_child(center_container);
+ panel->add_child(center_container);
missing_source_label = memnew(Label);
missing_source_label->set_text(TTR("No atlas source with a valid texture selected."));
center_container->add_child(missing_source_label);
margin_container = memnew(MarginContainer);
+ margin_container->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
center_container->add_child(margin_container);
hbox = memnew(HBoxContainer);
+ hbox->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
hbox->add_theme_constant_override("separation", 10);
hbox->hide();
margin_container->add_child(hbox);
VBoxContainer *left_vbox = memnew(VBoxContainer);
+ left_vbox->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
hbox->add_child(left_vbox);
VBoxContainer *right_vbox = memnew(VBoxContainer);
+ right_vbox->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
hbox->add_child(right_vbox);
// Base tiles.
Label *base_tile_label = memnew(Label);
+ base_tile_label->set_mouse_filter(Control::MOUSE_FILTER_PASS);
base_tile_label->set_text(TTR("Base Tiles"));
base_tile_label->set_align(Label::ALIGN_CENTER);
left_vbox->add_child(base_tile_label);
base_tiles_root_control = memnew(Control);
+ base_tiles_root_control->set_mouse_filter(Control::MOUSE_FILTER_PASS);
base_tiles_root_control->set_v_size_flags(Control::SIZE_EXPAND_FILL);
base_tiles_root_control->connect("gui_input", callable_mp(this, &TileAtlasView::_base_tiles_root_control_gui_input));
left_vbox->add_child(base_tiles_root_control);
background_left = memnew(Control);
+ background_left->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
background_left->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
background_left->set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED);
- background_left->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
background_left->connect("draw", callable_mp(this, &TileAtlasView::_draw_background_left));
base_tiles_root_control->add_child(background_left);
base_tiles_drawing_root = memnew(Control);
+ base_tiles_drawing_root->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_drawing_root->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
base_tiles_drawing_root->set_texture_filter(TEXTURE_FILTER_NEAREST);
- base_tiles_drawing_root->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_root_control->add_child(base_tiles_drawing_root);
base_tiles_draw = memnew(Control);
+ base_tiles_draw->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_draw->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
base_tiles_draw->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles));
- base_tiles_draw->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_drawing_root->add_child(base_tiles_draw);
base_tiles_texture_grid = memnew(Control);
+ base_tiles_texture_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_texture_grid->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
base_tiles_texture_grid->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles_texture_grid));
- base_tiles_texture_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_drawing_root->add_child(base_tiles_texture_grid);
base_tiles_shape_grid = memnew(Control);
+ base_tiles_shape_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_shape_grid->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
base_tiles_shape_grid->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles_shape_grid));
- base_tiles_shape_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_drawing_root->add_child(base_tiles_shape_grid);
base_tiles_dark = memnew(Control);
+ base_tiles_dark->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_dark->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
base_tiles_dark->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles_dark));
- base_tiles_dark->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
base_tiles_drawing_root->add_child(base_tiles_dark);
// Alternative tiles.
Label *alternative_tiles_label = memnew(Label);
+ alternative_tiles_label->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
alternative_tiles_label->set_text(TTR("Alternative Tiles"));
alternative_tiles_label->set_align(Label::ALIGN_CENTER);
right_vbox->add_child(alternative_tiles_label);
alternative_tiles_root_control = memnew(Control);
+ alternative_tiles_root_control->set_mouse_filter(Control::MOUSE_FILTER_PASS);
alternative_tiles_root_control->connect("gui_input", callable_mp(this, &TileAtlasView::_alternative_tiles_root_control_gui_input));
right_vbox->add_child(alternative_tiles_root_control);
background_right = memnew(Control);
+ background_right->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
background_right->set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED);
background_right->connect("draw", callable_mp(this, &TileAtlasView::_draw_background_right));
- background_right->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+
alternative_tiles_root_control->add_child(background_right);
alternative_tiles_drawing_root = memnew(Control);
- alternative_tiles_drawing_root->set_texture_filter(TEXTURE_FILTER_NEAREST);
alternative_tiles_drawing_root->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ alternative_tiles_drawing_root->set_texture_filter(TEXTURE_FILTER_NEAREST);
alternative_tiles_root_control->add_child(alternative_tiles_drawing_root);
alternatives_draw = memnew(Control);
- alternatives_draw->connect("draw", callable_mp(this, &TileAtlasView::_draw_alternatives));
alternatives_draw->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ alternatives_draw->connect("draw", callable_mp(this, &TileAtlasView::_draw_alternatives));
alternative_tiles_drawing_root->add_child(alternatives_draw);
}
diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h
index 28fd3ed1e0..bafc2b3985 100644
--- a/editor/plugins/tiles/tile_atlas_view.h
+++ b/editor/plugins/tiles/tile_atlas_view.h
@@ -34,6 +34,7 @@
#include "editor/editor_zoom_widget.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
+#include "scene/gui/center_container.h"
#include "scene/gui/label.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/scroll_container.h"
@@ -48,17 +49,24 @@ private:
TileSetAtlasSource *tile_set_atlas_source;
int source_id = -1;
+ enum DragType {
+ DRAG_TYPE_NONE,
+ DRAG_TYPE_PAN,
+ };
+ DragType drag_type = DRAG_TYPE_NONE;
float previous_zoom = 1.0;
EditorZoomWidget *zoom_widget;
+ Button *button_center_view;
+ CenterContainer *center_container;
+ Vector2 panning;
+ void _update_zoom_and_panning(bool p_zoom_on_mouse_pos = false);
void _zoom_widget_changed();
- void _scroll_changed();
- void _update_zoom(float p_zoom, bool p_zoom_on_mouse_pos = false, Vector2i p_scroll = Vector2i(-1, -1));
+ void _center_view();
void _gui_input(const Ref<InputEvent> &p_event);
Map<Vector2, Map<int, Rect2i>> alternative_tiles_rect_cache;
void _update_alternative_tiles_rect_cache();
- ScrollContainer *scroll_container;
MarginContainer *margin_container;
int margin_container_paddings[4] = { 0, 0, 0, 0 };
HBoxContainer *hbox;
@@ -102,16 +110,15 @@ private:
Size2i _compute_alternative_tiles_control_size();
protected:
+ void _notification(int p_what);
static void _bind_methods();
public:
// Global.
void set_atlas_source(TileSet *p_tile_set, TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id);
- ScrollContainer *get_scroll_container() { return scroll_container; };
-
float get_zoom() const;
- void set_transform(float p_zoom, Vector2i p_scroll);
+ void set_transform(float p_zoom, Vector2i p_panning);
void set_padding(Side p_side, int p_padding);
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 191440bdb3..dd2922286f 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -32,202 +32,2436 @@
#include "tile_set_editor.h"
-TileData *TileDataEditor::_get_tile_data(TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile) {
- ERR_FAIL_COND_V(!p_tile_set, nullptr);
- ERR_FAIL_COND_V(!p_tile_set->has_source(p_atlas_source_id), nullptr);
+#include "core/math/geometry_2d.h"
+#include "core/os/keyboard.h"
+
+#include "editor/editor_properties.h"
+#include "editor/editor_scale.h"
+
+void TileDataEditor::_call_tile_set_changed() {
+ _tile_set_changed();
+}
+
+TileData *TileDataEditor::_get_tile_data(TileMapCell p_cell) {
+ ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr);
+ ERR_FAIL_COND_V(!tile_set->has_source(p_cell.source_id), nullptr);
TileData *td = nullptr;
- TileSetSource *source = *p_tile_set->get_source(p_atlas_source_id);
+ TileSetSource *source = *tile_set->get_source(p_cell.source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
- ERR_FAIL_COND_V(!atlas_source->has_tile(p_atlas_coords), nullptr);
- ERR_FAIL_COND_V(!atlas_source->has_alternative_tile(p_atlas_coords, p_alternative_tile), nullptr);
- td = Object::cast_to<TileData>(atlas_source->get_tile_data(p_atlas_coords, p_alternative_tile));
+ ERR_FAIL_COND_V(!atlas_source->has_tile(p_cell.get_atlas_coords()), nullptr);
+ ERR_FAIL_COND_V(!atlas_source->has_alternative_tile(p_cell.get_atlas_coords(), p_cell.alternative_tile), nullptr);
+ td = Object::cast_to<TileData>(atlas_source->get_tile_data(p_cell.get_atlas_coords(), p_cell.alternative_tile));
}
return td;
}
-void TileDataEditor::edit(TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
+void TileDataEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("needs_redraw"));
}
-void TileDataTextureOffsetEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
- ERR_FAIL_COND(!tile_data);
+void TileDataEditor::set_tile_set(Ref<TileSet> p_tile_set) {
+ if (tile_set.is_valid()) {
+ tile_set->disconnect("changed", callable_mp(this, &TileDataEditor::_call_tile_set_changed));
+ }
+ tile_set = p_tile_set;
+ if (tile_set.is_valid()) {
+ tile_set->connect("changed", callable_mp(this, &TileDataEditor::_call_tile_set_changed));
+ }
+ _call_tile_set_changed();
+}
- bool valid;
- Variant value = tile_data->get(p_property, &valid);
- if (!valid) {
- return;
+bool DummyObject::_set(const StringName &p_name, const Variant &p_value) {
+ if (properties.has(p_name)) {
+ properties[p_name] = p_value;
+ return true;
}
- ERR_FAIL_COND(value.get_type() != Variant::VECTOR2I);
+ return false;
+}
- Vector2i tile_set_tile_size = p_tile_set->get_tile_size();
- Rect2i rect = Rect2i(-tile_set_tile_size / 2, tile_set_tile_size);
- p_tile_set->draw_tile_shape(p_canvas_item, p_transform.xform(rect), Color(1.0, 0.0, 0.0));
+bool DummyObject::_get(const StringName &p_name, Variant &r_ret) const {
+ if (properties.has(p_name)) {
+ r_ret = properties[p_name];
+ return true;
+ }
+ return false;
+}
+
+bool DummyObject::has_dummy_property(StringName p_name) {
+ return properties.has(p_name);
+}
+
+void DummyObject::add_dummy_property(StringName p_name) {
+ ERR_FAIL_COND(properties.has(p_name));
+ properties[p_name] = Variant();
}
-void TileDataIntegerEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+void DummyObject::remove_dummy_property(StringName p_name) {
+ ERR_FAIL_COND(!properties.has(p_name));
+ properties.erase(p_name);
+}
+
+void DummyObject::clear_dummy_properties() {
+ properties.clear();
+}
+
+void GenericTilePolygonEditor::_base_control_draw() {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
+
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons"));
+ const Ref<Texture2D> add_handle = get_theme_icon(SNAME("EditorHandleAdd"), SNAME("EditorIcons"));
+
+ Size2 tile_size = tile_set->get_tile_size();
+
+ Transform2D xform;
+ xform.set_origin(base_control->get_size() / 2 + panning);
+ xform.set_scale(Vector2(editor_zoom_widget->get_zoom(), editor_zoom_widget->get_zoom()));
+ base_control->draw_set_transform_matrix(xform);
+
+ // Draw the tile shape filled.
+ tile_set->draw_tile_shape(base_control, Rect2(-tile_size / 2, tile_size), Color(1.0, 1.0, 1.0, 0.3), true);
+
+ // Draw the background.
+ if (background_texture.is_valid()) {
+ base_control->draw_texture_rect_region(background_texture, Rect2(-background_region.size / 2 - background_offset, background_region.size), background_region, background_modulate, background_transpose);
+ }
+
+ // Draw the polygons.
+ for (unsigned int i = 0; i < polygons.size(); i++) {
+ const Vector<Vector2> &polygon = polygons[i];
+ Color color = polygon_color;
+ if (!in_creation_polygon.is_empty()) {
+ color = color.darkened(0.3);
+ }
+ color.a = 0.5;
+ Vector<Color> v_color;
+ v_color.push_back(color);
+ base_control->draw_polygon(polygon, v_color);
+
+ color.a = 0.7;
+ for (int j = 0; j < polygon.size(); j++) {
+ base_control->draw_line(polygon[j], polygon[(j + 1) % polygon.size()], color);
+ }
+ }
+
+ // Draw the polygon in creation.
+ if (!in_creation_polygon.is_empty()) {
+ for (int i = 0; i < in_creation_polygon.size() - 1; i++) {
+ base_control->draw_line(in_creation_polygon[i], in_creation_polygon[i + 1], Color(1.0, 1.0, 1.0));
+ }
+ }
+
+ Point2 in_creation_point = xform.affine_inverse().xform(base_control->get_local_mouse_position());
+ float in_creation_distance = grab_threshold * 2.0;
+ _snap_to_tile_shape(in_creation_point, in_creation_distance, grab_threshold / editor_zoom_widget->get_zoom());
+ if (button_pixel_snap->is_pressed()) {
+ _snap_to_half_pixel(in_creation_point);
+ }
+
+ if (drag_type == DRAG_TYPE_CREATE_POINT && !in_creation_polygon.is_empty()) {
+ base_control->draw_line(in_creation_polygon[in_creation_polygon.size() - 1], in_creation_point, Color(1.0, 1.0, 1.0));
+ }
+
+ // Draw the handles.
+ int tinted_polygon_index = -1;
+ int tinted_point_index = -1;
+ if (drag_type == DRAG_TYPE_DRAG_POINT) {
+ tinted_polygon_index = drag_polygon_index;
+ tinted_point_index = drag_point_index;
+ } else if (hovered_point_index >= 0) {
+ tinted_polygon_index = hovered_polygon_index;
+ tinted_point_index = hovered_point_index;
+ }
+
+ base_control->draw_set_transform_matrix(Transform2D());
+ if (!in_creation_polygon.is_empty()) {
+ for (int i = 0; i < in_creation_polygon.size(); i++) {
+ base_control->draw_texture(handle, xform.xform(in_creation_polygon[i]) - handle->get_size() / 2);
+ }
+ } else {
+ for (int i = 0; i < (int)polygons.size(); i++) {
+ const Vector<Vector2> &polygon = polygons[i];
+ for (int j = 0; j < polygon.size(); j++) {
+ const Color modulate = (tinted_polygon_index == i && tinted_point_index == j) ? Color(0.5, 1, 2) : Color(1, 1, 1);
+ base_control->draw_texture(handle, xform.xform(polygon[j]) - handle->get_size() / 2, modulate);
+ }
+ }
+ }
+
+ // Draw the text on top of the selected point.
+ if (tinted_polygon_index >= 0) {
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ String text = multiple_polygon_mode ? vformat("%d:%d", tinted_polygon_index, tinted_point_index) : vformat("%d", tinted_point_index);
+ Size2 text_size = font->get_string_size(text, font_size);
+ base_control->draw_string(font, xform.xform(polygons[tinted_polygon_index][tinted_point_index]) - text_size * 0.5, text, HALIGN_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
+ }
+
+ if (drag_type == DRAG_TYPE_CREATE_POINT) {
+ base_control->draw_texture(handle, xform.xform(in_creation_point) - handle->get_size() / 2, Color(0.5, 1, 2));
+ }
+
+ // Draw the point creation preview in edit mode.
+ if (hovered_segment_index >= 0) {
+ base_control->draw_texture(add_handle, xform.xform(hovered_segment_point) - add_handle->get_size() / 2);
+ }
+
+ // Draw the tile shape line.
+ base_control->draw_set_transform_matrix(xform);
+ tile_set->draw_tile_shape(base_control, Rect2(-tile_size / 2, tile_size), grid_color, false);
+ base_control->draw_set_transform_matrix(Transform2D());
+}
+
+void GenericTilePolygonEditor::_center_view() {
+ panning = Vector2();
+ base_control->update();
+ button_center_view->set_disabled(true);
+}
+
+void GenericTilePolygonEditor::_zoom_changed() {
+ base_control->update();
+}
+
+void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) {
+ switch (p_item_pressed) {
+ case RESET_TO_DEFAULT_TILE:
+ undo_redo->create_action(TTR("Edit Polygons"));
+ undo_redo->add_do_method(this, "clear_polygons");
+ undo_redo->add_do_method(this, "add_polygon", tile_set->get_tile_shape_polygon());
+ undo_redo->add_do_method(base_control, "update");
+ undo_redo->add_do_method(this, "emit_signal", "polygons_changed");
+ undo_redo->add_undo_method(this, "clear_polygons");
+ for (unsigned int i = 0; i < polygons.size(); i++) {
+ undo_redo->add_undo_method(this, "add_polygon", polygons[i]);
+ }
+ undo_redo->add_undo_method(base_control, "update");
+ undo_redo->add_undo_method(this, "emit_signal", "polygons_changed");
+ undo_redo->commit_action(true);
+ break;
+ case CLEAR_TILE:
+ undo_redo->create_action(TTR("Edit Polygons"));
+ undo_redo->add_do_method(this, "clear_polygons");
+ undo_redo->add_do_method(base_control, "update");
+ undo_redo->add_do_method(this, "emit_signal", "polygons_changed");
+ undo_redo->add_undo_method(this, "clear_polygons");
+ for (unsigned int i = 0; i < polygons.size(); i++) {
+ undo_redo->add_undo_method(this, "add_polygon", polygons[i]);
+ }
+ undo_redo->add_undo_method(base_control, "update");
+ undo_redo->add_undo_method(this, "emit_signal", "polygons_changed");
+ undo_redo->commit_action(true);
+ break;
+ default:
+ break;
+ }
+}
+
+void GenericTilePolygonEditor::_grab_polygon_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_point_index) {
+ const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
+ r_polygon_index = -1;
+ r_point_index = -1;
+ float closest_distance = grab_threshold + 1.0;
+ for (unsigned int i = 0; i < polygons.size(); i++) {
+ const Vector<Vector2> &polygon = polygons[i];
+ for (int j = 0; j < polygon.size(); j++) {
+ float distance = p_pos.distance_to(p_polygon_xform.xform(polygon[j]));
+ if (distance < grab_threshold && distance < closest_distance) {
+ r_polygon_index = i;
+ r_point_index = j;
+ closest_distance = distance;
+ }
+ }
+ }
+}
+
+void GenericTilePolygonEditor::_grab_polygon_segment_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_segment_index, Vector2 &r_point) {
+ const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
+
+ Point2 point = p_polygon_xform.affine_inverse().xform(p_pos);
+ r_polygon_index = -1;
+ r_segment_index = -1;
+ float closest_distance = grab_threshold * 2.0;
+ for (unsigned int i = 0; i < polygons.size(); i++) {
+ const Vector<Vector2> &polygon = polygons[i];
+ for (int j = 0; j < polygon.size(); j++) {
+ Vector2 segment[2] = { polygon[j], polygon[(j + 1) % polygon.size()] };
+ Vector2 closest_point = Geometry2D::get_closest_point_to_segment(point, segment);
+ float distance = closest_point.distance_to(point);
+ if (distance < grab_threshold / editor_zoom_widget->get_zoom() && distance < closest_distance) {
+ r_polygon_index = i;
+ r_segment_index = j;
+ r_point = closest_point;
+ closest_distance = distance;
+ }
+ }
+ }
+}
+
+void GenericTilePolygonEditor::_snap_to_tile_shape(Point2 &r_point, float &r_current_snapped_dist, float p_snap_dist) {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ Vector<Point2> polygon = tile_set->get_tile_shape_polygon();
+ Point2 snapped_point = r_point;
+
+ // Snap to polygon vertices.
+ bool snapped = false;
+ for (int i = 0; i < polygon.size(); i++) {
+ float distance = r_point.distance_to(polygon[i]);
+ if (distance < p_snap_dist && distance < r_current_snapped_dist) {
+ snapped_point = polygon[i];
+ r_current_snapped_dist = distance;
+ snapped = true;
+ }
+ }
+
+ // Snap to edges if we did not snap to vertices.
+ if (!snapped) {
+ for (int i = 0; i < polygon.size(); i++) {
+ Point2 segment[2] = { polygon[i], polygon[(i + 1) % polygon.size()] };
+ Point2 point = Geometry2D::get_closest_point_to_segment(r_point, segment);
+ float distance = r_point.distance_to(point);
+ if (distance < p_snap_dist && distance < r_current_snapped_dist) {
+ snapped_point = point;
+ r_current_snapped_dist = distance;
+ }
+ }
+ }
+
+ r_point = snapped_point;
+}
+
+void GenericTilePolygonEditor::_snap_to_half_pixel(Point2 &r_point) {
+ r_point = (r_point * 2).round() / 2.0;
+}
+
+void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) {
+ real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
+
+ hovered_polygon_index = -1;
+ hovered_point_index = -1;
+ hovered_segment_index = -1;
+ hovered_segment_point = Vector2();
+
+ Transform2D xform;
+ xform.set_origin(base_control->get_size() / 2 + panning);
+ xform.set_scale(Vector2(editor_zoom_widget->get_zoom(), editor_zoom_widget->get_zoom()));
+
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (drag_type == DRAG_TYPE_DRAG_POINT) {
+ ERR_FAIL_INDEX(drag_polygon_index, (int)polygons.size());
+ ERR_FAIL_INDEX(drag_point_index, polygons[drag_polygon_index].size());
+ Point2 point = xform.affine_inverse().xform(mm->get_position());
+ float distance = grab_threshold * 2.0;
+ _snap_to_tile_shape(point, distance, grab_threshold / editor_zoom_widget->get_zoom());
+ if (button_pixel_snap->is_pressed()) {
+ _snap_to_half_pixel(point);
+ }
+ polygons[drag_polygon_index].write[drag_point_index] = point;
+ } else if (drag_type == DRAG_TYPE_PAN) {
+ panning += mm->get_position() - drag_last_pos;
+ drag_last_pos = mm->get_position();
+ button_center_view->set_disabled(panning.is_equal_approx(Vector2()));
+ } else {
+ // Update hovered point.
+ _grab_polygon_point(mm->get_position(), xform, hovered_polygon_index, hovered_point_index);
+
+ // If we have no hovered point, check if we hover a segment.
+ if (hovered_point_index == -1) {
+ _grab_polygon_segment_point(mm->get_position(), xform, hovered_polygon_index, hovered_segment_index, hovered_segment_point);
+ }
+ }
+ }
+
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_ctrl_pressed()) {
+ editor_zoom_widget->set_zoom_by_increments(1);
+ _zoom_changed();
+ accept_event();
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_ctrl_pressed()) {
+ editor_zoom_widget->set_zoom_by_increments(-1);
+ _zoom_changed();
+ accept_event();
+ } else if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb->is_pressed()) {
+ if (tools_button_group->get_pressed_button() != button_create) {
+ in_creation_polygon.clear();
+ }
+ if (tools_button_group->get_pressed_button() == button_create) {
+ // Create points.
+ if (in_creation_polygon.size() >= 3 && mb->get_position().distance_to(xform.xform(in_creation_polygon[0])) < grab_threshold) {
+ // Closes and create polygon.
+ if (!multiple_polygon_mode) {
+ clear_polygons();
+ }
+ int added = add_polygon(in_creation_polygon);
+
+ in_creation_polygon.clear();
+ button_edit->set_pressed(true);
+ undo_redo->create_action(TTR("Edit Polygons"));
+ if (!multiple_polygon_mode) {
+ undo_redo->add_do_method(this, "clear_polygons");
+ }
+ undo_redo->add_do_method(this, "add_polygon", in_creation_polygon);
+ undo_redo->add_do_method(base_control, "update");
+ undo_redo->add_undo_method(this, "remove_polygon", added);
+ undo_redo->add_undo_method(base_control, "update");
+ undo_redo->commit_action(false);
+ emit_signal(SNAME("polygons_changed"));
+ } else {
+ // Create a new point.
+ drag_type = DRAG_TYPE_CREATE_POINT;
+ }
+ } else if (tools_button_group->get_pressed_button() == button_edit) {
+ // Edit points.
+ int closest_polygon;
+ int closest_point;
+ _grab_polygon_point(mb->get_position(), xform, closest_polygon, closest_point);
+ if (closest_polygon >= 0) {
+ drag_type = DRAG_TYPE_DRAG_POINT;
+ drag_polygon_index = closest_polygon;
+ drag_point_index = closest_point;
+ drag_old_polygon = polygons[drag_polygon_index];
+ } else {
+ // Create a point.
+ Vector2 point_to_create;
+ _grab_polygon_segment_point(mb->get_position(), xform, closest_polygon, closest_point, point_to_create);
+ if (closest_polygon >= 0) {
+ polygons[closest_polygon].insert(closest_point + 1, point_to_create);
+ drag_type = DRAG_TYPE_DRAG_POINT;
+ drag_polygon_index = closest_polygon;
+ drag_point_index = closest_point + 1;
+ drag_old_polygon = polygons[closest_polygon];
+ }
+ }
+ } else if (tools_button_group->get_pressed_button() == button_delete) {
+ // Remove point.
+ int closest_polygon;
+ int closest_point;
+ _grab_polygon_point(mb->get_position(), xform, closest_polygon, closest_point);
+ if (closest_polygon >= 0) {
+ PackedVector2Array old_polygon = polygons[closest_polygon];
+ polygons[closest_polygon].remove(closest_point);
+ undo_redo->create_action(TTR("Edit Polygons"));
+ if (polygons[closest_polygon].size() < 3) {
+ remove_polygon(closest_polygon);
+ undo_redo->add_do_method(this, "remove_polygon", closest_polygon);
+ undo_redo->add_undo_method(this, "add_polygon", old_polygon, closest_polygon);
+ } else {
+ undo_redo->add_do_method(this, "set_polygon", closest_polygon, polygons[closest_polygon]);
+ undo_redo->add_undo_method(this, "set_polygon", closest_polygon, old_polygon);
+ }
+ undo_redo->add_do_method(base_control, "update");
+ undo_redo->add_undo_method(base_control, "update");
+ undo_redo->commit_action(false);
+ emit_signal(SNAME("polygons_changed"));
+ }
+ }
+ } else {
+ if (drag_type == DRAG_TYPE_DRAG_POINT) {
+ undo_redo->create_action(TTR("Edit Polygons"));
+ undo_redo->add_do_method(this, "set_polygon", drag_polygon_index, polygons[drag_polygon_index]);
+ undo_redo->add_do_method(base_control, "update");
+ undo_redo->add_undo_method(this, "set_polygon", drag_polygon_index, drag_old_polygon);
+ undo_redo->add_undo_method(base_control, "update");
+ undo_redo->commit_action(false);
+ emit_signal(SNAME("polygons_changed"));
+ } else if (drag_type == DRAG_TYPE_CREATE_POINT) {
+ Point2 point = xform.affine_inverse().xform(mb->get_position());
+ float distance = grab_threshold * 2;
+ _snap_to_tile_shape(point, distance, grab_threshold / editor_zoom_widget->get_zoom());
+ if (button_pixel_snap->is_pressed()) {
+ _snap_to_half_pixel(point);
+ }
+ in_creation_polygon.push_back(point);
+ }
+ drag_type = DRAG_TYPE_NONE;
+ drag_point_index = -1;
+ }
+
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
+ if (mb->is_pressed()) {
+ if (tools_button_group->get_pressed_button() == button_edit) {
+ // Remove point or pan.
+ int closest_polygon;
+ int closest_point;
+ _grab_polygon_point(mb->get_position(), xform, closest_polygon, closest_point);
+ if (closest_polygon >= 0) {
+ PackedVector2Array old_polygon = polygons[closest_polygon];
+ polygons[closest_polygon].remove(closest_point);
+ undo_redo->create_action(TTR("Edit Polygons"));
+ if (polygons[closest_polygon].size() < 3) {
+ remove_polygon(closest_polygon);
+ undo_redo->add_do_method(this, "remove_polygon", closest_polygon);
+ undo_redo->add_undo_method(this, "add_polygon", old_polygon, closest_polygon);
+ } else {
+ undo_redo->add_do_method(this, "set_polygon", closest_polygon, polygons[closest_polygon]);
+ undo_redo->add_undo_method(this, "set_polygon", closest_polygon, old_polygon);
+ }
+ undo_redo->add_do_method(base_control, "update");
+ undo_redo->add_undo_method(base_control, "update");
+ undo_redo->commit_action(false);
+ emit_signal(SNAME("polygons_changed"));
+ } else {
+ drag_type = DRAG_TYPE_PAN;
+ drag_last_pos = mb->get_position();
+ }
+ } else {
+ drag_type = DRAG_TYPE_PAN;
+ drag_last_pos = mb->get_position();
+ }
+ } else {
+ drag_type = DRAG_TYPE_NONE;
+ }
+ } else if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
+ if (mb->is_pressed()) {
+ drag_type = DRAG_TYPE_PAN;
+ drag_last_pos = mb->get_position();
+ } else {
+ drag_type = DRAG_TYPE_NONE;
+ }
+ }
+ }
+
+ base_control->update();
+}
+
+void GenericTilePolygonEditor::set_tile_set(Ref<TileSet> p_tile_set) {
+ if (tile_set != p_tile_set) {
+ // Set the default tile shape
+ clear_polygons();
+ if (p_tile_set.is_valid()) {
+ add_polygon(p_tile_set->get_tile_shape_polygon());
+ }
+ }
+ tile_set = p_tile_set;
+}
+
+void GenericTilePolygonEditor::set_background(Ref<Texture2D> p_texture, Rect2 p_region, Vector2 p_offset, bool p_flip_h, bool p_flip_v, bool p_transpose, Color p_modulate) {
+ background_texture = p_texture;
+ background_region = p_region;
+ background_offset = p_offset;
+ background_h_flip = p_flip_h;
+ background_v_flip = p_flip_v;
+ background_transpose = p_transpose;
+ background_modulate = p_modulate;
+ base_control->update();
+}
+
+int GenericTilePolygonEditor::get_polygon_count() {
+ return polygons.size();
+}
+
+int GenericTilePolygonEditor::add_polygon(Vector<Point2> p_polygon, int p_index) {
+ ERR_FAIL_COND_V(p_polygon.size() < 3, -1);
+ ERR_FAIL_COND_V(!multiple_polygon_mode && polygons.size() >= 1, -1);
+
+ if (p_index < 0) {
+ polygons.push_back(p_polygon);
+ base_control->update();
+ button_edit->set_pressed(true);
+ return polygons.size() - 1;
+ } else {
+ polygons.insert(p_index, p_polygon);
+ button_edit->set_pressed(true);
+ base_control->update();
+ return p_index;
+ }
+}
+
+void GenericTilePolygonEditor::remove_polygon(int p_index) {
+ ERR_FAIL_INDEX(p_index, (int)polygons.size());
+ polygons.remove(p_index);
+
+ if (polygons.size() == 0) {
+ button_create->set_pressed(true);
+ }
+ base_control->update();
+}
+
+void GenericTilePolygonEditor::clear_polygons() {
+ polygons.clear();
+ base_control->update();
+}
+
+void GenericTilePolygonEditor::set_polygon(int p_polygon_index, Vector<Point2> p_polygon) {
+ ERR_FAIL_INDEX(p_polygon_index, (int)polygons.size());
+ ERR_FAIL_COND(p_polygon.size() < 3);
+ polygons[p_polygon_index] = p_polygon;
+ button_edit->set_pressed(true);
+ base_control->update();
+}
+
+Vector<Point2> GenericTilePolygonEditor::get_polygon(int p_polygon_index) {
+ ERR_FAIL_INDEX_V(p_polygon_index, (int)polygons.size(), Vector<Point2>());
+ return polygons[p_polygon_index];
+}
+
+void GenericTilePolygonEditor::set_polygons_color(Color p_color) {
+ polygon_color = p_color;
+ base_control->update();
+}
+
+void GenericTilePolygonEditor::set_multiple_polygon_mode(bool p_multiple_polygon_mode) {
+ multiple_polygon_mode = p_multiple_polygon_mode;
+}
+
+void GenericTilePolygonEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY:
+ button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveCreate"), SNAME("EditorIcons")));
+ button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons")));
+ button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveDelete"), SNAME("EditorIcons")));
+ button_center_view->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons")));
+ button_pixel_snap->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
+ button_advanced_menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons")));
+ break;
+ }
+}
+
+void GenericTilePolygonEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_polygon_count"), &GenericTilePolygonEditor::get_polygon_count);
+ ClassDB::bind_method(D_METHOD("add_polygon", "polygon", "index"), &GenericTilePolygonEditor::add_polygon, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("remove_polygon", "index"), &GenericTilePolygonEditor::remove_polygon);
+ ClassDB::bind_method(D_METHOD("clear_polygons"), &GenericTilePolygonEditor::clear_polygons);
+ ClassDB::bind_method(D_METHOD("set_polygon", "index", "polygon"), &GenericTilePolygonEditor::set_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon", "index"), &GenericTilePolygonEditor::set_polygon);
+
+ ADD_SIGNAL(MethodInfo("polygons_changed"));
+}
+
+GenericTilePolygonEditor::GenericTilePolygonEditor() {
+ toolbar = memnew(HBoxContainer);
+ add_child(toolbar);
+
+ tools_button_group.instantiate();
+
+ button_create = memnew(Button);
+ button_create->set_flat(true);
+ button_create->set_toggle_mode(true);
+ button_create->set_button_group(tools_button_group);
+ button_create->set_pressed(true);
+ toolbar->add_child(button_create);
+
+ button_edit = memnew(Button);
+ button_edit->set_flat(true);
+ button_edit->set_toggle_mode(true);
+ button_edit->set_button_group(tools_button_group);
+ toolbar->add_child(button_edit);
+
+ button_delete = memnew(Button);
+ button_delete->set_flat(true);
+ button_delete->set_toggle_mode(true);
+ button_delete->set_button_group(tools_button_group);
+ toolbar->add_child(button_delete);
+
+ button_advanced_menu = memnew(MenuButton);
+ button_advanced_menu->set_flat(true);
+ button_advanced_menu->set_toggle_mode(true);
+ button_advanced_menu->get_popup()->add_item(TTR("Reset to default tile shape"), RESET_TO_DEFAULT_TILE);
+ button_advanced_menu->get_popup()->add_item(TTR("Clear"), CLEAR_TILE);
+ button_advanced_menu->get_popup()->connect("id_pressed", callable_mp(this, &GenericTilePolygonEditor::_advanced_menu_item_pressed));
+ toolbar->add_child(button_advanced_menu);
+
+ toolbar->add_child(memnew(VSeparator));
+
+ button_pixel_snap = memnew(Button);
+ button_pixel_snap->set_flat(true);
+ button_pixel_snap->set_toggle_mode(true);
+ button_pixel_snap->set_pressed(true);
+ toolbar->add_child(button_pixel_snap);
+
+ Control *root = memnew(Control);
+ root->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ root->set_custom_minimum_size(Size2(0, 200 * EDSCALE));
+ root->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ add_child(root);
+
+ panel = memnew(Panel);
+ panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ root->add_child(panel);
+
+ base_control = memnew(Control);
+ base_control->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+ base_control->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ base_control->connect("draw", callable_mp(this, &GenericTilePolygonEditor::_base_control_draw));
+ base_control->connect("gui_input", callable_mp(this, &GenericTilePolygonEditor::_base_control_gui_input));
+ base_control->set_clip_contents(true);
+ root->add_child(base_control);
+
+ editor_zoom_widget = memnew(EditorZoomWidget);
+ editor_zoom_widget->set_position(Vector2(5, 5));
+ editor_zoom_widget->connect("zoom_changed", callable_mp(this, &GenericTilePolygonEditor::_zoom_changed).unbind(1));
+ root->add_child(editor_zoom_widget);
+
+ button_center_view = memnew(Button);
+ button_center_view->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons")));
+ button_center_view->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT, Control::PRESET_MODE_MINSIZE, 5);
+ button_center_view->connect("pressed", callable_mp(this, &GenericTilePolygonEditor::_center_view));
+ button_center_view->set_flat(true);
+ button_center_view->set_disabled(true);
+ root->add_child(button_center_view);
+}
+
+void TileDataDefaultEditor::_property_value_changed(StringName p_property, Variant p_value, StringName p_field) {
+ ERR_FAIL_COND(!dummy_object);
+ dummy_object->set(p_property, p_value);
+}
+
+Variant TileDataDefaultEditor::_get_painted_value() {
+ ERR_FAIL_COND_V(!dummy_object, Variant());
+ return dummy_object->get(property);
+}
+
+void TileDataDefaultEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
ERR_FAIL_COND(!tile_data);
+ Variant value = tile_data->get(property);
+ dummy_object->set(property, value);
+ if (property_editor) {
+ property_editor->update_property();
+ }
+}
- bool valid;
- Variant value = tile_data->get(p_property, &valid);
- if (!valid) {
- return;
+void TileDataDefaultEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND(!tile_data);
+ tile_data->set(property, p_value);
+}
+
+Variant TileDataDefaultEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND_V(!tile_data, Variant());
+ return tile_data->get(property);
+}
+
+void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) {
+ for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) {
+ Vector2i coords = E->key().get_atlas_coords();
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E->key().alternative_tile, property), E->get());
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E->key().alternative_tile, property), p_new_value);
+ }
+}
+
+void TileDataDefaultEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) {
+ if (drag_type == DRAG_TYPE_PAINT_RECT) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+
+ p_canvas_item->draw_set_transform_matrix(p_transform);
+
+ Rect2i rect;
+ rect.set_position(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_pos));
+ rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position())));
+ rect = rect.abs();
+
+ Set<TileMapCell> edited;
+ for (int x = rect.get_position().x; x <= rect.get_end().x; x++) {
+ for (int y = rect.get_position().y; y <= rect.get_end().y; y++) {
+ Vector2i coords = Vector2i(x, y);
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ edited.insert(cell);
+ }
+ }
+ }
+
+ for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) {
+ Vector2i coords = E->get().get_atlas_coords();
+ p_canvas_item->draw_rect(p_tile_set_atlas_source->get_tile_texture_region(coords), selection_color, false);
+ }
+ p_canvas_item->draw_set_transform_matrix(Transform2D());
+ }
+};
+
+void TileDataDefaultEditor::forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform){
+
+};
+
+void TileDataDefaultEditor::forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (drag_type == DRAG_TYPE_PAINT) {
+ Vector<Vector2i> line = Geometry2D::bresenham_line(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_last_pos), p_tile_atlas_view->get_atlas_tile_coords_at_pos(mm->get_position()));
+ for (int i = 0; i < line.size(); i++) {
+ Vector2i coords = p_tile_set_atlas_source->get_tile_at_coords(line[i]);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ if (!drag_modified.has(cell)) {
+ drag_modified[cell] = _get_value(p_tile_set_atlas_source, coords, 0);
+ }
+ _set_value(p_tile_set_atlas_source, coords, 0, drag_painted_value);
+ }
+ }
+ drag_last_pos = mm->get_position();
+ }
+ }
+
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb->is_pressed()) {
+ if (picker_button->is_pressed()) {
+ Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position());
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ _set_painted_value(p_tile_set_atlas_source, coords, 0);
+ picker_button->set_pressed(false);
+ }
+ } else if (mb->is_ctrl_pressed()) {
+ drag_type = DRAG_TYPE_PAINT_RECT;
+ drag_modified.clear();
+ drag_painted_value = _get_painted_value();
+ drag_start_pos = mb->get_position();
+ } else {
+ drag_type = DRAG_TYPE_PAINT;
+ drag_modified.clear();
+ drag_painted_value = _get_painted_value();
+ Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position());
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ drag_modified[cell] = _get_value(p_tile_set_atlas_source, coords, 0);
+ _set_value(p_tile_set_atlas_source, coords, 0, drag_painted_value);
+ }
+ drag_last_pos = mb->get_position();
+ }
+ } else {
+ if (drag_type == DRAG_TYPE_PAINT_RECT) {
+ Rect2i rect;
+ rect.set_position(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_pos));
+ rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position()));
+ rect = rect.abs();
+
+ drag_modified.clear();
+ for (int x = rect.get_position().x; x <= rect.get_end().x; x++) {
+ for (int y = rect.get_position().y; y <= rect.get_end().y; y++) {
+ Vector2i coords = Vector2i(x, y);
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ drag_modified[cell] = _get_value(p_tile_set_atlas_source, coords, 0);
+ }
+ }
+ }
+ undo_redo->create_action(TTR("Painting Tiles Property"));
+ _setup_undo_redo_action(p_tile_set_atlas_source, drag_modified, drag_painted_value);
+ undo_redo->commit_action(true);
+ drag_type = DRAG_TYPE_NONE;
+ } else if (drag_type == DRAG_TYPE_PAINT) {
+ undo_redo->create_action(TTR("Painting Tiles Property"));
+ _setup_undo_redo_action(p_tile_set_atlas_source, drag_modified, drag_painted_value);
+ undo_redo->commit_action(false);
+ drag_type = DRAG_TYPE_NONE;
+ }
+ }
+ }
}
- ERR_FAIL_COND(value.get_type() != Variant::INT);
+}
- Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font("bold", "EditorFonts");
- int height = font->get_height();
- int width = 200;
- p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-width / 2, height / 2), vformat("%d", value), HALIGN_CENTER, width, -1, Color(1, 1, 1), 1, Color(0, 0, 0, 1));
+void TileDataDefaultEditor::forward_painting_alternatives_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (drag_type == DRAG_TYPE_PAINT) {
+ Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mm->get_position());
+ Vector2i coords = Vector2i(tile.x, tile.y);
+ int alternative_tile = tile.z;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = alternative_tile;
+ if (!drag_modified.has(cell)) {
+ drag_modified[cell] = _get_value(p_tile_set_atlas_source, coords, alternative_tile);
+ }
+ _set_value(p_tile_set_atlas_source, coords, alternative_tile, drag_painted_value);
+ }
+
+ drag_last_pos = mm->get_position();
+ }
+ }
+
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb->is_pressed()) {
+ if (picker_button->is_pressed()) {
+ Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mb->get_position());
+ Vector2i coords = Vector2i(tile.x, tile.y);
+ int alternative_tile = tile.z;
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ _set_painted_value(p_tile_set_atlas_source, coords, alternative_tile);
+ picker_button->set_pressed(false);
+ }
+ } else {
+ drag_type = DRAG_TYPE_PAINT;
+ drag_modified.clear();
+ drag_painted_value = _get_painted_value();
+
+ Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mb->get_position());
+ Vector2i coords = Vector2i(tile.x, tile.y);
+ int alternative_tile = tile.z;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = alternative_tile;
+ drag_modified[cell] = _get_value(p_tile_set_atlas_source, coords, alternative_tile);
+ _set_value(p_tile_set_atlas_source, coords, alternative_tile, drag_painted_value);
+ }
+ drag_last_pos = mb->get_position();
+ }
+ } else {
+ undo_redo->create_action(TTR("Painting Tiles Property"));
+ _setup_undo_redo_action(p_tile_set_atlas_source, drag_modified, drag_painted_value);
+ undo_redo->commit_action(false);
+ drag_type = DRAG_TYPE_NONE;
+ }
+ }
+ }
}
-void TileDataFloatEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
ERR_FAIL_COND(!tile_data);
bool valid;
- Variant value = tile_data->get(p_property, &valid);
+ Variant value = tile_data->get(property, &valid);
if (!valid) {
return;
}
- ERR_FAIL_COND(value.get_type() != Variant::FLOAT);
- Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font("bold", "EditorFonts");
- int height = font->get_height();
- int width = 200;
- p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-width / 2, height / 2), vformat("%.2f", value), HALIGN_CENTER, width, -1, Color(1, 1, 1), 1, Color(0, 0, 0, 1));
+ if (value.get_type() == Variant::BOOL) {
+ Ref<Texture2D> texture = (bool)value ? tile_bool_checked : tile_bool_unchecked;
+ int size = MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 3;
+ Rect2 rect = p_transform.xform(Rect2(Vector2(-size / 2, -size / 2), Vector2(size, size)));
+ p_canvas_item->draw_texture_rect(texture, rect);
+ } else if (value.get_type() == Variant::COLOR) {
+ int size = MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 3;
+ Rect2 rect = p_transform.xform(Rect2(Vector2(-size / 2, -size / 2), Vector2(size, size)));
+ p_canvas_item->draw_rect(rect, value);
+ } else {
+ Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ String text;
+ switch (value.get_type()) {
+ case Variant::INT:
+ text = vformat("%d", value);
+ break;
+ case Variant::FLOAT:
+ text = vformat("%.2f", value);
+ break;
+ case Variant::STRING:
+ case Variant::STRING_NAME:
+ text = value;
+ break;
+ default:
+ return;
+ break;
+ }
+
+ Color color = Color(1, 1, 1);
+ if (p_selected) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ selection_color.set_v(0.9);
+ color = selection_color;
+ } else if (is_visible_in_tree()) {
+ Variant painted_value = _get_painted_value();
+ bool equal = (painted_value.get_type() == Variant::FLOAT && value.get_type() == Variant::FLOAT) ? Math::is_equal_approx(float(painted_value), float(value)) : painted_value == value;
+ if (equal) {
+ color = Color(0.7, 0.7, 0.7);
+ }
+ }
+
+ Vector2 string_size = font->get_string_size(text);
+ p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, -1, color, 1, Color(0, 0, 0, 1));
+ }
+}
+
+void TileDataDefaultEditor::setup_property_editor(Variant::Type p_type, String p_property, String p_label, Variant p_default_value) {
+ ERR_FAIL_COND_MSG(!property.is_empty(), "Cannot setup TileDataDefaultEditor twice");
+ property = p_property;
+
+ // Update everything.
+ if (property_editor) {
+ property_editor->queue_delete();
+ }
+
+ // Update the dummy object.
+ dummy_object->add_dummy_property(p_property);
+
+ // Get the default value for the type.
+ if (p_default_value == Variant()) {
+ Callable::CallError error;
+ Variant painted_value;
+ Variant::construct(p_type, painted_value, nullptr, 0, error);
+ dummy_object->set(p_property, painted_value);
+ } else {
+ dummy_object->set(p_property, p_default_value);
+ }
+
+ // Create and setup the property editor.
+ property_editor = EditorInspectorDefaultPlugin::get_editor_for_property(dummy_object, p_type, p_property, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT);
+ property_editor->set_object_and_property(dummy_object, p_property);
+ if (p_label.is_empty()) {
+ property_editor->set_label(p_property);
+ } else {
+ property_editor->set_label(p_label);
+ }
+ property_editor->connect("property_changed", callable_mp(this, &TileDataDefaultEditor::_property_value_changed).unbind(1));
+ property_editor->update_property();
+ add_child(property_editor);
+}
+
+void TileDataDefaultEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED:
+ picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
+ tile_bool_checked = get_theme_icon(SNAME("TileChecked"), SNAME("EditorIcons"));
+ tile_bool_unchecked = get_theme_icon(SNAME("TileUnchecked"), SNAME("EditorIcons"));
+ break;
+ default:
+ break;
+ }
}
-void TileDataPositionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+TileDataDefaultEditor::TileDataDefaultEditor() {
+ label = memnew(Label);
+ label->set_text(TTR("Painting:"));
+ add_child(label);
+
+ toolbar->add_child(memnew(VSeparator));
+
+ picker_button = memnew(Button);
+ picker_button->set_flat(true);
+ picker_button->set_toggle_mode(true);
+ picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", KEY_P));
+ toolbar->add_child(picker_button);
+}
+
+TileDataDefaultEditor::~TileDataDefaultEditor() {
+ toolbar->queue_delete();
+ memdelete(dummy_object);
+}
+
+void TileDataTextureOffsetEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
+ ERR_FAIL_COND(!tile_data);
+
+ Vector2i tile_set_tile_size = tile_set->get_tile_size();
+ Rect2i rect = Rect2i(-tile_set_tile_size / 2, tile_set_tile_size);
+ Color color = Color(1.0, 0.0, 0.0);
+ if (p_selected) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ color = selection_color;
+ }
+ tile_set->draw_tile_shape(p_canvas_item, p_transform.xform(rect), color);
+}
+
+void TileDataPositionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
ERR_FAIL_COND(!tile_data);
bool valid;
- Variant value = tile_data->get(p_property, &valid);
+ Variant value = tile_data->get(property, &valid);
if (!valid) {
return;
}
ERR_FAIL_COND(value.get_type() != Variant::VECTOR2I && value.get_type() != Variant::VECTOR2);
- Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon("EditorPosition", "EditorIcons");
- p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(value)) - position_icon->get_size() / 2);
+ Color color = Color(1.0, 1.0, 1.0);
+ if (p_selected) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ color = selection_color;
+ }
+ Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(value)) - position_icon->get_size() / 2, color);
}
-void TileDataYSortEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+void TileDataYSortEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
ERR_FAIL_COND(!tile_data);
- bool valid;
- Variant value = tile_data->get(p_property, &valid);
- if (!valid) {
- return;
+ Color color = Color(1.0, 1.0, 1.0);
+ if (p_selected) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ color = selection_color;
}
- ERR_FAIL_COND(value.get_type() != Variant::INT);
+ Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(0, tile_data->get_y_sort_origin())) - position_icon->get_size() / 2, color);
+}
- Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon("EditorPosition", "EditorIcons");
- p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(0, value)) - position_icon->get_size() / 2);
+void TileDataOcclusionShapeEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
+ ERR_FAIL_COND(!tile_data);
+
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ Color color = grid_color.darkened(0.2);
+ if (p_selected) {
+ color = selection_color.darkened(0.2);
+ }
+ color.a *= 0.5;
+
+ Vector<Color> debug_occlusion_color;
+ debug_occlusion_color.push_back(color);
+
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+ Ref<OccluderPolygon2D> occluder = tile_data->get_occluder(occlusion_layer);
+ if (occluder.is_valid() && occluder->get_polygon().size() >= 3) {
+ p_canvas_item->draw_polygon(Variant(occluder->get_polygon()), debug_occlusion_color);
+ }
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
}
-void TileDataOcclusionShapeEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+Variant TileDataOcclusionShapeEditor::_get_painted_value() {
+ Ref<OccluderPolygon2D> occluder_polygon;
+ occluder_polygon.instantiate();
+ if (polygon_editor->get_polygon_count() >= 1) {
+ occluder_polygon->set_polygon(polygon_editor->get_polygon(0));
+ }
+ return occluder_polygon;
+}
+
+void TileDataOcclusionShapeEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
ERR_FAIL_COND(!tile_data);
- Vector<String> components = String(p_property).split("/", true);
- if (components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
- int occlusion_layer = components[0].trim_prefix("occlusion_layer_").to_int();
- if (occlusion_layer >= 0 && occlusion_layer < p_tile_set->get_occlusion_layers_count()) {
- // Draw all shapes.
- Vector<Color> debug_occlusion_color;
- debug_occlusion_color.push_back(Color(0.5, 0, 0, 0.6));
+ Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder(occlusion_layer);
+ polygon_editor->clear_polygons();
+ if (occluder_polygon.is_valid()) {
+ polygon_editor->add_polygon(occluder_polygon->get_polygon());
+ }
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+}
+
+void TileDataOcclusionShapeEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND(!tile_data);
+ Ref<OccluderPolygon2D> occluder_polygon = p_value;
+ tile_data->set_occluder(occlusion_layer, occluder_polygon);
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
- Ref<OccluderPolygon2D> occluder = tile_data->get_occluder(occlusion_layer);
- if (occluder.is_valid() && occluder->get_polygon().size() >= 3) {
- p_canvas_item->draw_polygon(Variant(occluder->get_polygon()), debug_occlusion_color);
- }
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+}
+
+Variant TileDataOcclusionShapeEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND_V(!tile_data, Variant());
+ return tile_data->get_occluder(occlusion_layer);
+}
+
+void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) {
+ for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) {
+ Vector2i coords = E->key().get_atlas_coords();
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, occlusion_layer), E->get());
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, occlusion_layer), p_new_value);
+ }
+}
+
+void TileDataOcclusionShapeEditor::_tile_set_changed() {
+ polygon_editor->set_tile_set(tile_set);
+}
+
+void TileDataOcclusionShapeEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ polygon_editor->set_polygons_color(get_tree()->get_debug_collisions_color());
+ break;
+ default:
+ break;
+ }
+}
+
+TileDataOcclusionShapeEditor::TileDataOcclusionShapeEditor() {
+ polygon_editor = memnew(GenericTilePolygonEditor);
+ add_child(polygon_editor);
+}
+
+void TileDataCollisionEditor::_property_value_changed(StringName p_property, Variant p_value, StringName p_field) {
+ dummy_object->set(p_property, p_value);
+}
+
+void TileDataCollisionEditor::_polygons_changed() {
+ // Update the dummy object properties and their editors.
+ for (int i = 0; i < polygon_editor->get_polygon_count(); i++) {
+ StringName one_way_property = vformat("polygon_%d_one_way", i);
+ StringName one_way_margin_property = vformat("polygon_%d_one_way_margin", i);
+
+ if (!dummy_object->has_dummy_property(one_way_property)) {
+ dummy_object->add_dummy_property(one_way_property);
+ dummy_object->set(one_way_property, false);
+ }
+
+ if (!dummy_object->has_dummy_property(one_way_margin_property)) {
+ dummy_object->add_dummy_property(one_way_margin_property);
+ dummy_object->set(one_way_margin_property, 1.0);
}
+
+ if (!property_editors.has(one_way_property)) {
+ EditorProperty *one_way_property_editor = EditorInspectorDefaultPlugin::get_editor_for_property(dummy_object, Variant::BOOL, one_way_property, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT);
+ one_way_property_editor->set_object_and_property(dummy_object, one_way_property);
+ one_way_property_editor->set_label(one_way_property);
+ one_way_property_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1));
+ one_way_property_editor->update_property();
+ add_child(one_way_property_editor);
+ property_editors[one_way_property] = one_way_property_editor;
+ }
+
+ if (!property_editors.has(one_way_margin_property)) {
+ EditorProperty *one_way_margin_property_editor = EditorInspectorDefaultPlugin::get_editor_for_property(dummy_object, Variant::FLOAT, one_way_margin_property, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT);
+ one_way_margin_property_editor->set_object_and_property(dummy_object, one_way_margin_property);
+ one_way_margin_property_editor->set_label(one_way_margin_property);
+ one_way_margin_property_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1));
+ one_way_margin_property_editor->update_property();
+ add_child(one_way_margin_property_editor);
+ property_editors[one_way_margin_property] = one_way_margin_property_editor;
+ }
+ }
+
+ // Remove uneeded properties and their editors.
+ for (int i = polygon_editor->get_polygon_count(); dummy_object->has_dummy_property(vformat("polygon_%d_one_way", i)); i++) {
+ dummy_object->remove_dummy_property(vformat("polygon_%d_one_way", i));
+ }
+ for (int i = polygon_editor->get_polygon_count(); dummy_object->has_dummy_property(vformat("polygon_%d_one_way_margin", i)); i++) {
+ dummy_object->remove_dummy_property(vformat("polygon_%d_one_way_margin", i));
+ }
+ for (int i = polygon_editor->get_polygon_count(); property_editors.has(vformat("polygon_%d_one_way", i)); i++) {
+ property_editors[vformat("polygon_%d_one_way", i)]->queue_delete();
+ property_editors.erase(vformat("polygon_%d_one_way", i));
+ }
+ for (int i = polygon_editor->get_polygon_count(); property_editors.has(vformat("polygon_%d_one_way_margin", i)); i++) {
+ property_editors[vformat("polygon_%d_one_way_margin", i)]->queue_delete();
+ property_editors.erase(vformat("polygon_%d_one_way_margin", i));
}
}
-void TileDataCollisionShapeEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+Variant TileDataCollisionEditor::_get_painted_value() {
+ Array array;
+ for (int i = 0; i < polygon_editor->get_polygon_count(); i++) {
+ ERR_FAIL_COND_V(polygon_editor->get_polygon(i).size() < 3, Variant());
+ Dictionary dict;
+ dict["points"] = polygon_editor->get_polygon(i);
+ dict["one_way"] = dummy_object->get(vformat("polygon_%d_one_way", i));
+ dict["one_way_margin"] = dummy_object->get(vformat("polygon_%d_one_way_margin", i));
+ array.push_back(dict);
+ }
+
+ return array;
+}
+
+void TileDataCollisionEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
ERR_FAIL_COND(!tile_data);
- Vector<String> components = String(p_property).split("/", true);
- if (components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_int()) {
- int physics_layer = components[0].trim_prefix("physics_layer_").to_int();
- if (physics_layer >= 0 && physics_layer < p_tile_set->get_physics_layers_count()) {
- // Draw all shapes.
- Color debug_collision_color = p_canvas_item->get_tree()->get_debug_collisions_color();
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
- for (int i = 0; i < tile_data->get_collision_shapes_count(physics_layer); i++) {
- Ref<Shape2D> shape = tile_data->get_collision_shape_shape(physics_layer, i);
- if (shape.is_valid()) {
- shape->draw(p_canvas_item->get_canvas_item(), debug_collision_color);
- }
- }
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
+ polygon_editor->clear_polygons();
+ for (int i = 0; i < tile_data->get_collision_polygons_count(physics_layer); i++) {
+ Vector<Vector2> polygon = tile_data->get_collision_polygon_points(physics_layer, i);
+ if (polygon.size() >= 3) {
+ polygon_editor->add_polygon(polygon);
}
}
+
+ _polygons_changed();
+ for (int i = 0; i < tile_data->get_collision_polygons_count(physics_layer); i++) {
+ dummy_object->set(vformat("polygon_%d_one_way", i), tile_data->is_collision_polygon_one_way(physics_layer, i));
+ dummy_object->set(vformat("polygon_%d_one_way_margin", i), tile_data->get_collision_polygon_one_way_margin(physics_layer, i));
+ }
+ for (Map<StringName, EditorProperty *>::Element *E = property_editors.front(); E; E = E->next()) {
+ E->get()->update_property();
+ }
+
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
}
-void TileDataTerrainsEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+void TileDataCollisionEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
ERR_FAIL_COND(!tile_data);
- Vector<String> components = String(p_property).split("/", true);
- if (components[0] == "terrain_mode" || components[0] == "terrain" || components[0] == "terrains_peering_bit") {
- TileSetPluginAtlasTerrain::draw_terrains(p_canvas_item, p_transform, p_tile_set, tile_data);
+ Array array = p_value;
+ tile_data->set_collision_polygons_count(physics_layer, array.size());
+ for (int i = 0; i < array.size(); i++) {
+ Dictionary dict = array[i];
+ tile_data->set_collision_polygon_points(physics_layer, i, dict["points"]);
+ tile_data->set_collision_polygon_one_way(physics_layer, i, dict["one_way"]);
+ tile_data->set_collision_polygon_one_way_margin(physics_layer, i, dict["one_way_margin"]);
+ }
+
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+}
+
+Variant TileDataCollisionEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND_V(!tile_data, Variant());
+
+ Array array;
+ for (int i = 0; i < tile_data->get_collision_polygons_count(physics_layer); i++) {
+ Dictionary dict;
+ dict["points"] = tile_data->get_collision_polygon_points(physics_layer, i);
+ dict["one_way"] = tile_data->is_collision_polygon_one_way(physics_layer, i);
+ dict["one_way_margin"] = tile_data->get_collision_polygon_one_way_margin(physics_layer, i);
+ array.push_back(dict);
+ }
+ return array;
+}
+
+void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) {
+ Array new_array = p_new_value;
+ for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) {
+ Array old_array = E->get();
+
+ Vector2i coords = E->key().get_atlas_coords();
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E->key().alternative_tile, physics_layer), old_array.size());
+ for (int i = 0; i < old_array.size(); i++) {
+ Dictionary dict = old_array[i];
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["points"]);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way"]);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way_margin"]);
+ }
+
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E->key().alternative_tile, physics_layer), new_array.size());
+ for (int i = 0; i < new_array.size(); i++) {
+ Dictionary dict = new_array[i];
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["points"]);
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way"]);
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way_margin"]);
+ }
+ }
+}
+
+void TileDataCollisionEditor::_tile_set_changed() {
+ polygon_editor->set_tile_set(tile_set);
+ _polygons_changed();
+}
+
+void TileDataCollisionEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ polygon_editor->set_polygons_color(get_tree()->get_debug_collisions_color());
+ break;
+ default:
+ break;
}
}
-void TileDataNavigationPolygonEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
- TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+TileDataCollisionEditor::TileDataCollisionEditor() {
+ polygon_editor = memnew(GenericTilePolygonEditor);
+ polygon_editor->set_multiple_polygon_mode(true);
+ polygon_editor->connect("polygons_changed", callable_mp(this, &TileDataCollisionEditor::_polygons_changed));
+ add_child(polygon_editor);
+
+ _polygons_changed();
+}
+
+TileDataCollisionEditor::~TileDataCollisionEditor() {
+ memdelete(dummy_object);
+}
+
+void TileDataCollisionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
ERR_FAIL_COND(!tile_data);
- Vector<String> components = String(p_property).split("/", true);
- if (components[0].begins_with("navigation_layer_") && components[0].trim_prefix("navigation_layer_").is_valid_int()) {
- int navigation_layer = components[0].trim_prefix("navigation_layer_").to_int();
- if (navigation_layer >= 0 && navigation_layer < p_tile_set->get_navigation_layers_count()) {
- // Draw all shapes.
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+ // Draw all shapes.
+ Vector<Color> color;
+ if (p_selected) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ selection_color.a = 0.7;
+ color.push_back(selection_color);
+ } else {
+ Color debug_collision_color = p_canvas_item->get_tree()->get_debug_collisions_color();
+ color.push_back(debug_collision_color);
+ }
- Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(navigation_layer);
- if (navigation_polygon.is_valid()) {
- Vector<Vector2> verts = navigation_polygon->get_vertices();
- if (verts.size() < 3) {
- return;
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+ for (int i = 0; i < tile_data->get_collision_polygons_count(physics_layer); i++) {
+ Vector<Vector2> polygon = tile_data->get_collision_polygon_points(physics_layer, i);
+ if (polygon.size() >= 3) {
+ p_canvas_item->draw_polygon(polygon, color);
+ }
+ }
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
+}
+
+void TileDataTerrainsEditor::_update_terrain_selector() {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ // Update the terrain set selector.
+ Vector<String> options;
+ options.push_back(String(TTR("No terrains")) + String(":-1"));
+ for (int i = 0; i < tile_set->get_terrain_sets_count(); i++) {
+ options.push_back(vformat("Terrain Set %d", i));
+ }
+ terrain_set_property_editor->setup(options);
+ terrain_set_property_editor->update_property();
+
+ // Update the terrain selector.
+ int terrain_set = int(dummy_object->get("terrain_set"));
+ if (terrain_set == -1) {
+ terrain_property_editor->hide();
+ } else {
+ options.clear();
+ Vector<Vector<Ref<Texture2D>>> icons = tile_set->generate_terrains_icons(Size2(16, 16) * EDSCALE);
+ options.push_back(String(TTR("No terrain")) + String(":-1"));
+ for (int i = 0; i < tile_set->get_terrains_count(terrain_set); i++) {
+ String name = tile_set->get_terrain_name(terrain_set, i);
+ if (name.is_empty()) {
+ options.push_back(vformat("Terrain %d", i));
+ } else {
+ options.push_back(name);
+ }
+ }
+ terrain_property_editor->setup(options);
+ terrain_property_editor->update_property();
+
+ // Kind of a hack to set icons.
+ // We could provide a way to modify that in the EditorProperty.
+ OptionButton *option_button = Object::cast_to<OptionButton>(terrain_property_editor->get_child(0));
+ for (int terrain = 0; terrain < tile_set->get_terrains_count(terrain_set); terrain++) {
+ option_button->set_item_icon(terrain + 1, icons[terrain_set][terrain]);
+ }
+ terrain_property_editor->show();
+ }
+}
+
+void TileDataTerrainsEditor::_property_value_changed(StringName p_property, Variant p_value, StringName p_field) {
+ Variant old_value = dummy_object->get(p_property);
+ dummy_object->set(p_property, p_value);
+ if (p_property == "terrain_set") {
+ if (p_value != old_value) {
+ dummy_object->set("terrain", -1);
+ }
+ _update_terrain_selector();
+ }
+ emit_signal(SNAME("needs_redraw"));
+}
+
+void TileDataTerrainsEditor::_tile_set_changed() {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ // Fix if wrong values are selected.
+ if (int(dummy_object->get("terrain_set")) > tile_set->get_terrain_sets_count()) {
+ dummy_object->set("terrain_set", -1);
+ }
+ int terrain_set = int(dummy_object->get("terrain"));
+ if (terrain_set >= 0) {
+ if (int(dummy_object->get("terrain")) > tile_set->get_terrains_count(terrain_set)) {
+ dummy_object->set("terrain", -1);
+ }
+ }
+
+ _update_terrain_selector();
+}
+
+void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ // Draw the hovered terrain bit, or the whole tile if it has the wrong terrain set.
+ Vector2i hovered_coords = TileSetSource::INVALID_ATLAS_COORDS;
+ if (drag_type == DRAG_TYPE_NONE) {
+ Vector2i mouse_pos = p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position());
+ hovered_coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_pos);
+ hovered_coords = p_tile_set_atlas_source->get_tile_at_coords(hovered_coords);
+ if (hovered_coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(hovered_coords, 0));
+ int terrain_set = tile_data->get_terrain_set();
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(hovered_coords);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, 0);
+
+ if (terrain_set >= 0 && terrain_set == int(dummy_object->get("terrain_set"))) {
+ // Draw hovered bit.
+ Transform2D xform;
+ xform.set_origin(position);
+
+ Vector<Color> color;
+ color.push_back(Color(1.0, 1.0, 1.0, 0.5));
+
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (Geometry2D::is_point_in_polygon(xform.affine_inverse().xform(mouse_pos), polygon)) {
+ p_canvas_item->draw_set_transform_matrix(p_transform * xform);
+ p_canvas_item->draw_polygon(polygon, color);
+ }
+ }
+ }
+ } else {
+ // Draw hovered tile.
+ Vector2i tile_size = tile_set->get_tile_size();
+ Rect2i rect = p_transform.xform(Rect2i(position - tile_size / 2, tile_size));
+ tile_set->draw_tile_shape(p_canvas_item, rect, Color(1.0, 1.0, 1.0, 0.5), true);
+ }
+ }
+ }
+
+ // Dim terrains with wrong terrain set.
+ Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ for (int i = 0; i < p_tile_set_atlas_source->get_tiles_count(); i++) {
+ Vector2i coords = p_tile_set_atlas_source->get_tile_id(i);
+ if (coords != hovered_coords) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ if (tile_data->get_terrain_set() != int(dummy_object->get("terrain_set"))) {
+ // Dimming
+ p_canvas_item->draw_set_transform_matrix(p_transform);
+ Rect2i rect = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ p_canvas_item->draw_rect(rect, Color(0.0, 0.0, 0.0, 0.3));
+
+ // Text
+ p_canvas_item->draw_set_transform_matrix(Transform2D());
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+
+ Color color = Color(1, 1, 1);
+ String text;
+ if (tile_data->get_terrain_set() >= 0) {
+ text = vformat("%d", tile_data->get_terrain_set());
+ } else {
+ text = "-";
+ }
+ Vector2 string_size = font->get_string_size(text);
+ p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, -1, color, 1, Color(0, 0, 0, 1));
+ }
+ }
+ }
+ p_canvas_item->draw_set_transform_matrix(Transform2D());
+
+ if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET_RECT) {
+ // Draw selection rectangle.
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+
+ p_canvas_item->draw_set_transform_matrix(p_transform);
+
+ Rect2i rect;
+ rect.set_position(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_pos));
+ rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position())));
+ rect = rect.abs();
+
+ Set<TileMapCell> edited;
+ for (int x = rect.get_position().x; x <= rect.get_end().x; x++) {
+ for (int y = rect.get_position().y; y <= rect.get_end().y; y++) {
+ Vector2i coords = Vector2i(x, y);
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ edited.insert(cell);
}
+ }
+ }
- Color color = p_canvas_item->get_tree()->get_debug_navigation_color();
+ for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) {
+ Vector2i coords = E->get().get_atlas_coords();
+ p_canvas_item->draw_rect(p_tile_set_atlas_source->get_tile_texture_region(coords), selection_color, false);
+ }
+ p_canvas_item->draw_set_transform_matrix(Transform2D());
+ } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS_RECT) {
+ // Highlight selected peering bits.
+ Dictionary painted = Dictionary(drag_painted_value);
+ int terrain_set = int(painted["terrain_set"]);
- RandomPCG rand;
- for (int i = 0; i < navigation_polygon->get_polygon_count(); i++) {
- // An array of vertices for this polygon.
- Vector<int> polygon = navigation_polygon->get_polygon(i);
- Vector<Vector2> vertices;
- vertices.resize(polygon.size());
+ Rect2i rect;
+ rect.set_position(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_pos));
+ rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position())));
+ rect = rect.abs();
+
+ Set<TileMapCell> edited;
+ for (int x = rect.get_position().x; x <= rect.get_end().x; x++) {
+ for (int y = rect.get_position().y; y <= rect.get_end().y; y++) {
+ Vector2i coords = Vector2i(x, y);
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ if (tile_data->get_terrain_set() == terrain_set) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ edited.insert(cell);
+ }
+ }
+ }
+ }
+
+ Vector2 end = p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position());
+ Vector<Point2> mouse_pos_rect_polygon;
+ mouse_pos_rect_polygon.push_back(drag_start_pos);
+ mouse_pos_rect_polygon.push_back(Vector2(end.x, drag_start_pos.y));
+ mouse_pos_rect_polygon.push_back(end);
+ mouse_pos_rect_polygon.push_back(Vector2(drag_start_pos.x, end.y));
+
+ Vector<Color> color;
+ color.push_back(Color(1.0, 1.0, 1.0, 0.5));
+
+ p_canvas_item->draw_set_transform_matrix(p_transform);
+
+ for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) {
+ Vector2i coords = E->get().get_atlas_coords();
+
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
for (int j = 0; j < polygon.size(); j++) {
- ERR_FAIL_INDEX(polygon[j], verts.size());
- vertices.write[j] = verts[polygon[j]];
+ polygon.write[j] += position;
+ }
+ if (!Geometry2D::intersect_polygons(polygon, mouse_pos_rect_polygon).is_empty()) {
+ // Draw bit.
+ p_canvas_item->draw_polygon(polygon, color);
}
+ }
+ }
+ }
+
+ p_canvas_item->draw_set_transform_matrix(Transform2D());
+ }
+}
+
+void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ // Draw the hovered terrain bit, or the whole tile if it has the wrong terrain set.
+ Vector2i hovered_coords = TileSetSource::INVALID_ATLAS_COORDS;
+ int hovered_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ if (drag_type == DRAG_TYPE_NONE) {
+ Vector2i mouse_pos = p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position());
+ Vector3i hovered = p_tile_atlas_view->get_alternative_tile_at_pos(mouse_pos);
+ hovered_coords = Vector2i(hovered.x, hovered.y);
+ hovered_alternative = hovered.z;
+ if (hovered_coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(hovered_coords, hovered_alternative));
+ int terrain_set = tile_data->get_terrain_set();
+ Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(hovered_coords, hovered_alternative);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, hovered_alternative);
+
+ if (terrain_set == int(dummy_object->get("terrain_set"))) {
+ // Draw hovered bit.
+ Transform2D xform;
+ xform.set_origin(position);
- // Generate the polygon color, slightly randomly modified from the settings one.
- Color random_variation_color;
- random_variation_color.set_hsv(color.get_h() + rand.random(-1.0, 1.0) * 0.05, color.get_s(), color.get_v() + rand.random(-1.0, 1.0) * 0.1);
- random_variation_color.a = color.a;
- Vector<Color> colors;
- colors.push_back(random_variation_color);
+ Vector<Color> color;
+ color.push_back(Color(1.0, 1.0, 1.0, 0.5));
- RenderingServer::get_singleton()->canvas_item_add_polygon(p_canvas_item->get_canvas_item(), vertices, colors);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (Geometry2D::is_point_in_polygon(xform.affine_inverse().xform(mouse_pos), polygon)) {
+ p_canvas_item->draw_set_transform_matrix(p_transform * xform);
+ p_canvas_item->draw_polygon(polygon, color);
+ }
+ }
}
+ } else {
+ // Draw hovered tile.
+ Vector2i tile_size = tile_set->get_tile_size();
+ Rect2i rect = p_transform.xform(Rect2i(position - tile_size / 2, tile_size));
+ tile_set->draw_tile_shape(p_canvas_item, rect, Color(1.0, 1.0, 1.0, 0.5), true);
}
+ }
+ }
+
+ // Dim terrains with wrong terrain set.
+ Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ for (int i = 0; i < p_tile_set_atlas_source->get_tiles_count(); i++) {
+ Vector2i coords = p_tile_set_atlas_source->get_tile_id(i);
+ for (int j = 1; j < p_tile_set_atlas_source->get_alternative_tiles_count(coords); j++) {
+ int alternative_tile = p_tile_set_atlas_source->get_alternative_tile_id(coords, j);
+ if (coords != hovered_coords || alternative_tile != hovered_alternative) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, alternative_tile));
+ if (tile_data->get_terrain_set() != int(dummy_object->get("terrain_set"))) {
+ // Dimming
+ p_canvas_item->draw_set_transform_matrix(p_transform);
+ Rect2i rect = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
+ p_canvas_item->draw_rect(rect, Color(0.0, 0.0, 0.0, 0.3));
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
+ // Text
+ p_canvas_item->draw_set_transform_matrix(Transform2D());
+ Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+
+ Color color = Color(1, 1, 1);
+ String text;
+ if (tile_data->get_terrain_set() >= 0) {
+ text = vformat("%d", tile_data->get_terrain_set());
+ } else {
+ text = "-";
+ }
+ Vector2 string_size = font->get_string_size(text);
+ p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, -1, color, 1, Color(0, 0, 0, 1));
+ }
+ }
}
}
+
+ p_canvas_item->draw_set_transform_matrix(Transform2D());
+}
+
+void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) {
+ Vector<Vector2i> line = Geometry2D::bresenham_line(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_last_pos), p_tile_atlas_view->get_atlas_tile_coords_at_pos(mm->get_position()));
+ for (int i = 0; i < line.size(); i++) {
+ Vector2i coords = p_tile_set_atlas_source->get_tile_at_coords(line[i]);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ int terrain_set = drag_painted_value;
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+
+ // Save the old terrain_set and terrains bits.
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ if (!drag_modified.has(cell)) {
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+ }
+
+ // Set the terrain_set.
+ tile_data->set_terrain_set(terrain_set);
+ }
+ }
+ drag_last_pos = mm->get_position();
+ } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
+ int terrain_set = Dictionary(drag_painted_value)["terrain_set"];
+ int terrain = Dictionary(drag_painted_value)["terrain"];
+ Vector<Vector2i> line = Geometry2D::bresenham_line(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_last_pos), p_tile_atlas_view->get_atlas_tile_coords_at_pos(mm->get_position()));
+ for (int i = 0; i < line.size(); i++) {
+ Vector2i coords = p_tile_set_atlas_source->get_tile_at_coords(line[i]);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ if (tile_data->get_terrain_set() == terrain_set) {
+ // Save the old terrain_set and terrains bits.
+ if (!drag_modified.has(cell)) {
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+ }
+
+ // Set the terrains bits.
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ if (tile_data->is_valid_peering_bit_terrain(bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(tile_data->get_terrain_set(), bit);
+ if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
+ tile_data->set_peering_bit_terrain(bit, terrain);
+ }
+ }
+ }
+ }
+ }
+ }
+ drag_last_pos = mm->get_position();
+ }
+ }
+
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb->is_pressed()) {
+ if (picker_button->is_pressed()) {
+ Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position());
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ int terrain_set = tile_data->get_terrain_set();
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ dummy_object->set("terrain_set", terrain_set);
+ dummy_object->set("terrain", -1);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ dummy_object->set("terrain", tile_data->get_peering_bit_terrain(bit));
+ }
+ }
+ }
+ terrain_set_property_editor->update_property();
+ _update_terrain_selector();
+ picker_button->set_pressed(false);
+ }
+ } else {
+ Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position());
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ TileData *tile_data = nullptr;
+ if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ }
+ int terrain_set = int(dummy_object->get("terrain_set"));
+ int terrain = int(dummy_object->get("terrain"));
+ if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
+ if (mb->is_ctrl_pressed()) {
+ // Paint terrain set with rect.
+ drag_type = DRAG_TYPE_PAINT_TERRAIN_SET_RECT;
+ drag_modified.clear();
+ drag_painted_value = terrain_set;
+ drag_start_pos = mb->get_position();
+ } else {
+ // Paint terrain set.
+ drag_type = DRAG_TYPE_PAINT_TERRAIN_SET;
+ drag_modified.clear();
+ drag_painted_value = terrain_set;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+
+ // Save the old terrain_set and terrains bits.
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+
+ // Set the terrain_set.
+ tile_data->set_terrain_set(terrain_set);
+ }
+ drag_last_pos = mb->get_position();
+ }
+ } else if (tile_data && tile_data->get_terrain_set() == terrain_set) {
+ if (mb->is_ctrl_pressed()) {
+ // Paint terrain set with rect.
+ drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS_RECT;
+ drag_modified.clear();
+ Dictionary painted_dict;
+ painted_dict["terrain_set"] = terrain_set;
+ painted_dict["terrain"] = terrain;
+ drag_painted_value = painted_dict;
+ drag_start_pos = mb->get_position();
+ } else {
+ // Paint terrain bits.
+ drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS;
+ drag_modified.clear();
+ Dictionary painted_dict;
+ painted_dict["terrain_set"] = terrain_set;
+ painted_dict["terrain"] = terrain;
+ drag_painted_value = painted_dict;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+
+ // Save the old terrain_set and terrains bits.
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+
+ // Set the terrain bit.
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ tile_data->set_peering_bit_terrain(bit, terrain);
+ }
+ }
+ }
+ }
+ drag_last_pos = mb->get_position();
+ }
+ }
+ }
+ } else {
+ if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET_RECT) {
+ Rect2i rect;
+ rect.set_position(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_pos));
+ rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position()));
+ rect = rect.abs();
+
+ Set<TileMapCell> edited;
+ for (int x = rect.get_position().x; x <= rect.get_end().x; x++) {
+ for (int y = rect.get_position().y; y <= rect.get_end().y; y++) {
+ Vector2i coords = Vector2i(x, y);
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ edited.insert(cell);
+ }
+ }
+ }
+ undo_redo->create_action(TTR("Painting Terrain Set"));
+ for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) {
+ Vector2i coords = E->get().get_atlas_coords();
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->get().alternative_tile), tile_data->get_terrain_set());
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->get().alternative_tile), drag_painted_value);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_data->is_valid_peering_bit_terrain(bit)) {
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->get().alternative_tile), tile_data->get_peering_bit_terrain(bit));
+ }
+ }
+ }
+ undo_redo->commit_action(true);
+ drag_type = DRAG_TYPE_NONE;
+ } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) {
+ undo_redo->create_action(TTR("Painting Terrain Set"));
+ for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) {
+ Dictionary dict = E->get();
+ Vector2i coords = E->key().get_atlas_coords();
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), drag_painted_value);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), dict["terrain_set"]);
+ Array array = dict["terrain_peering_bits"];
+ for (int i = 0; i < array.size(); i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) {
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]);
+ }
+ }
+ }
+ undo_redo->commit_action(false);
+ drag_type = DRAG_TYPE_NONE;
+ } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
+ Dictionary painted = Dictionary(drag_painted_value);
+ int terrain_set = int(painted["terrain_set"]);
+ int terrain = int(painted["terrain"]);
+ undo_redo->create_action(TTR("Painting Terrain"));
+ for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) {
+ Dictionary dict = E->get();
+ Vector2i coords = E->key().get_atlas_coords();
+ Array array = dict["terrain_peering_bits"];
+ for (int i = 0; i < array.size(); i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), terrain);
+ }
+ if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) {
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]);
+ }
+ }
+ }
+ undo_redo->commit_action(false);
+ drag_type = DRAG_TYPE_NONE;
+ } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS_RECT) {
+ Dictionary painted = Dictionary(drag_painted_value);
+ int terrain_set = int(painted["terrain_set"]);
+ int terrain = int(painted["terrain"]);
+
+ Rect2i rect;
+ rect.set_position(p_tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_pos));
+ rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position()));
+ rect = rect.abs();
+
+ Set<TileMapCell> edited;
+ for (int x = rect.get_position().x; x <= rect.get_end().x; x++) {
+ for (int y = rect.get_position().y; y <= rect.get_end().y; y++) {
+ Vector2i coords = Vector2i(x, y);
+ coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+ if (tile_data->get_terrain_set() == terrain_set) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ edited.insert(cell);
+ }
+ }
+ }
+ }
+
+ Vector<Point2> mouse_pos_rect_polygon;
+ mouse_pos_rect_polygon.push_back(drag_start_pos);
+ mouse_pos_rect_polygon.push_back(Vector2(mb->get_position().x, drag_start_pos.y));
+ mouse_pos_rect_polygon.push_back(mb->get_position());
+ mouse_pos_rect_polygon.push_back(Vector2(drag_start_pos.x, mb->get_position().y));
+
+ undo_redo->create_action(TTR("Painting Terrain"));
+ for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) {
+ Vector2i coords = E->get().get_atlas_coords();
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0));
+
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ for (int j = 0; j < polygon.size(); j++) {
+ polygon.write[j] += position;
+ }
+ if (!Geometry2D::intersect_polygons(polygon, mouse_pos_rect_polygon).is_empty()) {
+ // Draw bit.
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->get().alternative_tile), terrain);
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->get().alternative_tile), tile_data->get_peering_bit_terrain(bit));
+ }
+ }
+ }
+ }
+ undo_redo->commit_action(true);
+ drag_type = DRAG_TYPE_NONE;
+ }
+ }
+ }
+ }
+}
+
+void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_set_atlas_source, const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) {
+ Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mm->get_position());
+ Vector2i coords = Vector2i(tile.x, tile.y);
+ int alternative_tile = tile.z;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = alternative_tile;
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, alternative_tile));
+ if (!drag_modified.has(cell)) {
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+ }
+ tile_data->set_terrain_set(drag_painted_value);
+ }
+
+ drag_last_pos = mm->get_position();
+ } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
+ Dictionary painted = Dictionary(drag_painted_value);
+ int terrain_set = int(painted["terrain_set"]);
+ int terrain = int(painted["terrain"]);
+
+ Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mm->get_position());
+ Vector2i coords = Vector2i(tile.x, tile.y);
+ int alternative_tile = tile.z;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = alternative_tile;
+
+ // Save the old terrain_set and terrains bits.
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, alternative_tile));
+ if (tile_data->get_terrain_set() == terrain_set) {
+ if (!drag_modified.has(cell)) {
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+ }
+
+ // Set the terrains bits.
+ Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+ for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
+ if (tile_data->is_valid_peering_bit_terrain(bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(tile_data->get_terrain_set(), bit);
+ if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
+ tile_data->set_peering_bit_terrain(bit, terrain);
+ }
+ }
+ }
+ }
+ }
+ drag_last_pos = mm->get_position();
+ }
+ }
+
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb->is_pressed()) {
+ if (picker_button->is_pressed()) {
+ Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mb->get_position());
+ Vector2i coords = Vector2i(tile.x, tile.y);
+ int alternative_tile = tile.z;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, alternative_tile));
+ int terrain_set = tile_data->get_terrain_set();
+ Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+ dummy_object->set("terrain_set", terrain_set);
+ dummy_object->set("terrain", -1);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ dummy_object->set("terrain", tile_data->get_peering_bit_terrain(bit));
+ }
+ }
+ }
+ terrain_set_property_editor->update_property();
+ _update_terrain_selector();
+ picker_button->set_pressed(false);
+ }
+ } else {
+ int terrain_set = int(dummy_object->get("terrain_set"));
+ int terrain = int(dummy_object->get("terrain"));
+
+ Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mb->get_position());
+ Vector2i coords = Vector2i(tile.x, tile.y);
+ int alternative_tile = tile.z;
+
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, alternative_tile));
+
+ if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
+ drag_type = DRAG_TYPE_PAINT_TERRAIN_SET;
+ drag_modified.clear();
+ drag_painted_value = int(dummy_object->get("terrain_set"));
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = alternative_tile;
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+ tile_data->set_terrain_set(drag_painted_value);
+ }
+ drag_last_pos = mb->get_position();
+ } else if (tile_data && tile_data->get_terrain_set() == terrain_set) {
+ // Paint terrain bits.
+ drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS;
+ drag_modified.clear();
+ Dictionary painted_dict;
+ painted_dict["terrain_set"] = terrain_set;
+ painted_dict["terrain"] = terrain;
+ drag_painted_value = painted_dict;
+
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ TileMapCell cell;
+ cell.source_id = 0;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = alternative_tile;
+
+ // Save the old terrain_set and terrains bits.
+ Dictionary dict;
+ dict["terrain_set"] = tile_data->get_terrain_set();
+ Array array;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ array.push_back(tile_data->is_valid_peering_bit_terrain(bit) ? tile_data->get_peering_bit_terrain(bit) : -1);
+ }
+ dict["terrain_peering_bits"] = array;
+ drag_modified[cell] = dict;
+
+ // Set the terrain bit.
+ Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit);
+ if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
+ tile_data->set_peering_bit_terrain(bit, terrain);
+ }
+ }
+ }
+ }
+ drag_last_pos = mb->get_position();
+ }
+ }
+ } else {
+ if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) {
+ undo_redo->create_action(TTR("Painting Tiles Property"));
+ for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) {
+ Dictionary dict = E->get();
+ Vector2i coords = E->key().get_atlas_coords();
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), dict["terrain_set"]);
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), drag_painted_value);
+ Array array = dict["terrain_peering_bits"];
+ for (int i = 0; i < array.size(); i++) {
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]);
+ }
+ }
+ undo_redo->commit_action(false);
+ drag_type = DRAG_TYPE_NONE;
+ } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
+ Dictionary painted = Dictionary(drag_painted_value);
+ int terrain_set = int(painted["terrain_set"]);
+ int terrain = int(painted["terrain"]);
+ undo_redo->create_action(TTR("Painting Terrain"));
+ for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) {
+ Dictionary dict = E->get();
+ Vector2i coords = E->key().get_atlas_coords();
+ Array array = dict["terrain_peering_bits"];
+ for (int i = 0; i < array.size(); i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) {
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), terrain);
+ }
+ if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) {
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]);
+ }
+ }
+ }
+ undo_redo->commit_action(false);
+ drag_type = DRAG_TYPE_NONE;
+ }
+ }
+ }
+ }
+}
+
+void TileDataTerrainsEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
+ ERR_FAIL_COND(!tile_data);
+
+ tile_set->draw_terrains(p_canvas_item, p_transform, tile_data);
+}
+
+void TileDataTerrainsEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED:
+ picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
+ break;
+ default:
+ break;
+ }
+}
+
+TileDataTerrainsEditor::TileDataTerrainsEditor() {
+ label = memnew(Label);
+ label->set_text("Painting:");
+ add_child(label);
+
+ // Toolbar
+ toolbar->add_child(memnew(VSeparator));
+
+ picker_button = memnew(Button);
+ picker_button->set_flat(true);
+ picker_button->set_toggle_mode(true);
+ picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", KEY_P));
+ toolbar->add_child(picker_button);
+
+ // Setup
+ dummy_object->add_dummy_property("terrain_set");
+ dummy_object->set("terrain_set", -1);
+ dummy_object->add_dummy_property("terrain");
+ dummy_object->set("terrain", -1);
+
+ // Get the default value for the type.
+ terrain_set_property_editor = memnew(EditorPropertyEnum);
+ terrain_set_property_editor->set_object_and_property(dummy_object, "terrain_set");
+ terrain_set_property_editor->set_label("Terrain Set");
+ terrain_set_property_editor->connect("property_changed", callable_mp(this, &TileDataTerrainsEditor::_property_value_changed).unbind(1));
+ add_child(terrain_set_property_editor);
+
+ terrain_property_editor = memnew(EditorPropertyEnum);
+ terrain_property_editor->set_object_and_property(dummy_object, "terrain");
+ terrain_property_editor->set_label("Terrain");
+ terrain_property_editor->connect("property_changed", callable_mp(this, &TileDataTerrainsEditor::_property_value_changed).unbind(1));
+ add_child(terrain_property_editor);
+}
+
+TileDataTerrainsEditor::~TileDataTerrainsEditor() {
+ toolbar->queue_delete();
+ memdelete(dummy_object);
+}
+
+Variant TileDataNavigationEditor::_get_painted_value() {
+ Ref<NavigationPolygon> navigation_polygon;
+ navigation_polygon.instantiate();
+
+ for (int i = 0; i < polygon_editor->get_polygon_count(); i++) {
+ Vector<Vector2> polygon = polygon_editor->get_polygon(i);
+ navigation_polygon->add_outline(polygon);
+ }
+
+ navigation_polygon->make_polygons_from_outlines();
+ return navigation_polygon;
+}
+
+void TileDataNavigationEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND(!tile_data);
+
+ Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(navigation_layer);
+ polygon_editor->clear_polygons();
+ if (navigation_polygon.is_valid()) {
+ for (int i = 0; i < navigation_polygon->get_outline_count(); i++) {
+ polygon_editor->add_polygon(navigation_polygon->get_outline(i));
+ }
+ }
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+}
+
+void TileDataNavigationEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND(!tile_data);
+ Ref<NavigationPolygon> navigation_polygon = p_value;
+ tile_data->set_navigation_polygon(navigation_layer, navigation_polygon);
+
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+}
+
+Variant TileDataNavigationEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
+ TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile));
+ ERR_FAIL_COND_V(!tile_data, Variant());
+ return tile_data->get_navigation_polygon(navigation_layer);
+}
+
+void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) {
+ for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) {
+ Vector2i coords = E->key().get_atlas_coords();
+ undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, navigation_layer), E->get());
+ undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, navigation_layer), p_new_value);
+ }
+}
+
+void TileDataNavigationEditor::_tile_set_changed() {
+ polygon_editor->set_tile_set(tile_set);
+}
+
+void TileDataNavigationEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ polygon_editor->set_polygons_color(get_tree()->get_debug_navigation_color());
+ break;
+ default:
+ break;
+ }
+}
+
+TileDataNavigationEditor::TileDataNavigationEditor() {
+ polygon_editor = memnew(GenericTilePolygonEditor);
+ polygon_editor->set_multiple_polygon_mode(true);
+ add_child(polygon_editor);
+}
+
+void TileDataNavigationEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+ TileData *tile_data = _get_tile_data(p_cell);
+ ERR_FAIL_COND(!tile_data);
+
+ // Draw all shapes.
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+
+ Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(navigation_layer);
+ if (navigation_polygon.is_valid()) {
+ Vector<Vector2> verts = navigation_polygon->get_vertices();
+ if (verts.size() < 3) {
+ return;
+ }
+
+ Color color = p_canvas_item->get_tree()->get_debug_navigation_color();
+ if (p_selected) {
+ Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
+ Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
+ selection_color.a = 0.7;
+ color = selection_color;
+ }
+
+ RandomPCG rand;
+ for (int i = 0; i < navigation_polygon->get_polygon_count(); i++) {
+ // An array of vertices for this polygon.
+ Vector<int> polygon = navigation_polygon->get_polygon(i);
+ Vector<Vector2> vertices;
+ vertices.resize(polygon.size());
+ for (int j = 0; j < polygon.size(); j++) {
+ ERR_FAIL_INDEX(polygon[j], verts.size());
+ vertices.write[j] = verts[polygon[j]];
+ }
+
+ // Generate the polygon color, slightly randomly modified from the settings one.
+ Color random_variation_color;
+ random_variation_color.set_hsv(color.get_h() + rand.random(-1.0, 1.0) * 0.05, color.get_s(), color.get_v() + rand.random(-1.0, 1.0) * 0.1);
+ random_variation_color.a = color.a;
+ Vector<Color> colors;
+ colors.push_back(random_variation_color);
+
+ RenderingServer::get_singleton()->canvas_item_add_polygon(p_canvas_item->get_canvas_item(), vertices, colors);
+ }
+ }
+
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
}
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index b82189e1ee..781f26cc02 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -31,87 +31,378 @@
#ifndef TILE_DATA_EDITORS_H
#define TILE_DATA_EDITORS_H
+#include "tile_atlas_view.h"
+
+#include "editor/editor_node.h"
+#include "editor/editor_properties.h"
+
+#include "scene/gui/box_container.h"
#include "scene/gui/control.h"
+#include "scene/gui/label.h"
#include "scene/resources/tile_set.h"
-class TileDataEditor : public Control {
- GDCLASS(TileDataEditor, Control);
+class TileDataEditor : public VBoxContainer {
+ GDCLASS(TileDataEditor, VBoxContainer);
+
+private:
+ void _call_tile_set_changed();
protected:
- TileData *tile_data;
- String property;
+ Ref<TileSet> tile_set;
+ TileData *_get_tile_data(TileMapCell p_cell);
+ virtual void _tile_set_changed(){};
- TileData *_get_tile_data(TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile);
+ static void _bind_methods();
public:
- // Edits a TileData property.
- void edit(TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property);
+ void set_tile_set(Ref<TileSet> p_tile_set);
+
+ // Input to handle painting.
+ virtual Control *get_toolbar() { return nullptr; };
+ virtual void forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform){};
+ virtual void forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform){};
+ virtual void forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event){};
+ virtual void forward_painting_alternatives_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event){};
- // Used to draw the value over a tile.
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property){};
+ // Used to draw the tile data property value over a tile.
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false){};
};
-class TileDataTextureOffsetEditor : public TileDataEditor {
- GDCLASS(TileDataTextureOffsetEditor, TileDataEditor);
+class DummyObject : public Object {
+ GDCLASS(DummyObject, Object)
+private:
+ Map<String, Variant> properties;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ bool has_dummy_property(StringName p_name);
+ void add_dummy_property(StringName p_name);
+ void remove_dummy_property(StringName p_name);
+ void clear_dummy_properties();
};
-class TileDataIntegerEditor : public TileDataEditor {
- GDCLASS(TileDataIntegerEditor, TileDataEditor);
+class GenericTilePolygonEditor : public VBoxContainer {
+ GDCLASS(GenericTilePolygonEditor, VBoxContainer);
+
+private:
+ Ref<TileSet> tile_set;
+ LocalVector<Vector<Point2>> polygons;
+ bool multiple_polygon_mode = false;
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ // UI
+ int hovered_polygon_index = -1;
+ int hovered_point_index = -1;
+ int hovered_segment_index = -1;
+ Vector2 hovered_segment_point;
+
+ enum DragType {
+ DRAG_TYPE_NONE,
+ DRAG_TYPE_DRAG_POINT,
+ DRAG_TYPE_CREATE_POINT,
+ DRAG_TYPE_PAN,
+ };
+ DragType drag_type;
+ int drag_polygon_index;
+ int drag_point_index;
+ Vector2 drag_last_pos;
+ PackedVector2Array drag_old_polygon;
+
+ HBoxContainer *toolbar;
+ Ref<ButtonGroup> tools_button_group;
+ Button *button_create;
+ Button *button_edit;
+ Button *button_delete;
+ Button *button_pixel_snap;
+ MenuButton *button_advanced_menu;
+
+ Vector<Point2> in_creation_polygon;
+
+ Panel *panel;
+ Control *base_control;
+ EditorZoomWidget *editor_zoom_widget;
+ Button *button_center_view;
+ Vector2 panning;
+
+ Ref<Texture2D> background_texture;
+ Rect2 background_region;
+ Vector2 background_offset;
+ bool background_h_flip;
+ bool background_v_flip;
+ bool background_transpose;
+ Color background_modulate;
+
+ Color polygon_color = Color(1.0, 0.0, 0.0);
+
+ enum AdvancedMenuOption {
+ RESET_TO_DEFAULT_TILE,
+ CLEAR_TILE,
+ };
+
+ void _base_control_draw();
+ void _zoom_changed();
+ void _advanced_menu_item_pressed(int p_item_pressed);
+ void _center_view();
+ void _base_control_gui_input(Ref<InputEvent> p_event);
+
+ void _snap_to_tile_shape(Point2 &r_point, float &r_current_snapped_dist, float p_snap_dist);
+ void _snap_to_half_pixel(Point2 &r_point);
+ void _grab_polygon_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_point_index);
+ void _grab_polygon_segment_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_segment_index, Vector2 &r_point);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ void set_tile_set(Ref<TileSet> p_tile_set);
+ void set_background(Ref<Texture2D> p_texture, Rect2 p_region = Rect2(), Vector2 p_offset = Vector2(), bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false, Color p_modulate = Color(1.0, 1.0, 1.0, 0.0));
+
+ int get_polygon_count();
+ int add_polygon(Vector<Point2> p_polygon, int p_index = -1);
+ void remove_polygon(int p_index);
+ void clear_polygons();
+ void set_polygon(int p_polygon_index, Vector<Point2> p_polygon);
+ Vector<Point2> get_polygon(int p_polygon_index);
+
+ void set_polygons_color(Color p_color);
+ void set_multiple_polygon_mode(bool p_multiple_polygon_mode);
+
+ GenericTilePolygonEditor();
};
-class TileDataFloatEditor : public TileDataEditor {
- GDCLASS(TileDataFloatEditor, TileDataEditor);
+class TileDataDefaultEditor : public TileDataEditor {
+ GDCLASS(TileDataDefaultEditor, TileDataEditor);
+
+private:
+ // Toolbar
+ HBoxContainer *toolbar = memnew(HBoxContainer);
+ Button *picker_button;
+
+ // UI
+ Ref<Texture2D> tile_bool_checked;
+ Ref<Texture2D> tile_bool_unchecked;
+ Label *label;
+
+ EditorProperty *property_editor = nullptr;
+
+ // Painting state.
+ enum DragType {
+ DRAG_TYPE_NONE = 0,
+ DRAG_TYPE_PAINT,
+ DRAG_TYPE_PAINT_RECT,
+ };
+ DragType drag_type = DRAG_TYPE_NONE;
+ Vector2 drag_start_pos;
+ Vector2 drag_last_pos;
+ Map<TileMapCell, Variant> drag_modified;
+ Variant drag_painted_value;
+
+ void _property_value_changed(StringName p_property, Variant p_value, StringName p_field);
+
+protected:
+ DummyObject *dummy_object = memnew(DummyObject);
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ StringName type;
+ String property;
+ void _notification(int p_what);
+
+ virtual Variant _get_painted_value();
+ virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile);
+ virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value);
+ virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile);
+ virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value);
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ virtual Control *get_toolbar() override { return toolbar; };
+ virtual void forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override;
+ virtual void forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override;
+ virtual void forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event) override;
+ virtual void forward_painting_alternatives_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event) override;
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
+
+ void setup_property_editor(Variant::Type p_type, String p_property, String p_label = "", Variant p_default_value = Variant());
+
+ TileDataDefaultEditor();
+ ~TileDataDefaultEditor();
};
-class TileDataPositionEditor : public TileDataEditor {
- GDCLASS(TileDataPositionEditor, TileDataEditor);
+class TileDataTextureOffsetEditor : public TileDataDefaultEditor {
+ GDCLASS(TileDataTextureOffsetEditor, TileDataDefaultEditor);
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
};
-class TileDataYSortEditor : public TileDataEditor {
- GDCLASS(TileDataYSortEditor, TileDataEditor);
+class TileDataPositionEditor : public TileDataDefaultEditor {
+ GDCLASS(TileDataPositionEditor, TileDataDefaultEditor);
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
};
-class TileDataOcclusionShapeEditor : public TileDataEditor {
- GDCLASS(TileDataOcclusionShapeEditor, TileDataEditor);
+class TileDataYSortEditor : public TileDataDefaultEditor {
+ GDCLASS(TileDataYSortEditor, TileDataDefaultEditor);
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
};
-class TileDataCollisionShapeEditor : public TileDataEditor {
- GDCLASS(TileDataCollisionShapeEditor, TileDataEditor);
+class TileDataOcclusionShapeEditor : public TileDataDefaultEditor {
+ GDCLASS(TileDataOcclusionShapeEditor, TileDataDefaultEditor);
+
+private:
+ int occlusion_layer = -1;
+
+ // UI
+ GenericTilePolygonEditor *polygon_editor;
+
+ void _polygon_changed(PackedVector2Array p_polygon);
+
+ virtual Variant _get_painted_value() override;
+ virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override;
+ virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override;
+ virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override;
+ virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override;
+
+protected:
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ virtual void _tile_set_changed() override;
+
+ void _notification(int p_what);
+
+public:
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
+
+ void set_occlusion_layer(int p_occlusion_layer) { occlusion_layer = p_occlusion_layer; }
+
+ TileDataOcclusionShapeEditor();
+};
+
+class TileDataCollisionEditor : public TileDataDefaultEditor {
+ GDCLASS(TileDataCollisionEditor, TileDataDefaultEditor);
+
+ int physics_layer = -1;
+
+ // UI
+ GenericTilePolygonEditor *polygon_editor;
+ DummyObject *dummy_object = memnew(DummyObject);
+ Map<StringName, EditorProperty *> property_editors;
+
+ void _property_value_changed(StringName p_property, Variant p_value, StringName p_field);
+ void _polygons_changed();
+
+ virtual Variant _get_painted_value() override;
+ virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override;
+ virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override;
+ virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override;
+ virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override;
+
+protected:
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ virtual void _tile_set_changed() override;
+
+ void _notification(int p_what);
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
+
+ void set_physics_layer(int p_physics_layer) { physics_layer = p_physics_layer; }
+
+ TileDataCollisionEditor();
+ ~TileDataCollisionEditor();
};
class TileDataTerrainsEditor : public TileDataEditor {
GDCLASS(TileDataTerrainsEditor, TileDataEditor);
+private:
+ // Toolbar
+ HBoxContainer *toolbar = memnew(HBoxContainer);
+ Button *picker_button;
+
+ // Painting state.
+ enum DragType {
+ DRAG_TYPE_NONE = 0,
+ DRAG_TYPE_PAINT_TERRAIN_SET,
+ DRAG_TYPE_PAINT_TERRAIN_SET_RECT,
+ DRAG_TYPE_PAINT_TERRAIN_BITS,
+ DRAG_TYPE_PAINT_TERRAIN_BITS_RECT,
+ };
+ DragType drag_type = DRAG_TYPE_NONE;
+ Vector2 drag_start_pos;
+ Vector2 drag_last_pos;
+ Map<TileMapCell, Variant> drag_modified;
+ Variant drag_painted_value;
+
+ // UI
+ Label *label;
+ DummyObject *dummy_object = memnew(DummyObject);
+ EditorPropertyEnum *terrain_set_property_editor = nullptr;
+ EditorPropertyEnum *terrain_property_editor = nullptr;
+
+ void _property_value_changed(StringName p_property, Variant p_value, StringName p_field);
+
+ void _update_terrain_selector();
+
+protected:
+ virtual void _tile_set_changed() override;
+
+ void _notification(int p_what);
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ virtual Control *get_toolbar() override { return toolbar; };
+ virtual void forward_draw_over_atlas(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override;
+ virtual void forward_draw_over_alternatives(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, CanvasItem *p_canvas_item, Transform2D p_transform) override;
+ virtual void forward_painting_atlas_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event) override;
+ virtual void forward_painting_alternatives_gui_input(TileAtlasView *p_tile_atlas_view, TileSetAtlasSource *p_tile_atlas_source, const Ref<InputEvent> &p_event) override;
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
+
+ TileDataTerrainsEditor();
+ ~TileDataTerrainsEditor();
};
-class TileDataNavigationPolygonEditor : public TileDataEditor {
- GDCLASS(TileDataNavigationPolygonEditor, TileDataEditor);
+class TileDataNavigationEditor : public TileDataDefaultEditor {
+ GDCLASS(TileDataNavigationEditor, TileDataDefaultEditor);
+
+private:
+ int navigation_layer = -1;
+ PackedVector2Array navigation_polygon;
+
+ // UI
+ GenericTilePolygonEditor *polygon_editor;
+
+ void _polygon_changed(PackedVector2Array p_polygon);
+
+ virtual Variant _get_painted_value() override;
+ virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override;
+ virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override;
+ virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override;
+ virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override;
+
+protected:
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ virtual void _tile_set_changed() override;
+
+ void _notification(int p_what);
public:
- virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
+
+ void set_navigation_layer(int p_navigation_layer) { navigation_layer = p_navigation_layer; }
+
+ TileDataNavigationEditor();
};
#endif // TILE_DATA_EDITORS_H
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 7ad6462c0e..6e3c55d801 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -47,18 +47,18 @@ void TileMapEditorTilesPlugin::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED:
- select_tool_button->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- paint_tool_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
- line_tool_button->set_icon(get_theme_icon("CurveLinear", "EditorIcons"));
- rect_tool_button->set_icon(get_theme_icon("Rectangle", "EditorIcons"));
- bucket_tool_button->set_icon(get_theme_icon("Bucket", "EditorIcons"));
+ select_tool_button->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ paint_tool_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ line_tool_button->set_icon(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")));
+ rect_tool_button->set_icon(get_theme_icon(SNAME("Rectangle"), SNAME("EditorIcons")));
+ bucket_tool_button->set_icon(get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons")));
- picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
- erase_button->set_icon(get_theme_icon("Eraser", "EditorIcons"));
+ picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
+ erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
- toggle_grid_button->set_icon(get_theme_icon("Grid", "EditorIcons"));
+ toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
- missing_atlas_texture_icon = get_theme_icon("TileSet", "EditorIcons");
+ missing_atlas_texture_icon = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
break;
@@ -168,22 +168,22 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
if (atlas_source) {
texture = atlas_source->get_texture();
if (texture.is_valid()) {
- item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
+ item_text = vformat("%s (ID: %d)", texture->get_path().get_file(), source_id);
} else {
- item_text = vformat("No Texture Atlas Source (id:%d)", source_id);
+ item_text = vformat("No Texture Atlas Source (ID: %d)", source_id);
}
}
// Scene collection source.
TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
if (scene_collection_source) {
- texture = get_theme_icon("PackedScene", "EditorIcons");
- item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id);
+ texture = get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
+ item_text = vformat(TTR("Scene Collection Source (ID: %d)"), source_id);
}
// Use default if not valid.
if (item_text.is_empty()) {
- item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id);
+ item_text = vformat(TTR("Unknown Type Source (ID: %d)"), source_id);
}
if (!texture.is_valid()) {
texture = missing_atlas_texture_icon;
@@ -200,7 +200,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
} else {
sources_list->set_current(0);
}
- sources_list->emit_signal("item_selected", sources_list->get_current());
+ sources_list->emit_signal(SNAME("item_selected"), sources_list->get_current());
}
// Synchronize
@@ -302,11 +302,11 @@ void TileMapEditorTilesPlugin::_update_scenes_collection_view() {
int item_index = 0;
if (scene.is_valid()) {
- item_index = scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
+ item_index = scene_tiles_list->add_item(vformat("%s (Path: %s, ID: %d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
Variant udata = i;
EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
} else {
- item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons"));
+ item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")));
}
scene_tiles_list->set_item_metadata(item_index, scene_id);
@@ -1865,6 +1865,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
toggle_grid_button = memnew(Button);
toggle_grid_button->set_flat(true);
toggle_grid_button->set_toggle_mode(true);
+ toggle_grid_button->set_tooltip(TTR("Toggle grid visibility."));
toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_grid_toggled));
toolbar->add_child(toggle_grid_button);
@@ -1955,9 +1956,9 @@ void TileMapEditorTerrainsPlugin::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED:
- paint_tool_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
- picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
- erase_button->set_icon(get_theme_icon("Eraser", "EditorIcons"));
+ paint_tool_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
+ erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
break;
}
}
@@ -2989,76 +2990,31 @@ void TileMapEditorTerrainsPlugin::_update_terrains_tree() {
}
// Fill in the terrain list.
+ Vector<Vector<Ref<Texture2D>>> icons = tile_set->generate_terrains_icons(Size2(16, 16) * EDSCALE);
for (int terrain_set_index = 0; terrain_set_index < tile_set->get_terrain_sets_count(); terrain_set_index++) {
// Add an item for the terrain set.
TreeItem *terrain_set_tree_item = terrains_tree->create_item();
String matches;
if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- terrain_set_tree_item->set_icon(0, get_theme_icon("TerrainMatchCornersAndSides", "EditorIcons"));
+ terrain_set_tree_item->set_icon(0, get_theme_icon(SNAME("TerrainMatchCornersAndSides"), SNAME("EditorIcons")));
matches = String(TTR("Matches Corners and Sides"));
} else if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- terrain_set_tree_item->set_icon(0, get_theme_icon("TerrainMatchCorners", "EditorIcons"));
+ terrain_set_tree_item->set_icon(0, get_theme_icon(SNAME("TerrainMatchCorners"), SNAME("EditorIcons")));
matches = String(TTR("Matches Corners Only"));
} else {
- terrain_set_tree_item->set_icon(0, get_theme_icon("TerrainMatchSides", "EditorIcons"));
+ terrain_set_tree_item->set_icon(0, get_theme_icon(SNAME("TerrainMatchSides"), SNAME("EditorIcons")));
matches = String(TTR("Matches Sides Only"));
}
terrain_set_tree_item->set_text(0, vformat("Terrain Set %d (%s)", terrain_set_index, matches));
terrain_set_tree_item->set_selectable(0, false);
for (int terrain_index = 0; terrain_index < tile_set->get_terrains_count(terrain_set_index); terrain_index++) {
- // Compute the terrains_tile_pattern used for terrain preview (whenever possible).
- TerrainsTilePattern terrains_tile_pattern;
- int max_bit_count = -1;
- for (Set<TerrainsTilePattern>::Element *E = per_terrain_terrains_tile_patterns[terrain_set_index][terrain_index].front(); E; E = E->next()) {
- int count = 0;
- for (int i = 0; i < E->get().size(); i++) {
- if (int(E->get()[i]) == terrain_index) {
- count++;
- }
- }
- if (count > max_bit_count) {
- terrains_tile_pattern = E->get();
- max_bit_count = count;
- }
- }
-
- // Get the preview.
- Ref<Texture2D> icon;
- Rect2 region;
- if (max_bit_count >= 0) {
- double max_probability = -1.0;
- for (Set<TileMapCell>::Element *E = per_terrain_terrains_tile_patterns_tiles[terrain_set_index][terrains_tile_pattern].front(); E; E = E->next()) {
- Ref<TileSetSource> source = tile_set->get_source(E->get().source_id);
-
- Ref<TileSetAtlasSource> atlas_source = source;
- if (atlas_source.is_valid()) {
- TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(E->get().get_atlas_coords(), E->get().alternative_tile));
- if (tile_data->get_probability() > max_probability) {
- icon = atlas_source->get_texture();
- region = atlas_source->get_tile_texture_region(E->get().get_atlas_coords());
- max_probability = tile_data->get_probability();
- }
- }
- }
- } else {
- Ref<Image> image;
- image.instantiate();
- image->create(1, 1, false, Image::FORMAT_RGBA8);
- image->set_pixel(0, 0, tile_set->get_terrain_color(terrain_set_index, terrain_index));
- Ref<ImageTexture> image_texture;
- image_texture.instantiate();
- image_texture->create_from_image(image);
- image_texture->set_size_override(Size2(32, 32) * EDSCALE);
- icon = image_texture;
- }
-
// Add the item to the terrain list.
TreeItem *terrain_tree_item = terrains_tree->create_item(terrain_set_tree_item);
terrain_tree_item->set_text(0, tile_set->get_terrain_name(terrain_set_index, terrain_index));
terrain_tree_item->set_icon_max_width(0, 32 * EDSCALE);
- terrain_tree_item->set_icon(0, icon);
- terrain_tree_item->set_icon_region(0, region);
+ terrain_tree_item->set_icon(0, icons[terrain_set_index][terrain_index]);
+
Dictionary metadata_dict;
metadata_dict["terrain_set"] = terrain_set_index;
metadata_dict["terrain_id"] = terrain_index;
@@ -3232,8 +3188,8 @@ void TileMapEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED:
- missing_tile_texture = get_theme_icon("StatusWarning", "EditorIcons");
- warning_pattern_texture = get_theme_icon("WarningPattern", "EditorIcons");
+ missing_tile_texture = get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"));
+ warning_pattern_texture = get_theme_icon(SNAME("WarningPattern"), SNAME("EditorIcons"));
break;
case NOTIFICATION_INTERNAL_PROCESS:
if (is_visible_in_tree() && tileset_changed_needs_update) {
@@ -3483,7 +3439,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
}
// Draw the IDs for debug.
- /*Ref<Font> font = get_theme_font("font", "Label");
+ /*Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
for (int x = displayed_rect.position.x; x < (displayed_rect.position.x + displayed_rect.size.x); x++) {
for (int y = displayed_rect.position.y; y < (displayed_rect.position.y + displayed_rect.size.y); y++) {
p_overlay->draw_string(font, xform.xform(tile_map->map_to_world(Vector2(x, y))) + Vector2i(-tile_shape_size.x / 2, 0), vformat("%s", Vector2(x, y)));
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index f6007afe4e..6b617cf4d8 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -58,7 +58,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id(int p_id) {
int previous_source = source_id;
source_id = p_id; // source_id must be updated before, because it's used by the source list update.
tile_set->set_source_id(previous_source, p_id);
- emit_signal("changed", "id");
+ emit_signal(SNAME("changed"), "id");
}
int TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id() {
@@ -69,7 +69,7 @@ bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_set(const StringN
bool valid = false;
tile_set_atlas_source->set(p_name, p_value, &valid);
if (valid) {
- emit_signal("changed", String(p_name).utf8().get_data());
+ emit_signal(SNAME("changed"), String(p_name).utf8().get_data());
}
return valid;
}
@@ -148,14 +148,14 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_na
tile_set_atlas_source->move_tile_in_atlas(coords, as_vector2i);
tiles.clear();
tiles.insert({ as_vector2i, 0 });
- emit_signal("changed", "atlas_coords");
+ emit_signal(SNAME("changed"), "atlas_coords");
return true;
} else if (alternative == 0 && p_name == "size_in_atlas") {
Vector2i as_vector2i = Vector2i(p_value);
ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i), false);
tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i);
- emit_signal("changed", "size_in_atlas");
+ emit_signal(SNAME("changed"), "size_in_atlas");
return true;
} else if (alternative > 0 && p_name == "alternative_id") {
int as_int = int(p_value);
@@ -172,7 +172,7 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_na
tiles.insert({ coords, as_int }); // tiles must be updated before.
tile_set_atlas_source->set_alternative_tile_id(coords, previous_alternative_tile, as_int);
- emit_signal("changed", "alternative_id");
+ emit_signal(SNAME("changed"), "alternative_id");
return true;
}
}
@@ -191,7 +191,7 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_na
}
if (any_valid) {
- emit_signal("changed", String(p_name).utf8().get_data());
+ emit_signal(SNAME("changed"), String(p_name).utf8().get_data());
}
return any_valid;
@@ -357,6 +357,7 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_bind_methods() {
void TileSetAtlasSourceEditor::_inspector_property_selected(String p_property) {
selected_property = p_property;
_update_atlas_view();
+ _update_current_tile_data_editor();
}
void TileSetAtlasSourceEditor::_update_tile_id_label() {
@@ -398,17 +399,315 @@ void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() {
}
}
+void TileSetAtlasSourceEditor::_update_atlas_source_inspector() {
+ // Update visibility.
+ bool visible = tools_button_group->get_pressed_button() == tool_setup_atlas_source_button;
+ atlas_source_inspector_label->set_visible(visible);
+ atlas_source_inspector->set_visible(visible);
+}
+
void TileSetAtlasSourceEditor::_update_tile_inspector() {
- bool has_atlas_tile_selected = (tools_button_group->get_pressed_button() == tool_select_button) && !selection.is_empty();
+ // Update visibility.
+ if (tools_button_group->get_pressed_button() == tool_select_button) {
+ if (!selection.is_empty()) {
+ tile_proxy_object->edit(tile_set_atlas_source, selection);
+ }
+ tile_inspector_label->show();
+ tile_inspector->set_visible(!selection.is_empty());
+ tile_inspector_no_tile_selected_label->set_visible(selection.is_empty());
+ } else {
+ tile_inspector_label->hide();
+ tile_inspector->hide();
+ tile_inspector_no_tile_selected_label->hide();
+ }
+}
- // Update the proxy object.
- if (has_atlas_tile_selected) {
- tile_proxy_object->edit(tile_set_atlas_source, selection);
+void TileSetAtlasSourceEditor::_update_tile_data_editors() {
+ String previously_selected;
+ if (tile_data_editors_tree && tile_data_editors_tree->get_selected()) {
+ previously_selected = tile_data_editors_tree->get_selected()->get_metadata(0);
+ }
+
+ tile_data_editors_tree->clear();
+
+ TreeItem *root = tile_data_editors_tree->create_item();
+
+ TreeItem *group;
+#define ADD_TILE_DATA_EDITOR_GROUP(text) \
+ group = tile_data_editors_tree->create_item(root); \
+ group->set_custom_bg_color(0, group_color); \
+ group->set_selectable(0, false); \
+ group->set_disable_folding(true); \
+ group->set_text(0, text);
+
+ TreeItem *item;
+#define ADD_TILE_DATA_EDITOR(parent, text, property) \
+ item = tile_data_editors_tree->create_item(parent); \
+ item->set_text(0, text); \
+ item->set_metadata(0, property); \
+ if (property == previously_selected) { \
+ item->select(0); \
+ }
+
+ // Theming.
+ tile_data_editors_tree->add_theme_constant_override("vseparation", 1);
+ tile_data_editors_tree->add_theme_constant_override("hseparation", 3);
+
+ Color group_color = get_theme_color(SNAME("prop_category"), SNAME("Editor"));
+
+ // List of editors.
+ // --- Rendering ---
+ ADD_TILE_DATA_EDITOR_GROUP("Rendering");
+
+ ADD_TILE_DATA_EDITOR(group, "Texture Offset", "texture_offset");
+ if (!tile_data_editors.has("texture_offset")) {
+ TileDataTextureOffsetEditor *tile_data_texture_offset_editor = memnew(TileDataTextureOffsetEditor);
+ tile_data_texture_offset_editor->hide();
+ tile_data_texture_offset_editor->setup_property_editor(Variant::VECTOR2, "texture_offset");
+ tile_data_texture_offset_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_texture_offset_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors["texture_offset"] = tile_data_texture_offset_editor;
+ }
+
+ ADD_TILE_DATA_EDITOR(group, "Modulate", "modulate");
+ if (!tile_data_editors.has("modulate")) {
+ TileDataDefaultEditor *tile_data_modulate_editor = memnew(TileDataDefaultEditor());
+ tile_data_modulate_editor->hide();
+ tile_data_modulate_editor->setup_property_editor(Variant::COLOR, "modulate", "", Color(1.0, 1.0, 1.0, 1.0));
+ tile_data_modulate_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_modulate_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors["modulate"] = tile_data_modulate_editor;
+ }
+
+ ADD_TILE_DATA_EDITOR(group, "Z Index", "z_index");
+ if (!tile_data_editors.has("z_index")) {
+ TileDataDefaultEditor *tile_data_z_index_editor = memnew(TileDataDefaultEditor());
+ tile_data_z_index_editor->hide();
+ tile_data_z_index_editor->setup_property_editor(Variant::INT, "z_index");
+ tile_data_z_index_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_z_index_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors["z_index"] = tile_data_z_index_editor;
+ }
+
+ ADD_TILE_DATA_EDITOR(group, "Y Sort Origin", "y_sort_origin");
+ if (!tile_data_editors.has("y_sort_origin")) {
+ TileDataYSortEditor *tile_data_y_sort_editor = memnew(TileDataYSortEditor);
+ tile_data_y_sort_editor->hide();
+ tile_data_y_sort_editor->setup_property_editor(Variant::INT, "y_sort_origin");
+ tile_data_y_sort_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_y_sort_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors["y_sort_origin"] = tile_data_y_sort_editor;
+ }
+
+ for (int i = 0; i < tile_set->get_occlusion_layers_count(); i++) {
+ ADD_TILE_DATA_EDITOR(group, vformat("Occlusion Layer %d", i), vformat("occlusion_layer_%d", i));
+ if (!tile_data_editors.has(vformat("occlusion_layer_%d", i))) {
+ TileDataOcclusionShapeEditor *tile_data_occlusion_shape_editor = memnew(TileDataOcclusionShapeEditor());
+ tile_data_occlusion_shape_editor->hide();
+ tile_data_occlusion_shape_editor->set_occlusion_layer(i);
+ tile_data_occlusion_shape_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_occlusion_shape_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors[vformat("occlusion_layer_%d", i)] = tile_data_occlusion_shape_editor;
+ }
+ }
+ for (int i = tile_set->get_occlusion_layers_count(); tile_data_editors.has(vformat("occlusion_layer_%d", i)); i++) {
+ tile_data_editors[vformat("occlusion_layer_%d", i)]->queue_delete();
+ tile_data_editors.erase(vformat("occlusion_layer_%d", i));
+ }
+
+ // --- Rendering ---
+ ADD_TILE_DATA_EDITOR(root, "Terrains", "terrain_set");
+ if (!tile_data_editors.has("terrain_set")) {
+ TileDataTerrainsEditor *tile_data_terrains_editor = memnew(TileDataTerrainsEditor);
+ tile_data_terrains_editor->hide();
+ tile_data_terrains_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_terrains_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors["terrain_set"] = tile_data_terrains_editor;
+ }
+
+ // --- Miscellaneous ---
+ ADD_TILE_DATA_EDITOR(root, "Probability", "probability");
+ if (!tile_data_editors.has("probability")) {
+ TileDataDefaultEditor *tile_data_probability_editor = memnew(TileDataDefaultEditor());
+ tile_data_probability_editor->hide();
+ tile_data_probability_editor->setup_property_editor(Variant::FLOAT, "probability", "", 1.0);
+ tile_data_probability_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_probability_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors["probability"] = tile_data_probability_editor;
+ }
+
+ // --- Physics ---
+ ADD_TILE_DATA_EDITOR_GROUP("Physics");
+ for (int i = 0; i < tile_set->get_physics_layers_count(); i++) {
+ ADD_TILE_DATA_EDITOR(group, vformat("Physics Layer %d", i), vformat("physics_layer_%d", i));
+ if (!tile_data_editors.has(vformat("physics_layer_%d", i))) {
+ TileDataCollisionEditor *tile_data_collision_editor = memnew(TileDataCollisionEditor());
+ tile_data_collision_editor->hide();
+ tile_data_collision_editor->set_physics_layer(i);
+ tile_data_collision_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_collision_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors[vformat("physics_layer_%d", i)] = tile_data_collision_editor;
+ }
+ }
+ for (int i = tile_set->get_physics_layers_count(); tile_data_editors.has(vformat("physics_layer_%d", i)); i++) {
+ tile_data_editors[vformat("physics_layer_%d", i)]->queue_delete();
+ tile_data_editors.erase(vformat("physics_layer_%d", i));
+ }
+
+ // --- Navigation ---
+ ADD_TILE_DATA_EDITOR_GROUP("Navigation");
+ for (int i = 0; i < tile_set->get_navigation_layers_count(); i++) {
+ ADD_TILE_DATA_EDITOR(group, vformat("Navigation Layer %d", i), vformat("navigation_layer_%d", i));
+ if (!tile_data_editors.has(vformat("navigation_layer_%d", i))) {
+ TileDataNavigationEditor *tile_data_navigation_editor = memnew(TileDataNavigationEditor());
+ tile_data_navigation_editor->hide();
+ tile_data_navigation_editor->set_navigation_layer(i);
+ tile_data_navigation_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_navigation_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors[vformat("navigation_layer_%d", i)] = tile_data_navigation_editor;
+ }
+ }
+ for (int i = tile_set->get_navigation_layers_count(); tile_data_editors.has(vformat("navigation_layer_%d", i)); i++) {
+ tile_data_editors[vformat("navigation_layer_%d", i)]->queue_delete();
+ tile_data_editors.erase(vformat("navigation_layer_%d", i));
+ }
+
+ // --- Custom Data ---
+ ADD_TILE_DATA_EDITOR_GROUP("Custom Data");
+ for (int i = 0; i < tile_set->get_custom_data_layers_count(); i++) {
+ if (tile_set->get_custom_data_name(i).is_empty()) {
+ ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), vformat("custom_data_%d", i));
+ } else {
+ ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_name(i), vformat("custom_data_%d", i));
+ }
+ if (!tile_data_editors.has(vformat("custom_data_%d", i))) {
+ TileDataDefaultEditor *tile_data_custom_data_editor = memnew(TileDataDefaultEditor());
+ tile_data_custom_data_editor->hide();
+ tile_data_custom_data_editor->setup_property_editor(tile_set->get_custom_data_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_name(i));
+ tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
+ tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
+ tile_data_editors[vformat("custom_data_%d", i)] = tile_data_custom_data_editor;
+ }
+ }
+ for (int i = tile_set->get_custom_data_layers_count(); tile_data_editors.has(vformat("custom_data_%d", i)); i++) {
+ tile_data_editors[vformat("custom_data_%d", i)]->queue_delete();
+ tile_data_editors.erase(vformat("custom_data_%d", i));
+ }
+
+#undef ADD_TILE_DATA_EDITOR_GROUP
+#undef ADD_TILE_DATA_EDITOR
+
+ // Add tile data editors as children.
+ for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) {
+ // Tile Data Editor.
+ TileDataEditor *tile_data_editor = E->get();
+ if (!tile_data_editor->is_inside_tree()) {
+ tile_data_painting_editor_container->add_child(tile_data_editor);
+ }
+ tile_data_editor->set_tile_set(tile_set);
+
+ // Toolbar.
+ Control *toolbar = tile_data_editor->get_toolbar();
+ if (!toolbar->is_inside_tree()) {
+ tool_settings_tile_data_toolbar_container->add_child(toolbar);
+ }
+ toolbar->hide();
}
// Update visibility.
- tile_inspector_label->set_visible(has_atlas_tile_selected);
- tile_inspector->set_visible(has_atlas_tile_selected);
+ bool is_visible = tools_button_group->get_pressed_button() == tool_paint_button;
+ tile_data_editor_dropdown_button->set_visible(is_visible);
+ tile_data_editor_dropdown_button->set_text(TTR("Select a property editor"));
+ tile_data_editors_label->set_visible(is_visible);
+}
+
+void TileSetAtlasSourceEditor::_update_current_tile_data_editor() {
+ // Find the property to use.
+ String property;
+ if (tools_button_group->get_pressed_button() == tool_select_button && tile_inspector->is_visible() && !tile_inspector->get_selected_path().is_empty()) {
+ Vector<String> components = tile_inspector->get_selected_path().split("/");
+ if (components.size() >= 1) {
+ property = components[0];
+
+ // Workaround for terrains as they don't have a common first component.
+ if (property.begins_with("terrains_")) {
+ property = "terrain_set";
+ }
+ }
+ } else if (tools_button_group->get_pressed_button() == tool_paint_button && tile_data_editors_tree->get_selected()) {
+ property = tile_data_editors_tree->get_selected()->get_metadata(0);
+ tile_data_editor_dropdown_button->set_text(tile_data_editors_tree->get_selected()->get_text(0));
+ }
+
+ // Hide all editors but the current one.
+ for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) {
+ E->get()->hide();
+ E->get()->get_toolbar()->hide();
+ }
+ if (tile_data_editors.has(property)) {
+ current_tile_data_editor = tile_data_editors[property];
+ } else {
+ current_tile_data_editor = nullptr;
+ }
+
+ // Get the correct editor for the TileData's property.
+ if (current_tile_data_editor) {
+ current_tile_data_editor_toolbar = current_tile_data_editor->get_toolbar();
+ current_property = property;
+ current_tile_data_editor->set_visible(tools_button_group->get_pressed_button() == tool_paint_button);
+ current_tile_data_editor_toolbar->set_visible(tools_button_group->get_pressed_button() == tool_paint_button);
+ }
+}
+
+void TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_draw() {
+ if (!has_theme_icon(SNAME("arrow"), SNAME("OptionButton"))) {
+ return;
+ }
+
+ RID ci = tile_data_editor_dropdown_button->get_canvas_item();
+ Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"), SNAME("OptionButton"));
+ Color clr = Color(1, 1, 1);
+ if (get_theme_constant(SNAME("modulate_arrow"))) {
+ switch (tile_data_editor_dropdown_button->get_draw_mode()) {
+ case BaseButton::DRAW_PRESSED:
+ clr = get_theme_color(SNAME("font_pressed_color"));
+ break;
+ case BaseButton::DRAW_HOVER:
+ clr = get_theme_color(SNAME("font_hover_color"));
+ break;
+ case BaseButton::DRAW_DISABLED:
+ clr = get_theme_color(SNAME("font_disabled_color"));
+ break;
+ default:
+ clr = get_theme_color(SNAME("font_color"));
+ }
+ }
+
+ Size2 size = tile_data_editor_dropdown_button->get_size();
+
+ Point2 ofs;
+ if (is_layout_rtl()) {
+ ofs = Point2(get_theme_constant(SNAME("arrow_margin"), SNAME("OptionButton")), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ } else {
+ ofs = Point2(size.width - arrow->get_width() - get_theme_constant(SNAME("arrow_margin"), SNAME("OptionButton")), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ }
+ arrow->draw(ci, ofs, clr);
+}
+
+void TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_pressed() {
+ Size2 size = tile_data_editor_dropdown_button->get_size();
+ tile_data_editors_popup->set_position(tile_data_editor_dropdown_button->get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
+ tile_data_editors_popup->set_size(Size2(size.width, 0));
+ tile_data_editors_popup->popup();
+}
+
+void TileSetAtlasSourceEditor::_tile_data_editors_tree_selected() {
+ tile_data_editors_popup->call_deferred(SNAME("hide"));
+ _update_current_tile_data_editor();
+ tile_atlas_control->update();
+ tile_atlas_control_unscaled->update();
+ alternative_tiles_control->update();
+ alternative_tiles_control_unscaled->update();
}
void TileSetAtlasSourceEditor::_update_atlas_view() {
@@ -441,7 +740,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() {
Button *button = memnew(Button);
alternative_tiles_control->add_child(button);
button->set_flat(true);
- button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
button->add_theme_style_override("normal", memnew(StyleBoxEmpty));
button->add_theme_style_override("hover", memnew(StyleBoxEmpty));
button->add_theme_style_override("focus", memnew(StyleBoxEmpty));
@@ -467,19 +766,28 @@ void TileSetAtlasSourceEditor::_update_atlas_view() {
}
void TileSetAtlasSourceEditor::_update_toolbar() {
- // Hide all settings.
- for (int i = 0; i < tool_settings->get_child_count(); i++) {
- Object::cast_to<CanvasItem>(tool_settings->get_child(i))->hide();
- }
-
- // SHow only the correct settings.
- if (tools_button_group->get_pressed_button() == tool_select_button) {
- } else if (tools_button_group->get_pressed_button() == tool_add_remove_button) {
- tool_settings_vsep->show();
- tools_settings_erase_button->show();
- } else if (tools_button_group->get_pressed_button() == tool_add_remove_rect_button) {
+ // Show the tools and settings.
+ if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) {
+ if (current_tile_data_editor_toolbar) {
+ current_tile_data_editor_toolbar->hide();
+ }
tool_settings_vsep->show();
tools_settings_erase_button->show();
+ tool_advanced_menu_buttom->show();
+ } else if (tools_button_group->get_pressed_button() == tool_select_button) {
+ if (current_tile_data_editor_toolbar) {
+ current_tile_data_editor_toolbar->hide();
+ }
+ tool_settings_vsep->hide();
+ tools_settings_erase_button->hide();
+ tool_advanced_menu_buttom->hide();
+ } else if (tools_button_group->get_pressed_button() == tool_paint_button) {
+ if (current_tile_data_editor_toolbar) {
+ current_tile_data_editor_toolbar->show();
+ }
+ tool_settings_vsep->hide();
+ tools_settings_erase_button->hide();
+ tool_advanced_menu_buttom->hide();
}
}
@@ -499,357 +807,336 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Update the hovered coords.
hovered_base_tile_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- // Handle the event.
- Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid()) {
- Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
- Vector2i last_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_last_mouse_pos);
- Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
+ // Forward the event to the current tile data editor if we are in the painting mode.
+ if (tools_button_group->get_pressed_button() == tool_paint_button) {
+ if (current_tile_data_editor) {
+ current_tile_data_editor->forward_painting_atlas_gui_input(tile_atlas_view, tile_set_atlas_source, p_event);
+ }
+ // Update only what's needed.
+ tile_set_atlas_source_changed_needs_update = false;
- Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
+ tile_atlas_control->update();
+ tile_atlas_control_unscaled->update();
+ alternative_tiles_control->update();
+ alternative_tiles_control_unscaled->update();
+ tile_atlas_view->update();
+ return;
+ } else {
+ // Handle the event.
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
+ Vector2i last_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_last_mouse_pos);
+ Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- if (drag_type == DRAG_TYPE_NONE) {
- if (selection.size() == 1) {
- // Change the cursor depending on the hovered thing.
- TileSelection selected = selection.front()->get();
- if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
- Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
- Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
- Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
- Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
- Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0);
- const Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) };
- const Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) };
- CursorShape cursor_shape = CURSOR_ARROW;
- bool can_grow[4];
- for (int i = 0; i < 4; i++) {
- can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]);
- can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1;
- }
- for (int i = 0; i < 4; i++) {
- Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i];
- if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) {
- cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE;
+ Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
+
+ if (drag_type == DRAG_TYPE_NONE) {
+ if (selection.size() == 1) {
+ // Change the cursor depending on the hovered thing.
+ TileSelection selected = selection.front()->get();
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
+ Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
+ Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
+ Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
+ Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
+ Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0);
+ const Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) };
+ const Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) };
+ CursorShape cursor_shape = CURSOR_ARROW;
+ bool can_grow[4];
+ for (int i = 0; i < 4; i++) {
+ can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]);
+ can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1;
}
- Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4];
- if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) {
- cursor_shape = (i % 2) ? CURSOR_HSIZE : CURSOR_VSIZE;
+ for (int i = 0; i < 4; i++) {
+ Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i];
+ if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) {
+ cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE;
+ }
+ Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4];
+ if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) {
+ cursor_shape = (i % 2) ? CURSOR_HSIZE : CURSOR_VSIZE;
+ }
}
+ tile_atlas_control->set_default_cursor_shape(cursor_shape);
}
- tile_atlas_control->set_default_cursor_shape(cursor_shape);
}
- }
- } else if (drag_type == DRAG_TYPE_CREATE_BIG_TILE) {
- // Create big tile.
- new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
-
- Rect2i new_rect = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
- new_rect.size += Vector2i(1, 1);
- // Check if the new tile can fit in the new rect.
- if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) {
- // Move and resize the tile.
- tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size);
- drag_current_tile = new_rect.position;
- }
- } else if (drag_type == DRAG_TYPE_CREATE_TILES) {
- // Create tiles.
- last_base_tiles_coords = last_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
- new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
-
- Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
- for (int i = 0; i < line.size(); i++) {
- if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetSource::INVALID_ATLAS_COORDS) {
- tile_set_atlas_source->create_tile(line[i]);
- drag_modified_tiles.insert(line[i]);
+ } else if (drag_type == DRAG_TYPE_CREATE_BIG_TILE) {
+ // Create big tile.
+ new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
+
+ Rect2i new_rect = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
+ new_rect.size += Vector2i(1, 1);
+ // Check if the new tile can fit in the new rect.
+ if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) {
+ // Move and resize the tile.
+ tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size);
+ drag_current_tile = new_rect.position;
+ }
+ } else if (drag_type == DRAG_TYPE_CREATE_TILES) {
+ // Create tiles.
+ last_base_tiles_coords = last_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
+ new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
+
+ Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
+ for (int i = 0; i < line.size(); i++) {
+ if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetSource::INVALID_ATLAS_COORDS) {
+ tile_set_atlas_source->create_tile(line[i]);
+ drag_modified_tiles.insert(line[i]);
+ }
}
- }
- drag_last_mouse_pos = tile_atlas_control->get_local_mouse_position();
+ drag_last_mouse_pos = tile_atlas_control->get_local_mouse_position();
- } else if (drag_type == DRAG_TYPE_REMOVE_TILES) {
- // Remove tiles.
- last_base_tiles_coords = last_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
- new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
+ } else if (drag_type == DRAG_TYPE_REMOVE_TILES) {
+ // Remove tiles.
+ last_base_tiles_coords = last_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
+ new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
- Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
- for (int i = 0; i < line.size(); i++) {
- Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(line[i]);
- if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
- drag_modified_tiles.insert(base_tile_coords);
+ Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
+ for (int i = 0; i < line.size(); i++) {
+ Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(line[i]);
+ if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ drag_modified_tiles.insert(base_tile_coords);
+ }
}
- }
- drag_last_mouse_pos = tile_atlas_control->get_local_mouse_position();
- } else if (drag_type == DRAG_TYPE_MOVE_TILE) {
- // Move tile.
- Vector2 mouse_offset = (Vector2(tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile)) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
- Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position() - mouse_offset);
- coords = coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
- if (drag_current_tile != coords && tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, coords)) {
- tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, coords);
- selection.clear();
- selection.insert({ coords, 0 });
- drag_current_tile = coords;
+ drag_last_mouse_pos = tile_atlas_control->get_local_mouse_position();
+ } else if (drag_type == DRAG_TYPE_MOVE_TILE) {
+ // Move tile.
+ Vector2 mouse_offset = (Vector2(tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile)) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
+ Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position() - mouse_offset);
+ coords = coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
+ if (drag_current_tile != coords && tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, coords)) {
+ tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, coords);
+ selection.clear();
+ selection.insert({ coords, 0 });
+ drag_current_tile = coords;
- // Update only what's needed.
- tile_set_atlas_source_changed_needs_update = false;
- _update_tile_inspector();
- _update_atlas_view();
- _update_tile_id_label();
- }
- } else if (drag_type >= DRAG_TYPE_RESIZE_TOP_LEFT && drag_type <= DRAG_TYPE_RESIZE_LEFT) {
- // Resizing a tile.
- new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(-1, -1)).min(grid_size);
+ // Update only what's needed.
+ tile_set_atlas_source_changed_needs_update = false;
+ _update_tile_inspector();
+ _update_atlas_view();
+ _update_tile_id_label();
+ _update_current_tile_data_editor();
+ }
+ } else if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) {
+ if (Vector2(drag_start_mouse_pos).distance_to(tile_atlas_control->get_local_mouse_position()) > 5.0 * EDSCALE) {
+ drag_type = DRAG_TYPE_NONE;
+ }
+ } else if (drag_type >= DRAG_TYPE_RESIZE_TOP_LEFT && drag_type <= DRAG_TYPE_RESIZE_LEFT) {
+ // Resizing a tile.
+ new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(-1, -1)).min(grid_size);
- Rect2i old_rect = Rect2i(drag_current_tile, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile));
- Rect2i new_rect = old_rect;
+ Rect2i old_rect = Rect2i(drag_current_tile, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile));
+ Rect2i new_rect = old_rect;
- if (drag_type == DRAG_TYPE_RESIZE_LEFT || drag_type == DRAG_TYPE_RESIZE_TOP_LEFT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_LEFT) {
- new_rect.position.x = MIN(new_base_tiles_coords.x + 1, old_rect.get_end().x - 1);
- new_rect.size.x = old_rect.get_end().x - new_rect.position.x;
- }
- if (drag_type == DRAG_TYPE_RESIZE_TOP || drag_type == DRAG_TYPE_RESIZE_TOP_LEFT || drag_type == DRAG_TYPE_RESIZE_TOP_RIGHT) {
- new_rect.position.y = MIN(new_base_tiles_coords.y + 1, old_rect.get_end().y - 1);
- new_rect.size.y = old_rect.get_end().y - new_rect.position.y;
- }
+ if (drag_type == DRAG_TYPE_RESIZE_LEFT || drag_type == DRAG_TYPE_RESIZE_TOP_LEFT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_LEFT) {
+ new_rect.position.x = MIN(new_base_tiles_coords.x + 1, old_rect.get_end().x - 1);
+ new_rect.size.x = old_rect.get_end().x - new_rect.position.x;
+ }
+ if (drag_type == DRAG_TYPE_RESIZE_TOP || drag_type == DRAG_TYPE_RESIZE_TOP_LEFT || drag_type == DRAG_TYPE_RESIZE_TOP_RIGHT) {
+ new_rect.position.y = MIN(new_base_tiles_coords.y + 1, old_rect.get_end().y - 1);
+ new_rect.size.y = old_rect.get_end().y - new_rect.position.y;
+ }
- if (drag_type == DRAG_TYPE_RESIZE_RIGHT || drag_type == DRAG_TYPE_RESIZE_TOP_RIGHT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_RIGHT) {
- new_rect.set_end(Vector2i(MAX(new_base_tiles_coords.x, old_rect.position.x + 1), new_rect.get_end().y));
- }
- if (drag_type == DRAG_TYPE_RESIZE_BOTTOM || drag_type == DRAG_TYPE_RESIZE_BOTTOM_LEFT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_RIGHT) {
- new_rect.set_end(Vector2i(new_rect.get_end().x, MAX(new_base_tiles_coords.y, old_rect.position.y + 1)));
- }
+ if (drag_type == DRAG_TYPE_RESIZE_RIGHT || drag_type == DRAG_TYPE_RESIZE_TOP_RIGHT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_RIGHT) {
+ new_rect.set_end(Vector2i(MAX(new_base_tiles_coords.x, old_rect.position.x + 1), new_rect.get_end().y));
+ }
+ if (drag_type == DRAG_TYPE_RESIZE_BOTTOM || drag_type == DRAG_TYPE_RESIZE_BOTTOM_LEFT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_RIGHT) {
+ new_rect.set_end(Vector2i(new_rect.get_end().x, MAX(new_base_tiles_coords.y, old_rect.position.y + 1)));
+ }
- if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) {
- tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size);
- selection.clear();
- selection.insert({ new_rect.position, 0 });
- drag_current_tile = new_rect.position;
+ if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) {
+ tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size);
+ selection.clear();
+ selection.insert({ new_rect.position, 0 });
+ drag_current_tile = new_rect.position;
- // Update only what's needed.
- tile_set_atlas_source_changed_needs_update = false;
- _update_tile_inspector();
- _update_atlas_view();
- _update_tile_id_label();
+ // Update only what's needed.
+ tile_set_atlas_source_changed_needs_update = false;
+ _update_tile_inspector();
+ _update_atlas_view();
+ _update_tile_id_label();
+ _update_current_tile_data_editor();
+ }
}
+
+ // Redraw for the hovered tile.
+ tile_atlas_control->update();
+ tile_atlas_control_unscaled->update();
+ alternative_tiles_control->update();
+ alternative_tiles_control_unscaled->update();
+ tile_atlas_view->update();
+ return;
}
- // Redraw for the hovered tile.
- tile_atlas_control->update();
- tile_atlas_control_unscaled->update();
- alternative_tiles_control->update();
- alternative_tiles_control_unscaled->update();
- tile_atlas_view->update();
- return;
- }
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb->is_pressed()) {
+ // Left click pressed.
+ if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) {
+ if (tools_settings_erase_button->is_pressed()) {
+ // Erasing
+ if (mb->is_ctrl_pressed() || mb->is_shift_pressed()) {
+ // Remove tiles using rect.
+
+ // Setup the dragging info.
+ drag_type = DRAG_TYPE_REMOVE_TILES_USING_RECT;
+ drag_start_mouse_pos = mouse_local_pos;
+ drag_last_mouse_pos = drag_start_mouse_pos;
+ } else {
+ // Remove tiles.
- Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid()) {
- Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
- if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (mb->is_pressed()) {
- // Left click pressed.
- if (tools_button_group->get_pressed_button() == tool_add_remove_button) {
- if (tools_settings_erase_button->is_pressed()) {
- // Remove tiles.
-
- // Setup the dragging info.
- drag_type = DRAG_TYPE_REMOVE_TILES;
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
-
- // Remove a first tile.
- Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
- if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
- coords = tile_set_atlas_source->get_tile_at_coords(coords);
- }
- if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
- drag_modified_tiles.insert(coords);
- }
- } else {
- if (mb->is_shift_pressed()) {
- // Create a big tile.
- Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
- // Setup the dragging info, only if we start on an empty tile.
- drag_type = DRAG_TYPE_CREATE_BIG_TILE;
+ // Setup the dragging info.
+ drag_type = DRAG_TYPE_REMOVE_TILES;
drag_start_mouse_pos = mouse_local_pos;
drag_last_mouse_pos = drag_start_mouse_pos;
- drag_current_tile = coords;
- // Create a tile.
- tile_set_atlas_source->create_tile(coords);
+ // Remove a first tile.
+ Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ coords = tile_set_atlas_source->get_tile_at_coords(coords);
+ }
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ drag_modified_tiles.insert(coords);
+ }
}
} else {
- // Create tiles.
-
- // Setup the dragging info.
- drag_type = DRAG_TYPE_CREATE_TILES;
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
-
- // Create a first tile if needed.
- Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
- if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
- tile_set_atlas_source->create_tile(coords);
- drag_modified_tiles.insert(coords);
- }
- }
- }
- } else if (tools_button_group->get_pressed_button() == tool_add_remove_rect_button) {
- if (tools_settings_erase_button->is_pressed()) {
- // Remove tiles using rect.
-
- // Setup the dragging info.
- drag_type = DRAG_TYPE_REMOVE_TILES_USING_RECT;
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
- } else {
- if (mb->is_shift_pressed()) {
- // Create a big tile.
- Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
- // Setup the dragging info, only if we start on an empty tile.
- drag_type = DRAG_TYPE_CREATE_BIG_TILE;
+ // Creating
+ if (mb->is_shift_pressed()) {
+ // Create a big tile.
+ Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
+ // Setup the dragging info, only if we start on an empty tile.
+ drag_type = DRAG_TYPE_CREATE_BIG_TILE;
+ drag_start_mouse_pos = mouse_local_pos;
+ drag_last_mouse_pos = drag_start_mouse_pos;
+ drag_current_tile = coords;
+
+ // Create a tile.
+ tile_set_atlas_source->create_tile(coords);
+ }
+ } else if (mb->is_ctrl_pressed()) {
+ // Create tiles using rect.
+ drag_type = DRAG_TYPE_CREATE_TILES_USING_RECT;
drag_start_mouse_pos = mouse_local_pos;
drag_last_mouse_pos = drag_start_mouse_pos;
- drag_current_tile = coords;
+ } else {
+ // Create tiles.
- // Create a tile.
- tile_set_atlas_source->create_tile(coords);
+ // Setup the dragging info.
+ drag_type = DRAG_TYPE_CREATE_TILES;
+ drag_start_mouse_pos = mouse_local_pos;
+ drag_last_mouse_pos = drag_start_mouse_pos;
+
+ // Create a first tile if needed.
+ Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
+ tile_set_atlas_source->create_tile(coords);
+ drag_modified_tiles.insert(coords);
+ }
}
- } else {
- // Create tiles using rect.
- drag_type = DRAG_TYPE_CREATE_TILES_USING_RECT;
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
}
- }
- } else if (tools_button_group->get_pressed_button() == tool_select_button) {
- // Dragging a handle.
- drag_type = DRAG_TYPE_NONE;
- if (selection.size() == 1) {
- TileSelection selected = selection.front()->get();
- if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
- Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
- Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
- Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
- Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0);
- const Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) };
- const Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) };
- CursorShape cursor_shape = CURSOR_ARROW;
- bool can_grow[4];
- for (int i = 0; i < 4; i++) {
- can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]);
- can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1;
- }
- for (int i = 0; i < 4; i++) {
- Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i];
- if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) {
- drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP_LEFT + i * 2);
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
- drag_current_tile = selected.tile;
- drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
- cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE;
+ } else if (tools_button_group->get_pressed_button() == tool_select_button) {
+ // Dragging a handle.
+ drag_type = DRAG_TYPE_NONE;
+ if (selection.size() == 1) {
+ TileSelection selected = selection.front()->get();
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
+ Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
+ Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
+ Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
+ Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0);
+ const Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) };
+ const Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) };
+ CursorShape cursor_shape = CURSOR_ARROW;
+ bool can_grow[4];
+ for (int i = 0; i < 4; i++) {
+ can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]);
+ can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1;
}
- Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4];
- if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) {
- drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP + i * 2);
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
- drag_current_tile = selected.tile;
- drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
- cursor_shape = (i % 2) ? CURSOR_HSIZE : CURSOR_VSIZE;
+ for (int i = 0; i < 4; i++) {
+ Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i];
+ if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) {
+ drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP_LEFT + i * 2);
+ drag_start_mouse_pos = mouse_local_pos;
+ drag_last_mouse_pos = drag_start_mouse_pos;
+ drag_current_tile = selected.tile;
+ drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
+ cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE;
+ }
+ Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4];
+ if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) {
+ drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP + i * 2);
+ drag_start_mouse_pos = mouse_local_pos;
+ drag_last_mouse_pos = drag_start_mouse_pos;
+ drag_current_tile = selected.tile;
+ drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
+ cursor_shape = (i % 2) ? CURSOR_HSIZE : CURSOR_VSIZE;
+ }
}
+ tile_atlas_control->set_default_cursor_shape(cursor_shape);
}
- tile_atlas_control->set_default_cursor_shape(cursor_shape);
}
- }
- // Selecting then dragging a tile.
- if (drag_type == DRAG_TYPE_NONE) {
- TileSelection selected = { TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE };
- Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
- coords = tile_set_atlas_source->get_tile_at_coords(coords);
+ // Selecting then dragging a tile.
+ if (drag_type == DRAG_TYPE_NONE) {
+ TileSelection selected = { TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE };
+ Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
- selected = { coords, 0 };
+ coords = tile_set_atlas_source->get_tile_at_coords(coords);
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ selected = { coords, 0 };
+ }
}
- }
- bool shift = mb->is_shift_pressed();
- if (!shift && selection.size() == 1 && selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
- // Start move dragging.
- drag_type = DRAG_TYPE_MOVE_TILE;
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
- drag_current_tile = selected.tile;
- drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
- tile_atlas_control->set_default_cursor_shape(CURSOR_MOVE);
- } else {
- // Start selection dragging.
- drag_type = DRAG_TYPE_RECT_SELECT;
- drag_start_mouse_pos = mouse_local_pos;
- drag_last_mouse_pos = drag_start_mouse_pos;
+ bool shift = mb->is_shift_pressed();
+ if (!shift && selection.size() == 1 && selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
+ // Start move dragging.
+ drag_type = DRAG_TYPE_MOVE_TILE;
+ drag_start_mouse_pos = mouse_local_pos;
+ drag_last_mouse_pos = drag_start_mouse_pos;
+ drag_current_tile = selected.tile;
+ drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
+ tile_atlas_control->set_default_cursor_shape(CURSOR_MOVE);
+ } else {
+ // Start selection dragging.
+ drag_type = DRAG_TYPE_RECT_SELECT;
+ drag_start_mouse_pos = mouse_local_pos;
+ drag_last_mouse_pos = drag_start_mouse_pos;
+ }
}
}
+ } else {
+ // Left click released.
+ _end_dragging();
}
- } else {
- // Left click released.
- _end_dragging();
- }
- tile_atlas_control->update();
- tile_atlas_control_unscaled->update();
- alternative_tiles_control->update();
- alternative_tiles_control_unscaled->update();
- tile_atlas_view->update();
- return;
- } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
- if (mb->is_pressed()) {
+ tile_atlas_control->update();
+ tile_atlas_control_unscaled->update();
+ alternative_tiles_control->update();
+ alternative_tiles_control_unscaled->update();
+ tile_atlas_view->update();
+ return;
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
// Right click pressed.
-
- TileSelection selected = { tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos), 0 };
- if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
- selected.tile = tile_set_atlas_source->get_tile_at_coords(selected.tile);
- }
-
- // Set the selection if needed.
- if (selection.size() <= 1) {
- if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
- undo_redo->create_action(TTR("Select tiles"));
- undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
- selection.clear();
- selection.insert(selected);
- undo_redo->add_do_method(this, "_set_selection_from_array", _get_selection_as_array());
- undo_redo->commit_action(false);
- _update_tile_inspector();
- _update_tile_id_label();
- }
- }
-
- // Pops up the correct menu, depending on whether we have a tile or not.
- if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
- // We have a tile.
- menu_option_coords = selected.tile;
- menu_option_alternative = 0;
- base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
- } else if (hovered_base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
- // We don't have a tile, but can create one.
- menu_option_coords = hovered_base_tile_coords;
- menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
- empty_base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
+ if (mb->is_pressed()) {
+ drag_type = DRAG_TYPE_MAY_POPUP_MENU;
+ drag_start_mouse_pos = tile_atlas_control->get_local_mouse_position();
+ } else {
+ // Right click released.
+ _end_dragging();
}
- } else {
- // Right click released.
- _end_dragging();
+ tile_atlas_control->update();
+ tile_atlas_control_unscaled->update();
+ alternative_tiles_control->update();
+ alternative_tiles_control_unscaled->update();
+ tile_atlas_view->update();
+ return;
}
- tile_atlas_control->update();
- tile_atlas_control_unscaled->update();
- alternative_tiles_control->update();
- alternative_tiles_control_unscaled->update();
- tile_atlas_view->update();
- return;
}
}
}
@@ -1000,10 +1287,45 @@ void TileSetAtlasSourceEditor::_end_dragging() {
}
_update_tile_inspector();
_update_tile_id_label();
+ _update_current_tile_data_editor();
undo_redo->add_do_method(this, "_set_selection_from_array", _get_selection_as_array());
undo_redo->commit_action(false);
- break;
- }
+ } break;
+ case DRAG_TYPE_MAY_POPUP_MENU: {
+ Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
+ TileSelection selected = { tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos), 0 };
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
+ selected.tile = tile_set_atlas_source->get_tile_at_coords(selected.tile);
+ }
+
+ // Set the selection if needed.
+ if (selection.size() <= 1) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
+ undo_redo->create_action(TTR("Select tiles"));
+ undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
+ selection.clear();
+ selection.insert(selected);
+ undo_redo->add_do_method(this, "_set_selection_from_array", _get_selection_as_array());
+ undo_redo->commit_action(false);
+ _update_tile_inspector();
+ _update_tile_id_label();
+ _update_current_tile_data_editor();
+ }
+ }
+
+ // Pops up the correct menu, depending on whether we have a tile or not.
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
+ // We have a tile.
+ menu_option_coords = selected.tile;
+ menu_option_alternative = 0;
+ base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
+ } else if (hovered_base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
+ // We don't have a tile, but can create one.
+ menu_option_coords = hovered_base_tile_coords;
+ menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ empty_base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
+ }
+ } break;
case DRAG_TYPE_RESIZE_TOP_LEFT:
case DRAG_TYPE_RESIZE_TOP:
case DRAG_TYPE_RESIZE_TOP_RIGHT:
@@ -1166,6 +1488,7 @@ void TileSetAtlasSourceEditor::_set_selection_from_array(Array p_selection) {
_update_tile_inspector();
_update_tile_id_label();
_update_atlas_view();
+ _update_current_tile_data_editor();
}
Array TileSetAtlasSourceEditor::_get_selection_as_array() {
@@ -1297,7 +1620,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile), Color(1.0, 1.0, 1.0), false);
} else {
// Draw empty tile, only in add/remove tiles mode.
- if (tools_button_group->get_pressed_button() == tool_add_remove_button || tools_button_group->get_pressed_button() == tool_add_remove_rect_button) {
+ if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) {
Vector2i margins = tile_set_atlas_source->get_margins();
Vector2i separation = tile_set_atlas_source->get_separation();
Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
@@ -1310,9 +1633,8 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
}
void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
- // Draw the preview of the selected property.
- TileDataEditor *tile_data_editor = TileSetEditor::get_singleton()->get_tile_data_editor(selected_property);
- if (tile_data_editor && tile_inspector->is_visible_in_tree()) {
+ if (current_tile_data_editor) {
+ // Draw the preview of the selected property.
for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
Vector2i coords = tile_set_atlas_source->get_tile_id(i);
Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(coords);
@@ -1321,7 +1643,41 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
xform.translate(position);
- tile_data_editor->draw_over_tile(tile_atlas_control_unscaled, xform, *tile_set, tile_set_atlas_source_id, coords, 0, selected_property);
+ if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, 0 })) {
+ continue;
+ }
+
+ TileMapCell cell;
+ cell.source_id = tile_set_atlas_source_id;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = 0;
+ current_tile_data_editor->draw_over_tile(tile_atlas_control_unscaled, xform, cell);
+ }
+
+ // Draw the selection on top of other.
+ if (tools_button_group->get_pressed_button() == tool_select_button) {
+ for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
+ if (E->get().alternative != 0) {
+ continue;
+ }
+ Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(E->get().tile);
+ Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(E->get().tile, 0);
+
+ Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
+ xform.translate(position);
+
+ TileMapCell cell;
+ cell.source_id = tile_set_atlas_source_id;
+ cell.set_atlas_coords(E->get().tile);
+ cell.alternative_tile = 0;
+ current_tile_data_editor->draw_over_tile(tile_atlas_control_unscaled, xform, cell, true);
+ }
+ }
+
+ // Call the TileData's editor custom draw function.
+ if (tools_button_group->get_pressed_button() == tool_paint_button) {
+ Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
+ current_tile_data_editor->forward_draw_over_atlas(tile_atlas_view, tile_set_atlas_source, tile_atlas_control_unscaled, xform);
}
}
}
@@ -1330,6 +1686,19 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
// Update the hovered alternative tile.
hovered_alternative_tile_coords = tile_atlas_view->get_alternative_tile_at_pos(alternative_tiles_control->get_local_mouse_position());
+ // Forward the event to the current tile data editor if we are in the painting mode.
+ if (tools_button_group->get_pressed_button() == tool_paint_button) {
+ if (current_tile_data_editor) {
+ current_tile_data_editor->forward_painting_alternatives_gui_input(tile_atlas_view, tile_set_atlas_source, p_event);
+ }
+ tile_atlas_control->update();
+ tile_atlas_control_unscaled->update();
+ alternative_tiles_control->update();
+ alternative_tiles_control_unscaled->update();
+ tile_atlas_view->update();
+ return;
+ }
+
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
tile_atlas_control->update();
@@ -1425,7 +1794,60 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
}
void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
- //TODO
+ // Draw the preview of the selected property.
+ if (current_tile_data_editor) {
+ // Draw the preview of the currently selected property.
+ for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
+ Vector2i coords = tile_set_atlas_source->get_tile_id(i);
+ for (int j = 0; j < tile_set_atlas_source->get_alternative_tiles_count(coords); j++) {
+ int alternative_tile = tile_set_atlas_source->get_alternative_tile_id(coords, j);
+ if (alternative_tile == 0) {
+ continue;
+ }
+ Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
+ Vector2 position = (rect.get_position() + rect.get_end()) / 2;
+
+ Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
+ xform.translate(position);
+
+ if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, alternative_tile })) {
+ continue;
+ }
+
+ TileMapCell cell;
+ cell.source_id = tile_set_atlas_source_id;
+ cell.set_atlas_coords(coords);
+ cell.alternative_tile = alternative_tile;
+ current_tile_data_editor->draw_over_tile(alternative_tiles_control_unscaled, xform, cell);
+ }
+ }
+
+ // Draw the selection on top of other.
+ if (tools_button_group->get_pressed_button() == tool_select_button) {
+ for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
+ if (E->get().alternative == 0) {
+ continue;
+ }
+ Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E->get().tile, E->get().alternative);
+ Vector2 position = (rect.get_position() + rect.get_end()) / 2;
+
+ Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
+ xform.translate(position);
+
+ TileMapCell cell;
+ cell.source_id = tile_set_atlas_source_id;
+ cell.set_atlas_coords(E->get().tile);
+ cell.alternative_tile = E->get().alternative;
+ current_tile_data_editor->draw_over_tile(alternative_tiles_control_unscaled, xform, cell, true);
+ }
+ }
+
+ // Call the TileData's editor custom draw function.
+ if (tools_button_group->get_pressed_button() == tool_paint_button) {
+ Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
+ current_tile_data_editor->forward_draw_over_alternatives(tile_atlas_view, tile_set_atlas_source, alternative_tiles_control_unscaled, xform);
+ }
+ }
}
void TileSetAtlasSourceEditor::_tile_set_atlas_source_changed() {
@@ -1436,7 +1858,7 @@ void TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed(String p_what)
if (p_what == "texture" && !atlas_source_proxy_object->get("texture").is_null()) {
confirm_auto_create_tiles->popup_centered();
} else if (p_what == "id") {
- emit_signal("source_id_changed", atlas_source_proxy_object->get_id());
+ emit_signal(SNAME("source_id_changed"), atlas_source_proxy_object->get_id());
}
}
@@ -1449,15 +1871,23 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
AtlasTileProxyObject *tile_data = Object::cast_to<AtlasTileProxyObject>(p_edited);
if (tile_data) {
Vector<String> components = String(p_property).split("/", true, 2);
- if (components.size() == 2 && components[1] == "shapes_count") {
+ if (components.size() == 2 && components[1] == "polygons_count") {
int layer_index = components[0].trim_prefix("physics_layer_").to_int();
- int new_shapes_count = p_new_value;
- int old_shapes_count = tile_data->get(vformat("physics_layer_%d/shapes_count", layer_index));
- if (new_shapes_count < old_shapes_count) {
- for (int i = new_shapes_count - 1; i < old_shapes_count; i++) {
- ADD_UNDO(tile_data, vformat("physics_layer_%d/shape_%d/shape", layer_index, i));
- ADD_UNDO(tile_data, vformat("physics_layer_%d/shape_%d/one_way", layer_index, i));
- ADD_UNDO(tile_data, vformat("physics_layer_%d/shape_%d/one_way_margin", layer_index, i));
+ int new_polygons_count = p_new_value;
+ int old_polygons_count = tile_data->get(vformat("physics_layer_%d/polygons_count", layer_index));
+ if (new_polygons_count < old_polygons_count) {
+ for (int i = new_polygons_count - 1; i < old_polygons_count; i++) {
+ ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/points", layer_index, i));
+ ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/one_way", layer_index, i));
+ ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/one_way_margin", layer_index, i));
+ }
+ }
+ } else if (p_property == "terrain_set") {
+ int current_terrain_set = tile_data->get("terrain_set");
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(current_terrain_set, bit)) {
+ ADD_UNDO(tile_data, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]));
}
}
}
@@ -1500,7 +1930,10 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
_update_fix_selected_and_hovered_tiles();
_update_tile_id_label();
_update_atlas_view();
+ _update_atlas_source_inspector();
_update_tile_inspector();
+ _update_tile_data_editors();
+ _update_current_tile_data_editor();
}
void TileSetAtlasSourceEditor::init_source() {
@@ -1616,16 +2049,16 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED:
- tool_select_button->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
- tool_add_remove_button->set_icon(get_theme_icon("EditAddRemove", "EditorIcons"));
- tool_add_remove_rect_button->set_icon(get_theme_icon("RectangleAddRemove", "EditorIcons"));
+ tool_setup_atlas_source_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
+ tool_select_button->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ tool_paint_button->set_icon(get_theme_icon(SNAME("CanvasItem"), SNAME("EditorIcons")));
- tools_settings_erase_button->set_icon(get_theme_icon("Eraser", "EditorIcons"));
+ tools_settings_erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
- tool_advanced_menu_buttom->set_icon(get_theme_icon("Tools", "EditorIcons"));
+ tool_advanced_menu_buttom->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- resize_handle = get_theme_icon("EditorHandle", "EditorIcons");
- resize_handle_disabled = get_theme_icon("EditorHandleDisabled", "EditorIcons");
+ resize_handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
+ resize_handle_disabled = get_theme_icon(SNAME("EditorHandleDisabled"), SNAME("EditorIcons"));
break;
case NOTIFICATION_INTERNAL_PROCESS:
if (tile_set_atlas_source_changed_needs_update) {
@@ -1636,7 +2069,10 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
_update_fix_selected_and_hovered_tiles();
_update_tile_id_label();
_update_atlas_view();
+ _update_atlas_source_inspector();
_update_tile_inspector();
+ _update_tile_data_editors();
+ _update_current_tile_data_editor();
tile_set_atlas_source_changed_needs_update = false;
}
@@ -1675,7 +2111,6 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
// Tile inspector.
tile_inspector_label = memnew(Label);
tile_inspector_label->set_text(TTR("Tile Properties:"));
- tile_inspector_label->hide();
middle_vbox_container->add_child(tile_inspector_label);
tile_proxy_object = memnew(AtlasTileProxyObject(this));
@@ -1689,6 +2124,36 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_inspector->connect("property_selected", callable_mp(this, &TileSetAtlasSourceEditor::_inspector_property_selected));
middle_vbox_container->add_child(tile_inspector);
+ tile_inspector_no_tile_selected_label = memnew(Label);
+ tile_inspector_no_tile_selected_label->set_align(Label::ALIGN_CENTER);
+ tile_inspector_no_tile_selected_label->set_text(TTR("No tile selected."));
+ middle_vbox_container->add_child(tile_inspector_no_tile_selected_label);
+
+ // Property values palette.
+ tile_data_editors_popup = memnew(Popup);
+
+ tile_data_editors_label = memnew(Label);
+ tile_data_editors_label->set_text(TTR("Paint Properties:"));
+ middle_vbox_container->add_child(tile_data_editors_label);
+
+ tile_data_editor_dropdown_button = memnew(Button);
+ tile_data_editor_dropdown_button->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_draw));
+ tile_data_editor_dropdown_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_pressed));
+ middle_vbox_container->add_child(tile_data_editor_dropdown_button);
+ tile_data_editor_dropdown_button->add_child(tile_data_editors_popup);
+
+ tile_data_editors_tree = memnew(Tree);
+ tile_data_editors_tree->set_hide_root(true);
+ tile_data_editors_tree->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ tile_data_editors_tree->set_h_scroll_enabled(false);
+ tile_data_editors_tree->set_v_scroll_enabled(false);
+ tile_data_editors_tree->connect("item_selected", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editors_tree_selected));
+ tile_data_editors_popup->add_child(tile_data_editors_tree);
+
+ tile_data_painting_editor_container = memnew(VBoxContainer);
+ tile_data_painting_editor_container->set_h_size_flags(SIZE_EXPAND_FILL);
+ middle_vbox_container->add_child(tile_data_painting_editor_container);
+
// Atlas source inspector.
atlas_source_inspector_label = memnew(Label);
atlas_source_inspector_label->set_text(TTR("Atlas Properties:"));
@@ -1711,7 +2176,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
// -- Dialogs --
confirm_auto_create_tiles = memnew(AcceptDialog);
- confirm_auto_create_tiles->set_title(TTR("Create tiles automatically in non-transparent texture regions?"));
+ confirm_auto_create_tiles->set_title(TTR("Auto Create Tiles in Non-Transparent Texture Regions?"));
confirm_auto_create_tiles->set_text(TTR("The atlas's texture was modified.\nWould you like to automatically create tiles in the atlas?"));
confirm_auto_create_tiles->get_ok_button()->set_text(TTR("Yes"));
confirm_auto_create_tiles->add_cancel_button()->set_text(TTR("No"));
@@ -1720,46 +2185,40 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
// -- Toolbox --
tools_button_group.instantiate();
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_id_label).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_source_inspector).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_inspector).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_data_editors).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_current_tile_data_editor).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1));
+ tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_toolbar).unbind(1));
toolbox = memnew(HBoxContainer);
right_panel->add_child(toolbox);
+ tool_setup_atlas_source_button = memnew(Button);
+ tool_setup_atlas_source_button->set_flat(true);
+ tool_setup_atlas_source_button->set_toggle_mode(true);
+ tool_setup_atlas_source_button->set_pressed(true);
+ tool_setup_atlas_source_button->set_button_group(tools_button_group);
+ tool_setup_atlas_source_button->set_tooltip(TTR("Atlas setup. Add/Remove tiles tool (use the shift key to create big tiles, control for rectangle editing)."));
+ toolbox->add_child(tool_setup_atlas_source_button);
+
tool_select_button = memnew(Button);
tool_select_button->set_flat(true);
tool_select_button->set_toggle_mode(true);
- tool_select_button->set_pressed(true);
+ tool_select_button->set_pressed(false);
tool_select_button->set_button_group(tools_button_group);
tool_select_button->set_tooltip(TTR("Select tiles."));
- tool_select_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles));
- tool_select_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_id_label));
- tool_select_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_inspector));
- tool_select_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view));
- tool_select_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_toolbar));
toolbox->add_child(tool_select_button);
- tool_add_remove_button = memnew(Button);
- tool_add_remove_button->set_flat(true);
- tool_add_remove_button->set_toggle_mode(true);
- tool_add_remove_button->set_button_group(tools_button_group);
- tool_add_remove_button->set_tooltip(TTR("Add/Remove tiles tool (use the shift key to create big tiles)."));
- tool_add_remove_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles));
- tool_add_remove_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_id_label));
- tool_add_remove_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_inspector));
- tool_add_remove_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view));
- tool_add_remove_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_toolbar));
- toolbox->add_child(tool_add_remove_button);
-
- tool_add_remove_rect_button = memnew(Button);
- tool_add_remove_rect_button->set_flat(true);
- tool_add_remove_rect_button->set_toggle_mode(true);
- tool_add_remove_rect_button->set_button_group(tools_button_group);
- tool_add_remove_rect_button->set_tooltip(TTR("Add/Remove tiles rectangle tool (use the shift key to create big tiles)."));
- tool_add_remove_rect_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles));
- tool_add_remove_rect_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_id_label));
- tool_add_remove_rect_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_inspector));
- tool_add_remove_rect_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view));
- tool_add_remove_rect_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_toolbar));
- toolbox->add_child(tool_add_remove_rect_button);
+ tool_paint_button = memnew(Button);
+ tool_paint_button->set_flat(true);
+ tool_paint_button->set_toggle_mode(true);
+ tool_paint_button->set_button_group(tools_button_group);
+ tool_paint_button->set_tooltip(TTR("Paint properties."));
+ toolbox->add_child(tool_paint_button);
// Tool settings.
tool_settings = memnew(HBoxContainer);
@@ -1768,6 +2227,9 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tool_settings_vsep = memnew(VSeparator);
tool_settings->add_child(tool_settings_vsep);
+ tool_settings_tile_data_toolbar_container = memnew(HBoxContainer);
+ tool_settings->add_child(tool_settings_tile_data_toolbar_container);
+
tools_settings_erase_button = memnew(Button);
tools_settings_erase_button->set_flat(true);
tools_settings_erase_button->set_toggle_mode(true);
@@ -1775,9 +2237,6 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tools_settings_erase_button->set_shortcut_context(this);
tool_settings->add_child(tools_settings_erase_button);
- VSeparator *tool_advanced_vsep = memnew(VSeparator);
- toolbox->add_child(tool_advanced_vsep);
-
tool_advanced_menu_buttom = memnew(MenuButton);
tool_advanced_menu_buttom->set_flat(true);
tool_advanced_menu_buttom->get_popup()->add_item(TTR("Cleanup Tiles Outside Texture"), ADVANCED_CLEANUP_TILES_OUTSIDE_TEXTURE);
@@ -1844,7 +2303,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
alternative_tiles_control_unscaled = memnew(Control);
alternative_tiles_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
alternative_tiles_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw));
- tile_atlas_view->add_control_over_atlas_tiles(alternative_tiles_control_unscaled, false);
+ tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control_unscaled, false);
alternative_tiles_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
tile_atlas_view_missing_source_label = memnew(Label);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index 70f2cdbe01..dbb0756a16 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -32,6 +32,7 @@
#define TILE_SET_ATLAS_SOURCE_EDITOR_H
#include "tile_atlas_view.h"
+#include "tile_data_editors.h"
#include "editor/editor_node.h"
#include "scene/gui/split_container.h"
@@ -113,10 +114,27 @@ private:
bool tile_set_atlas_source_changed_needs_update = false;
+ // -- Properties painting --
+ VBoxContainer *tile_data_painting_editor_container;
+ Label *tile_data_editors_label;
+ Button *tile_data_editor_dropdown_button;
+ Popup *tile_data_editors_popup;
+ Tree *tile_data_editors_tree;
+ void _tile_data_editor_dropdown_button_draw();
+ void _tile_data_editor_dropdown_button_pressed();
+
+ // -- Tile data editors --
+ String current_property;
+ Control *current_tile_data_editor_toolbar = nullptr;
+ Map<String, TileDataEditor *> tile_data_editors;
+ TileDataEditor *current_tile_data_editor = nullptr;
+ void _tile_data_editors_tree_selected();
+
// -- Inspector --
AtlasTileProxyObject *tile_proxy_object;
Label *tile_inspector_label;
EditorInspector *tile_inspector;
+ Label *tile_inspector_no_tile_selected_label;
String selected_property;
void _inspector_property_selected(String p_property);
@@ -142,6 +160,8 @@ private:
DRAG_TYPE_RECT_SELECT,
+ DRAG_TYPE_MAY_POPUP_MENU,
+
// Warning: keep in this order.
DRAG_TYPE_RESIZE_TOP_LEFT,
DRAG_TYPE_RESIZE_TOP,
@@ -179,15 +199,16 @@ private:
// Tool buttons.
Ref<ButtonGroup> tools_button_group;
+ Button *tool_setup_atlas_source_button;
Button *tool_select_button;
- Button *tool_add_remove_button;
- Button *tool_add_remove_rect_button;
+ Button *tool_paint_button;
Label *tool_tile_id_label;
+ // Tool settings.
HBoxContainer *tool_settings;
VSeparator *tool_settings_vsep;
+ HBoxContainer *tool_settings_tile_data_toolbar_container;
Button *tools_settings_erase_button;
-
MenuButton *tool_advanced_menu_buttom;
// Selection.
@@ -226,7 +247,10 @@ private:
void _update_tile_id_label();
void _update_source_inspector();
void _update_fix_selected_and_hovered_tiles();
+ void _update_atlas_source_inspector();
void _update_tile_inspector();
+ void _update_tile_data_editors();
+ void _update_current_tile_data_editor();
void _update_manage_tile_properties_button();
void _update_atlas_view();
void _update_toolbar();
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index ae5620a4e3..76ce6f0065 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -159,7 +159,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
// Scene collection source.
TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
if (scene_collection_source) {
- texture = get_theme_icon("PackedScene", "EditorIcons");
+ texture = get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id);
}
@@ -181,7 +181,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
if ((int)sources_list->get_item_metadata(i) == to_select) {
sources_list->set_current(i);
if (old_selected != to_select) {
- sources_list->emit_signal("item_selected", sources_list->get_current());
+ sources_list->emit_signal(SNAME("item_selected"), sources_list->get_current());
}
break;
}
@@ -192,7 +192,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
if (sources_list->get_current() < 0 && sources_list->get_item_count() > 0) {
sources_list->set_current(0);
if (old_selected != int(sources_list->get_item_metadata(0))) {
- sources_list->emit_signal("item_selected", sources_list->get_current());
+ sources_list->emit_signal(SNAME("item_selected"), sources_list->get_current());
}
}
@@ -292,9 +292,9 @@ void TileSetEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED:
- sources_delete_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
- sources_add_button->set_icon(get_theme_icon("Add", "EditorIcons"));
- missing_texture_texture = get_theme_icon("TileSet", "EditorIcons");
+ sources_delete_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ sources_add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ missing_texture_texture = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
break;
case NOTIFICATION_INTERNAL_PROCESS:
if (tile_set_changed_needs_update) {
@@ -347,11 +347,11 @@ void TileSetEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p
int old_layer_count = tile_set->get_physics_layers_count();
if (new_layer_count < old_layer_count) {
for (int physics_layer_index = new_layer_count - 1; physics_layer_index < old_layer_count; physics_layer_index++) {
- ADD_UNDO(tile_data, vformat("physics_layer_%d/shapes_count", physics_layer_index));
- for (int shape_index = 0; shape_index < tile_data->get_collision_shapes_count(physics_layer_index); shape_index++) {
- ADD_UNDO(tile_data, vformat("physics_layer_%d/shape_%d/shape", physics_layer_index, shape_index));
- ADD_UNDO(tile_data, vformat("physics_layer_%d/shape_%d/one_way", physics_layer_index, shape_index));
- ADD_UNDO(tile_data, vformat("physics_layer_%d/shape_%d/one_way_margin", physics_layer_index, shape_index));
+ ADD_UNDO(tile_data, vformat("physics_layer_%d/polygons_count", physics_layer_index));
+ for (int polygon_index = 0; polygon_index < tile_data->get_collision_polygons_count(physics_layer_index); polygon_index++) {
+ ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/points", physics_layer_index, polygon_index));
+ ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/one_way", physics_layer_index, polygon_index));
+ ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/one_way_margin", physics_layer_index, polygon_index));
}
}
}
@@ -359,53 +359,11 @@ void TileSetEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p
(components.size() == 2 && components[0].begins_with("terrain_set_") && components[0].trim_prefix("terrain_set_").is_valid_int() && components[1] == "mode") ||
(components.size() == 2 && components[0].begins_with("terrain_set_") && components[0].trim_prefix("terrain_set_").is_valid_int() && components[1] == "terrains_count" && tile_data->get_terrain_set() == components[0].trim_prefix("terrain_set_").to_int() && (int)p_new_value < tile_set->get_terrains_count(tile_data->get_terrain_set()))) {
ADD_UNDO(tile_data, "terrain_set");
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/right_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/right_corner");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/bottom_right_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/bottom_right_corner");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/bottom_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/bottom_corner");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/bottom_left_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/bottom_left_corner");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/left_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/left_corner");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/top_left_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/top_left_corner");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/top_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/top_corner");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/top_right_side");
- }
- if (tile_data->is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER)) {
- ADD_UNDO(tile_data, "terrains_peering_bit/top_right_corner");
+ for (int l = 0; l < TileSet::CELL_NEIGHBOR_MAX; l++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(l);
+ if (tile_data->is_valid_peering_bit_terrain(bit)) {
+ ADD_UNDO(tile_data, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[l]));
+ }
}
} else if (p_property == "navigation_layers_count") {
int new_layer_count = p_new_value;
@@ -440,30 +398,6 @@ void TileSetEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_drop_data_fw"), &TileSetEditor::drop_data_fw);
}
-TileDataEditor *TileSetEditor::get_tile_data_editor(String p_property) {
- Vector<String> components = String(p_property).split("/", true);
-
- if (p_property == "z_index") {
- return tile_data_integer_editor;
- } else if (p_property == "probability") {
- return tile_data_float_editor;
- } else if (p_property == "y_sort_origin") {
- return tile_data_y_sort_editor;
- } else if (p_property == "texture_offset") {
- return tile_data_texture_offset_editor;
- } else if (components.size() >= 1 && components[0].begins_with("occlusion_layer_")) {
- return tile_data_occlusion_shape_editor;
- } else if (components.size() >= 1 && components[0].begins_with("physics_layer_")) {
- return tile_data_collision_shape_editor;
- } else if (p_property == "mode" || p_property == "terrain" || (components.size() >= 1 && components[0] == "terrains_peering_bit")) {
- return tile_data_terrains_editor;
- } else if (components.size() >= 1 && components[0].begins_with("navigation_layer_")) {
- return tile_data_navigation_polygon_editor;
- }
-
- return nullptr;
-}
-
void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
if (p_tile_set == tile_set) {
return;
@@ -575,14 +509,4 @@ TileSetEditor::~TileSetEditor() {
if (tile_set.is_valid()) {
tile_set->disconnect("changed", callable_mp(this, &TileSetEditor::_tile_set_changed));
}
-
- // Delete tile data editors.
- memdelete(tile_data_texture_offset_editor);
- memdelete(tile_data_y_sort_editor);
- memdelete(tile_data_integer_editor);
- memdelete(tile_data_float_editor);
- memdelete(tile_data_occlusion_shape_editor);
- memdelete(tile_data_collision_shape_editor);
- memdelete(tile_data_terrains_editor);
- memdelete(tile_data_navigation_polygon_editor);
}
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index f584c043cc..9e50aca62f 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -33,7 +33,6 @@
#include "scene/gui/box_container.h"
#include "scene/resources/tile_set.h"
-#include "tile_data_editors.h"
#include "tile_set_atlas_source_editor.h"
#include "tile_set_scenes_collection_source_editor.h"
@@ -54,16 +53,6 @@ private:
void _update_atlas_sources_list(int force_selected_id = -1);
- // List of tile data editors.
- TileDataTextureOffsetEditor *tile_data_texture_offset_editor = memnew(TileDataTextureOffsetEditor);
- TileDataYSortEditor *tile_data_y_sort_editor = memnew(TileDataYSortEditor);
- TileDataIntegerEditor *tile_data_integer_editor = memnew(TileDataIntegerEditor);
- TileDataFloatEditor *tile_data_float_editor = memnew(TileDataFloatEditor);
- TileDataOcclusionShapeEditor *tile_data_occlusion_shape_editor = memnew(TileDataOcclusionShapeEditor);
- TileDataCollisionShapeEditor *tile_data_collision_shape_editor = memnew(TileDataCollisionShapeEditor);
- TileDataTerrainsEditor *tile_data_terrains_editor = memnew(TileDataTerrainsEditor);
- TileDataNavigationPolygonEditor *tile_data_navigation_polygon_editor = memnew(TileDataNavigationPolygonEditor);
-
// -- Sources management --
Button *sources_delete_button;
MenuButton *sources_add_button;
@@ -84,7 +73,6 @@ protected:
public:
_FORCE_INLINE_ static TileSetEditor *get_singleton() { return singleton; }
- TileDataEditor *get_tile_data_editor(String property);
void edit(Ref<TileSet> p_tile_set);
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index 568d4ca8d7..f74b3bf9c2 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -48,7 +48,7 @@ void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::se
int previous_source = source_id;
source_id = p_id; // source_id must be updated before, because it's used by the source list update.
tile_set->set_source_id(previous_source, p_id);
- emit_signal("changed", "id");
+ emit_signal(SNAME("changed"), "id");
}
int TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id() {
@@ -59,7 +59,7 @@ bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_s
bool valid = false;
tile_set_scenes_collection_source->set(p_name, p_value, &valid);
if (valid) {
- emit_signal("changed", String(p_name).utf8().get_data());
+ emit_signal(SNAME("changed"), String(p_name).utf8().get_data());
}
return valid;
}
@@ -120,7 +120,7 @@ bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_set(const Strin
ERR_FAIL_COND_V(tile_set_scenes_collection_source->has_scene_tile_id(as_int), false);
tile_set_scenes_collection_source->set_scene_tile_id(scene_id, as_int);
scene_id = as_int;
- emit_signal("changed", "id");
+ emit_signal(SNAME("changed"), "id");
for (int i = 0; i < tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_count(); i++) {
if (int(tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_metadata(i)) == scene_id) {
tile_set_scenes_collection_source_editor->scene_tiles_list->select(i);
@@ -130,11 +130,11 @@ bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_set(const Strin
return true;
} else if (p_name == "scene") {
tile_set_scenes_collection_source->set_scene_tile_scene(scene_id, p_value);
- emit_signal("changed", "scene");
+ emit_signal(SNAME("changed"), "scene");
return true;
} else if (p_name == "display_placeholder") {
tile_set_scenes_collection_source->set_scene_tile_display_placeholder(scene_id, p_value);
- emit_signal("changed", "display_placeholder");
+ emit_signal(SNAME("changed"), "display_placeholder");
return true;
}
@@ -186,7 +186,7 @@ void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_bind_methods()
void TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed(String p_what) {
if (p_what == "id") {
- emit_signal("source_id_changed", scenes_collection_source_proxy_object->get_id());
+ emit_signal(SNAME("source_id_changed"), scenes_collection_source_proxy_object->get_id());
}
}
@@ -284,7 +284,7 @@ void TileSetScenesCollectionSourceEditor::_update_scenes_list() {
Variant udata = i;
EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
} else {
- item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons"));
+ item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")));
}
scene_tiles_list->set_item_metadata(item_index, scene_id);
@@ -307,8 +307,8 @@ void TileSetScenesCollectionSourceEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED:
- scene_tile_add_button->set_icon(get_theme_icon("Add", "EditorIcons"));
- scene_tile_delete_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ scene_tile_add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ scene_tile_delete_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
_update_scenes_list();
break;
case NOTIFICATION_INTERNAL_PROCESS:
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index fb111efc17..339efc7b99 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -50,7 +50,7 @@ void TilesEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- tileset_tilemap_switch_button->set_icon(get_theme_icon("TileSet", "EditorIcons"));
+ tileset_tilemap_switch_button->set_icon(get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
if (tile_map_changed_needs_update) {
@@ -131,7 +131,7 @@ void TilesEditor::synchronize_atlas_sources_list(Object *p_current) {
item_list->deselect_all();
} else {
item_list->set_current(atlas_sources_lists_current);
- item_list->emit_signal("item_selected", atlas_sources_lists_current);
+ item_list->emit_signal(SNAME("item_selected"), atlas_sources_lists_current);
}
}
}
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 75a944e910..5804f54649 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -164,7 +164,7 @@ void VersionControlEditorPlugin::_refresh_stage_area() {
_refresh_file_diff();
}
}
- commit_status->set_text("New changes detected");
+ commit_status->set_text(TTR("New changes detected"));
}
} else {
WARN_PRINT("No VCS addon is initialized. Select a Version Control Addon from Project menu.");
@@ -184,11 +184,11 @@ void VersionControlEditorPlugin::_stage_selected() {
while (file_entry) {
if (file_entry->is_checked(0)) {
EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0));
- file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor"));
+ file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("success_color"), SNAME("Editor")));
staged_files_count++;
} else {
EditorVCSInterface::get_singleton()->unstage_file(file_entry->get_metadata(0));
- file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"));
+ file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
}
file_entry = file_entry->get_next();
@@ -210,7 +210,7 @@ void VersionControlEditorPlugin::_stage_all() {
TreeItem *file_entry = root->get_first_child();
while (file_entry) {
EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0));
- file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor"));
+ file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("success_color"), SNAME("Editor")));
file_entry->set_checked(0, true);
staged_files_count++;
@@ -235,16 +235,16 @@ void VersionControlEditorPlugin::_display_file_diff(String p_file_path) {
diff_file_name->set_text(p_file_path);
diff->clear();
- diff->push_font(EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts"));
+ diff->push_font(EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("source"), SNAME("EditorFonts")));
for (int i = 0; i < diff_content.size(); i++) {
Dictionary line_result = diff_content[i];
if (line_result["status"] == "+") {
- diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor"));
+ diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("success_color"), SNAME("Editor")));
} else if (line_result["status"] == "-") {
- diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"));
+ diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
} else {
- diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color("font_color", "Label"));
+ diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("font_color"), SNAME("Label")));
}
diff->add_text((String)line_result["content"]);
@@ -270,9 +270,9 @@ void VersionControlEditorPlugin::_clear_file_diff() {
void VersionControlEditorPlugin::_update_stage_status() {
String status;
if (staged_files_count == 1) {
- status = "Stage contains 1 file";
+ status = TTR("Stage contains 1 file");
} else {
- status = "Stage contains " + String::num_int64(staged_files_count) + " files";
+ status = vformat(TTR("Stage contains %d files"), staged_files_count);
}
commit_status->set_text(status);
}
@@ -280,9 +280,9 @@ void VersionControlEditorPlugin::_update_stage_status() {
void VersionControlEditorPlugin::_update_commit_status() {
String status;
if (staged_files_count == 1) {
- status = "Committed 1 file";
+ status = TTR("Committed 1 file");
} else {
- status = "Committed " + String::num_int64(staged_files_count) + " files ";
+ status = vformat(TTR("Committed %d files"), staged_files_count);
}
commit_status->set_text(status);
staged_files_count = 0;
@@ -407,7 +407,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
refresh_button = memnew(Button);
refresh_button->set_tooltip(TTR("Detect new changes"));
refresh_button->set_text(TTR("Refresh"));
- refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Reload", "EditorIcons"));
+ refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
refresh_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_refresh_stage_area));
stage_tools->add_child(refresh_button);
@@ -432,11 +432,11 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
change_type_to_strings[CHANGE_TYPE_DELETED] = TTR("Deleted");
change_type_to_strings[CHANGE_TYPE_TYPECHANGE] = TTR("Typechange");
- change_type_to_color[CHANGE_TYPE_NEW] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor");
- change_type_to_color[CHANGE_TYPE_MODIFIED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor");
- change_type_to_color[CHANGE_TYPE_RENAMED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("disabled_font_color", "Editor");
- change_type_to_color[CHANGE_TYPE_DELETED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor");
- change_type_to_color[CHANGE_TYPE_TYPECHANGE] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("font_color", "Editor");
+ change_type_to_color[CHANGE_TYPE_NEW] = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("success_color"), SNAME("Editor"));
+ change_type_to_color[CHANGE_TYPE_MODIFIED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor"));
+ change_type_to_color[CHANGE_TYPE_RENAMED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"));
+ change_type_to_color[CHANGE_TYPE_DELETED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor"));
+ change_type_to_color[CHANGE_TYPE_TYPECHANGE] = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("font_color"), SNAME("Editor"));
stage_buttons = memnew(HSplitContainer);
stage_buttons->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN_COLLAPSED);
@@ -476,6 +476,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
version_control_dock = memnew(PanelContainer);
version_control_dock->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ version_control_dock->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
version_control_dock->hide();
diff_vbc = memnew(VBoxContainer);
@@ -500,7 +501,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
diff_refresh_button = memnew(Button);
diff_refresh_button->set_tooltip(TTR("Detect changes in file diff"));
- diff_refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Reload", "EditorIcons"));
+ diff_refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
diff_refresh_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_refresh_file_diff));
diff_hbc->add_child(diff_refresh_button);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 00750c3032..f49279aa33 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -110,6 +110,7 @@ void VisualShaderGraphPlugin::_bind_methods() {
ClassDB::bind_method("set_uniform_name", &VisualShaderGraphPlugin::set_uniform_name);
ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression);
ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve);
+ ClassDB::bind_method("update_curve_xyz", &VisualShaderGraphPlugin::update_curve_xyz);
ClassDB::bind_method("update_constant", &VisualShaderGraphPlugin::update_constant);
}
@@ -163,7 +164,7 @@ void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p
}
void VisualShaderGraphPlugin::update_node_deferred(VisualShader::Type p_type, int p_node_id) {
- call_deferred("update_node", p_type, p_node_id);
+ call_deferred(SNAME("update_node"), p_type, p_node_id);
}
void VisualShaderGraphPlugin::update_node(VisualShader::Type p_type, int p_node_id) {
@@ -211,9 +212,19 @@ void VisualShaderGraphPlugin::set_uniform_name(VisualShader::Type p_type, int p_
}
void VisualShaderGraphPlugin::update_curve(int p_node_id) {
- if (links.has(p_node_id) && links[p_node_id].curve_editor) {
+ if (links.has(p_node_id) && links[p_node_id].curve_editors[0]) {
if (((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) {
- links[p_node_id].curve_editor->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve());
+ links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve());
+ }
+ }
+}
+
+void VisualShaderGraphPlugin::update_curve_xyz(int p_node_id) {
+ if (links.has(p_node_id) && links[p_node_id].curve_editors[0] && links[p_node_id].curve_editors[1] && links[p_node_id].curve_editors[2]) {
+ if (((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) {
+ links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_x());
+ links[p_node_id].curve_editors[1]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_y());
+ links[p_node_id].curve_editors[2]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_z());
}
}
}
@@ -265,8 +276,8 @@ void VisualShaderGraphPlugin::register_expression_edit(int p_node_id, CodeEdit *
links[p_node_id].expression_edit = p_expression_edit;
}
-void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, CurveEditor *p_curve_editor) {
- links[p_node_id].curve_editor = p_curve_editor;
+void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor) {
+ links[p_node_id].curve_editors[p_index] = p_curve_editor;
}
void VisualShaderGraphPlugin::update_uniform_refs() {
@@ -312,7 +323,7 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) {
}
void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) {
- links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, nullptr });
+ links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } });
}
void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) {
@@ -324,9 +335,9 @@ void VisualShaderGraphPlugin::register_uniform_name(int p_node_id, LineEdit *p_u
}
void VisualShaderGraphPlugin::update_theme() {
- vector_expanded_color[0] = VisualShaderEditor::get_singleton()->get_theme_color("axis_x_color", "Editor"); // red
- vector_expanded_color[1] = VisualShaderEditor::get_singleton()->get_theme_color("axis_y_color", "Editor"); // green
- vector_expanded_color[2] = VisualShaderEditor::get_singleton()->get_theme_color("axis_z_color", "Editor"); // blue
+ vector_expanded_color[0] = VisualShaderEditor::get_singleton()->get_theme_color(SNAME("axis_x_color"), SNAME("Editor")); // red
+ vector_expanded_color[1] = VisualShaderEditor::get_singleton()->get_theme_color(SNAME("axis_y_color"), SNAME("Editor")); // green
+ vector_expanded_color[2] = VisualShaderEditor::get_singleton()->get_theme_color(SNAME("axis_z_color"), SNAME("Editor")); // blue
}
void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
@@ -454,7 +465,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
vsnode->remove_meta("shader_type");
if (custom_editor) {
if (vsnode->is_show_prop_names()) {
- custom_editor->call_deferred("_show_prop_names", true);
+ custom_editor->call_deferred(SNAME("_show_prop_names"), true);
}
break;
}
@@ -472,6 +483,18 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
custom_editor = hbox;
}
+ Ref<VisualShaderNodeCurveXYZTexture> curve_xyz = vsnode;
+ if (curve_xyz.is_valid()) {
+ if (curve_xyz->get_texture().is_valid() && !curve_xyz->get_texture()->is_connected("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve_xyz))) {
+ curve_xyz->get_texture()->connect("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve_xyz), varray(p_id));
+ }
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbox->add_child(custom_editor);
+ custom_editor = hbox;
+ }
+
Ref<VisualShaderNodeFloatConstant> float_const = vsnode;
if (float_const.is_valid()) {
HBoxContainer *hbox = memnew(HBoxContainer);
@@ -495,36 +518,76 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
port_offset++;
node->add_child(custom_editor);
- if (curve.is_valid()) {
+ bool is_curve = curve.is_valid() || curve_xyz.is_valid();
+
+ if (is_curve) {
VisualShaderEditor::get_singleton()->graph->add_child(node);
VisualShaderEditor::get_singleton()->_update_created_node(node);
+ TextureButton *preview = memnew(TextureButton);
+ preview->set_toggle_mode(true);
+ preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")));
+ preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
+ preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+
+ register_output_port(p_id, 0, preview);
+
+ preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, 0), CONNECT_DEFERRED);
+ custom_editor->add_child(preview);
+
+ if (vsnode->get_output_port_for_preview() >= 0) {
+ show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview());
+ }
+ }
+
+ if (curve.is_valid()) {
CurveEditor *curve_editor = memnew(CurveEditor);
node->add_child(curve_editor);
- register_curve_editor(p_id, curve_editor);
+ register_curve_editor(p_id, 0, curve_editor);
curve_editor->set_custom_minimum_size(Size2(300, 0));
curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
if (curve->get_texture().is_valid()) {
curve_editor->set_curve(curve->get_texture()->get_curve());
}
+ }
- TextureButton *preview = memnew(TextureButton);
- preview->set_toggle_mode(true);
- preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
- preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
- preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ if (curve_xyz.is_valid()) {
+ CurveEditor *curve_editor_x = memnew(CurveEditor);
+ node->add_child(curve_editor_x);
+ register_curve_editor(p_id, 0, curve_editor_x);
+ curve_editor_x->set_custom_minimum_size(Size2(300, 0));
+ curve_editor_x->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve_xyz->get_texture().is_valid()) {
+ curve_editor_x->set_curve(curve_xyz->get_texture()->get_curve_x());
+ }
- register_output_port(p_id, 0, preview);
+ CurveEditor *curve_editor_y = memnew(CurveEditor);
+ node->add_child(curve_editor_y);
+ register_curve_editor(p_id, 1, curve_editor_y);
+ curve_editor_y->set_custom_minimum_size(Size2(300, 0));
+ curve_editor_y->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve_xyz->get_texture().is_valid()) {
+ curve_editor_y->set_curve(curve_xyz->get_texture()->get_curve_y());
+ }
- preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, 0), CONNECT_DEFERRED);
- custom_editor->add_child(preview);
+ CurveEditor *curve_editor_z = memnew(CurveEditor);
+ node->add_child(curve_editor_z);
+ register_curve_editor(p_id, 2, curve_editor_z);
+ curve_editor_z->set_custom_minimum_size(Size2(300, 0));
+ curve_editor_z->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve_xyz->get_texture().is_valid()) {
+ curve_editor_z->set_curve(curve_xyz->get_texture()->get_curve_z());
+ }
+ }
+ if (is_curve) {
VisualShaderNode::PortType port_left = vsnode->get_input_port_type(0);
VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0);
node->set_slot(0, true, port_left, type_color[port_left], true, port_right, type_color[port_right]);
- VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size);
+ VisualShaderEditor::get_singleton()->call_deferred(SNAME("_set_node_size"), (int)p_type, p_id, size);
}
+
if (vsnode->is_use_prop_slots()) {
return;
}
@@ -670,7 +733,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, false), CONNECT_DEFERRED);
Button *remove_btn = memnew(Button);
- remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons"));
+ remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_input_port), varray(p_id, i), CONNECT_DEFERRED);
hb->add_child(remove_btn);
@@ -683,7 +746,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) {
Label *hint_label = memnew(Label);
hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]");
- hint_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("font_readonly_color", "TextEdit"));
+ hint_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color(SNAME("font_readonly_color"), SNAME("TextEdit")));
hint_label->add_theme_style_override("normal", label_style);
hb->add_child(hint_label);
}
@@ -697,7 +760,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (valid_right) {
if (is_group) {
Button *remove_btn = memnew(Button);
- remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons"));
+ remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_output_port), varray(p_id, i), CONNECT_DEFERRED);
hb->add_child(remove_btn);
@@ -733,8 +796,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (vsnode->is_output_port_expandable(i)) {
TextureButton *expand = memnew(TextureButton);
expand->set_toggle_mode(true);
- expand->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiTreeArrowDown", "EditorIcons"));
- expand->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiTreeArrowRight", "EditorIcons"));
+ expand->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
+ expand->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")));
expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
expand->set_pressed(vsnode->_is_output_port_expanded(i));
expand->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_expand_output_port), varray(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
@@ -743,8 +806,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
- preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
- preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
+ preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")));
+ preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
register_output_port(p_id, j, preview);
@@ -810,7 +873,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
String error = vsnode->get_warning(visual_shader->get_mode(), p_type);
if (error != String()) {
Label *error_label = memnew(Label);
- error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("error_color", "Editor"));
+ error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
error_label->set_text(error);
node->add_child(error_label);
}
@@ -844,8 +907,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
}
- expression_box->add_theme_font_override("font", VisualShaderEditor::get_singleton()->get_theme_font("expression", "EditorFonts"));
- expression_box->add_theme_font_size_override("font_size", VisualShaderEditor::get_singleton()->get_theme_font_size("expression_size", "EditorFonts"));
+ expression_box->add_theme_font_override("font", VisualShaderEditor::get_singleton()->get_theme_font(SNAME("expression"), SNAME("EditorFonts")));
+ expression_box->add_theme_font_size_override("font_size", VisualShaderEditor::get_singleton()->get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts")));
expression_box->add_theme_color_override("font_color", text_color);
expression_syntax_highlighter->set_number_color(number_color);
expression_syntax_highlighter->set_symbol_color(symbol_color);
@@ -872,7 +935,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
VisualShaderEditor::get_singleton()->_update_created_node(node);
if (is_resizable) {
- VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size);
+ VisualShaderEditor::get_singleton()->call_deferred(SNAME("_set_node_size"), (int)p_type, p_id, size);
}
}
}
@@ -888,6 +951,7 @@ void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id) {
void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
if (visual_shader->get_shader_type() == p_type) {
VisualShaderEditor::get_singleton()->graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
+ connections.push_back({ p_from_node, p_from_port, p_to_node, p_to_port });
if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr) {
links[p_to_node].input_ports[p_to_port].default_input_button->hide();
}
@@ -897,6 +961,12 @@ void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_fro
void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
if (visual_shader->get_shader_type() == p_type) {
VisualShaderEditor::get_singleton()->graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
+ for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
+ if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
+ connections.erase(E);
+ break;
+ }
+ }
if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr && links[p_to_node].visual_node->get_input_port_default_value(p_to_port).get_type() != Variant::NIL) {
links[p_to_node].input_ports[p_to_port].default_input_button->show();
set_input_port_default_value(p_type, p_to_node, p_to_port, links[p_to_node].visual_node->get_input_port_default_value(p_to_port));
@@ -1141,8 +1211,8 @@ void VisualShaderEditor::_update_options_menu() {
bool is_first_item = true;
- Color unsupported_color = get_theme_color("error_color", "Editor");
- Color supported_color = get_theme_color("warning_color", "Editor");
+ Color unsupported_color = get_theme_color(SNAME("error_color"), SNAME("Editor"));
+ Color supported_color = get_theme_color(SNAME("warning_color"), SNAME("Editor"));
static bool low_driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name") == "GLES2";
@@ -1215,22 +1285,22 @@ void VisualShaderEditor::_update_options_menu() {
}
switch (options[i].return_type) {
case VisualShaderNode::PORT_TYPE_SCALAR:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("float", "EditorIcons"));
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")));
break;
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("int", "EditorIcons"));
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons")));
break;
case VisualShaderNode::PORT_TYPE_VECTOR:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Vector3", "EditorIcons"));
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")));
break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons"));
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")));
break;
case VisualShaderNode::PORT_TYPE_TRANSFORM:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform3D", "EditorIcons"));
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")));
break;
case VisualShaderNode::PORT_TYPE_SAMPLER:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons"));
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")));
break;
default:
break;
@@ -1279,12 +1349,12 @@ void VisualShaderEditor::_draw_color_over_button(Object *obj, Color p_color) {
return;
}
- Ref<StyleBox> normal = get_theme_stylebox("normal", "Button");
+ Ref<StyleBox> normal = get_theme_stylebox(SNAME("normal"), SNAME("Button"));
button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color);
}
void VisualShaderEditor::_update_created_node(GraphNode *node) {
- const Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode");
+ const Ref<StyleBoxFlat> sb = node->get_theme_stylebox(SNAME("frame"), SNAME("GraphNode"));
Color c = sb->get_border_color();
const Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0, 0.85) : Color(0.0, 0.0, 0.0, 0.85);
c = mono_color;
@@ -2204,6 +2274,8 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) {
void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_path, int p_node_idx) {
ERR_FAIL_INDEX(p_idx, add_options.size());
+ VisualShader::Type type = get_current_shader_type();
+
Ref<VisualShaderNode> vsnode;
bool is_custom = add_options[p_idx].is_custom;
@@ -2230,6 +2302,29 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
}
}
+ VisualShaderNodeUniformRef *uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(vsn);
+
+ if (uniform_ref && to_node != -1 && to_slot != -1) {
+ VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
+ bool success = false;
+
+ for (int i = 0; i < uniform_ref->get_uniforms_count(); i++) {
+ if (uniform_ref->get_port_type_by_index(i) == input_port_type) {
+ uniform_ref->set_uniform_name(uniform_ref->get_uniform_name_by_index(i));
+ success = true;
+ break;
+ }
+ }
+ if (!success) {
+ for (int i = 0; i < uniform_ref->get_uniforms_count(); i++) {
+ if (visual_shader->is_port_types_compatible(uniform_ref->get_port_type_by_index(i), input_port_type)) {
+ uniform_ref->set_uniform_name(uniform_ref->get_uniform_name_by_index(i));
+ break;
+ }
+ }
+ }
+ }
+
vsnode = Ref<VisualShaderNode>(vsn);
} else {
ERR_FAIL_COND(add_options[p_idx].script.is_null());
@@ -2250,8 +2345,6 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
}
saved_node_pos_dirty = false;
- VisualShader::Type type = get_current_shader_type();
-
int id_to_use = visual_shader->get_valid_node_id(type);
if (p_resource_path.is_empty()) {
@@ -2315,6 +2408,13 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot);
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot);
} else {
+ // Need to setting up Input node properly before committing since `is_port_types_compatible` (calling below) is using `mode` and `shader_type`.
+ VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(vsnode.ptr());
+ if (input) {
+ input->set_shader_mode(visual_shader->get_mode());
+ input->set_shader_type(visual_shader->get_shader_type());
+ }
+
// Attempting to connect to the first correct port.
for (int i = 0; i < vsnode->get_output_port_count(); i++) {
if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(i), input_port_type)) {
@@ -2370,7 +2470,12 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
VisualShaderNodeCurveTexture *curve = Object::cast_to<VisualShaderNodeCurveTexture>(vsnode.ptr());
if (curve) {
- graph_plugin->call_deferred("update_curve", id_to_use);
+ graph_plugin->call_deferred(SNAME("update_curve"), id_to_use);
+ }
+
+ VisualShaderNodeCurveXYZTexture *curve_xyz = Object::cast_to<VisualShaderNodeCurveXYZTexture>(vsnode.ptr());
+ if (curve_xyz) {
+ graph_plugin->call_deferred(SNAME("update_curve_xyz"), id_to_use);
}
if (p_resource_path.is_empty()) {
@@ -2381,7 +2486,7 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
VisualShaderNodeTexture *texture2d = Object::cast_to<VisualShaderNodeTexture>(vsnode.ptr());
VisualShaderNodeTexture3D *texture3d = Object::cast_to<VisualShaderNodeTexture3D>(vsnode.ptr());
- if (texture2d || texture3d || curve) {
+ if (texture2d || texture3d || curve || curve_xyz) {
undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path));
return;
}
@@ -2403,7 +2508,7 @@ void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_t
VisualShader::Type type = get_current_shader_type();
drag_buffer.push_back({ type, p_node, p_from, p_to });
if (!drag_dirty) {
- call_deferred("_nodes_dragged");
+ call_deferred(SNAME("_nodes_dragged"));
}
drag_dirty = true;
}
@@ -2927,7 +3032,7 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
members_dialog->set_position(members_dialog->get_position() - Point2(difference, 0));
}
- node_filter->call_deferred("grab_focus"); // still not visible
+ node_filter->call_deferred(SNAME("grab_focus")); // still not visible
node_filter->select_all();
}
@@ -2970,11 +3075,11 @@ void VisualShaderEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- highend_label->set_modulate(get_theme_color("vulkan_color", "Editor"));
+ highend_label->set_modulate(get_theme_color(SNAME("vulkan_color"), SNAME("Editor")));
- node_filter->set_right_icon(Control::get_theme_icon("Search", "EditorIcons"));
+ node_filter->set_right_icon(Control::get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
- preview_shader->set_icon(Control::get_theme_icon("Shader", "EditorIcons"));
+ preview_shader->set_icon(Control::get_theme_icon(SNAME("Shader"), SNAME("EditorIcons")));
{
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
@@ -2997,8 +3102,8 @@ void VisualShaderEditor::_notification(int p_what) {
}
}
- preview_text->add_theme_font_override("font", get_theme_font("expression", "EditorFonts"));
- preview_text->add_theme_font_size_override("font_size", get_theme_font_size("expression_size", "EditorFonts"));
+ preview_text->add_theme_font_override("font", get_theme_font(SNAME("expression"), SNAME("EditorFonts")));
+ preview_text->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts")));
preview_text->add_theme_color_override("font_color", text_color);
syntax_highlighter->set_number_color(number_color);
syntax_highlighter->set_symbol_color(symbol_color);
@@ -3012,13 +3117,13 @@ void VisualShaderEditor::_notification(int p_what) {
preview_text->add_comment_delimiter("/*", "*/", false);
preview_text->add_comment_delimiter("//", "", true);
- error_panel->add_theme_style_override("panel", get_theme_stylebox("panel", "Panel"));
- error_label->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts"));
- error_label->add_theme_font_size_override("font_size", get_theme_font_size("status_source_size", "EditorFonts"));
- error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
+ error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Panel")));
+ error_label->add_theme_font_override("font", get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ error_label->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
+ error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
}
- tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Tools", "EditorIcons"));
+ tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree()) {
_update_graph();
@@ -3576,6 +3681,10 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
_add_node(curve_node_option_idx, -1, arr[i], i);
+ } else if (type == "CurveXYZTexture") {
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
+ saved_node_pos_dirty = true;
+ _add_node(curve_xyz_node_option_idx, -1, arr[i], i);
} else if (ClassDB::get_parent_class(type) == "Texture2D") {
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
@@ -3848,7 +3957,7 @@ VisualShaderEditor::VisualShaderEditor() {
error_label = memnew(Label);
error_panel->add_child(error_label);
- error_label->set_autowrap(true);
+ error_label->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
///////////////////////////////////////
// POPUP MENU
@@ -3934,7 +4043,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_child(members_dialog);
alert = memnew(AcceptDialog);
- alert->get_label()->set_autowrap(true);
+ alert->get_label()->set_autowrap_mode(Label::AUTOWRAP_WORD);
alert->get_label()->set_align(Label::ALIGN_CENTER);
alert->get_label()->set_valign(Label::VALIGN_CENTER);
alert->get_label()->set_custom_minimum_size(Size2(400, 60) * EDSCALE);
@@ -4297,6 +4406,8 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1));
curve_node_option_idx = add_options.size();
add_options.push_back(AddOption("CurveTexture", "Textures", "Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), -1, -1));
+ curve_xyz_node_option_idx = add_options.size();
+ add_options.push_back(AddOption("CurveXYZTexture", "Textures", "Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."), -1, -1));
texture2d_node_option_idx = add_options.size();
add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), -1, -1));
texture2d_array_node_option_idx = add_options.size();
@@ -4494,18 +4605,18 @@ public:
}
void _item_selected(int p_item) {
- VisualShaderEditor::get_singleton()->call_deferred("_input_select_item", input, get_item_text(p_item));
+ VisualShaderEditor::get_singleton()->call_deferred(SNAME("_input_select_item"), input, get_item_text(p_item));
}
void setup(const Ref<VisualShaderNodeInput> &p_input) {
input = p_input;
Ref<Texture2D> type_icon[6] = {
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("float", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("int", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Vector3", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform3D", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons"),
+ 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("Vector3"), 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")),
};
add_item("[None]");
@@ -4538,20 +4649,20 @@ public:
}
void _item_selected(int p_item) {
- VisualShaderEditor::get_singleton()->call_deferred("_uniform_select_item", uniform_ref, get_item_text(p_item));
+ VisualShaderEditor::get_singleton()->call_deferred(SNAME("_uniform_select_item"), uniform_ref, get_item_text(p_item));
}
void setup(const Ref<VisualShaderNodeUniformRef> &p_uniform_ref) {
uniform_ref = p_uniform_ref;
Ref<Texture2D> type_icon[7] = {
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("float", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("int", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Vector3", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform3D", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Color", "EditorIcons"),
- EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons"),
+ 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("Vector3"), 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")),
};
add_item("[None]");
@@ -4759,7 +4870,7 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
void EditorPropertyShaderMode::_option_selected(int p_which) {
//will not use this, instead will do all the logic setting manually
- //emit_signal("property_changed", get_edited_property(), p_which);
+ //emit_signal(SNAME("property_changed"), get_edited_property(), p_which);
Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object()));
@@ -4857,7 +4968,7 @@ void EditorInspectorShaderModePlugin::parse_begin(Object *p_object) {
//do none
}
-bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
+bool EditorInspectorShaderModePlugin::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) {
if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
EditorPropertyShaderMode *editor = memnew(EditorPropertyShaderMode);
Vector<String> options = p_hint_text.split(",");
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 4c7489a694..f53726edb9 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -75,7 +75,7 @@ private:
LineEdit *uniform_name = nullptr;
OptionButton *const_op = nullptr;
CodeEdit *expression_edit = nullptr;
- CurveEditor *curve_editor = nullptr;
+ CurveEditor *curve_editors[3] = { nullptr, nullptr, nullptr };
};
Ref<VisualShader> visual_shader;
@@ -97,7 +97,7 @@ public:
void register_default_input_button(int p_node_id, int p_port_id, Button *p_button);
void register_constant_option_btn(int p_node_id, OptionButton *p_button);
void register_expression_edit(int p_node_id, CodeEdit *p_expression_edit);
- void register_curve_editor(int p_node_id, CurveEditor *p_curve_editor);
+ void register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor);
void clear_links();
void set_shader_type(VisualShader::Type p_type);
bool is_preview_visible(int p_id) const;
@@ -117,6 +117,7 @@ public:
void update_uniform_refs();
void set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name);
void update_curve(int p_node_id);
+ void update_curve_xyz(int p_node_id);
void update_constant(VisualShader::Type p_type, int p_node_id);
void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression);
int get_constant_index(float p_constant) const;
@@ -289,6 +290,7 @@ class VisualShaderEditor : public VBoxContainer {
int texture3d_node_option_idx;
int custom_node_option_idx;
int curve_node_option_idx;
+ int curve_xyz_node_option_idx;
List<String> keyword_list;
List<VisualShaderNodeUniformRef> uniform_refs;
@@ -505,7 +507,7 @@ class EditorInspectorShaderModePlugin : public EditorInspectorPlugin {
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
- virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide = false) override;
+ virtual bool 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 = false) override;
virtual void parse_end() override;
};
diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp
index d30cc7ad17..5bbc0c9dd5 100644
--- a/editor/plugins/voxel_gi_editor_plugin.cpp
+++ b/editor/plugins/voxel_gi_editor_plugin.cpp
@@ -69,10 +69,7 @@ void VoxelGIEditorPlugin::_notification(int p_what) {
const Vector3i size = voxel_gi->get_estimated_cell_size();
String text = vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z);
- int data_size = 4;
- if (GLOBAL_GET("rendering/quality/voxel_gi/anisotropic")) {
- data_size += 4;
- }
+ const int data_size = 4;
const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0);
text += " - " + vformat(TTR("VRAM Size: %s MB"), String::num(size_mb, 2));
@@ -84,13 +81,13 @@ void VoxelGIEditorPlugin::_notification(int p_what) {
Color color;
if (size_mb <= 16.0 + CMP_EPSILON) {
// Fast.
- color = bake_info->get_theme_color("success_color", "Editor");
+ color = bake_info->get_theme_color(SNAME("success_color"), SNAME("Editor"));
} else if (size_mb <= 64.0 + CMP_EPSILON) {
// Medium.
- color = bake_info->get_theme_color("warning_color", "Editor");
+ color = bake_info->get_theme_color(SNAME("warning_color"), SNAME("Editor"));
} else {
// Slow.
- color = bake_info->get_theme_color("error_color", "Editor");
+ color = bake_info->get_theme_color(SNAME("error_color"), SNAME("Editor"));
}
bake_info->add_theme_color_override("font_color", color);
@@ -146,7 +143,7 @@ VoxelGIEditorPlugin::VoxelGIEditorPlugin(EditorNode *p_node) {
bake_hb->hide();
bake = memnew(Button);
bake->set_flat(true);
- bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons"));
+ bake->set_icon(editor->get_gui_base()->get_theme_icon(SNAME("Bake"), SNAME("EditorIcons")));
bake->set_text(TTR("Bake GI Probe"));
bake->connect("pressed", callable_mp(this, &VoxelGIEditorPlugin::_bake));
bake_hb->add_child(bake);
diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index 0b6a3798b3..3441060fad 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -139,7 +139,7 @@ void ProgressDialog::_popup() {
Size2 ms = main->get_combined_minimum_size();
ms.width = MAX(500 * EDSCALE, ms.width);
- Ref<StyleBox> style = main->get_theme_stylebox("panel", "PopupMenu");
+ Ref<StyleBox> style = main->get_theme_stylebox(SNAME("panel"), SNAME("PopupMenu"));
ms += style->get_minimum_size();
main->set_offset(SIDE_LEFT, style->get_margin(SIDE_LEFT));
main->set_offset(SIDE_RIGHT, -style->get_margin(SIDE_RIGHT));
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 75736a0723..1e818b9d43 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -49,8 +49,8 @@
#include "servers/display_server.h"
void ProjectExportDialog::_theme_changed() {
- duplicate_preset->set_icon(presets->get_theme_icon("Duplicate", "EditorIcons"));
- delete_preset->set_icon(presets->get_theme_icon("Remove", "EditorIcons"));
+ duplicate_preset->set_icon(presets->get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")));
+ delete_preset->set_icon(presets->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
}
void ProjectExportDialog::_notification(int p_what) {
@@ -61,9 +61,10 @@ void ProjectExportDialog::_notification(int p_what) {
}
} break;
case NOTIFICATION_READY: {
- duplicate_preset->set_icon(presets->get_theme_icon("Duplicate", "EditorIcons"));
- delete_preset->set_icon(presets->get_theme_icon("Remove", "EditorIcons"));
+ duplicate_preset->set_icon(presets->get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")));
+ delete_preset->set_icon(presets->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
connect("confirmed", callable_mp(this, &ProjectExportDialog::_export_pck_zip));
+ _update_export_all();
} break;
}
}
@@ -182,10 +183,12 @@ void ProjectExportDialog::_update_export_all() {
}
}
+ export_all_button->set_disabled(!can_export);
+
if (can_export) {
- export_all_button->set_disabled(false);
+ export_all_button->set_tooltip(TTR("Export the project for all the presets defined."));
} else {
- export_all_button->set_disabled(true);
+ export_all_button->set_tooltip(TTR("All presets must have an export path defined for Export All to work."));
}
}
@@ -433,6 +436,7 @@ void ProjectExportDialog::_export_path_changed(const StringName &p_property, con
current->set_export_path(p_value);
_update_presets();
+ _update_export_all();
}
void ProjectExportDialog::_enc_filters_changed(const String &p_filters) {
@@ -589,6 +593,10 @@ void ProjectExportDialog::_delete_preset_confirm() {
get_ok_button()->set_disabled(true);
EditorExport::get_singleton()->remove_export_preset(idx);
_update_presets();
+
+ // The Export All button might become enabled (if all other presets have an export path defined),
+ // or it could be disabled (if there are no presets anymore).
+ _update_export_all();
}
Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
@@ -722,7 +730,7 @@ void ProjectExportDialog::_fill_resource_tree() {
bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> &current, bool p_only_scenes) {
p_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- p_item->set_icon(0, presets->get_theme_icon("folder", "FileDialog"));
+ p_item->set_icon(0, presets->get_theme_icon(SNAME("folder"), SNAME("FileDialog")));
p_item->set_text(0, p_dir->get_name() + "/");
p_item->set_editable(0, true);
p_item->set_metadata(0, p_dir->get_path());
@@ -1005,8 +1013,11 @@ ProjectExportDialog::ProjectExportDialog() {
preset_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hbox->add_child(preset_vb);
+ Label *l = memnew(Label(TTR("Presets")));
+ l->set_theme_type_variation("HeaderSmall");
+
HBoxContainer *preset_hb = memnew(HBoxContainer);
- preset_hb->add_child(memnew(Label(TTR("Presets"))));
+ preset_hb->add_child(l);
preset_hb->add_spacer();
preset_vb->add_child(preset_hb);
@@ -1142,7 +1153,7 @@ ProjectExportDialog::ProjectExportDialog() {
enc_directory = memnew(CheckButton);
enc_directory->connect("toggled", callable_mp(this, &ProjectExportDialog::_enc_directory_changed));
- enc_directory->set_text("Encrypt Index (File Names and Info)");
+ enc_directory->set_text(TTR("Encrypt Index (File Names and Info)"));
sec_vb->add_child(enc_directory);
enc_in_filters = memnew(LineEdit);
@@ -1161,7 +1172,7 @@ ProjectExportDialog::ProjectExportDialog() {
script_key->connect("text_changed", callable_mp(this, &ProjectExportDialog::_script_encryption_key_changed));
script_key_error = memnew(Label);
script_key_error->set_text("- " + TTR("Invalid Encryption Key (must be 64 hexadecimal characters long)"));
- script_key_error->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"));
+ script_key_error->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
sec_vb->add_margin_child(TTR("Encryption Key (256-bits as hexadecimal):"), script_key);
sec_vb->add_child(script_key_error);
sections->add_child(sec_vb);
@@ -1199,8 +1210,8 @@ ProjectExportDialog::ProjectExportDialog() {
updating = false;
get_cancel_button()->set_text(TTR("Close"));
- get_ok_button()->set_text(TTR("Export PCK/Zip"));
- export_button = add_button(TTR("Export Project"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
+ get_ok_button()->set_text(TTR("Export PCK/ZIP..."));
+ export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
export_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_project));
// Disable initially before we select a valid preset
export_button->set_disabled(true);
@@ -1208,20 +1219,20 @@ ProjectExportDialog::ProjectExportDialog() {
export_all_dialog = memnew(ConfirmationDialog);
add_child(export_all_dialog);
- export_all_dialog->set_title("Export All");
- export_all_dialog->set_text(TTR("Export mode?"));
+ export_all_dialog->set_title(TTR("Export All"));
+ export_all_dialog->set_text(TTR("Choose an export mode:"));
export_all_dialog->get_ok_button()->hide();
export_all_dialog->add_button(TTR("Debug"), true, "debug");
export_all_dialog->add_button(TTR("Release"), true, "release");
export_all_dialog->connect("custom_action", callable_mp(this, &ProjectExportDialog::_export_all_dialog_action));
- export_all_button = add_button(TTR("Export All"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
+ export_all_button = add_button(TTR("Export All..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
export_all_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_all_dialog));
export_all_button->set_disabled(true);
export_pck_zip = memnew(EditorFileDialog);
export_pck_zip->add_filter("*.zip ; " + TTR("ZIP File"));
- export_pck_zip->add_filter("*.pck ; " + TTR("Godot Game Pack"));
+ export_pck_zip->add_filter("*.pck ; " + TTR("Godot Project Pack"));
export_pck_zip->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
export_pck_zip->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
add_child(export_pck_zip);
@@ -1230,7 +1241,7 @@ ProjectExportDialog::ProjectExportDialog() {
export_error = memnew(Label);
main_vb->add_child(export_error);
export_error->hide();
- export_error->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"));
+ export_error->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
export_templates_error = memnew(HBoxContainer);
main_vb->add_child(export_templates_error);
@@ -1238,11 +1249,11 @@ ProjectExportDialog::ProjectExportDialog() {
Label *export_error2 = memnew(Label);
export_templates_error->add_child(export_error2);
- export_error2->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"));
+ export_error2->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
export_error2->set_text(" - " + TTR("Export templates for this platform are missing:") + " ");
error_dialog = memnew(AcceptDialog);
- error_dialog->set_title("Error");
+ error_dialog->set_title(TTR("Error"));
error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted:") + " ");
main_vb->add_child(error_dialog);
error_dialog->hide();
@@ -1282,8 +1293,6 @@ ProjectExportDialog::ProjectExportDialog() {
default_filename = "UnnamedProject";
}
}
-
- _update_export_all();
}
ProjectExportDialog::~ProjectExportDialog() {
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 50a763f05a..46a1253ca0 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -113,20 +113,20 @@ private:
switch (p_type) {
case MESSAGE_ERROR: {
- msg->add_theme_color_override("font_color", msg->get_theme_color("error_color", "Editor"));
+ msg->add_theme_color_override("font_color", msg->get_theme_color(SNAME("error_color"), SNAME("Editor")));
msg->set_modulate(Color(1, 1, 1, 1));
- new_icon = msg->get_theme_icon("StatusError", "EditorIcons");
+ new_icon = msg->get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons"));
} break;
case MESSAGE_WARNING: {
- msg->add_theme_color_override("font_color", msg->get_theme_color("warning_color", "Editor"));
+ msg->add_theme_color_override("font_color", msg->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
msg->set_modulate(Color(1, 1, 1, 1));
- new_icon = msg->get_theme_icon("StatusWarning", "EditorIcons");
+ new_icon = msg->get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"));
} break;
case MESSAGE_SUCCESS: {
msg->set_modulate(Color(1, 1, 1, 0));
- new_icon = msg->get_theme_icon("StatusSuccess", "EditorIcons");
+ new_icon = msg->get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons"));
} break;
}
@@ -336,9 +336,9 @@ private:
project_path->set_text(sp);
_path_text_changed(sp);
if (p.ends_with(".zip")) {
- install_path->call_deferred("grab_focus");
+ install_path->call_deferred(SNAME("grab_focus"));
} else {
- get_ok_button()->call_deferred("grab_focus");
+ get_ok_button()->call_deferred(SNAME("grab_focus"));
}
}
@@ -346,14 +346,14 @@ private:
String sp = p_path.simplify_path();
project_path->set_text(sp);
_path_text_changed(sp);
- get_ok_button()->call_deferred("grab_focus");
+ get_ok_button()->call_deferred(SNAME("grab_focus"));
}
void _install_path_selected(const String &p_path) {
String sp = p_path.simplify_path();
install_path->set_text(sp);
_path_text_changed(sp);
- get_ok_button()->call_deferred("grab_focus");
+ get_ok_button()->call_deferred(SNAME("grab_focus"));
}
void _browse_path() {
@@ -448,7 +448,7 @@ private:
}
hide();
- emit_signal("projects_updated");
+ emit_signal(SNAME("projects_updated"));
} else {
if (mode == MODE_IMPORT) {
@@ -617,7 +617,7 @@ private:
EditorSettings::get_singleton()->save();
hide();
- emit_signal("project_created", dir);
+ emit_signal(SNAME("project_created"), dir);
}
}
@@ -640,11 +640,11 @@ private:
project_name->clear();
_text_changed("");
- if (status_rect->get_texture() == msg->get_theme_icon("StatusError", "EditorIcons")) {
+ if (status_rect->get_texture() == msg->get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons"))) {
msg->show();
}
- if (install_status_rect->get_texture() == msg->get_theme_icon("StatusError", "EditorIcons")) {
+ if (install_status_rect->get_texture() == msg->get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons"))) {
msg->show();
}
}
@@ -715,7 +715,7 @@ public:
_text_changed(proj);
}
- project_name->call_deferred("grab_focus");
+ project_name->call_deferred(SNAME("grab_focus"));
create_dir->hide();
@@ -758,8 +758,8 @@ public:
name_container->show();
install_path_container->hide();
rasterizer_container->show();
- project_name->call_deferred("grab_focus");
- project_name->call_deferred("select_all");
+ project_name->call_deferred(SNAME("grab_focus"));
+ project_name->call_deferred(SNAME("select_all"));
} else if (mode == MODE_INSTALL) {
set_title(TTR("Install Project:") + " " + zip_title);
@@ -966,7 +966,7 @@ public:
} break;
case NOTIFICATION_DRAW: {
if (hover) {
- draw_style_box(get_theme_stylebox("hover", "Tree"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("hover"), SNAME("Tree")), Rect2(Point2(), get_size()));
}
} break;
}
@@ -1141,7 +1141,7 @@ void ProjectList::_notification(int p_what) {
void ProjectList::load_project_icon(int p_index) {
Item &item = _projects.write[p_index];
- Ref<Texture2D> default_icon = get_theme_icon("DefaultProjectIcon", "EditorIcons");
+ Ref<Texture2D> default_icon = get_theme_icon(SNAME("DefaultProjectIcon"), SNAME("EditorIcons"));
Ref<Texture2D> icon;
if (item.icon != "") {
Ref<Image> img;
@@ -1327,8 +1327,8 @@ void ProjectList::create_project_item_control(int p_index) {
Item &item = _projects.write[p_index];
ERR_FAIL_COND(item.control != nullptr); // Already created
- Ref<Texture2D> favorite_icon = get_theme_icon("Favorites", "EditorIcons");
- Color font_color = get_theme_color("font_color", "Tree");
+ Ref<Texture2D> favorite_icon = get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons"));
+ Color font_color = get_theme_color(SNAME("font_color"), SNAME("Tree"));
ProjectListItemControl *hb = memnew(ProjectListItemControl);
hb->connect("draw", callable_mp(this, &ProjectList::_panel_draw), varray(hb));
@@ -1353,7 +1353,7 @@ void ProjectList::create_project_item_control(int p_index) {
TextureRect *tf = memnew(TextureRect);
// The project icon may not be loaded by the time the control is displayed,
// so use a loading placeholder.
- tf->set_texture(get_theme_icon("ProjectIconLoading", "EditorIcons"));
+ tf->set_texture(get_theme_icon(SNAME("ProjectIconLoading"), SNAME("EditorIcons")));
tf->set_v_size_flags(SIZE_SHRINK_CENTER);
if (item.missing) {
tf->set_modulate(Color(1, 1, 1, 0.5));
@@ -1372,8 +1372,8 @@ void ProjectList::create_project_item_control(int p_index) {
ec->set_mouse_filter(MOUSE_FILTER_PASS);
vb->add_child(ec);
Label *title = memnew(Label(!item.missing ? item.project_name : TTR("Missing Project")));
- title->add_theme_font_override("font", get_theme_font("title", "EditorFonts"));
- title->add_theme_font_size_override("font_size", get_theme_font_size("title_size", "EditorFonts"));
+ title->add_theme_font_override("font", get_theme_font(SNAME("title"), SNAME("EditorFonts")));
+ title->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("title_size"), SNAME("EditorFonts")));
title->add_theme_color_override("font_color", font_color);
title->set_clip_text(true);
vb->add_child(title);
@@ -1726,15 +1726,15 @@ void ProjectList::_panel_draw(Node *p_hb) {
Control *hb = Object::cast_to<Control>(p_hb);
if (is_layout_rtl() && get_v_scrollbar()->is_visible_in_tree()) {
- hb->draw_line(Point2(get_v_scrollbar()->get_minimum_size().x, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color("guide_color", "Tree"));
+ hb->draw_line(Point2(get_v_scrollbar()->get_minimum_size().x, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color(SNAME("guide_color"), SNAME("Tree")));
} else {
- hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color("guide_color", "Tree"));
+ hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color(SNAME("guide_color"), SNAME("Tree")));
}
String key = _projects[p_hb->get_index()].project_key;
if (_selected_project_keys.has(key)) {
- hb->draw_style_box(get_theme_stylebox("selected", "Tree"), Rect2(Point2(), hb->get_size()));
+ hb->draw_style_box(get_theme_stylebox(SNAME("selected"), SNAME("Tree")), Rect2(Point2(), hb->get_size()));
}
}
@@ -1765,10 +1765,10 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
select_project(clicked_index);
}
- emit_signal(SIGNAL_SELECTION_CHANGED);
+ emit_signal(SNAME(SIGNAL_SELECTION_CHANGED));
if (!mb->is_ctrl_pressed() && mb->is_double_click()) {
- emit_signal(SIGNAL_PROJECT_ASK_OPEN);
+ emit_signal(SNAME(SIGNAL_PROJECT_ASK_OPEN));
}
}
}
@@ -1826,7 +1826,7 @@ void ProjectManager::_notification(int p_what) {
update();
} break;
case NOTIFICATION_ENTER_TREE: {
- search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
Engine::get_singleton()->set_editor_hint(false);
@@ -2446,7 +2446,7 @@ ProjectManager::ProjectManager() {
Panel *panel = memnew(Panel);
add_child(panel);
panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
- panel->add_theme_style_override("panel", get_theme_stylebox("Background", "EditorStyles"));
+ panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles")));
VBoxContainer *vb = memnew(VBoxContainer);
panel->add_child(vb);
@@ -2484,7 +2484,7 @@ ProjectManager::ProjectManager() {
hb->add_child(search_box);
loading_label = memnew(Label(TTR("Loading, please wait...")));
- loading_label->add_theme_font_override("font", get_theme_font("bold", "EditorFonts"));
+ loading_label->add_theme_font_override("font", get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
loading_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hb->add_child(loading_label);
// Hide the label but make it still take up space. This prevents reflows when showing the label.
@@ -2510,7 +2510,7 @@ ProjectManager::ProjectManager() {
}
PanelContainer *pc = memnew(PanelContainer);
- pc->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
+ pc->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
pc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
search_tree_vb->add_child(pc);
@@ -2618,7 +2618,7 @@ ProjectManager::ProjectManager() {
language_btn = memnew(OptionButton);
language_btn->set_flat(true);
- language_btn->set_icon(get_theme_icon("Environment", "EditorIcons"));
+ language_btn->set_icon(get_theme_icon(SNAME("Environment"), SNAME("EditorIcons")));
language_btn->set_focus_mode(Control::FOCUS_NONE);
language_btn->connect("item_selected", callable_mp(this, &ProjectManager::_language_selected));
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index e76d757516..2c4b28e13d 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -444,7 +444,7 @@ void ProjectSettingsEditor::_update_action_map_editor() {
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
- const Ref<Texture2D> builtin_icon = get_theme_icon("PinPressed", "EditorIcons");
+ const Ref<Texture2D> builtin_icon = get_theme_icon(SNAME("PinPressed"), SNAME("EditorIcons"));
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
const String property_name = E->get().name;
@@ -483,18 +483,18 @@ void ProjectSettingsEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
inspector->edit(ps);
- search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
- restart_close_button->set_icon(get_theme_icon("Close", "EditorIcons"));
- restart_container->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
- restart_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons"));
- restart_label->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"));
+ restart_close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ restart_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ restart_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
+ restart_label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
_update_action_map_editor();
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
} break;
}
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 7414c2d8e6..db8334b485 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -119,16 +119,16 @@ void CustomPropertyEditor::_menu_option(int p_which) {
}
v = val;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
} else if (hint == PROPERTY_HINT_ENUM) {
v = menu->get_item_metadata(p_which);
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
} break;
case Variant::STRING: {
if (hint == PROPERTY_HINT_ENUM) {
v = hint_text.get_slice(",", p_which);
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
} break;
case Variant::OBJECT: {
@@ -159,13 +159,13 @@ void CustomPropertyEditor::_menu_option(int p_which) {
REF r = v;
if (!r.is_null()) {
- emit_signal("resource_edit_request");
+ emit_signal(SNAME("resource_edit_request"));
hide();
}
} break;
case OBJ_MENU_CLEAR: {
v = Variant();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
} break;
@@ -204,7 +204,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
}
v = res;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
} break;
@@ -214,7 +214,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
} break;
case OBJ_MENU_PASTE: {
v = EditorSettings::get_singleton()->get_resource_clipboard();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
} break;
case OBJ_MENU_NEW_SCRIPT: {
@@ -248,7 +248,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
Ref<Resource> new_res = conversions[to_type]->convert(v);
v = new_res;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
break;
}
ERR_FAIL_COND(inheritors_array.is_empty());
@@ -281,7 +281,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
}
v = obj;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
} break;
}
@@ -544,8 +544,8 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
text_edit->set_text(v);
text_edit->deselect();
- int button_margin = text_edit->get_theme_constant("button_margin", "Dialogs");
- int margin = text_edit->get_theme_constant("margin", "Dialogs");
+ int button_margin = text_edit->get_theme_constant(SNAME("button_margin"), SNAME("Dialogs"));
+ int margin = text_edit->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
action_buttons[0]->set_anchor(SIDE_LEFT, Control::ANCHOR_END);
action_buttons[0]->set_anchor(SIDE_TOP, Control::ANCHOR_END);
@@ -975,7 +975,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
}
for (int i = 0; i < conversions.size(); i++) {
String what = conversions[i]->converts_to();
- menu->add_item(vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
+ menu->add_item(vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i);
}
}
@@ -1016,13 +1016,13 @@ void CustomPropertyEditor::_file_selected(String p_file) {
case Variant::STRING: {
if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_DIR) {
v = ProjectSettings::get_singleton()->localize_path(p_file);
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
}
if (hint == PROPERTY_HINT_GLOBAL_FILE || hint == PROPERTY_HINT_GLOBAL_DIR) {
v = p_file;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
}
@@ -1037,7 +1037,7 @@ void CustomPropertyEditor::_file_selected(String p_file) {
break;
}
v = res;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
} break;
default: {
@@ -1070,7 +1070,7 @@ void CustomPropertyEditor::_type_create_selected(int p_idx) {
}
v = newval;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
easing_draw->update();
} else if (type == Variant::OBJECT) {
@@ -1092,14 +1092,14 @@ void CustomPropertyEditor::_type_create_selected(int p_idx) {
ERR_FAIL_COND(!Object::cast_to<Resource>(obj));
v = obj;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
}
}
void CustomPropertyEditor::_color_changed(const Color &p_color) {
v = p_color;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
@@ -1115,7 +1115,7 @@ void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node));
vt->setup_local_to_scene();
v = vt;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
return;
}
@@ -1140,8 +1140,8 @@ void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
}
if (!node) {
v = p_path;
- emit_signal("variant_changed");
- call_deferred("hide"); //to not mess with dialogs
+ emit_signal(SNAME("variant_changed"));
+ call_deferred(SNAME("hide")); //to not mess with dialogs
return;
}
@@ -1152,8 +1152,8 @@ void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
}
v = p_path;
- emit_signal("variant_changed");
- call_deferred("hide"); //to not mess with dialogs
+ emit_signal(SNAME("variant_changed"));
+ call_deferred(SNAME("hide")); //to not mess with dialogs
}
void CustomPropertyEditor::_action_pressed(int p_which) {
@@ -1164,7 +1164,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
switch (type) {
case Variant::BOOL: {
v = checks20[0]->is_pressed();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
} break;
case Variant::INT: {
if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS ||
@@ -1181,7 +1181,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
}
v = f;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
} break;
@@ -1218,7 +1218,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
file->popup_file_dialog();
} else {
v = "";
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
}
@@ -1234,7 +1234,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
file->popup_file_dialog();
} else {
v = "";
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
}
}
@@ -1248,7 +1248,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
} else if (p_which == 1) {
v = NodePath();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
} else if (p_which == 2) {
if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) {
@@ -1282,7 +1282,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
ERR_BREAK(!Object::cast_to<Resource>(obj));
v = obj;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
}
} else if (p_which == 1) {
@@ -1303,13 +1303,13 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
RES r = v;
if (!r.is_null()) {
- emit_signal("resource_edit_request");
+ emit_signal(SNAME("resource_edit_request"));
hide();
}
} else if (p_which == 3) {
v = Variant();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
} else if (p_which == 4) {
Ref<Resource> res_orig = v;
@@ -1342,7 +1342,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
}
v = res;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
hide();
}
@@ -1386,7 +1386,7 @@ void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) {
v = val;
easing_draw->update();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
}
@@ -1396,7 +1396,7 @@ void CustomPropertyEditor::_draw_easing() {
Size2 s = easing_draw->get_size();
Rect2 r(Point2(), s);
r = r.grow(3);
- easing_draw->get_theme_stylebox("normal", "LineEdit")->draw(ci, r);
+ easing_draw->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->draw(ci, r);
int points = 48;
@@ -1404,9 +1404,9 @@ void CustomPropertyEditor::_draw_easing() {
float exp = v;
bool flip = hint_text == "attenuation";
- Ref<Font> f = easing_draw->get_theme_font("font", "Label");
- int font_size = easing_draw->get_theme_font_size("font_size", "Label");
- Color color = easing_draw->get_theme_color("font_color", "Label");
+ Ref<Font> f = easing_draw->get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = easing_draw->get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Color color = easing_draw->get_theme_color(SNAME("font_color"), SNAME("Label"));
for (int i = 1; i <= points; i++) {
float ifl = i / float(points);
@@ -1428,17 +1428,17 @@ void CustomPropertyEditor::_draw_easing() {
void CustomPropertyEditor::_text_edit_changed() {
v = text_edit->get_text();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
void CustomPropertyEditor::_create_dialog_callback() {
v = create_dialog->get_selected_type();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
void CustomPropertyEditor::_create_selected_property(const String &p_prop) {
v = p_prop;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
void CustomPropertyEditor::_modified(String p_string) {
@@ -1463,7 +1463,7 @@ void CustomPropertyEditor::_modified(String p_string) {
}
if (v != prev_v) {
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
} break;
case Variant::FLOAT: {
@@ -1471,14 +1471,14 @@ void CustomPropertyEditor::_modified(String p_string) {
String text = TS->parse_number(value_editor[0]->get_text());
v = _parse_real_expression(text);
if (v != prev_v) {
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
}
} break;
case Variant::STRING: {
v = value_editor[0]->get_text();
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
} break;
case Variant::VECTOR2: {
Vector2 vec;
@@ -1603,7 +1603,7 @@ void CustomPropertyEditor::_modified(String p_string) {
case Variant::NODE_PATH: {
v = NodePath(value_editor[0]->get_text());
if (v != prev_v) {
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
} break;
case Variant::DICTIONARY: {
@@ -1642,15 +1642,15 @@ real_t CustomPropertyEditor::_parse_real_expression(String text) {
void CustomPropertyEditor::_emit_changed_whole_or_field() {
if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
} else {
- emit_signal("variant_field_changed", field_names[focused_value_editor]);
+ emit_signal(SNAME("variant_field_changed"), field_names[focused_value_editor]);
}
}
void CustomPropertyEditor::_range_modified(double p_value) {
v = p_value;
- emit_signal("variant_changed");
+ emit_signal(SNAME("variant_changed"));
}
void CustomPropertyEditor::_focus_enter() {
@@ -1684,7 +1684,7 @@ void CustomPropertyEditor::_focus_exit() {
}
void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) {
- Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox("panel");
+ Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox(SNAME("panel"));
int margin_top = sb->get_margin(SIDE_TOP);
int margin_left = sb->get_margin(SIDE_LEFT);
int margin_bottom = sb->get_margin(SIDE_BOTTOM);
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index 00652c02c8..d26fc6ad9d 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -119,38 +119,41 @@ void PropertySelector::_update_search() {
bool found = false;
Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = {
- search_options->get_theme_icon("Variant", "EditorIcons"),
- search_options->get_theme_icon("bool", "EditorIcons"),
- search_options->get_theme_icon("int", "EditorIcons"),
- search_options->get_theme_icon("float", "EditorIcons"),
- search_options->get_theme_icon("String", "EditorIcons"),
- search_options->get_theme_icon("Vector2", "EditorIcons"),
- search_options->get_theme_icon("Vector2i", "EditorIcons"),
- search_options->get_theme_icon("Rect2", "EditorIcons"),
- search_options->get_theme_icon("Rect2i", "EditorIcons"),
- search_options->get_theme_icon("Vector3", "EditorIcons"),
- search_options->get_theme_icon("Vector3i", "EditorIcons"),
- search_options->get_theme_icon("Transform2D", "EditorIcons"),
- search_options->get_theme_icon("Plane", "EditorIcons"),
- search_options->get_theme_icon("Quaternion", "EditorIcons"),
- search_options->get_theme_icon("AABB", "EditorIcons"),
- search_options->get_theme_icon("Basis", "EditorIcons"),
- search_options->get_theme_icon("Transform3D", "EditorIcons"),
- search_options->get_theme_icon("Color", "EditorIcons"),
- search_options->get_theme_icon("NodePath", "EditorIcons"),
- search_options->get_theme_icon("RID", "EditorIcons"),
- search_options->get_theme_icon("MiniObject", "EditorIcons"),
- search_options->get_theme_icon("Callable", "EditorIcons"),
- search_options->get_theme_icon("Signal", "EditorIcons"),
- search_options->get_theme_icon("Dictionary", "EditorIcons"),
- search_options->get_theme_icon("Array", "EditorIcons"),
- search_options->get_theme_icon("PackedByteArray", "EditorIcons"),
- search_options->get_theme_icon("PackedInt32Array", "EditorIcons"),
- search_options->get_theme_icon("PackedFloat32Array", "EditorIcons"),
- search_options->get_theme_icon("PackedStringArray", "EditorIcons"),
- search_options->get_theme_icon("PackedVector2Array", "EditorIcons"),
- search_options->get_theme_icon("PackedVector3Array", "EditorIcons"),
- search_options->get_theme_icon("PackedColorArray", "EditorIcons")
+ search_options->get_theme_icon(SNAME("Variant"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("int"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("String"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Vector2i"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Rect2"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Rect2i"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Vector3i"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Transform2D"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Plane"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Quaternion"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("AABB"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Basis"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("StringName"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("NodePath"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("RID"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("MiniObject"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Callable"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Signal"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Dictionary"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("Array"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedByteArray"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedInt32Array"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedInt64Array"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedFloat32Array"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedFloat64Array"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedStringArray"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedVector2Array"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedVector3Array"), SNAME("EditorIcons")),
+ search_options->get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons"))
};
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
@@ -164,7 +167,7 @@ void PropertySelector::_update_search() {
Ref<Texture2D> icon;
if (E->get().name == "Script Variables") {
- icon = search_options->get_theme_icon("Script", "EditorIcons");
+ icon = search_options->get_theme_icon(SNAME("Script"), SNAME("EditorIcons"));
} else {
icon = EditorNode::get_singleton()->get_class_icon(E->get().name);
}
@@ -241,7 +244,7 @@ void PropertySelector::_update_search() {
script_methods = false;
String rep = E->get().name.replace("*", "");
if (E->get().name == "*Script Methods") {
- icon = search_options->get_theme_icon("Script", "EditorIcons");
+ icon = search_options->get_theme_icon(SNAME("Script"), SNAME("EditorIcons"));
script_methods = true;
} else {
icon = EditorNode::get_singleton()->get_class_icon(rep);
@@ -334,7 +337,7 @@ void PropertySelector::_confirmed() {
if (!ti) {
return;
}
- emit_signal("selected", ti->get_metadata(0));
+ emit_signal(SNAME("selected"), ti->get_metadata(0));
hide();
}
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index e8e13bab21..bda7540a23 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -64,7 +64,7 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) {
// Store refs to used icons.
String ext = file.get_extension();
if (!icons.has(ext)) {
- icons.insert(ext, get_theme_icon((has_theme_icon(file_type, "EditorIcons") ? file_type : "Object"), "EditorIcons"));
+ icons.insert(ext, get_theme_icon((has_theme_icon(file_type, SNAME("EditorIcons")) ? file_type : String("Object")), SNAME("EditorIcons")));
}
}
}
@@ -140,7 +140,7 @@ void EditorQuickOpen::_confirmed() {
return;
}
_cleanup();
- emit_signal("quick_open");
+ emit_signal(SNAME("quick_open"));
hide();
}
@@ -228,7 +228,7 @@ void EditorQuickOpen::_notification(int p_what) {
}
void EditorQuickOpen::_theme_changed() {
- search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(search_options->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
}
void EditorQuickOpen::_bind_methods() {
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index 0f15d4b119..d86e2656d4 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -35,12 +35,18 @@
#include "editor_scale.h"
#include "editor_settings.h"
#include "editor_themes.h"
-#include "modules/regex/regex.h"
#include "plugins/script_editor_plugin.h"
#include "scene/gui/control.h"
#include "scene/gui/label.h"
#include "scene/gui/tab_container.h"
+#include "modules/modules_enabled.gen.h"
+#ifdef MODULE_REGEX_ENABLED
+#include "modules/regex/regex.h"
+#else
+#error "Can't build editor rename dialog without RegEx module."
+#endif
+
RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_undo_redo) {
scene_tree_editor = p_scene_tree_editor;
undo_redo = p_undo_redo;
@@ -385,11 +391,11 @@ void RenameDialog::_update_preview(String new_text) {
if (new_name == preview_node->get_name()) {
// New name is identical to the old one. Don't color it as much to avoid distracting the user.
- const Color accent_color = EditorNode::get_singleton()->get_gui_base()->get_theme_color("accent_color", "Editor");
- const Color text_color = EditorNode::get_singleton()->get_gui_base()->get_theme_color("default_color", "RichTextLabel");
+ const Color accent_color = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ const Color text_color = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("default_color"), SNAME("RichTextLabel"));
lbl_preview->add_theme_color_override("font_color", accent_color.lerp(text_color, 0.5));
} else {
- lbl_preview->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor"));
+ lbl_preview->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("success_color"), SNAME("Editor")));
}
}
@@ -475,7 +481,7 @@ void RenameDialog::_error_handler(void *p_self, const char *p_func, const char *
self->has_errors = true;
self->lbl_preview_title->set_text(TTR("Regular Expression Error:"));
- self->lbl_preview->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"));
+ self->lbl_preview->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor")));
self->lbl_preview->set_text(vformat(TTR("At character %s"), err_str));
}
@@ -588,7 +594,7 @@ void RenameDialog::rename() {
continue;
}
- scene_tree_editor->emit_signal("node_prerename", n, new_name);
+ scene_tree_editor->emit_signal(SNAME("node_prerename"), n, new_name);
undo_redo->add_do_method(scene_tree_editor, "_rename_node", n->get_instance_id(), new_name);
undo_redo->add_undo_method(scene_tree_editor, "_rename_node", n->get_instance_id(), n->get_name());
}
diff --git a/editor/reparent_dialog.cpp b/editor/reparent_dialog.cpp
index aab046c235..f862260212 100644
--- a/editor/reparent_dialog.cpp
+++ b/editor/reparent_dialog.cpp
@@ -50,7 +50,7 @@ void ReparentDialog::_cancel() {
void ReparentDialog::_reparent() {
if (tree->get_selected()) {
- emit_signal("reparent", tree->get_selected()->get_path(), keep_transform->is_pressed());
+ emit_signal(SNAME("reparent"), tree->get_selected()->get_path(), keep_transform->is_pressed());
hide();
}
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 2114ca41d3..6d1deb86c6 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -229,7 +229,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
editor_data->get_undo_redo().commit_action();
editor->push_item(instances[instances.size() - 1]);
for (int i = 0; i < instances.size(); i++) {
- emit_signal("node_created", instances[i]);
+ emit_signal(SNAME("node_created"), instances[i]);
}
}
@@ -359,7 +359,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
}
- if (reset_create_dialog) {
+ if (reset_create_dialog && !p_confirm_override) {
create_dialog->set_base_type("Node");
reset_create_dialog = false;
}
@@ -385,7 +385,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
create_dialog->popup_create(true);
if (!p_confirm_override) {
- emit_signal("add_node_used");
+ emit_signal(SNAME("add_node_used"));
}
} break;
case TOOL_INSTANTIATE: {
@@ -402,7 +402,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
quick_open->popup_dialog("PackedScene", true);
quick_open->set_title(TTR("Instantiate Child Scene"));
if (!p_confirm_override) {
- emit_signal("add_node_used");
+ emit_signal(SNAME("add_node_used"));
}
} break;
case TOOL_EXPAND_COLLAPSE: {
@@ -544,6 +544,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
}
+ if (reset_create_dialog) {
+ create_dialog->set_base_type("Node");
+ reset_create_dialog = false;
+ }
+
Node *selected = scene_tree->get_selected();
if (!selected && !editor_selection->get_selected_node_list().is_empty()) {
selected = editor_selection->get_selected_node_list().front()->get();
@@ -1057,7 +1062,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (e) {
Node *node = e->get();
if (node) {
- scene_tree->emit_signal("open", node->get_filename());
+ scene_tree->emit_signal(SNAME("open"), node->get_filename());
}
}
} break;
@@ -1090,7 +1095,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (e) {
Node *node = e->get();
if (node && node->get_scene_inherited_state().is_valid()) {
- scene_tree->emit_signal("open", node->get_scene_inherited_state()->get_path());
+ scene_tree->emit_signal(SNAME("open"), node->get_scene_inherited_state()->get_path());
}
}
} break;
@@ -1134,12 +1139,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
}
- editor_data->get_undo_redo().create_action(TTR("New Scene Root"));
- editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", new_node);
- editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree");
- editor_data->get_undo_redo().add_do_reference(new_node);
- editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)nullptr);
- editor_data->get_undo_redo().commit_action();
+ add_root_node(new_node);
editor->edit_node(new_node);
editor_selection->clear();
@@ -1162,6 +1162,28 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
}
+void SceneTreeDock::_property_selected(int p_idx) {
+ ERR_FAIL_NULL(property_drop_node);
+ _perform_property_drop(property_drop_node, menu_properties->get_item_metadata(p_idx), ResourceLoader::load(resource_drop_path));
+ property_drop_node = nullptr;
+}
+
+void SceneTreeDock::_perform_property_drop(Node *p_node, String p_property, RES p_res) {
+ editor_data->get_undo_redo().create_action(vformat(TTR("Set %s"), p_property));
+ editor_data->get_undo_redo().add_do_property(p_node, p_property, p_res);
+ editor_data->get_undo_redo().add_undo_property(p_node, p_property, p_node->get(p_property));
+ editor_data->get_undo_redo().commit_action();
+}
+
+void SceneTreeDock::add_root_node(Node *p_node) {
+ editor_data->get_undo_redo().create_action(TTR("New Scene Root"));
+ editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", p_node);
+ editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree");
+ editor_data->get_undo_redo().add_do_reference(p_node);
+ editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)nullptr);
+ editor_data->get_undo_redo().commit_action();
+}
+
void SceneTreeDock::_node_collapsed(Object *p_obj) {
TreeItem *ti = Object::cast_to<TreeItem>(p_obj);
if (!ti) {
@@ -1194,28 +1216,27 @@ void SceneTreeDock::_notification(int p_what) {
spatial_editor_plugin->get_spatial_editor()->connect("item_lock_status_changed", Callable(scene_tree, "_update_tree"));
spatial_editor_plugin->get_spatial_editor()->connect("item_group_status_changed", Callable(scene_tree, "_update_tree"));
- button_add->set_icon(get_theme_icon("Add", "EditorIcons"));
- button_instance->set_icon(get_theme_icon("Instance", "EditorIcons"));
- button_create_script->set_icon(get_theme_icon("ScriptCreate", "EditorIcons"));
- button_detach_script->set_icon(get_theme_icon("ScriptRemove", "EditorIcons"));
+ button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ button_instance->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ button_create_script->set_icon(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons")));
+ button_detach_script->set_icon(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons")));
- filter->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
filter->set_clear_button_enabled(true);
- EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed));
- scene_tree->get_scene_tree()->connect("item_collapsed", callable_mp(this, &SceneTreeDock::_node_collapsed));
-
// create_root_dialog
HBoxContainer *top_row = memnew(HBoxContainer);
top_row->set_name("NodeShortcutsTopRow");
top_row->set_h_size_flags(SIZE_EXPAND_FILL);
- top_row->add_child(memnew(Label(TTR("Create Root Node:"))));
+ Label *l = memnew(Label(TTR("Create Root Node:")));
+ l->set_theme_type_variation("HeaderSmall");
+ top_row->add_child(l);
top_row->add_spacer();
Button *node_shortcuts_toggle = memnew(Button);
node_shortcuts_toggle->set_flat(true);
node_shortcuts_toggle->set_name("NodeShortcutsToggle");
- node_shortcuts_toggle->set_icon(get_theme_icon("Favorites", "EditorIcons"));
+ node_shortcuts_toggle->set_icon(get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")));
node_shortcuts_toggle->set_toggle_mode(true);
node_shortcuts_toggle->set_tooltip(TTR("Switch to Favorite Nodes"));
node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection"));
@@ -1235,19 +1256,19 @@ void SceneTreeDock::_notification(int p_what) {
button_2d = memnew(Button);
beginner_node_shortcuts->add_child(button_2d);
button_2d->set_text(TTR("2D Scene"));
- button_2d->set_icon(get_theme_icon("Node2D", "EditorIcons"));
+ button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons")));
button_2d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_2D_SCENE, false));
button_3d = memnew(Button);
beginner_node_shortcuts->add_child(button_3d);
button_3d->set_text(TTR("3D Scene"));
- button_3d->set_icon(get_theme_icon("Node3D", "EditorIcons"));
+ button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons")));
button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_3D_SCENE, false));
button_ui = memnew(Button);
beginner_node_shortcuts->add_child(button_ui);
button_ui->set_text(TTR("User Interface"));
- button_ui->set_icon(get_theme_icon("Control", "EditorIcons"));
+ button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons")));
button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_USER_INTERFACE, false));
VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer);
@@ -1257,7 +1278,7 @@ void SceneTreeDock::_notification(int p_what) {
button_custom = memnew(Button);
node_shortcuts->add_child(button_custom);
button_custom->set_text(TTR("Other Node"));
- button_custom->set_icon(get_theme_icon("Add", "EditorIcons"));
+ button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
button_custom->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_NEW, false));
node_shortcuts->add_spacer();
@@ -1273,16 +1294,16 @@ void SceneTreeDock::_notification(int p_what) {
clear_inherit_confirm->disconnect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected));
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- button_add->set_icon(get_theme_icon("Add", "EditorIcons"));
- button_instance->set_icon(get_theme_icon("Instance", "EditorIcons"));
- button_create_script->set_icon(get_theme_icon("ScriptCreate", "EditorIcons"));
- button_detach_script->set_icon(get_theme_icon("ScriptRemove", "EditorIcons"));
- button_2d->set_icon(get_theme_icon("Node2D", "EditorIcons"));
- button_3d->set_icon(get_theme_icon("Node3D", "EditorIcons"));
- button_ui->set_icon(get_theme_icon("Control", "EditorIcons"));
- button_custom->set_icon(get_theme_icon("Add", "EditorIcons"));
-
- filter->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ button_instance->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ button_create_script->set_icon(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons")));
+ button_detach_script->set_icon(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons")));
+ button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons")));
+ button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons")));
+ button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons")));
+ button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+
+ filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
filter->set_clear_button_enabled(true);
} break;
case NOTIFICATION_PROCESS: {
@@ -1409,9 +1430,102 @@ void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, List<Pai
_fill_path_renames(base_path, new_base_path, p_node, p_renames);
}
+bool SceneTreeDock::_update_node_path(const NodePath &p_root_path, NodePath &r_node_path, List<Pair<NodePath, NodePath>> *p_renames) {
+ NodePath root_path_new = p_root_path;
+ for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
+ if (p_root_path == F->get().first) {
+ root_path_new = F->get().second;
+ break;
+ }
+ }
+
+ // Goes through all paths to check if it's matching.
+ for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
+ NodePath rel_path_old = p_root_path.rel_path_to(F->get().first);
+
+ // If old path detected, then it needs to be replaced with the new one.
+ if (r_node_path == rel_path_old) {
+ NodePath rel_path_new = F->get().second;
+
+ // If not empty, get new relative path.
+ if (!rel_path_new.is_empty()) {
+ rel_path_new = root_path_new.rel_path_to(rel_path_new);
+ }
+
+ r_node_path = rel_path_new;
+ return true;
+ }
+
+ // Update the node itself if it has a valid node path and has not been deleted.
+ if (p_root_path == F->get().first && r_node_path != NodePath() && F->get().second != NodePath()) {
+ NodePath abs_path = NodePath(String(root_path_new).plus_file(r_node_path)).simplified();
+ NodePath rel_path_new = F->get().second.rel_path_to(abs_path);
+
+ r_node_path = rel_path_new;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Variant &r_variant, List<Pair<NodePath, NodePath>> *p_renames) {
+ switch (r_variant.get_type()) {
+ case Variant::NODE_PATH: {
+ NodePath node_path = r_variant;
+ if (_update_node_path(p_root_path, node_path, p_renames)) {
+ r_variant = node_path;
+ return true;
+ }
+ } break;
+
+ case Variant::ARRAY: {
+ Array a = r_variant;
+ bool updated = false;
+ for (int i = 0; i < a.size(); i++) {
+ Variant value = a[i];
+ if (_check_node_path_recursive(p_root_path, value, p_renames)) {
+ if (!updated) {
+ a = a.duplicate(); // Need to duplicate for undo-redo to work.
+ updated = true;
+ }
+ a[i] = value;
+ }
+ }
+ if (updated) {
+ r_variant = a;
+ return true;
+ }
+ } break;
+
+ case Variant::DICTIONARY: {
+ Dictionary d = r_variant;
+ bool updated = false;
+ for (int i = 0; i < d.size(); i++) {
+ Variant value = d.get_value_at_index(i);
+ if (_check_node_path_recursive(p_root_path, value, p_renames)) {
+ if (!updated) {
+ d = d.duplicate(); // Need to duplicate for undo-redo to work.
+ updated = true;
+ }
+ d[d.get_key_at_index(i)] = value;
+ }
+ }
+ if (updated) {
+ r_variant = d;
+ return true;
+ }
+ } break;
+
+ default: {
+ }
+ }
+
+ return false;
+}
+
void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodePath>> *p_renames, Map<Ref<Animation>, Set<int>> *r_rem_anims) {
Map<Ref<Animation>, Set<int>> rem_anims;
-
if (!r_rem_anims) {
r_rem_anims = &rem_anims;
}
@@ -1424,60 +1538,22 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP
return;
}
- // Renaming node paths used in script instances
- if (p_base->get_script_instance()) {
- ScriptInstance *si = p_base->get_script_instance();
-
- if (si) {
- List<PropertyInfo> properties;
- si->get_property_list(&properties);
- NodePath root_path = p_base->get_path();
-
- for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- String propertyname = E->get().name;
- Variant p = p_base->get(propertyname);
- if (p.get_type() == Variant::NODE_PATH) {
- NodePath root_path_new = root_path;
- for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
- if (root_path == F->get().first) {
- root_path_new = F->get().second;
- break;
- }
- }
-
- // Goes through all paths to check if its matching
- for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
- NodePath rel_path_old = root_path.rel_path_to(F->get().first);
-
- // if old path detected, then it needs to be replaced with the new one
- if (p == rel_path_old) {
- NodePath rel_path_new = F->get().second;
-
- // if not empty, get new relative path
- if (!rel_path_new.is_empty()) {
- rel_path_new = root_path_new.rel_path_to(F->get().second);
- }
-
- editor_data->get_undo_redo().add_do_property(p_base, propertyname, rel_path_new);
- editor_data->get_undo_redo().add_undo_property(p_base, propertyname, rel_path_old);
+ // Renaming node paths used in node properties.
+ List<PropertyInfo> properties;
+ p_base->get_property_list(&properties);
+ NodePath base_root_path = p_base->get_path();
- p_base->set(propertyname, rel_path_new);
- break;
- }
-
- // update the node itself if it has a valid node path and has not been deleted
- if (root_path == F->get().first && p != NodePath() && F->get().second != NodePath()) {
- NodePath abs_path = NodePath(String(root_path).plus_file(p)).simplified();
- NodePath rel_path_new = F->get().second.rel_path_to(abs_path);
-
- editor_data->get_undo_redo().add_do_property(p_base, propertyname, rel_path_new);
- editor_data->get_undo_redo().add_undo_property(p_base, propertyname, p);
-
- p_base->set(propertyname, rel_path_new);
- }
- }
- }
- }
+ for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ if (!(E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR))) {
+ continue;
+ }
+ String propertyname = E->get().name;
+ Variant old_variant = p_base->get(propertyname);
+ Variant updated_variant = old_variant;
+ if (_check_node_path_recursive(base_root_path, updated_variant, p_renames)) {
+ editor_data->get_undo_redo().add_do_property(p_base, propertyname, updated_variant);
+ editor_data->get_undo_redo().add_undo_property(p_base, propertyname, old_variant);
+ p_base->set(propertyname, updated_variant);
}
}
@@ -2114,7 +2190,7 @@ void SceneTreeDock::_do_create(Node *p_parent) {
ct->set_size(ms);
}
- emit_signal("node_created", c);
+ emit_signal(SNAME("node_created"), c);
}
void SceneTreeDock::_create() {
@@ -2210,7 +2286,7 @@ void SceneTreeDock::_create() {
_do_reparent(last_created, -1, nodes, true);
}
- scene_tree->get_scene_tree()->call_deferred("grab_focus");
+ scene_tree->get_scene_tree()->call_deferred(SNAME("grab_focus"));
}
void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties, bool p_remove_old) {
@@ -2457,9 +2533,51 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_
Node *node = get_node(p_to);
ERR_FAIL_COND(!node);
- int to_pos = -1;
- _normalize_drop(node, to_pos, p_type);
- _perform_instantiate_scenes(p_files, node, to_pos);
+ if (scene_tree->get_scene_tree()->get_drop_mode_flags() & Tree::DROP_MODE_INBETWEEN) {
+ // Dropped PackedScene, instance it.
+ int to_pos = -1;
+ _normalize_drop(node, to_pos, p_type);
+ _perform_instantiate_scenes(p_files, node, to_pos);
+ } else {
+ String res_path = p_files[0];
+ StringName res_type = EditorFileSystem::get_singleton()->get_file_type(res_path);
+ List<String> valid_properties;
+
+ List<PropertyInfo> pinfo;
+ node->get_property_list(&pinfo);
+
+ for (PropertyInfo &p : pinfo) {
+ if (!(p.usage & PROPERTY_USAGE_EDITOR) || !(p.usage & PROPERTY_USAGE_STORAGE) || p.hint != PROPERTY_HINT_RESOURCE_TYPE) {
+ continue;
+ }
+ Vector<String> valid_types = p.hint_string.split(",");
+
+ for (String &prop_type : valid_types) {
+ if (res_type == prop_type || ClassDB::is_parent_class(res_type, prop_type) || EditorNode::get_editor_data().script_class_is_parent(res_type, prop_type)) {
+ valid_properties.push_back(p.name);
+ break;
+ }
+ }
+ }
+
+ if (valid_properties.size() > 1) {
+ property_drop_node = node;
+ resource_drop_path = res_path;
+
+ bool capitalize = bool(EDITOR_GET("interface/inspector/capitalize_properties"));
+ menu_properties->clear();
+ for (String &p : valid_properties) {
+ menu_properties->add_item(capitalize ? p.capitalize() : p);
+ menu_properties->set_item_metadata(menu_properties->get_item_count() - 1, p);
+ }
+
+ menu_properties->set_size(Size2(1, 1));
+ menu_properties->set_position(get_screen_position() + get_local_mouse_position());
+ menu_properties->popup();
+ } else if (!valid_properties.is_empty()) {
+ _perform_property_drop(node, valid_properties[0], ResourceLoader::load(res_path));
+ }
+ }
}
void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
@@ -2541,8 +2659,8 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (!EditorNode::get_singleton()->get_edited_scene()) {
menu->clear();
if (profile_allow_editing) {
- menu->add_icon_shortcut(get_theme_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_theme_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
}
menu->set_size(Size2(1, 1));
@@ -2574,10 +2692,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_separator();
}
- menu->add_icon_shortcut(get_theme_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_theme_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
}
- menu->add_icon_shortcut(get_theme_icon("Collapse", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Collapse"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE);
menu->add_separator();
existing_script = selected->get_script();
@@ -2601,14 +2719,14 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (full_selection.size() == 1) {
add_separator = true;
- menu->add_icon_shortcut(get_theme_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
if (existing_script.is_valid()) {
- menu->add_icon_shortcut(get_theme_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ScriptExtend"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT);
}
}
if (existing_script.is_valid() && existing_script_removable) {
add_separator = true;
- menu->add_icon_shortcut(get_theme_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/detach_script"), TOOL_DETACH_SCRIPT);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/detach_script"), TOOL_DETACH_SCRIPT);
} else if (full_selection.size() > 1) {
bool script_exists = false;
for (List<Node *>::Element *E = full_selection.front(); E; E = E->next()) {
@@ -2620,7 +2738,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (script_exists) {
add_separator = true;
- menu->add_icon_shortcut(get_theme_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/detach_script"), TOOL_DETACH_SCRIPT);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/detach_script"), TOOL_DETACH_SCRIPT);
}
}
@@ -2631,7 +2749,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (profile_allow_editing) {
if (full_selection.size() == 1) {
- menu->add_icon_shortcut(get_theme_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Rename"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
}
bool can_replace = true;
@@ -2643,29 +2761,29 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
}
if (can_replace) {
- menu->add_icon_shortcut(get_theme_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
}
if (scene_tree->get_selected() != edited_scene) {
menu->add_separator();
- menu->add_icon_shortcut(get_theme_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
- menu->add_icon_shortcut(get_theme_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
- menu->add_icon_shortcut(get_theme_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
- menu->add_icon_shortcut(get_theme_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
- menu->add_icon_shortcut(get_theme_icon("ReparentToNewNode", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent_to_new_node"), TOOL_REPARENT_TO_NEW_NODE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Reparent"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ReparentToNewNode"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/reparent_to_new_node"), TOOL_REPARENT_TO_NEW_NODE);
if (selection.size() == 1) {
- menu->add_icon_shortcut(get_theme_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("NewRoot"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT);
}
}
}
if (selection.size() == 1) {
if (profile_allow_editing) {
menu->add_separator();
- menu->add_icon_shortcut(get_theme_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
+ 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("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
}
bool is_external = (selection[0]->get_filename() != "");
@@ -2677,7 +2795,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (profile_allow_editing) {
menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE);
}
- menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED);
+ menu->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED);
} else if (!is_top_level) {
menu->add_separator();
bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(selection[0]);
@@ -2687,7 +2805,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER);
menu->add_item(TTR("Make Local"), TOOL_SCENE_MAKE_LOCAL);
}
- menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN);
+ menu->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open in Editor"), TOOL_SCENE_OPEN);
if (profile_allow_editing) {
menu->set_item_checked(menu->get_item_idx_from_text(TTR("Editable Children")), editable);
menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder);
@@ -2699,14 +2817,14 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (profile_allow_editing && selection.size() > 1) {
//this is not a commonly used action, it makes no sense for it to be where it was nor always present.
menu->add_separator();
- menu->add_icon_shortcut(get_theme_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Rename"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
}
menu->add_separator();
- menu->add_icon_item(get_theme_icon("Help", "EditorIcons"), TTR("Open Documentation"), TOOL_OPEN_DOCUMENTATION);
+ menu->add_icon_item(get_theme_icon(SNAME("Help"), SNAME("EditorIcons")), TTR("Open Documentation"), TOOL_OPEN_DOCUMENTATION);
if (profile_allow_editing) {
menu->add_separator();
- menu->add_icon_shortcut(get_theme_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
}
menu->set_size(Size2(1, 1));
menu->set_position(p_menu_pos);
@@ -2848,7 +2966,7 @@ void SceneTreeDock::_remote_tree_selected() {
edit_remote->set_pressed(true);
edit_local->set_pressed(false);
- emit_signal("remote_tree_selected");
+ emit_signal(SNAME("remote_tree_selected"));
}
void SceneTreeDock::_local_tree_selected() {
@@ -3157,6 +3275,9 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
scene_tree->connect("nodes_dragged", callable_mp(this, &SceneTreeDock::_nodes_drag_begin));
scene_tree->get_scene_tree()->connect("item_double_clicked", callable_mp(this, &SceneTreeDock::_focus_node));
+ scene_tree->get_scene_tree()->connect("item_collapsed", callable_mp(this, &SceneTreeDock::_node_collapsed));
+
+ editor_selection->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed));
scene_tree->set_undo_redo(&editor_data->get_undo_redo());
scene_tree->set_editor_selection(editor_selection);
@@ -3215,6 +3336,10 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
first_enter = true;
restore_script_editor_on_drag = false;
+ menu_properties = memnew(PopupMenu);
+ add_child(menu_properties);
+ menu_properties->connect("id_pressed", callable_mp(this, &SceneTreeDock::_property_selected));
+
clear_inherit_confirm = memnew(ConfirmationDialog);
clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)"));
clear_inherit_confirm->get_ok_button()->set_text(TTR("Clear"));
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index a313337540..fd9299fb2b 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -123,8 +123,13 @@ class SceneTreeDock : public VBoxContainer {
HBoxContainer *tool_hbc;
void _tool_selected(int p_tool, bool p_confirm_override = false);
+ void _property_selected(int p_idx);
void _node_collapsed(Object *p_obj);
+ Node *property_drop_node = nullptr;
+ String resource_drop_path;
+ void _perform_property_drop(Node *p_node, String p_property, RES p_res);
+
EditorData *editor_data;
EditorSelection *editor_selection;
@@ -147,6 +152,7 @@ class SceneTreeDock : public VBoxContainer {
PopupMenu *menu;
PopupMenu *menu_subresources;
+ PopupMenu *menu_properties;
ConfirmationDialog *clear_inherit_confirm;
bool first_enter;
@@ -247,6 +253,9 @@ class SceneTreeDock : public VBoxContainer {
static SceneTreeDock *singleton;
static void _update_configuration_warning();
+ static bool _update_node_path(const NodePath &p_root_path, NodePath &r_node_path, List<Pair<NodePath, NodePath>> *p_renames);
+ static bool _check_node_path_recursive(const NodePath &p_root_path, Variant &r_variant, List<Pair<NodePath, NodePath>> *p_renames);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -258,6 +267,7 @@ public:
void _focus_node();
void import_subscene();
+ void add_root_node(Node *p_node);
void set_edited_scene(Node *p_scene);
void instantiate(const String &p_file);
void instantiate_scenes(const Vector<String> &p_files, Node *p_parent = nullptr);
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 3aa04e4dc3..c6f2c9253e 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -63,15 +63,15 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
if (p_id == BUTTON_SUBSCENE) {
if (n == get_scene_node()) {
if (n && n->get_scene_inherited_state().is_valid()) {
- emit_signal("open", n->get_scene_inherited_state()->get_path());
+ emit_signal(SNAME("open"), n->get_scene_inherited_state()->get_path());
}
} else {
- emit_signal("open", n->get_filename());
+ emit_signal(SNAME("open"), n->get_filename());
}
} else if (p_id == BUTTON_SCRIPT) {
Ref<Script> script_typed = n->get_script();
if (!script_typed.is_null()) {
- emit_signal("open_script", script_typed);
+ emit_signal(SNAME("open_script"), script_typed);
}
} else if (p_id == BUTTON_VISIBILITY) {
@@ -197,19 +197,19 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
item->set_metadata(0, p_node->get_path());
if (connect_to_script_mode) {
- Color accent = get_theme_color("accent_color", "Editor");
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
Ref<Script> script = p_node->get_script();
if (!script.is_null() && EditorNode::get_singleton()->get_object_custom_type_base(p_node) != script) {
//has script
- item->add_button(0, get_theme_icon("Script", "EditorIcons"), BUTTON_SCRIPT);
+ item->add_button(0, get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), BUTTON_SCRIPT);
} else {
//has no script (or script is a custom type)
- item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor"));
+ item->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
item->set_selectable(0, false);
if (!script.is_null()) { // make sure to mark the script if a custom type
- item->add_button(0, get_theme_icon("Script", "EditorIcons"), BUTTON_SCRIPT);
+ item->add_button(0, get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), BUTTON_SCRIPT);
item->set_button_disabled(0, item->get_button_count(0) - 1, true);
}
@@ -226,7 +226,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
}
} else if (part_of_subscene) {
if (valid_types.size() == 0) {
- item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor"));
+ item->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
}
} else if (marked.has(p_node)) {
String node_name = p_node->get_name();
@@ -235,15 +235,15 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
}
item->set_text(0, node_name);
item->set_selectable(0, marked_selectable);
- item->set_custom_color(0, get_theme_color("accent_color", "Editor"));
+ item->set_custom_color(0, get_theme_color(SNAME("accent_color"), SNAME("Editor")));
} else if (!p_node->can_process()) {
- item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor"));
+ item->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
} else if (!marked_selectable && !marked_children_selectable) {
Node *node = p_node;
while (node) {
if (marked.has(node)) {
item->set_selectable(0, false);
- item->set_custom_color(0, get_theme_color("error_color", "Editor"));
+ item->set_custom_color(0, get_theme_color(SNAME("error_color"), SNAME("Editor")));
break;
}
node = node->get_parent();
@@ -254,7 +254,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
String warning = p_node->get_configuration_warnings_as_string();
if (!warning.is_empty()) {
- item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning);
+ item->add_button(0, get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning);
}
int num_connections = p_node->get_persistent_signal_connection_count();
@@ -279,11 +279,11 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
Ref<Texture2D> icon_temp;
SceneTreeEditorButton signal_temp = BUTTON_SIGNALS;
if (num_connections >= 1 && num_groups >= 1) {
- icon_temp = get_theme_icon("SignalsAndGroups", "EditorIcons");
+ icon_temp = get_theme_icon(SNAME("SignalsAndGroups"), SNAME("EditorIcons"));
} else if (num_connections >= 1) {
- icon_temp = get_theme_icon("Signals", "EditorIcons");
+ icon_temp = get_theme_icon(SNAME("Signals"), SNAME("EditorIcons"));
} else if (num_groups >= 1) {
- icon_temp = get_theme_icon("Groups", "EditorIcons");
+ icon_temp = get_theme_icon(SNAME("Groups"), SNAME("EditorIcons"));
signal_temp = BUTTON_GROUPS;
}
@@ -293,7 +293,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
}
if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) {
- item->add_button(0, get_theme_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
+ item->add_button(0, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
String tooltip = TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path() + "\n" + TTR("Type:") + " " + p_node->get_class();
if (p_node->get_editor_description() != String()) {
@@ -302,7 +302,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
item->set_tooltip(0, tooltip);
} else if (p_node != get_scene_node() && p_node->get_filename() != "" && can_open_instance) {
- item->add_button(0, get_theme_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
+ item->add_button(0, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
String tooltip = TTR("Instance:") + " " + p_node->get_filename() + "\n" + TTR("Type:") + " " + p_node->get_class();
if (p_node->get_editor_description() != String()) {
@@ -332,7 +332,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
Ref<Script> script = p_node->get_script();
if (!script.is_null()) {
- item->add_button(0, get_theme_icon("Script", "EditorIcons"), BUTTON_SCRIPT, false, TTR("Open Script:") + " " + script->get_path());
+ item->add_button(0, get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), BUTTON_SCRIPT, false, TTR("Open Script:") + " " + script->get_path());
if (EditorNode::get_singleton()->get_object_custom_type_base(p_node) == script) {
item->set_button_color(0, item->get_button_count(0) - 1, Color(1, 1, 1, 0.5));
}
@@ -341,19 +341,19 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
if (p_node->is_class("CanvasItem")) {
bool is_locked = p_node->has_meta("_edit_lock_"); //_edit_group_
if (is_locked) {
- item->add_button(0, get_theme_icon("Lock", "EditorIcons"), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it."));
+ item->add_button(0, get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it."));
}
bool is_grouped = p_node->has_meta("_edit_group_");
if (is_grouped) {
- item->add_button(0, get_theme_icon("Group", "EditorIcons"), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable."));
+ item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable."));
}
bool v = p_node->call("is_visible");
if (v) {
- item->add_button(0, get_theme_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
+ item->add_button(0, get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
} else {
- item->add_button(0, get_theme_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
+ item->add_button(0, get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
}
if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) {
@@ -364,19 +364,19 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
} else if (p_node->is_class("Node3D")) {
bool is_locked = p_node->has_meta("_edit_lock_");
if (is_locked) {
- item->add_button(0, get_theme_icon("Lock", "EditorIcons"), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it."));
+ item->add_button(0, get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it."));
}
bool is_grouped = p_node->has_meta("_edit_group_");
if (is_grouped) {
- item->add_button(0, get_theme_icon("Group", "EditorIcons"), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable."));
+ item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable."));
}
bool v = p_node->call("is_visible");
if (v) {
- item->add_button(0, get_theme_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
+ item->add_button(0, get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
} else {
- item->add_button(0, get_theme_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
+ item->add_button(0, get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
}
if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) {
@@ -388,7 +388,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
bool is_pinned = AnimationPlayerEditor::singleton->get_player() == p_node && AnimationPlayerEditor::singleton->is_pinned();
if (is_pinned) {
- item->add_button(0, get_theme_icon("Pin", "EditorIcons"), BUTTON_PIN, false, TTR("AnimationPlayer is pinned.\nClick to unpin."));
+ item->add_button(0, get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")), BUTTON_PIN, false, TTR("AnimationPlayer is pinned.\nClick to unpin."));
}
}
}
@@ -429,7 +429,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
if (!valid) {
//item->set_selectable(0,marked_selectable);
- item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor"));
+ item->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
item->set_selectable(0, false);
}
}
@@ -475,9 +475,9 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
}
if (visible) {
- item->set_button(0, idx, get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
+ item->set_button(0, idx, get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
} else {
- item->set_button(0, idx, get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
+ item->set_button(0, idx, get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")));
}
_update_visibility_color(p_node, item);
@@ -521,12 +521,16 @@ void SceneTreeEditor::_node_removed(Node *p_node) {
if (p_node == selected) {
selected = nullptr;
- emit_signal("node_selected");
+ _emit_node_selected();
}
}
void SceneTreeEditor::_node_renamed(Node *p_node) {
- emit_signal("node_renamed");
+ if (!get_scene_node()->is_ancestor_of(p_node)) {
+ return;
+ }
+
+ emit_signal(SNAME("node_renamed"));
if (!tree_dirty) {
MessageQueue::get_singleton()->push_call(this, "_update_tree");
@@ -611,32 +615,20 @@ void SceneTreeEditor::_tree_changed() {
pending_test_update = true;
}
-void SceneTreeEditor::_selected_changed() {
- TreeItem *s = tree->get_selected();
- ERR_FAIL_COND(!s);
- NodePath np = s->get_metadata(0);
-
- Node *n = get_node(np);
-
- if (n == selected) {
- return;
- }
-
- selected = get_node(np);
-
- blocked++;
- emit_signal("node_selected");
- blocked--;
-}
-
void SceneTreeEditor::_deselect_items() {
// Clear currently selected items in scene tree dock.
if (editor_selection) {
editor_selection->clear();
- emit_signal("node_changed");
+ emit_signal(SNAME("node_changed"));
}
}
+void SceneTreeEditor::_emit_node_selected() {
+ blocked++;
+ emit_signal(SNAME("node_selected"));
+ blocked--;
+}
+
void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_selected) {
TreeItem *item = Object::cast_to<TreeItem>(p_object);
ERR_FAIL_COND(!item);
@@ -659,7 +651,14 @@ void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_
} else {
editor_selection->remove_node(n);
}
- emit_signal("node_changed");
+
+ // Selection changed to be single node, so emit "selected" (for single node) rather than "changed" (for multiple nodes)
+ if (editor_selection->get_selected_nodes().size() == 1) {
+ selected = editor_selection->get_selected_node_list()[0];
+ _emit_node_selected();
+ } else {
+ emit_signal(SNAME("node_changed"));
+ }
}
void SceneTreeEditor::_notification(int p_what) {
@@ -748,7 +747,7 @@ void SceneTreeEditor::set_selected(Node *p_node, bool p_emit_selected) {
}
if (p_emit_selected) {
- emit_signal("node_selected");
+ _emit_node_selected();
}
}
@@ -805,10 +804,10 @@ void SceneTreeEditor::_renamed() {
if (!undo_redo) {
n->set_name(new_name);
which->set_metadata(0, n->get_path());
- emit_signal("node_renamed");
+ emit_signal(SNAME("node_renamed"));
} else {
undo_redo->create_action(TTR("Rename Node"));
- emit_signal("node_prerename", n, new_name);
+ emit_signal(SNAME("node_prerename"), n, new_name);
undo_redo->add_do_method(this, "_rename_node", n->get_instance_id(), new_name);
undo_redo->add_undo_method(this, "_rename_node", n->get_instance_id(), n->get_name());
undo_redo->commit_action();
@@ -985,7 +984,7 @@ Variant SceneTreeEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from
drag_data["nodes"] = objs;
tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN | Tree::DROP_MODE_ON_ITEM);
- emit_signal("nodes_dragged");
+ emit_signal(SNAME("nodes_dragged"));
return drag_data;
}
@@ -1026,15 +1025,24 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
return true;
}
+ bool scene_drop = true;
for (int i = 0; i < files.size(); i++) {
String file = files[i];
String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
if (ftype != "PackedScene") {
- return false;
+ scene_drop = false;
+ break;
}
}
- tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN | Tree::DROP_MODE_ON_ITEM); //so it works..
+ if (scene_drop) {
+ tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN | Tree::DROP_MODE_ON_ITEM);
+ } else {
+ if (files.size() > 1) {
+ return false;
+ }
+ tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
+ }
return true;
}
@@ -1077,7 +1085,7 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (String(d["type"]) == "nodes") {
Array nodes = d["nodes"];
- emit_signal("nodes_rearranged", nodes, np, section);
+ emit_signal(SNAME("nodes_rearranged"), nodes, np, section);
}
if (String(d["type"]) == "files") {
@@ -1085,9 +1093,9 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
String ftype = EditorFileSystem::get_singleton()->get_file_type(files[0]);
if (_is_script_type(ftype)) {
- emit_signal("script_dropped", files[0], np);
+ emit_signal(SNAME("script_dropped"), files[0], np);
} else {
- emit_signal("files_dropped", files, np, section);
+ emit_signal(SNAME("files_dropped"), files, np, section);
}
}
@@ -1096,14 +1104,14 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (se) {
String sp = se->get_edited_resource()->get_path();
if (_is_script_type(EditorFileSystem::get_singleton()->get_file_type(sp))) {
- emit_signal("script_dropped", sp, np);
+ emit_signal(SNAME("script_dropped"), sp, np);
}
}
}
}
void SceneTreeEditor::_rmb_select(const Vector2 &p_pos) {
- emit_signal("rmb_pressed", tree->get_screen_transform().xform(p_pos));
+ emit_signal(SNAME("rmb_pressed"), tree->get_screen_transform().xform(p_pos));
}
void SceneTreeEditor::update_warning() {
@@ -1165,6 +1173,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
if (p_label) {
Label *label = memnew(Label);
+ label->set_theme_type_variation("HeaderSmall");
label->set_position(Point2(10, 0));
label->set_text(TTR("Scene Tree (Nodes):"));
@@ -1188,7 +1197,6 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
tree->connect("empty_tree_rmb_selected", callable_mp(this, &SceneTreeEditor::_rmb_select));
}
- tree->connect("cell_selected", callable_mp(this, &SceneTreeEditor::_selected_changed));
tree->connect("item_edited", callable_mp(this, &SceneTreeEditor::_renamed), varray(), CONNECT_DEFERRED);
tree->connect("multi_selected", callable_mp(this, &SceneTreeEditor::_cell_multi_selected));
tree->connect("button_pressed", callable_mp(this, &SceneTreeEditor::_cell_button_pressed));
@@ -1238,7 +1246,7 @@ void SceneTreeDialog::_notification(int p_what) {
} break;
case NOTIFICATION_ENTER_TREE: {
connect("confirmed", callable_mp(this, &SceneTreeDialog::_select));
- filter->set_right_icon(tree->get_theme_icon("Search", "EditorIcons"));
+ filter->set_right_icon(tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
filter->set_clear_button_enabled(true);
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -1253,7 +1261,7 @@ void SceneTreeDialog::_cancel() {
void SceneTreeDialog::_select() {
if (tree->get_selected()) {
- emit_signal("selected", tree->get_selected()->get_path());
+ emit_signal(SNAME("selected"), tree->get_selected()->get_path());
hide();
}
}
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index acd49e8d92..e833bf93e0 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -81,7 +81,6 @@ class SceneTreeEditor : public Control {
TreeItem *_find(TreeItem *p_node, const NodePath &p_path);
void _notification(int p_what);
- void _selected_changed();
void _deselect_items();
void _rename_node(ObjectID p_node, const String &p_name);
@@ -133,6 +132,8 @@ class SceneTreeEditor : public Control {
Vector<StringName> valid_types;
+ void _emit_node_selected();
+
public:
void set_filter(const String &p_filter);
String get_filter() const;
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 01743bccab..2601382009 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -40,38 +40,35 @@
#include "editor/editor_scale.h"
#include "editor_file_system.h"
-void ScriptCreateDialog::_theme_changed() {
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- String lang = ScriptServer::get_language(i)->get_type();
- Ref<Texture2D> lang_icon = gc->get_theme_icon(lang, "EditorIcons");
- if (lang_icon.is_valid()) {
- language_menu->set_item_icon(i, lang_icon);
- }
- }
-
- String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", "");
- if (!last_lang.is_empty()) {
- for (int i = 0; i < language_menu->get_item_count(); i++) {
- if (language_menu->get_item_text(i) == last_lang) {
- language_menu->select(i);
- current_language = i;
- break;
+void ScriptCreateDialog::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ String lang = ScriptServer::get_language(i)->get_type();
+ Ref<Texture2D> lang_icon = get_theme_icon(lang, SNAME("EditorIcons"));
+ if (lang_icon.is_valid()) {
+ language_menu->set_item_icon(i, lang_icon);
+ }
}
- }
- } else {
- language_menu->select(default_language);
- }
- path_button->set_icon(gc->get_theme_icon("Folder", "EditorIcons"));
- parent_browse_button->set_icon(gc->get_theme_icon("Folder", "EditorIcons"));
- parent_search_button->set_icon(gc->get_theme_icon("ClassList", "EditorIcons"));
- status_panel->add_theme_style_override("panel", gc->get_theme_stylebox("bg", "Tree"));
-}
+ String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", "");
+ if (!last_lang.is_empty()) {
+ for (int i = 0; i < language_menu->get_item_count(); i++) {
+ if (language_menu->get_item_text(i) == last_lang) {
+ language_menu->select(i);
+ current_language = i;
+ break;
+ }
+ }
+ } else {
+ language_menu->select(default_language);
+ }
-void ScriptCreateDialog::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- _theme_changed();
+ path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
+ parent_browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
+ parent_search_button->set_icon(get_theme_icon(SNAME("ClassList"), SNAME("EditorIcons")));
+ status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
} break;
}
}
@@ -329,7 +326,7 @@ void ScriptCreateDialog::_create_new() {
}
}
- emit_signal("script_created", scr);
+ emit_signal(SNAME("script_created"), scr);
hide();
}
@@ -342,7 +339,7 @@ void ScriptCreateDialog::_load_exist() {
return;
}
- emit_signal("script_created", p_script);
+ emit_signal(SNAME("script_created"), p_script);
hide();
}
@@ -451,7 +448,7 @@ void ScriptCreateDialog::_lang_changed(int l) {
override_info += ", ";
}
}
- template_menu->set_item_icon(extended.id, gc->get_theme_icon("Override", "EditorIcons"));
+ template_menu->set_item_icon(extended.id, get_theme_icon(SNAME("Override"), SNAME("EditorIcons")));
template_menu->get_popup()->set_item_tooltip(extended.id, override_info.as_string());
}
// Reselect last selected template
@@ -609,18 +606,18 @@ void ScriptCreateDialog::_path_submitted(const String &p_path) {
void ScriptCreateDialog::_msg_script_valid(bool valid, const String &p_msg) {
error_label->set_text("- " + p_msg);
if (valid) {
- error_label->add_theme_color_override("font_color", gc->get_theme_color("success_color", "Editor"));
+ error_label->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor")));
} else {
- error_label->add_theme_color_override("font_color", gc->get_theme_color("error_color", "Editor"));
+ error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
}
}
void ScriptCreateDialog::_msg_path_valid(bool valid, const String &p_msg) {
path_error_label->set_text("- " + p_msg);
if (valid) {
- path_error_label->add_theme_color_override("font_color", gc->get_theme_color("success_color", "Editor"));
+ path_error_label->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor")));
} else {
- path_error_label->add_theme_color_override("font_color", gc->get_theme_color("error_color", "Editor"));
+ path_error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
}
}
@@ -748,15 +745,11 @@ void ScriptCreateDialog::_bind_methods() {
}
ScriptCreateDialog::ScriptCreateDialog() {
- /* DIALOG */
-
/* Main Controls */
- gc = memnew(GridContainer);
+ GridContainer *gc = memnew(GridContainer);
gc->set_columns(2);
- gc->connect("theme_changed", callable_mp(this, &ScriptCreateDialog::_theme_changed));
-
/* Error Messages Field */
VBoxContainer *vb = memnew(VBoxContainer);
@@ -771,7 +764,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
builtin_warning_label->set_text(
TTR("Note: Built-in scripts have some limitations and can't be edited using an external editor."));
vb->add_child(builtin_warning_label);
- builtin_warning_label->set_autowrap(true);
+ builtin_warning_label->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
builtin_warning_label->hide();
script_name_warning_label = memnew(Label);
@@ -779,11 +772,12 @@ ScriptCreateDialog::ScriptCreateDialog() {
TTR("Warning: Having the script name be the same as a built-in type is usually not desired."));
vb->add_child(script_name_warning_label);
script_name_warning_label->add_theme_color_override("font_color", Color(1, 0.85, 0.4));
- script_name_warning_label->set_autowrap(true);
+ script_name_warning_label->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
script_name_warning_label->hide();
status_panel = memnew(PanelContainer);
status_panel->set_h_size_flags(Control::SIZE_FILL);
+ status_panel->set_v_size_flags(Control::SIZE_EXPAND_FILL);
status_panel->add_child(vb);
/* Spacing */
@@ -795,10 +789,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
vb->add_child(gc);
vb->add_child(spacing);
vb->add_child(status_panel);
- HBoxContainer *hb = memnew(HBoxContainer);
- hb->add_child(vb);
-
- add_child(hb);
+ add_child(vb);
/* Language */
@@ -827,14 +818,13 @@ ScriptCreateDialog::ScriptCreateDialog() {
base_type = "Object";
- hb = memnew(HBoxContainer);
+ HBoxContainer *hb = memnew(HBoxContainer);
hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
parent_name = memnew(LineEdit);
parent_name->connect("text_changed", callable_mp(this, &ScriptCreateDialog::_parent_name_changed));
parent_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hb->add_child(parent_name);
parent_search_button = memnew(Button);
- parent_search_button->set_flat(true);
parent_search_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_class_in_tree));
hb->add_child(parent_search_button);
parent_browse_button = memnew(Button);
@@ -894,7 +884,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
add_child(file_browse);
get_ok_button()->set_text(TTR("Create"));
alert = memnew(AcceptDialog);
- alert->get_label()->set_autowrap(true);
+ alert->get_label()->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
alert->get_label()->set_align(Label::ALIGN_CENTER);
alert->get_label()->set_valign(Label::VALIGN_CENTER);
alert->get_label()->set_custom_minimum_size(Size2(325, 60) * EDSCALE);
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index a020be0478..7c2ef1e150 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -45,7 +45,6 @@ class CreateDialog;
class ScriptCreateDialog : public ConfirmationDialog {
GDCLASS(ScriptCreateDialog, ConfirmationDialog);
- GridContainer *gc;
LineEdit *class_name;
Label *error_label;
Label *path_error_label;
@@ -127,7 +126,6 @@ class ScriptCreateDialog : public ConfirmationDialog {
void _update_dialog();
protected:
- void _theme_changed();
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index c2c99ed17f..0524b91634 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -176,15 +176,15 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
}
void EditorSettingsDialog::_update_icons() {
- search_box->set_right_icon(shortcuts->get_theme_icon("Search", "EditorIcons"));
+ search_box->set_right_icon(shortcuts->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
search_box->set_clear_button_enabled(true);
- shortcut_search_box->set_right_icon(shortcuts->get_theme_icon("Search", "EditorIcons"));
+ shortcut_search_box->set_right_icon(shortcuts->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
shortcut_search_box->set_clear_button_enabled(true);
- restart_close_button->set_icon(shortcuts->get_theme_icon("Close", "EditorIcons"));
- restart_container->add_theme_style_override("panel", shortcuts->get_theme_stylebox("bg", "Tree"));
- restart_icon->set_texture(shortcuts->get_theme_icon("StatusWarning", "EditorIcons"));
- restart_label->add_theme_color_override("font_color", shortcuts->get_theme_color("warning_color", "Editor"));
+ restart_close_button->set_icon(shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ restart_container->add_theme_style_override("panel", shortcuts->get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ restart_icon->set_texture(shortcuts->get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
+ restart_label->add_theme_color_override("font_color", shortcuts->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
}
void EditorSettingsDialog::_event_config_confirmed() {
@@ -253,8 +253,8 @@ void EditorSettingsDialog::_update_shortcuts() {
if (collapsed.has("Common")) {
common_section->set_collapsed(collapsed["Common"]);
}
- common_section->set_custom_bg_color(0, shortcuts->get_theme_color("prop_subsection", "Editor"));
- common_section->set_custom_bg_color(1, shortcuts->get_theme_color("prop_subsection", "Editor"));
+ common_section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
+ common_section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
// Get the action map for the editor, and add each item to the "Common" section.
OrderedHashMap<StringName, InputMap::Action> action_map = InputMap::get_singleton()->get_action_map();
@@ -303,16 +303,16 @@ void EditorSettingsDialog::_update_shortcuts() {
item->set_text(1, events_display_string);
if (!same_as_defaults) {
- item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), 2);
+ item->add_button(1, shortcuts->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), 2);
}
if (events_display_string == "None") {
// Fade out unassigned shortcut labels for easier visual grepping.
- item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5));
+ item->set_custom_color(1, shortcuts->get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.5));
}
- item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), 0);
- item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), 1);
+ item->add_button(1, shortcuts->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0);
+ item->add_button(1, shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")), 1);
item->set_tooltip(0, action_name);
item->set_tooltip(1, events_display_string);
item->set_metadata(0, "Common");
@@ -349,8 +349,8 @@ void EditorSettingsDialog::_update_shortcuts() {
}
sections[section_name] = section;
- section->set_custom_bg_color(0, shortcuts->get_theme_color("prop_subsection", "Editor"));
- section->set_custom_bg_color(1, shortcuts->get_theme_color("prop_subsection", "Editor"));
+ section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
+ section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
}
// Don't match unassigned shortcuts when searching for assigned keys in search results.
@@ -362,16 +362,16 @@ void EditorSettingsDialog::_update_shortcuts() {
item->set_text(1, sc->get_as_text());
if (!sc->is_shortcut(original) && !(sc->get_shortcut().is_null() && original.is_null())) {
- item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), 2);
+ item->add_button(1, shortcuts->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), 2);
}
if (sc->get_as_text() == "None") {
// Fade out unassigned shortcut labels for easier visual grepping.
- item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5));
+ item->set_custom_color(1, shortcuts->get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.5));
}
- item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), 0);
- item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), 1);
+ item->add_button(1, shortcuts->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0);
+ item->add_button(1, shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")), 1);
item->set_tooltip(0, E->get());
item->set_metadata(0, E->get());
}
@@ -426,7 +426,7 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column
if (button_idx == SHORTCUT_EDIT) {
// If editing, add a button which can be used to add an additional event.
- action_popup->add_icon_item(get_theme_icon("Add", "EditorIcons"), TTR("Add"));
+ action_popup->add_icon_item(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), TTR("Add"));
}
action_popup->set_position(get_position() + get_mouse_position());
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index 1893c6b6bb..d504d3b137 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -66,7 +66,7 @@ class ShaderGlobalsEditorInterface : public Object {
GDCLASS(ShaderGlobalsEditorInterface, Object)
void _var_changed() {
- emit_signal("var_changed");
+ emit_signal(SNAME("var_changed"));
}
protected:
@@ -84,7 +84,7 @@ protected:
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- undo_redo->create_action("Set Shader Global Variable");
+ undo_redo->create_action(TTR("Set Shader Global Variable"));
undo_redo->add_do_method(RS::get_singleton(), "global_variable_set", p_name, p_value);
undo_redo->add_undo_method(RS::get_singleton(), "global_variable_set", p_name, existing);
RS::GlobalVariableType type = RS::get_singleton()->global_variable_get_type(p_name);
@@ -110,7 +110,6 @@ protected:
undo_redo->commit_action();
block_update = false;
- print_line("all good?");
return true;
}
@@ -395,7 +394,7 @@ void ShaderGlobalsEditor::_variable_added() {
Variant value = create_var(RS::GlobalVariableType(variable_type->get_selected()));
- undo_redo->create_action("Add Shader Global Variable");
+ undo_redo->create_action(TTR("Add Shader Global Variable"));
undo_redo->add_do_method(RS::get_singleton(), "global_variable_add", var, RS::GlobalVariableType(variable_type->get_selected()), value);
undo_redo->add_undo_method(RS::get_singleton(), "global_variable_remove", var);
Dictionary gv;
@@ -410,10 +409,9 @@ void ShaderGlobalsEditor::_variable_added() {
}
void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) {
- print_line("deleted " + p_variable);
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- undo_redo->create_action("Add Shader Global Variable");
+ undo_redo->create_action(TTR("Add Shader Global Variable"));
undo_redo->add_do_method(RS::get_singleton(), "global_variable_remove", p_variable);
undo_redo->add_undo_method(RS::get_singleton(), "global_variable_add", p_variable, RS::get_singleton()->global_variable_get_type(p_variable), RS::get_singleton()->global_variable_get(p_variable));
@@ -425,7 +423,7 @@ void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) {
}
void ShaderGlobalsEditor::_changed() {
- emit_signal("globals_changed");
+ emit_signal(SNAME("globals_changed"));
if (!interface->block_update) {
interface->notify_property_list_changed();
}
@@ -439,7 +437,6 @@ void ShaderGlobalsEditor::_bind_methods() {
void ShaderGlobalsEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (is_visible_in_tree()) {
- print_line("OK load settings in globalseditor");
inspector->edit(interface);
}
}
diff --git a/editor/translations/af.po b/editor/translations/af.po
index 40669c01fb..bb7e7ca553 100644
--- a/editor/translations/af.po
+++ b/editor/translations/af.po
@@ -420,10 +420,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -472,7 +468,8 @@ msgid "Anim Move Keys"
msgstr "Anim Skuif Sleutels"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2557,7 +2554,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11989,10 +11986,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index ceeda7a037..6d8db6f47b 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -51,12 +51,13 @@
# Kareem Abduljaleel <karemjaleel34@gmail.com>, 2021.
# ILG - Game <moegypt277@gmail.com>, 2021.
# Hatim Jamal <hatimjamal8@gmail.com>, 2021.
+# HASSAN GAMER - حسن جيمر <gamerhassan55@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-07 02:12+0000\n"
-"Last-Translator: ILG - Game <moegypt277@gmail.com>\n"
+"PO-Revision-Date: 2021-07-09 14:32+0000\n"
+"Last-Translator: HASSAN GAMER - حسن جيمر <gamerhassan55@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot/ar/>\n"
"Language: ar\n"
@@ -65,7 +66,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -88,7 +89,7 @@ msgstr "مدخلات خاطئة %i (لم يتم تمريره) ÙÙŠ التعبيØ
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr "لا يمكن إستخدامه Ù†ÙØ³Ù‡ لأن الحالة ÙØ§Ø±ØºØ© (لم ÙŠÙمرر)"
+msgstr "لا يمكن استخدام self لأن النموذج ÙØ§Ø±Øº (لم يتم ادخاله)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -455,10 +456,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "مسارات الحركة يمكنها Ùقط أن تشير إلى عÙقد مشغّل الحركة."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "مشغل الحركة لا يمكنه أن يحرك Ù†ÙØ³Ù‡, Ùقط الاعبين الأخرين."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "لا يمكن Ø¥Ø¶Ø§ÙØ© مقطع جديد بدون جذر"
@@ -503,8 +500,9 @@ msgid "Anim Move Keys"
msgstr "Ù…ÙØªØ§Ø­ حركة التحريك"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Ø§Ù„Ø­Ø§ÙØ¸Ø© (Clipboard) ÙØ§Ø±ØºØ©"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Ø§Ù„Ø­Ø§ÙØ¸Ø© ÙØ§Ø±ØºØ©!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1156,7 +1154,7 @@ msgstr "شكراً من مجتمع غودوت!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "انقر للنسخ"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2531,7 +2529,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "هل تريد Ø­ÙØ¸ التغييرات للمشاهد التالية قبل الخروج؟"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"هل تود Ø­ÙØ¸ التغييرات التي اجريت على المشاهد الحالية قبل ÙØªØ­ Ù†Ø§ÙØ°Ø© ادارة "
"المشروع؟"
@@ -11996,10 +11994,6 @@ msgid "Can't copy the function node."
msgstr "لا يمكن نسخ Ø§Ù„ÙˆØ¸ÙŠÙØ© البرمجية للعÙقدة."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Ø§Ù„Ø­Ø§ÙØ¸Ø© ÙØ§Ø±ØºØ©!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "لصق عÙقد البرمجة البصرية VisualScript"
@@ -13198,6 +13192,12 @@ msgstr "يمكن تعيين المتغيرات Ùقط ÙÙŠ الذروة ."
msgid "Constants cannot be modified."
msgstr "لا يمكن تعديل الثوابت."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "مشغل الحركة لا يمكنه أن يحرك Ù†ÙØ³Ù‡, Ùقط الاعبين الأخرين."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Ø§Ù„Ø­Ø§ÙØ¸Ø© (Clipboard) ÙØ§Ø±ØºØ©"
+
#~ msgid "No"
#~ msgstr "لا"
diff --git a/editor/translations/az.po b/editor/translations/az.po
index 32efc852f8..054bc9263d 100644
--- a/editor/translations/az.po
+++ b/editor/translations/az.po
@@ -433,11 +433,6 @@ msgstr ""
"Animasiya parçaları yalnız AnimationPlayer düyünlərini işarə edə bilər."
#: editor/animation_track_editor.cpp
-#, fuzzy
-msgid "An animation player can't animate itself, only other players."
-msgstr "Animasiya pleyeri özünü canlandıra bilməz, yalnız digər pleyerlər."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Kök olmadan yeni iz əlavə etmək mümkün deyil"
@@ -483,8 +478,9 @@ msgid "Anim Move Keys"
msgstr "Animasya Köçürmə Açarları"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Panel(Clipboard) boÅŸdur"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -2480,7 +2476,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11552,10 +11548,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12576,3 +12568,10 @@ msgstr ""
#: servers/visual/shader_language.cpp
msgid "Constants cannot be modified."
msgstr ""
+
+#, fuzzy
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "Animasiya pleyeri özünü canlandıra bilməz, yalnız digər pleyerlər."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Panel(Clipboard) boÅŸdur"
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index 65a77ffd74..7bf3d40805 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -415,10 +415,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -463,7 +459,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2424,7 +2421,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11603,10 +11600,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "ПоÑтавÑне на възлите Ñ VisualScript"
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index 999d6f59d5..70a66820fb 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -415,10 +415,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨ টà§à¦°à§à¦¯à¦¾à¦•গà§à¦²à¦¿ কেবল অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à¦ªà§à¦²à§‡à¦¯à¦¼à¦¾à¦° নোডগà§à¦²à¦¿à¦¤à§‡ নিরà§à¦¦à§‡à¦¶ করতে পারে।"
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "à¦à¦•টি অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨ পà§à¦²à§‡à¦¯à¦¼à¦¾à¦° নিজেই অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦Ÿ করতে পারে না, কেবল অনà§à¦¯ পà§à¦²à§‡à§Ÿà¦¾à¦°à¥¤"
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "মূল ছাড়া নতà§à¦¨ টà§à¦°à§à¦¯à¦¾à¦• যà§à¦•à§à¦¤ করা সমà§à¦­à¦¬ নয়"
@@ -463,8 +459,10 @@ msgid "Anim Move Keys"
msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡ (Anim) চাবি/কী-সমà§à¦¹ সরান"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "কà§à¦²à§€à¦ªà¦¬à§‹à¦°à§à¦¡ খালি"
+#: modules/visual_script/visual_script_editor.cpp
+#, fuzzy
+msgid "Clipboard is empty!"
+msgstr "রিসোরà§à¦¸à§‡à¦° কà§à¦²à§€à¦ªà¦¬à§‹à¦°à§à¦¡ খালি!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2609,7 +2607,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "বনà§à¦§ করার পূরà§à¦¬à§‡ পরিবরà§à¦¤à¦¨à¦¸à¦®à§‚হ (সিন) সংরকà§à¦·à¦£ করবেন?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "পà§à¦°à¦œà§‡à¦•à§à¦Ÿ মà§à¦¯à¦¾à¦¨à§‡à¦œà¦¾à¦° ওপেন করার পূরà§à¦¬à§‡ পরিবরà§à¦¤à¦¨à¦¸à¦®à§‚হ (সিন) সংরকà§à¦·à¦£ করবেন?"
#: editor/editor_node.cpp
@@ -12737,11 +12735,6 @@ msgstr "'..' তে পরিচালনা করা সমà§à¦­à¦¬ নয়"
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
-msgid "Clipboard is empty!"
-msgstr "রিসোরà§à¦¸à§‡à¦° কà§à¦²à§€à¦ªà¦¬à§‹à¦°à§à¦¡ খালি!"
-
-#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
msgstr "নোড-সমূহ পà§à¦°à¦¤à¦¿à¦²à§‡à¦ªà¦¨/পেসà§à¦Ÿ করà§à¦¨"
@@ -13863,6 +13856,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "à¦à¦•টি অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨ পà§à¦²à§‡à¦¯à¦¼à¦¾à¦° নিজেই অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦Ÿ করতে পারে না, কেবল অনà§à¦¯ পà§à¦²à§‡à§Ÿà¦¾à¦°à¥¤"
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "কà§à¦²à§€à¦ªà¦¬à§‹à¦°à§à¦¡ খালি"
+
#, fuzzy
#~ msgid "No"
#~ msgstr "নোড"
diff --git a/editor/translations/br.po b/editor/translations/br.po
index 21e33b7372..9d1e52e009 100644
--- a/editor/translations/br.po
+++ b/editor/translations/br.po
@@ -414,12 +414,6 @@ msgstr ""
"Roudennoù Fiñvskeudenn a c'hell poentañ nemetken da skoulmoù AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Ul lennerezh fiñvskeudenn ne c'hell ket em lakaat da fiñval, nemet "
-"lennerezhioù all."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Dibosupl ouzhpenn ur roudenn nevez hep ur gwrizienn"
@@ -464,8 +458,9 @@ msgid "Anim Move Keys"
msgstr "Fiñval Alc'hwezioù Fiñvskeudenn"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Goullo ar gwask-paper"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2425,7 +2420,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11497,10 +11492,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12521,3 +12512,11 @@ msgstr ""
#: servers/visual/shader_language.cpp
msgid "Constants cannot be modified."
msgstr ""
+
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Ul lennerezh fiñvskeudenn ne c'hell ket em lakaat da fiñval, nemet "
+#~ "lennerezhioù all."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Goullo ar gwask-paper"
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index 26e9ac5a45..1032b7cdeb 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -15,12 +15,13 @@
# Carles Pastor Badosa <cpbadosa@gmail.com>, 2021.
# Roberto Pérez <djleizar@gmail.com>, 2021.
# Joel Garcia Cascalló <jocsencat@gmail.com>, 2021.
+# DFC <damiafluixacanals28@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-14 11:19+0000\n"
-"Last-Translator: Joel Garcia Cascalló <jocsencat@gmail.com>\n"
+"PO-Revision-Date: 2021-06-29 12:48+0000\n"
+"Last-Translator: DFC <damiafluixacanals28@gmail.com>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/godot-engine/"
"godot/ca/>\n"
"Language: ca\n"
@@ -28,7 +29,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.1-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -420,12 +421,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Les pistes d'Animació només poden apuntar a nodes AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Un reproductor d'Animacions no pot animar-se a si mateix, només altres "
-"reproductors."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "No es pot afegir una nova pista sense cap arrel"
@@ -471,8 +466,9 @@ msgid "Anim Move Keys"
msgstr "Mou les Claus"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "El porta-retalls és buit"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "El porta-retalls és buit!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1129,7 +1125,7 @@ msgstr "Gràcies de la part de la Comunitat del Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Fes click per a copiar."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2331,6 +2327,8 @@ msgid ""
"An error occurred while trying to save the editor layout.\n"
"Make sure the editor's user data path is writable."
msgstr ""
+"S'ha produit un error al desar el diseny de l'editor.\n"
+"Assegura't de que el directori de dades d'usuari de l'editor és editable."
#: editor/editor_node.cpp
msgid ""
@@ -2338,6 +2336,9 @@ msgid ""
"To restore the Default layout to its base settings, use the Delete Layout "
"option and delete the Default layout."
msgstr ""
+"S'ha anulat el diseny per defecte de l'editor.\n"
+"Per a restaurar el Diseny per defecte a la seva configuració base, usa la "
+"opció d'Esborrar el Diseny i esborra el Diseny per defecte."
#: editor/editor_node.cpp
msgid "Layout name not found!"
@@ -2401,7 +2402,7 @@ msgstr "No s'ha definit cap escena per executar."
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "Desar l'escena abans de executar-la..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2519,7 +2520,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Voleu Desar els canvis en les escenes següents abans de Sortir?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Desar els canvis a la(les) següent(s) escenes abans d'obrir el Gestor de "
"Projectes?"
@@ -3022,7 +3023,7 @@ msgstr "Quant a"
#: editor/editor_node.cpp
msgid "Support Godot Development"
-msgstr ""
+msgstr "Contribueix a el Desenvolupament de Godot"
#: editor/editor_node.cpp
msgid "Play the project."
@@ -3726,6 +3727,8 @@ msgstr "Estat: No s'ha pogut importar. Corregiu el fitxer i torneu a importar."
msgid ""
"Importing has been disabled for this file, so it can't be opened for editing."
msgstr ""
+"La importació s'ha desactivat per a aquest fitxer, per tant aquest no pot "
+"ser obert per a editar."
#: editor/filesystem_dock.cpp
msgid "Cannot move/rename resources root."
@@ -3772,6 +3775,12 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
+"Els fitxers o directoris següents entren en conflicte amb els elements de la "
+"ubicació de destí '%s':\n"
+"\n"
+"%s\n"
+"\n"
+"Vols reemplaçar-los?"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
@@ -4136,7 +4145,7 @@ msgstr "Carrega Valors predeterminats"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
-msgstr ""
+msgstr "Mantenir Fitxer (No Importar)"
#: editor/import_dock.cpp
msgid "%d Files"
@@ -12340,10 +12349,6 @@ msgid "Can't copy the function node."
msgstr "No es pot copiar el node de funció."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "El porta-retalls és buit!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Enganxa els Nodes de VisualScript"
@@ -13553,6 +13558,14 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Les constants no es poden modificar."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Un reproductor d'Animacions no pot animar-se a si mateix, només altres "
+#~ "reproductors."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "El porta-retalls és buit"
+
#~ msgid "No"
#~ msgstr "No"
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index 8f1e930115..3aaf91d758 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -30,8 +30,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-21 11:33+0000\n"
-"Last-Translator: swifterik <blaha.j502@gmail.com>\n"
+"PO-Revision-Date: 2021-06-25 02:57+0000\n"
+"Last-Translator: Vojtěch Šamla <auzkok@seznam.cz>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/"
"cs/>\n"
"Language: cs\n"
@@ -39,7 +39,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.1-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -431,10 +431,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Stopa animace může odkazovat pouze na uzly AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "PÅ™ehrávaÄ animace nemůže animovat sám sebe, pouze ostatní pÅ™ehrávaÄe."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Není možné přidat novou stopu bez kořenového uzlu"
@@ -479,8 +475,9 @@ msgid "Anim Move Keys"
msgstr "Animace: pÅ™esunout klíÄe"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Schránka je prázdná"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Schránka je prázdná!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2515,7 +2512,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Uložit zmÄ›ny následujících scén pÅ™ed ukonÄením?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Uložit změny následujících scén před otevřením Správce projektu?"
#: editor/editor_node.cpp
@@ -5224,11 +5221,11 @@ msgstr ""
"Ätvercové oblasti [0.0, 1.0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid ""
"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
-"Godot byl sestaven bez podpory ray tracingu, světelné mapy nelze zapéct."
+"Editor Godot byl sestaven bez podpory ray tracingu, světelné mapy nelze "
+"zapéct."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -11945,10 +11942,6 @@ msgid "Can't copy the function node."
msgstr "Nelze zkopírovat uzel funkce."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Schránka je prázdná!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Vložit VisualScript uzly"
@@ -13119,6 +13112,13 @@ msgstr "Odlišnosti mohou být přiřazeny pouze ve vertex funkci."
msgid "Constants cannot be modified."
msgstr "Konstanty není možné upravovat."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "PÅ™ehrávaÄ animace nemůže animovat sám sebe, pouze ostatní pÅ™ehrávaÄe."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Schránka je prázdná"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "Uzel InterpolatedCamera je zastaralý a bude odstraněn v Godot 4.0."
diff --git a/editor/translations/da.po b/editor/translations/da.po
index 77cd37e20b..9e09250fbc 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -434,11 +434,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animationsspor kan kun pege på AnimationPlayer noder."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"En animationsafspiller kan ikke animerer sig selv, kun andre afspillere."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Det er ikke muligt at tilføje et nyt spor uden en rod"
@@ -487,8 +482,9 @@ msgid "Anim Move Keys"
msgstr "Anim Flyt Nøgle"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Udklipsholder er tom"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2600,7 +2596,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Gem ændringer i følgende scene(r) før du afslutter?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Gem ændringer i følgende scene(r), før du åbner Projekt Manager?"
#: editor/editor_node.cpp
@@ -12267,10 +12263,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Indsæt VisualScript Nodes"
@@ -13392,6 +13384,13 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstanter kan ikke ændres."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "En animationsafspiller kan ikke animerer sig selv, kun andre afspillere."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Udklipsholder er tom"
+
#~ msgid "No"
#~ msgstr "Nej"
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 89ffa6e87c..bbf72f815b 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -69,12 +69,14 @@
# El Captian <elcaptian@posteo.me>, 2021.
# Ron Eric Hackländer <mail@roneric.net>, 2021.
# Stephan Kerbl <stephankerbl@gmail.com>, 2021.
+# Philipp Wabnitz <philipp.wabnitz@s2011.tu-chemnitz.de>, 2021.
+# jmih03 <joerni@mail.de>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-07 23:43+0000\n"
-"Last-Translator: Linux User <no-ads@mail.de>\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"Last-Translator: jmih03 <joerni@mail.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
"Language: de\n"
@@ -82,7 +84,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -473,11 +475,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animationsspuren können nur auf AnimationPlayer-Nodes zeigen."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Ein AnimationPlayer kann sich nicht selbst animieren, nur andere Objekte."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Ohne eine Wurzel kann keine neue Spur hinzugefügt werden"
@@ -524,8 +521,9 @@ msgid "Anim Move Keys"
msgstr "Schlüsselbilder bewegen"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Zwischenablage ist leer"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Zwischenablage ist leer!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1189,7 +1187,7 @@ msgstr "Die Godot-Gemeinschaft bedankt sich!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Zum kopieren klicken."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2579,7 +2577,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Änderungen in den folgenden Szenen vor dem Schließen speichern?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Änderungen in den folgenden Szenen vor dem Öffnen der Projektverwaltung "
"speichern?"
@@ -7153,7 +7151,7 @@ msgstr ""
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
-msgstr "Testhilfsprogramm"
+msgstr "Debugger"
#: editor/plugins/script_editor_plugin.cpp
msgid "Search Results"
@@ -7417,7 +7415,7 @@ msgstr "IK abspielen"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orthogonal"
-msgstr "Orthogonal"
+msgstr "Senkrecht"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Perspective"
@@ -7661,7 +7659,7 @@ msgid ""
"To zoom further, change the camera's clipping planes (View -> Settings...)"
msgstr ""
"Um weiter zoomen zu können müssen die Kameraausschnittebenen geändert werden "
-"(Anzeige -> Einstellungen… )"
+"(Ansicht -> Einstellungen… )"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -10353,7 +10351,7 @@ msgstr "Ereignis hinzufügen"
#: editor/project_settings_editor.cpp
msgid "Button"
-msgstr "Knopf"
+msgstr "Button"
#: editor/project_settings_editor.cpp
msgid "Left Button."
@@ -12108,10 +12106,6 @@ msgid "Can't copy the function node."
msgstr "Das Function-Node kann nicht kopiert werden."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Zwischenablage ist leer!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "VisualScript-Nodes einfügen"
@@ -12330,6 +12324,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Die drei Einstellungen Debug Keystore, Debug User und Debug Password müssen "
+"entweder alle angegeben, oder alle nicht angegeben sein."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12342,6 +12338,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Die drei Einstellungen Release Keystore, Release User und Release Password "
+"müssen entweder alle angegeben, oder alle nicht angegeben sein."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13342,6 +13340,13 @@ msgstr "Varyings können nur in Vertex-Funktion zugewiesen werden."
msgid "Constants cannot be modified."
msgstr "Konstanten können nicht verändert werden."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Ein AnimationPlayer kann sich nicht selbst animieren, nur andere Objekte."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Zwischenablage ist leer"
+
#~ msgid ""
#~ "Godot editor was built without ray tracing support; lightmaps can't be "
#~ "baked.\n"
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index 603b07a6d5..a0f4654639 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -396,10 +396,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -444,7 +440,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2403,7 +2400,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11475,10 +11472,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/el.po b/editor/translations/el.po
index d85918f2b2..035a82f99f 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -12,12 +12,13 @@
# lawfulRobot <czavantias@gmail.com>, 2020, 2021.
# Michalis <michalisntovas@yahoo.gr>, 2021.
# leriaz <leriaz@live.com>, 2021.
+# Shadofer <shadowrlrs@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-30 04:15+0000\n"
-"Last-Translator: lawfulRobot <czavantias@gmail.com>\n"
+"PO-Revision-Date: 2021-07-09 14:32+0000\n"
+"Last-Translator: Shadofer <shadowrlrs@gmail.com>\n"
"Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/"
"el/>\n"
"Language: el\n"
@@ -25,7 +26,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -50,8 +51,8 @@ msgstr "ΆκυÏη είσοδος %i (δεν πέÏασε) στην έκφÏασ
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
msgstr ""
-"Το self δεν μποÏεί να χÏησιμοποιηθεί επειδή το στιγμιότυπο είναι null (δεν "
-"πέÏασε)"
+"το self δεν μποÏεί να χÏησιμοποιηθεί επειδή το αντικείμενο είναι null (δέν "
+"έχει πεÏαστεί)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -421,10 +422,6 @@ msgstr ""
"Τα κομμάτια κίνησης μποÏοÏν να δείχνουν μόνο σε κόμβους AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Ένα AnimationPlayer δεν μποÏεί να κινήσει τον εαυτό του."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "ΑδÏνατη η Ï€Ïοσθήκη ÎºÎ¿Î¼Î¼Î±Ï„Î¹Î¿Ï Ï‡Ï‰Ïίς Ïίζα"
@@ -469,8 +466,9 @@ msgid "Anim Move Keys"
msgstr "Μετακίνηση Κλειδιών Κίνησης"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Το Ï€ÏόχειÏο είναι άδειο"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Το Ï€ÏόχειÏο είναι άδειο!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1131,7 +1129,7 @@ msgstr "ΕυχαÏιστίες από την κοινότητα της Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Πατήστε για αντιγÏαφή."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1634,17 +1632,16 @@ msgstr ""
"ΕνεÏγοποιήστε το 'Εισαγωγή ETC2' ή 'Εισαγωγή PVRTC' στις Ρυθμίσεις ΈÏγου."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'PVRTC' texture compression for the driver fallback "
"to GLES2.\n"
"Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback "
"Enabled'."
msgstr ""
-"Η πλατφόÏμα Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Î±Ï€Î±Î¹Ï„ÎµÎ¯ «ETC» συμπίεση υφών για εναλλαγή Î¿Î´Î·Î³Î¿Ï ÏƒÏ„Î¿ "
+"Η πλατφόÏμα Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Î±Ï€Î±Î¹Ï„ÎµÎ¯ συμπίεση υφών 'PVRTC' για εναλλαγή Î¿Î´Î·Î³Î¿Ï ÏƒÏ„Î¿ "
"GLES2.\n"
-"ΕνεÏγοποιήστε το «Import Etc» στις Ρυθμίσεις ΈÏγου, ή απενεÏγοποιήστε το "
-"«Driver Fallback Enabled»."
+"ΕνεÏγοποιήστε το 'Εισαγωγή PVRTC' στις Ρυθμίσεις ΈÏγου, ή απενεÏγοποιήστε το "
+"'ΕνεÏγοποίηση εναλλαγής οδηγοÏ'."
#: editor/editor_export.cpp platform/android/export/export.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
@@ -2523,7 +2520,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Αποθήκευση αλλαγών στις ακόλουθες σκηνές Ï€Ïιν την έξοδο;"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Αποθήκευση αλλαγών στις ακόλουθες σκηνές Ï€Ïιν το άνοιγμα του ΔιαχειÏιστή "
"ΈÏγων;"
@@ -5101,9 +5098,8 @@ msgid "Got:"
msgstr "Δοσμένο:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Failed SHA-256 hash check"
-msgstr "Η δοκιμή κατακεÏÎ¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï sha256 απέτυχε"
+msgstr "Ο έλεγχος κατακεÏÎ¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï sha256 απέτυχε"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5259,26 +5255,31 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Failed determining lightmap size. Maximum lightmap size too small?"
msgstr ""
+"Αποτυχία Ï€ÏοσδιοÏÎ¹ÏƒÎ¼Î¿Ï Ï„Î¿Ï… μεγέθους lighÏ„map. Το μέγιστο μέγεθος lightmap "
+"ίσως είναι Ï€Î¿Î»Ï Î¼Î¹ÎºÏÏŒ."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Some mesh is invalid. Make sure the UV2 channel values are contained within "
"the [0.0,1.0] square region."
msgstr ""
+"ΜέÏος του πλέγματος δεν είναι έγκυÏο. ΣιγουÏευτείτε πως οι τιμές του "
+"ÎºÎ±Î½Î±Î»Î¹Î¿Ï UV2 πεÏιλαμβάνονται στην τετÏαγωνική πεÏιοχή [0.0,1.0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
+"Ο Godot Editor φτιάχτηκε χωÏίς υποστήÏιξη ray-tracing, τα lightmaps δέν "
+"μποÏοÏν να δημιουÏγηθοÏν."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
msgstr "ΠÏοετοιμασία Lightmaps"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid "Select lightmap bake file:"
-msgstr "Επιλογή ΑÏχείου ΠÏοτÏπων"
+msgstr "Επιλογή ΑÏχείου ΠÏοτÏπων:"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5347,26 +5348,23 @@ msgstr "ΔημιουÏγία ΟÏιζοντίων και Καθέτων Οδηγ
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"
-msgstr ""
+msgstr "Θέσε τον άξονα πεÏιστÏοφής του CanvasItem \"%s\" σε (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Rotate %d CanvasItems"
-msgstr "ΠεÏιστÏοφή CanvasItem"
+msgstr "ΠεÏιστÏοφή %d CanvasItems"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Rotate CanvasItem \"%s\" to %d degrees"
-msgstr "ΠεÏιστÏοφή CanvasItem"
+msgstr "ΠεÏιστÏοφή του CanvasItem \"%s\" %d μοίÏες"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Move CanvasItem \"%s\" Anchor"
-msgstr "Μετακίνηση CanvasItem"
+msgstr "Μετακίνηση άγκυÏας του CanvasItem \"%s\""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale Node2D \"%s\" to (%s, %s)"
-msgstr ""
+msgstr "Αλλαγή μεγέθους scaling Node2D \"%s\" σε (%s, %s)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Resize Control \"%s\" to (%d, %d)"
@@ -12080,10 +12078,6 @@ msgid "Can't copy the function node."
msgstr "ΑδÏνατη η αντιγÏαφή του κόμβου συνάÏτησης."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Το Ï€ÏόχειÏο είναι άδειο!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Επικόλληση κόμβων VisualScript"
@@ -13294,6 +13288,12 @@ msgstr "Τα «varying» μποÏοÏν να ανατεθοÏν μόνο στηÎ
msgid "Constants cannot be modified."
msgstr "Οι σταθεÏές δεν μποÏοÏν να Ï„ÏοποποιηθοÏν."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "Ένα AnimationPlayer δεν μποÏεί να κινήσει τον εαυτό του."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Το Ï€ÏόχειÏο είναι άδειο"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
diff --git a/editor/translations/eo.po b/editor/translations/eo.po
index 21d94bda5e..0523742303 100644
--- a/editor/translations/eo.po
+++ b/editor/translations/eo.po
@@ -13,18 +13,19 @@
# Jakub Fabijan <animatorzPolski@gmail.com>, 2021.
# mourning20s <mourning20s@protonmail.com>, 2021.
# Manuel González <mgoopazo@gmail.com>, 2021.
+# Wang Tseryui <2251439097@qq.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2021-06-02 09:04+0000\n"
-"Last-Translator: mourning20s <mourning20s@protonmail.com>\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"Last-Translator: Wang Tseryui <2251439097@qq.com>\n"
"Language-Team: Esperanto <https://hosted.weblate.org/projects/godot-engine/"
"godot/eo/>\n"
"Language: eo\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -394,9 +395,8 @@ msgid "Rearrange Tracks"
msgstr "RearanÄi trakojn"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Transform tracks only apply to Spatial-based nodes."
-msgstr "Transformaj trakoj nur aplikas al Spatial-ajn nodojn."
+msgstr "Transformaj trakoj validas nur aplikas al Spatial-bazitaj nodoj."
#: editor/animation_track_editor.cpp
msgid ""
@@ -415,10 +415,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animaciaj trakoj nur eblas indiki al AnimationPlayer-aj nodoj."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Animado legilo ne volas animi si mem, nur aliajn ludantojn."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Ne eblas aldoni novan trakon sen radiko"
@@ -463,8 +459,9 @@ msgid "Anim Move Keys"
msgstr "Animado Movi Åœlosilojn"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Tondujo estas malplena"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1121,7 +1118,7 @@ msgstr "Dankon de la komunumo de Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Alklaku por kopii."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2510,7 +2507,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Konservi ÅanÄojn al la jena(j) sceno(j) antaÅ­ foriri?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Konservi ÅanÄojn al la jena(j) sceno(j) antaÅ­ malfermi projektan mastrumilon?"
@@ -11803,10 +11800,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12837,6 +12830,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstantoj ne povas esti modifitaj."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "Animado legilo ne volas animi si mem, nur aliajn ludantojn."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Tondujo estas malplena"
+
#~ msgid "No"
#~ msgstr "Ne"
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 660e17420d..5953536c60 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -64,12 +64,16 @@
# Juan camilo <jugarciago01@gmail.com>, 2021.
# Manuel González <mgoopazo@gmail.com>, 2021.
# softonicblip <blazeawardspace@gmail.com>, 2021.
+# Ib Quezada <ib@ibquezada.com>, 2021.
+# hiking <joaquinfc@protonmail.com>, 2021.
+# pabloggomez <pgg2733@gmail.com>, 2021.
+# Erick Figueroa <querecuto@hotmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-03 22:23+0000\n"
-"Last-Translator: softonicblip <blazeawardspace@gmail.com>\n"
+"PO-Revision-Date: 2021-07-05 21:41+0000\n"
+"Last-Translator: Erick Figueroa <querecuto@hotmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
"Language: es\n"
@@ -77,7 +81,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -103,8 +107,7 @@ msgstr "Entrada inválida %i (no aprobada) en la expresión"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr ""
-"No se puede utilizar «self» porque la instancia es nula (no transmitida)"
+msgstr "\"self\" no puede ser usado porque la instancia es nula (detenido)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -164,7 +167,7 @@ msgstr "Balanceado"
#: editor/animation_bezier_editor.cpp
msgid "Mirror"
-msgstr "Mirror"
+msgstr "Reflejar"
#: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp
msgid "Time:"
@@ -472,12 +475,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Las pistas de Animación solo pueden apuntar a nodos AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Un reproductor de animación no puede animarse a sí mismo, solo a otros "
-"reproductores."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "No es posible agregar una nueva pista sin una raíz"
@@ -525,8 +522,9 @@ msgid "Anim Move Keys"
msgstr "Mover Claves de Animación"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "El portapapeles está vacío"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "¡El portapapeles está vacío!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -869,7 +867,7 @@ msgstr "Eliminar"
#: editor/connections_dialog.cpp
msgid "Add Extra Call Argument:"
-msgstr "Añadir argumento extra de llamada:"
+msgstr "Añadir argumento de llamada extra:"
#: editor/connections_dialog.cpp
msgid "Extra Call Arguments:"
@@ -1188,7 +1186,7 @@ msgstr "¡Muchas gracias de parte de la comunidad de Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Clic para copiar."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1384,7 +1382,7 @@ msgstr "Silenciar"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr "Bypass"
+msgstr "Omitir"
#: editor/editor_audio_buses.cpp
msgid "Bus options"
@@ -2086,7 +2084,7 @@ msgstr "Propiedades de Temas"
#: editor/editor_help.cpp
msgid "Enumerations"
-msgstr "Enumerados"
+msgstr "Enumeraciones"
#: editor/editor_help.cpp
msgid "Constants"
@@ -2578,7 +2576,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "¿Guardar los cambios en las siguientes escenas antes de salir?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"¿Guardar los cambios en las siguientes escenas antes de abrir el "
"Administrador de Proyectos?"
@@ -4200,7 +4198,7 @@ msgstr "Importar como:"
#: editor/import_dock.cpp
msgid "Preset"
-msgstr "Preset"
+msgstr "Preajuste"
#: editor/import_dock.cpp
msgid "Reimport"
@@ -4929,8 +4927,8 @@ msgstr "Eliminar el nodo o transición seleccionado/a."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Toggle autoplay this animation on start, restart or seek to zero."
msgstr ""
-"Act./Desact. reproducción automática de esta animación al comenzar, "
-"reiniciar o hacer seek hasta el cero."
+"Alternar reproducción automática de esta animación al comenzar, reiniciar o "
+"poner a cero."
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Set the end animation. This is useful for sub-transitions."
@@ -5331,7 +5329,7 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
-msgstr "Bake Lightmaps"
+msgstr "Calcular Lightmaps"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Select lightmap bake file:"
@@ -6021,15 +6019,15 @@ msgstr "Flat 1"
#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
msgid "Ease In"
-msgstr "Ease In"
+msgstr "Entrada Suave"
#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
msgid "Ease Out"
-msgstr "Ease Out"
+msgstr "Salida Suave"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Smoothstep"
-msgstr "Smoothstep"
+msgstr "Suavizado"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
@@ -6081,7 +6079,7 @@ msgstr "Clic derecho para añadir punto"
#: editor/plugins/gi_probe_editor_plugin.cpp
msgid "Bake GI Probe"
-msgstr "Bake GI Probe"
+msgstr "Calcular GI Probe"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Gradient Edited"
@@ -7112,7 +7110,7 @@ msgstr "Salir de Aquí"
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Break"
-msgstr "Break"
+msgstr "Detener"
#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_editor_debugger.cpp
@@ -7243,7 +7241,7 @@ msgstr "Marcadores"
#: editor/plugins/script_text_editor.cpp
msgid "Breakpoints"
-msgstr "Breakpoints"
+msgstr "Puntos de interrupción"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
@@ -8034,7 +8032,7 @@ msgstr "Velocidad:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Loop"
-msgstr "Loop"
+msgstr "Bucle"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames:"
@@ -10546,7 +10544,7 @@ msgstr "Idiomas:"
#: editor/project_settings_editor.cpp
msgid "AutoLoad"
-msgstr "AutoLoad"
+msgstr "AutoCarga"
#: editor/project_settings_editor.cpp
msgid "Plugins"
@@ -10558,7 +10556,7 @@ msgstr "Valores de Importación por Defecto"
#: editor/property_editor.cpp
msgid "Preset..."
-msgstr "Preset..."
+msgstr "Preajuste..."
#: editor/property_editor.cpp
msgid "Zero"
@@ -10566,11 +10564,11 @@ msgstr "Cero"
#: editor/property_editor.cpp
msgid "Easing In-Out"
-msgstr "Easing In-Out"
+msgstr "Entrada-Salida Suave"
#: editor/property_editor.cpp
msgid "Easing Out-In"
-msgstr "Easing Out-In"
+msgstr "Salida-Entrada Suave"
#: editor/property_editor.cpp
msgid "File..."
@@ -11335,7 +11333,7 @@ msgstr "Fuente C++:"
#: editor/script_editor_debugger.cpp
msgid "Stack Trace"
-msgstr "Stack Trace"
+msgstr "Rastreo de Pila"
#: editor/script_editor_debugger.cpp
msgid "Errors"
@@ -11371,7 +11369,7 @@ msgstr "Fotogramas Apilados"
#: editor/script_editor_debugger.cpp
msgid "Profiler"
-msgstr "Profiler"
+msgstr "Perfilador"
#: editor/script_editor_debugger.cpp
msgid "Network Profiler"
@@ -11467,7 +11465,7 @@ msgstr "Atajos"
#: editor/settings_config_dialog.cpp
msgid "Binding"
-msgstr "Binding"
+msgstr "Vinculación"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Light Radius"
@@ -11804,7 +11802,7 @@ msgstr "Fin del reporte de la pila de excepciones"
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Bake NavMesh"
-msgstr "Bake NavMesh"
+msgstr "Calcular NavMesh"
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Clear the navigation mesh."
@@ -12106,10 +12104,6 @@ msgid "Can't copy the function node."
msgstr "No se puede copiar el nodo de función."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "¡El portapapeles está vacío!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Pegar nodos de VisualScript"
@@ -12328,6 +12322,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Deben configurarse los ajustes de Depuración de Claves, Depuración de "
+"Usuarios Y Depuración de Contraseñas O ninguno de ellos."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12339,6 +12335,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Deben configurarse los ajustes de Liberación del Almacén de Claves, "
+"Liberación del Usuario Y Liberación de la Contraseña O ninguno de ellos."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13334,6 +13332,14 @@ msgstr "Solo se pueden asignar variaciones en funciones de vértice."
msgid "Constants cannot be modified."
msgstr "Las constantes no pueden modificarse."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Un reproductor de animación no puede animarse a sí mismo, solo a otros "
+#~ "reproductores."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "El portapapeles está vacío"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index 3c3174f6c8..d1fe06a565 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -21,7 +21,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"PO-Revision-Date: 2021-06-20 13:35+0000\n"
"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
@@ -30,7 +30,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -424,12 +424,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Las pistas de Animación solo pueden apuntar a nodos AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Un reproductor de animación no puede animarse a sí mismo, solo a otros "
-"reproductores."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "No es posible agregar una nueva pista sin una raíz"
@@ -476,8 +470,9 @@ msgid "Anim Move Keys"
msgstr "Mover Claves de Anim"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "El portapapeles está vacío"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "El portapapeles está vacío!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1138,7 +1133,7 @@ msgstr "Gracias de parte de la comunidad Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Click para copiar."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2528,7 +2523,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Guardar cambios a la(s) siguiente(s) escena(s) antes de salir?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Guardar cambios a la(s) siguiente(s) escena(s) antes de abrir el Gestor de "
"Proyectos?"
@@ -12043,10 +12038,6 @@ msgid "Can't copy the function node."
msgstr "No se puede copiar el nodo de función."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "El portapapeles está vacío!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Pegar Nodos de VisualScript"
@@ -12265,6 +12256,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Deben estar configurados o bien Debug Keystore, Debug User Y Debug Password "
+"o bien ninguno de ellos."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12276,6 +12269,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Deben estar configurados o bien Release Keystore, Release User y Release "
+"Passoword o bien ninguno de ellos."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13259,6 +13254,14 @@ msgstr "Solo se pueden asignar variaciones en funciones de vértice."
msgid "Constants cannot be modified."
msgstr "Las constantes no pueden modificarse."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Un reproductor de animación no puede animarse a sí mismo, solo a otros "
+#~ "reproductores."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "El portapapeles está vacío"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamera ha sido deprecado y será eliminado en Godot 4.0."
diff --git a/editor/translations/et.po b/editor/translations/et.po
index d81e10e9d7..05a414f5a9 100644
--- a/editor/translations/et.po
+++ b/editor/translations/et.po
@@ -409,10 +409,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animatsiooni rajad võivad osutada ainult AnimationPlayer sõlmedele."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "AnimationPlayer ei saa animeerida iseennast, ainult teisi mängijaid."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Ei saa lisada uut rada ilma tüveta"
@@ -457,8 +453,9 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Lõikelaud on tühi"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2450,7 +2447,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11548,10 +11545,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12574,6 +12567,13 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstante ei saa muuta."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "AnimationPlayer ei saa animeerida iseennast, ainult teisi mängijaid."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Lõikelaud on tühi"
+
#~ msgid "Error trying to save layout!"
#~ msgstr "Viga paigutuse salvestamisel!"
diff --git a/editor/translations/eu.po b/editor/translations/eu.po
index e21c8ce5ba..87c91de10e 100644
--- a/editor/translations/eu.po
+++ b/editor/translations/eu.po
@@ -8,7 +8,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2021-06-14 12:34+0000\n"
+"PO-Revision-Date: 2021-06-20 13:35+0000\n"
"Last-Translator: Erik Zubiria <erik@ezsd.net>\n"
"Language-Team: Basque <https://hosted.weblate.org/projects/godot-engine/"
"godot/eu/>\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -259,93 +259,93 @@ msgstr "Interpolazio mota"
#: editor/animation_track_editor.cpp
msgid "Loop Wrap Mode (Interpolate end with beginning on loop)"
-msgstr ""
+msgstr "Loop Modu Bildua (bukaera interpolatu looparen hasierarekin)"
#: editor/animation_track_editor.cpp
msgid "Remove this track."
-msgstr ""
+msgstr "Pista hau ezabatu."
#: editor/animation_track_editor.cpp
msgid "Time (s): "
-msgstr ""
+msgstr "Denbora (s): "
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
-msgstr ""
+msgstr "Pista Akt./Desakt."
#: editor/animation_track_editor.cpp
msgid "Continuous"
-msgstr ""
+msgstr "Etengabea"
#: editor/animation_track_editor.cpp
msgid "Discrete"
-msgstr ""
+msgstr "Diskretua"
#: editor/animation_track_editor.cpp
msgid "Trigger"
-msgstr ""
+msgstr "Kakoa"
#: editor/animation_track_editor.cpp
msgid "Capture"
-msgstr ""
+msgstr "Kaptura"
#: editor/animation_track_editor.cpp
msgid "Nearest"
-msgstr ""
+msgstr "Gertukoena"
#: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp
#: editor/property_editor.cpp
msgid "Linear"
-msgstr ""
+msgstr "Lineal"
#: editor/animation_track_editor.cpp
msgid "Cubic"
-msgstr ""
+msgstr "Kubiko"
#: editor/animation_track_editor.cpp
msgid "Clamp Loop Interp"
-msgstr ""
+msgstr "Loop Ebakitzailearen Interp"
#: editor/animation_track_editor.cpp
msgid "Wrap Loop Interp"
-msgstr ""
+msgstr "Loop Inguratzailearen Interp"
#: editor/animation_track_editor.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Key"
-msgstr ""
+msgstr "Sartu Giltza"
#: editor/animation_track_editor.cpp
msgid "Duplicate Key(s)"
-msgstr ""
+msgstr "Bikoiztu Giltza(k)"
#: editor/animation_track_editor.cpp
msgid "Delete Key(s)"
-msgstr ""
+msgstr "Ezabatu Giltza(k)"
#: editor/animation_track_editor.cpp
msgid "Change Animation Update Mode"
-msgstr ""
+msgstr "Animazioaren Eguneraketa Modua Aldatu"
#: editor/animation_track_editor.cpp
msgid "Change Animation Interpolation Mode"
-msgstr ""
+msgstr "Animazioaren Interpolazio Modua Aldatu"
#: editor/animation_track_editor.cpp
msgid "Change Animation Loop Mode"
-msgstr ""
+msgstr "Animazioaren Loop Modua Aldatu"
#: editor/animation_track_editor.cpp
msgid "Remove Anim Track"
-msgstr ""
+msgstr "Ezabatu Animazio Pista"
#: editor/animation_track_editor.cpp
msgid "Create NEW track for %s and insert key?"
-msgstr ""
+msgstr "%s-rentzat pista berria sortu eta giltza sartu?"
#: editor/animation_track_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
-msgstr ""
+msgstr "%d pista berri sortu eta giltzak sartu?"
#: editor/animation_track_editor.cpp editor/create_dialog.cpp
#: editor/editor_audio_buses.cpp editor/editor_feature_profile.cpp
@@ -357,39 +357,41 @@ msgstr ""
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Create"
-msgstr ""
+msgstr "Sortu"
#: editor/animation_track_editor.cpp
msgid "Anim Insert"
-msgstr ""
+msgstr "Animazioa Sartu"
#: editor/animation_track_editor.cpp
msgid "AnimationPlayer can't animate itself, only other players."
-msgstr ""
+msgstr "AnimationPlayer bat ezin da norbera animatu, soilik beste playerrak."
#: editor/animation_track_editor.cpp
msgid "Anim Create & Insert"
-msgstr ""
+msgstr "Animazioa Sortu eta Txertatu"
#: editor/animation_track_editor.cpp
msgid "Anim Insert Track & Key"
-msgstr ""
+msgstr "Pista eta Animazio Giltza Sartu"
#: editor/animation_track_editor.cpp
msgid "Anim Insert Key"
-msgstr ""
+msgstr "Animazio Giltza Sartu"
#: editor/animation_track_editor.cpp
msgid "Change Animation Step"
-msgstr ""
+msgstr "Animazioaren Urratsa Aldatu"
#: editor/animation_track_editor.cpp
msgid "Rearrange Tracks"
-msgstr ""
+msgstr "Pistak Berrantolatu"
#: editor/animation_track_editor.cpp
msgid "Transform tracks only apply to Spatial-based nodes."
msgstr ""
+"Transformazio pistak Spatial-en oinarritutako nodoetan bakarrik aplikatzen "
+"dira."
#: editor/animation_track_editor.cpp
msgid ""
@@ -398,38 +400,38 @@ msgid ""
"-AudioStreamPlayer2D\n"
"-AudioStreamPlayer3D"
msgstr ""
+"Audio pistek era hontako nodoak bakarrik apunta ditzakete:\n"
+"-AudioStreamPlayer\n"
+"-AudioStreamPlayer2D\n"
+"-AudioStreamPlayer3D"
#: editor/animation_track_editor.cpp
msgid "Animation tracks can only point to AnimationPlayer nodes."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
+msgstr "Animazio pistek AnimationPlayer nodoak bakarrik apunta ditzakete."
#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
-msgstr ""
+msgstr "Ez da posiblea pista berri bat gehitzea sustrairik gabe"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Bezier-entzat pista baliogabea (ez dago azpipropietate egokirik)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
-msgstr ""
+msgstr "Gehitu Bezier Pista"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a key."
-msgstr ""
+msgstr "Pistaren bidea baliogabea da, beraz ezin da giltzarik gehitu."
#: editor/animation_track_editor.cpp
msgid "Track is not of type Spatial, can't insert key"
-msgstr ""
+msgstr "Pista ez da Spatial erakoa, ezin da giltza txertatu"
#: editor/animation_track_editor.cpp
msgid "Add Transform Track Key"
-msgstr ""
+msgstr "Gehitu Pistaren Transformazio Giltza"
#: editor/animation_track_editor.cpp
msgid "Add Track Key"
@@ -452,7 +454,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2421,7 +2424,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11516,10 +11519,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12541,3 +12540,7 @@ msgstr ""
#: servers/visual/shader_language.cpp
msgid "Constants cannot be modified."
msgstr ""
+
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Animazio irakurgailua ezin da norbera animatu, bakarrik beste batzuk."
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index ba8c4f9302..ddccfeaebe 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -20,12 +20,13 @@
# Ahmad Maftoun <CarCedo.Pro@gmail.com>, 2020.
# ItzMiad44909858f5774b6d <maidggg@gmail.com>, 2020.
# YASAN <yasandev@gmail.com>, 2021.
+# duniyal ras <duniyalr@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-03-16 10:40+0000\n"
-"Last-Translator: YASAN <yasandev@gmail.com>\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"Last-Translator: duniyal ras <duniyalr@gmail.com>\n"
"Language-Team: Persian <https://hosted.weblate.org/projects/godot-engine/"
"godot/fa/>\n"
"Language: fa\n"
@@ -33,7 +34,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.5.2-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -425,10 +426,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "آهنگ های انیمیشن Ùقط Ù…ÛŒ توانند به گره های انیمش پلیر اشاره کنند."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "یک مجری انیمیشن نمی تواند خود را محرک کند، Ùقط سایر مجریان."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "بدون ریشه اضاÙÙ‡ کردن مسیر امکان پذیر نیست"
@@ -473,8 +470,9 @@ msgid "Anim Move Keys"
msgstr "کلیدها را در انیمیشن جابجا کن"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Ø­Ø§ÙØ¸Ù‡ پنهان خالی است"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Ø­Ø§ÙØ¸Ù‡ پنهان خالی است!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1047,7 +1045,6 @@ msgid ""
msgstr "آیا پرونده‌های انتخاب شده از طرح حذ٠شوند؟ (غیر قابل بازیابی)"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -1056,7 +1053,8 @@ msgid ""
msgstr ""
"پرونده‌هایی که می‌خواهید حذ٠شوند برای منابع دیگر مورد نیاز هستند تا کار "
"کنند.\n"
-"آیا در هر صورت حذ٠شوند؟(بدون برگشت)"
+"آیا در هر صورت حذ٠شوند؟(بدون برگشت)\n"
+"شما میتوانید ÙØ§ÛŒÙ„ های حذ٠شده را در سطل زباله سیستم عامل خود بیابید ."
#: editor/dependency_editor.cpp
msgid "Cannot remove:"
@@ -1128,7 +1126,7 @@ msgstr "با تشکر از سوی جامعه‌ی Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "برای کپی کردن کلیک کنید."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1351,9 +1349,8 @@ msgid "Add Audio Bus"
msgstr "Ø§ÙØ²ÙˆØ¯Ù† کانل صوتی"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Master bus can't be deleted!"
-msgstr "استاد اتوبوس قابل حذ٠نیست!"
+msgstr "گذرگاه اصلی قابل حذ٠نیست!"
#: editor/editor_audio_buses.cpp
msgid "Delete Audio Bus"
@@ -1470,9 +1467,8 @@ msgid "Rename Autoload"
msgstr "بارگذاری خودکار را تغییر نام بده"
#: editor/editor_autoload_settings.cpp
-#, fuzzy
msgid "Toggle AutoLoad Globals"
-msgstr "تغییر حالت اتماتیک لود عمومی"
+msgstr "تغییر متغیر های عمومی مربوط به لود خودکار"
#: editor/editor_autoload_settings.cpp
msgid "Move Autoload"
@@ -2459,7 +2455,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -12111,10 +12107,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Ø­Ø§ÙØ¸Ù‡ پنهان خالی است!"
-
-#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Paste VisualScript Nodes"
msgstr "مسیر به سمت گره:"
@@ -13242,6 +13234,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "ثوابت قابل تغییر نیستند."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "یک مجری انیمیشن نمی تواند خود را محرک کند، Ùقط سایر مجریان."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Ø­Ø§ÙØ¸Ù‡ پنهان خالی است"
+
#~ msgid "No"
#~ msgstr "نه"
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index 4b7aad362e..834d1894e3 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -16,7 +16,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-19 20:16+0000\n"
+"PO-Revision-Date: 2021-06-20 13:35+0000\n"
"Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n"
"Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/"
"godot/fi/>\n"
@@ -25,7 +25,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -416,10 +416,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animaatioraidat voivat osoittaa vain AnimationPlayer solmuihin."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Animaatiotoistin ei voi animoida itseään, ainoastaan muita toistimia."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Uutta raitaa ei voida lisätä ilman juurta"
@@ -464,8 +460,9 @@ msgid "Anim Move Keys"
msgstr "Animaatio: siirrä avaimia"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Leikepöytä on tyhjä"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Leikepöytä on tyhjä!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1120,7 +1117,7 @@ msgstr "Kiitos Godot-yhteisöltä!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Napsauta kopioidaksesi."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2505,7 +2502,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Tallenetaanko muutokset seuraaviin skeneihin ennen sulkemista?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Tallennetaanko muutokset seuraaviin skeneihin ennen Projektienhallinnan "
"avaamista?"
@@ -11987,10 +11984,6 @@ msgid "Can't copy the function node."
msgstr "Ei voida kopioida funktiosolmua."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Leikepöytä on tyhjä!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Liitä VisualScript solmut"
@@ -12204,6 +12197,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Joko Debug Keystore, Debug User JA Debug Password asetukset on kaikki "
+"konfiguroitava TAI ei mitään niistä."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12215,6 +12210,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Joko Release Keystore, Release User JA Release Password asetukset on kaikki "
+"konfiguroitava TAI ei mitään niistä."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13183,6 +13180,13 @@ msgstr "Varying tyypin voi sijoittaa vain vertex-funktiossa."
msgid "Constants cannot be modified."
msgstr "Vakioita ei voi muokata."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Animaatiotoistin ei voi animoida itseään, ainoastaan muita toistimia."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Leikepöytä on tyhjä"
+
#~ msgid ""
#~ "Godot editor was built without ray tracing support; lightmaps can't be "
#~ "baked.\n"
diff --git a/editor/translations/fil.po b/editor/translations/fil.po
index 54df144dd9..892968821b 100644
--- a/editor/translations/fil.po
+++ b/editor/translations/fil.po
@@ -410,10 +410,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -458,8 +454,9 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Walang laman ang Clipboard"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2418,7 +2415,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11508,10 +11505,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12533,5 +12526,8 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Clipboard is empty"
+#~ msgstr "Walang laman ang Clipboard"
+
#~ msgid "No"
#~ msgstr "Hindi"
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index 577c44aff0..6fad70a7c2 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -73,19 +73,20 @@
# Kevin Bouancheau <kevin.bouancheau@gmail.com>, 2020.
# LaurentOngaro <laurent@gameamea.com>, 2020.
# Julien Humbert <julroy67@gmail.com>, 2020.
-# Nathan <bonnemainsnathan@gmail.com>, 2020.
+# Nathan <bonnemainsnathan@gmail.com>, 2020, 2021.
# Léo Vincent <l009.vincent@gmail.com>, 2020.
# Joseph Boudou <joseph.boudou@matabio.net>, 2020.
# Vincent Foulon <vincent.foulon80@gmail.com>, 2020.
# TechnoPorg <jonah.janzen@gmail.com>, 2021.
# ASTRALE <jules.cercy@etu.univ-lyon1.fr>, 2021.
# Julien Vanelian <julienvanelian@hotmail.com>, 2021.
+# Clément Topy <topy72.mine@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-30 23:03+0000\n"
-"Last-Translator: Julien Vanelian <julienvanelian@hotmail.com>\n"
+"PO-Revision-Date: 2021-07-01 14:33+0000\n"
+"Last-Translator: Clément Topy <topy72.mine@gmail.com>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot/fr/>\n"
"Language: fr\n"
@@ -93,7 +94,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -487,12 +488,6 @@ msgstr ""
"Les pistes d’animation ne peuvent pointer que sur des nœuds AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Un lecteur d’animation ne peut s’animer lui-même, seulement les autres "
-"lecteurs."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Impossible d’ajouter une nouvelle piste sans racine"
@@ -539,8 +534,9 @@ msgid "Anim Move Keys"
msgstr "Déplacer les clés d’animation"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Le presse-papiers est vide"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Le presse-papiers est vide !"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1203,7 +1199,7 @@ msgstr "La communauté Godot vous dit merci !"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Cliquez pour copier."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1403,7 +1399,7 @@ msgstr "Contourner"
#: editor/editor_audio_buses.cpp
msgid "Bus options"
-msgstr "Options de tranport"
+msgstr "Options de bus"
#: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp
#: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp
@@ -2596,7 +2592,7 @@ msgstr ""
"quitter ?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Enregistrer les modifications sur la (les) scène(s) suivante(s) avant "
"d'ouvrir le gestionnaire de projet ?"
@@ -3260,7 +3256,7 @@ msgstr "Ré-enregistrer"
#: editor/editor_node.cpp
msgid "New Inherited"
-msgstr "Nouveau hérité"
+msgstr "Nouvelle scène héritée"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -12145,10 +12141,6 @@ msgid "Can't copy the function node."
msgstr "Impossible de copier le nœud de fonction."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Le presse-papiers est vide !"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Coller les nœuds VisualScript"
@@ -12370,6 +12362,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Il faut configurer soit les paramètres Debug Keystore, Debug User ET Debug "
+"Password, soit aucun d'entre eux."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12382,6 +12376,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Il faut configurer soit les paramètres Release Keystore, Release User ET "
+"Release Password, soit aucun d'entre eux."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13387,6 +13383,14 @@ msgstr "Les variations ne peuvent être affectées que dans la fonction vertex."
msgid "Constants cannot be modified."
msgstr "Les constantes ne peuvent être modifiées."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Un lecteur d’animation ne peut s’animer lui-même, seulement les autres "
+#~ "lecteurs."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Le presse-papiers est vide"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamera a été déprécié et sera supprimé dans Godot 4.0."
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index e3b1137cee..8168c1a440 100644
--- a/editor/translations/ga.po
+++ b/editor/translations/ga.po
@@ -402,10 +402,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -450,7 +446,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2413,7 +2410,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11501,10 +11498,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/gl.po b/editor/translations/gl.po
index f6905f4bef..016a3ab589 100644
--- a/editor/translations/gl.po
+++ b/editor/translations/gl.po
@@ -408,12 +408,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "As pistas de animación só poden apuntar a nodos AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Un reproductor de animacións non pode animarse a si mesmo, só a outros "
-"reproductores."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Non é posible engadir unha nova pista sen unha raíz"
@@ -459,8 +453,9 @@ msgid "Anim Move Keys"
msgstr "Mover Claves de Animación"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "O portapapeis está baleiro"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "O portapapeis está baleiro!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2502,7 +2497,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Gardar os cambios nas seguintes escenas antes de saír?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Gardar os cambios nas seguintes escenas antes de abrir o Administrador de "
"Proxectos?"
@@ -11796,10 +11791,6 @@ msgid "Can't copy the function node."
msgstr "Non se pode copiar o nodo función."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "O portapapeis está baleiro!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Pegar Nodos VisualScript"
@@ -12896,3 +12887,11 @@ msgstr ""
#: servers/visual/shader_language.cpp
msgid "Constants cannot be modified."
msgstr ""
+
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Un reproductor de animacións non pode animarse a si mesmo, só a outros "
+#~ "reproductores."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "O portapapeis está baleiro"
diff --git a/editor/translations/he.po b/editor/translations/he.po
index f0e3fa4383..5dc30a6cc2 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -426,10 +426,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "רצועות הנפשה יכולות להצביע רק על ×יברי AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "נגן הנפשה ×ינו יכול להנפיש ×ת עצמו, רק ×©×—×§× ×™× ×חרי×."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "××™ ×פשר להוסיף רצועה חדשה בלי שורש"
@@ -478,8 +474,9 @@ msgid "Anim Move Keys"
msgstr "מפתחות הזזת ×נימצייה"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "לוח העתקה ריק"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "לוח העתקה ריק!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2508,7 +2505,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "לשמור ×ת ×”×©×™× ×•×™×™× ×œ×¡×¦× ×•×ª הב×ות לפני היצי××”?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "לשמור ×ת הסצנות הב×ות לפני פתיחת מנהל המיזמי×?"
#: editor/editor_node.cpp
@@ -12023,10 +12020,6 @@ msgid "Can't copy the function node."
msgstr "×œ× × ×™×ª×Ÿ להעתיק ×ת פונקצית המפרק."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "לוח העתקה ריק!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "הדבקת מפרקי VisualScript"
@@ -13165,6 +13158,12 @@ msgstr "ניתן להקצות ×©×™× ×•×™×™× ×¨×§ בפונקצית vertex."
msgid "Constants cannot be modified."
msgstr "××™ ×פשר לשנות קבועי×."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "נגן הנפשה ×ינו יכול להנפיש ×ת עצמו, רק ×©×—×§× ×™× ×חרי×."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "לוח העתקה ריק"
+
#~ msgid "No"
#~ msgstr "ל×"
diff --git a/editor/translations/hi.po b/editor/translations/hi.po
index a70f058a65..db1dcd67e6 100644
--- a/editor/translations/hi.po
+++ b/editor/translations/hi.po
@@ -417,10 +417,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "à¤à¤¨à¤¿à¤®à¥‡à¤¶à¤¨ टà¥à¤°à¥ˆà¤• केवल à¤à¤¨à¤¿à¤®à¥‡à¤¶à¤¨à¤ªà¥à¤²à¥‡à¤¯à¤° नोडà¥à¤¸ को इंगित कर सकते हैं।"
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "à¤à¤• à¤à¤¨à¥€à¤®à¥‡à¤¶à¤¨ खिलाड़ी खà¥à¤¦ को चेतन नहीं कर सकता, केवल अनà¥à¤¯ खिलाड़ी।"
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "रूट के बिना नया टà¥à¤°à¥ˆà¤• जोड़ना संभव नहीं"
@@ -465,8 +461,9 @@ msgid "Anim Move Keys"
msgstr "à¤à¤¨à¤¿à¤®à¥‡à¤Ÿà¥‡à¤¡ मूव कीज़"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡ खाली है"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2487,7 +2484,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "छोड़ने से पहले निमà¥à¤¨à¤²à¤¿à¤–ित दृशà¥à¤¯ (ओं) में परिवरà¥à¤¤à¤¨ सहेजें?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "परियोजना पà¥à¤°à¤¬à¤‚धक खोलने से पहले निमà¥à¤¨à¤²à¤¿à¤–ित दृशà¥à¤¯ (ओं) में परिवरà¥à¤¤à¤¨ सहेजें?"
#: editor/editor_node.cpp
@@ -11775,10 +11772,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12819,6 +12812,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "à¤à¤• à¤à¤¨à¥€à¤®à¥‡à¤¶à¤¨ खिलाड़ी खà¥à¤¦ को चेतन नहीं कर सकता, केवल अनà¥à¤¯ खिलाड़ी।"
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡ खाली है"
+
#~ msgid "No"
#~ msgstr "नहीं"
diff --git a/editor/translations/hr.po b/editor/translations/hr.po
index f49ba47c29..d737bb04b7 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -405,10 +405,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Animator ne može animirati sebe, samo druge objekte."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Nije moguće dodati novu stazu bez korijena"
@@ -453,8 +449,9 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Međuspremnik je prazan"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2425,7 +2422,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11527,10 +11524,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12553,6 +12546,12 @@ msgstr "Varijacije se mogu dodijeliti samo u vertex funkciji."
msgid "Constants cannot be modified."
msgstr "Konstante se ne mogu mijenjati."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "Animator ne može animirati sebe, samo druge objekte."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Međuspremnik je prazan"
+
#, fuzzy
#~ msgid "Pack File"
#~ msgstr "Otvori datoteku"
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index eda808eef4..85933dc05d 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -424,12 +424,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animáció sávok csak AnimationPlayer node-ra mutathatnak."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Egy AnimationPlayer nem tudja önmagát animálni, csak más AnimationPlayer "
-"node-okat."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Új sáv hozzáadása nem lehetséges gyökér nélkül"
@@ -474,8 +468,9 @@ msgid "Anim Move Keys"
msgstr "Animáció - Kulcsok Mozgatása"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "A vágólap üres"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2523,7 +2518,7 @@ msgstr ""
"Elmenti a következő jelenet(ek)en végzett változtatásokat kilépés előtt?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Elmenti a következő Scene(ek)en végzett változtatásokat a Projektkezelő "
"megnyitása előtt?"
@@ -11713,10 +11708,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12744,6 +12735,14 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Egy AnimationPlayer nem tudja önmagát animálni, csak más AnimationPlayer "
+#~ "node-okat."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "A vágólap üres"
+
#~ msgid "No"
#~ msgstr "Nem"
diff --git a/editor/translations/id.po b/editor/translations/id.po
index 08bfa5969d..e1029fc231 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -31,12 +31,13 @@
# Hanz <hanzhaxors@gmail.com>, 2021.
# Reza Almanda <rezaalmanda27@gmail.com>, 2021.
# Naufal Adriansyah <naufaladrn90@gmail.com>, 2021.
+# undisputedgoose <diablodvorak@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-05 14:28+0000\n"
-"Last-Translator: Naufal Adriansyah <naufaladrn90@gmail.com>\n"
+"PO-Revision-Date: 2021-07-05 14:32+0000\n"
+"Last-Translator: undisputedgoose <diablodvorak@gmail.com>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/"
"godot/id/>\n"
"Language: id\n"
@@ -44,7 +45,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.6-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -69,7 +70,7 @@ msgstr "Masukkan tidak sah %i (tidak diberikan) dalam ekspresi"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr "self tidak dapat digunakan karena instance adalah null"
+msgstr "self tidak dapat digunakan karena instansi adalah null"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -77,7 +78,7 @@ msgstr "operan salah untuk operator %s, %s dan %s."
#: core/math/expression.cpp
msgid "Invalid index of type %s for base type %s"
-msgstr "Tipe indeks %s tidak valid untuk tipe dasar %s"
+msgstr "Index tidak valid dari tipe %s untuk tipe dasar %s"
#: core/math/expression.cpp
msgid "Invalid named index '%s' for base type %s"
@@ -149,7 +150,7 @@ msgstr "Duplikat Key Terpilih"
#: editor/animation_bezier_editor.cpp
msgid "Delete Selected Key(s)"
-msgstr "Hapus Key Terpilih"
+msgstr "Hapus Kunci Terpilih"
#: editor/animation_bezier_editor.cpp
msgid "Add Bezier Point"
@@ -161,7 +162,7 @@ msgstr "Pindah Titik-titik Bezier"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Duplicate Keys"
-msgstr "Tombol Duplikat Anim"
+msgstr "Kunci Duplikat Anim"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Delete Keys"
@@ -341,7 +342,7 @@ msgstr "Interpolasi perulangan warp"
#: editor/animation_track_editor.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Key"
-msgstr "Masukkan Key"
+msgstr "Masukkan Kunci"
#: editor/animation_track_editor.cpp
msgid "Duplicate Key(s)"
@@ -437,11 +438,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Track animasi hanya bisa menunjuk ke node AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Pemutar animasi tidak bisa menganimasikan diri sendiri, hanya pemutar lain."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Tidak memungkinkan untuk menambah track baru tanpa akar"
@@ -487,8 +483,9 @@ msgid "Anim Move Keys"
msgstr "Pindahkan Kunci Anim"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Papan klip kosong"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Papan klip kosong!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -544,7 +541,7 @@ msgstr "Susun Track-track dengan node atau tampilkan sebagai daftar biasa."
#: editor/animation_track_editor.cpp
msgid "Snap:"
-msgstr "Pengancingan:"
+msgstr "Snap:"
#: editor/animation_track_editor.cpp
msgid "Animation step value."
@@ -676,7 +673,7 @@ msgstr "Pilih Trek untuk Disalin"
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
-msgstr "Kopy"
+msgstr "Salin"
#: editor/animation_track_editor.cpp
msgid "Select All/None"
@@ -769,7 +766,7 @@ msgstr "Perkecil Pandangan"
#: editor/code_editor.cpp
msgid "Reset Zoom"
-msgstr "Kebalikan Semula Pandangan"
+msgstr "Kembalikan Semula Pandangan"
#: editor/code_editor.cpp
msgid "Warnings"
@@ -1128,7 +1125,7 @@ msgstr "Memiliki"
#: editor/dependency_editor.cpp
msgid "Resources Without Explicit Ownership:"
-msgstr "Resource Tanpa Kepemilikan yang Jelas:"
+msgstr "Sumber Tanpa Kepemilikan yang Jelas:"
#: editor/dictionary_property_edit.cpp
msgid "Change Dictionary Key"
@@ -1144,7 +1141,7 @@ msgstr "Terimakasih dari komunitas Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Klik untuk salin."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1373,7 +1370,7 @@ msgstr "Master Bus tidak dapat dihapus!"
#: editor/editor_audio_buses.cpp
msgid "Delete Audio Bus"
-msgstr "Hapus Bus Audio"
+msgstr "Hapus Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Duplicate Audio Bus"
@@ -1507,7 +1504,7 @@ msgstr "Mengatur kembali Autoload-autoload"
#: editor/editor_autoload_settings.cpp
msgid "Can't add autoload:"
-msgstr "Tidak dapat menambahkan autoload:"
+msgstr "Tidak dapat menambahkan autoload"
#: editor/editor_autoload_settings.cpp
msgid "Add AutoLoad"
@@ -2526,7 +2523,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Simpan perubahan skena saat ini sebelum keluar?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Simpan perubahan skena saat ini sebelum membuka Manajer Proyek?"
#: editor/editor_node.cpp
@@ -2565,7 +2562,6 @@ msgid "Unable to load addon script from path: '%s'."
msgstr "Tidak bisa memuat script addon dari lokasi: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
"error in that script.\n"
@@ -3016,7 +3012,7 @@ msgstr "Tentang"
#: editor/editor_node.cpp
msgid "Support Godot Development"
-msgstr ""
+msgstr "Dukung pengembangan Godot"
#: editor/editor_node.cpp
msgid "Play the project."
@@ -7534,31 +7530,31 @@ msgstr "Tidak tersedia ketika menggunakan perender GLES2."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
-msgstr "TampilanBebas Kiri"
+msgstr "Tampilan Bebas Kiri"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Right"
-msgstr "TampilanBebas Kanan"
+msgstr "Tampilan Bebas Kanan"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Forward"
-msgstr "TampilanBebas Maju"
+msgstr "Tampilan Bebas Maju"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Backwards"
-msgstr "TampilanBebas Mundur"
+msgstr "Tampilan Bebas Mundur"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Up"
-msgstr "TampilanBebas Atas"
+msgstr "Tampilan Bebas Atas"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Down"
-msgstr "TampilanBebas Bawah"
+msgstr "Tampilan Bebas Bawah"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Speed Modifier"
-msgstr "Pengubah Kecepatan TampilanBebas"
+msgstr "Pengubah Kecepatan Tampilan Bebas"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Slow Modifier"
@@ -7569,9 +7565,12 @@ msgid "View Rotation Locked"
msgstr "Rotasi Tampilan Terkunci"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid ""
"To zoom further, change the camera's clipping planes (View -> Settings...)"
msgstr ""
+"Untuk memperbesar lebih jauh, ganti kamera clipping planes (Tinjau -> "
+"Setelan...)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -7657,11 +7656,11 @@ msgstr "Beralih Tampilan Ortogonal/Perspektif"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Insert Animation Key"
-msgstr "Sisipkan Kunci Animasi"
+msgstr "Masukkan Kunci Animasi"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Focus Origin"
-msgstr "Asal Fokus"
+msgstr "Fokus asal"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Focus Selection"
@@ -7669,7 +7668,7 @@ msgstr "Pemilihan Fokus"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Toggle Freelook"
-msgstr "Jungkitkan Mode Tampilan Bebas"
+msgstr "Aktifkan Mode Tampilan Bebas"
#: editor/plugins/spatial_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
@@ -7678,7 +7677,7 @@ msgstr "Transformasi"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Snap Object to Floor"
-msgstr "Kancingkan Objek ke Lantai"
+msgstr "Tempelkan Objek ke Lantai"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Dialog..."
@@ -12008,10 +12007,6 @@ msgid "Can't copy the function node."
msgstr "Tidak dapat menyalin node fungsi."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Papan klip kosong!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Rekatkan Node VisualScript"
@@ -13210,6 +13205,14 @@ msgstr "Variasi hanya bisa ditetapkan dalam fungsi vertex."
msgid "Constants cannot be modified."
msgstr "Konstanta tidak dapat dimodifikasi."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Pemutar animasi tidak bisa menganimasikan diri sendiri, hanya pemutar "
+#~ "lain."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Papan klip kosong"
+
#~ msgid "No"
#~ msgstr "Tidak"
diff --git a/editor/translations/is.po b/editor/translations/is.po
index 72472c2215..fc1423d841 100644
--- a/editor/translations/is.po
+++ b/editor/translations/is.po
@@ -426,10 +426,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -478,7 +474,8 @@ msgid "Anim Move Keys"
msgstr "Færa lykla af Anim"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2449,7 +2446,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Vista breytingar á neðangreindum senu(m) áður en Verkefna Stjóri er opnaður?"
@@ -11628,10 +11625,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/it.po b/editor/translations/it.po
index 3d0509ba15..60c362c63a 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -464,10 +464,6 @@ msgstr ""
"Le tracce di animazioni possono puntare solo a nodi di tipo AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Un AnimationPlayer non può animare se stesso, solo altri riproduttori."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Non è possibile aggiungere una nuova traccia senza un nodo radice"
@@ -515,8 +511,9 @@ msgid "Anim Move Keys"
msgstr "Sposta delle chiavi d'animazione"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Gli appunti sono vuoti"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Gli appunti sono vuoti!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2578,7 +2575,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Salvare le modifiche alle scene seguenti prima di uscire?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Salvare le modifiche alle scene seguenti prima di aprire il gestore di "
"progetti?"
@@ -12146,10 +12143,6 @@ msgid "Can't copy the function node."
msgstr "Non è possibile copiare il nodo della funzione."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Gli appunti sono vuoti!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Incolla Nodi VisualScript"
@@ -13371,6 +13364,13 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Le constanti non possono essere modificate."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Un AnimationPlayer non può animare se stesso, solo altri riproduttori."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Gli appunti sono vuoti"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 85768d721a..1fd770fe13 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -439,12 +439,6 @@ msgstr ""
"アニメーショントラックã¯ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãƒ—レイヤーノードã®ã¿æŒ‡å®šã§ãã¾ã™ã€‚"
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"アニメーションプレーヤーã¯ä»–ã®ãƒ—レーヤーã ã‘ã«ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’é©ç”¨ã™ã‚‹ã“ã¨ã¯"
-"ã§ãã¾ã›ã‚“。"
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "root ãŒç„¡ã‘ã‚Œã°æ–°è¦ãƒˆãƒ©ãƒƒã‚¯ã¯è¿½åŠ ã§ãã¾ã›ã‚“"
@@ -489,8 +483,9 @@ msgid "Anim Move Keys"
msgstr "アニメーションキーã®ç§»å‹•"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "クリップボードãŒç©ºã§ã™"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "クリップボードã¯ç©ºã§ã™!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2530,7 +2525,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "終了ã™ã‚‹å‰ã«ã€ä»¥ä¸‹ã®ã‚·ãƒ¼ãƒ³ã¸ã®å¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"プロジェクトマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã‚’é–‹ãå‰ã«ã€ä»¥ä¸‹ã®ã‚·ãƒ¼ãƒ³ã¸ã®å¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ"
@@ -11994,10 +11989,6 @@ msgid "Can't copy the function node."
msgstr "ファンクションノードをコピーã§ãã¾ã›ã‚“。"
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "クリップボードã¯ç©ºã§ã™!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "VisualScriptノードを貼り付ã‘"
@@ -13182,6 +13173,14 @@ msgstr "Varying変数ã¯é ‚点関数ã«ã®ã¿å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã
msgid "Constants cannot be modified."
msgstr "定数ã¯å¤‰æ›´ã§ãã¾ã›ã‚“。"
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "アニメーションプレーヤーã¯ä»–ã®ãƒ—レーヤーã ã‘ã«ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’é©ç”¨ã™ã‚‹ã“ã¨"
+#~ "ã¯ã§ãã¾ã›ã‚“。"
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "クリップボードãŒç©ºã§ã™"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamera ã¯å»ƒæ­¢äºˆå®šã§ã‚りã€Godot 4.0ã§é™¤åŽ»ã•れã¾ã™ã€‚"
diff --git a/editor/translations/ka.po b/editor/translations/ka.po
index ce5c6dc032..587624651a 100644
--- a/editor/translations/ka.po
+++ b/editor/translations/ka.po
@@ -436,10 +436,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "შეუძლებელირდáƒáƒáƒ›áƒáƒ¢áƒ áƒáƒ®áƒáƒšáƒ˜ ჩáƒáƒœáƒáƒ¬áƒ”რი ფესვის გáƒáƒ áƒ”შე"
@@ -491,9 +487,9 @@ msgid "Anim Move Keys"
msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ¡áƒáƒ¦áƒ”ბების გáƒáƒ“áƒáƒáƒ“გილებáƒ"
#: editor/animation_track_editor.cpp
-#, fuzzy
-msgid "Clipboard is empty"
-msgstr "ბუფერი ცáƒáƒ áƒ˜áƒ”ლიáƒ"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2529,7 +2525,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11863,10 +11859,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12909,6 +12901,10 @@ msgid "Constants cannot be modified."
msgstr ""
#, fuzzy
+#~ msgid "Clipboard is empty"
+#~ msgstr "ბუფერი ცáƒáƒ áƒ˜áƒ”ლიáƒ"
+
+#, fuzzy
#~ msgid "Add initial export..."
#~ msgstr "სáƒáƒ§áƒ•áƒáƒ áƒšáƒ”ბი:"
diff --git a/editor/translations/km.po b/editor/translations/km.po
index ee77bab308..fe396cf590 100644
--- a/editor/translations/km.po
+++ b/editor/translations/km.po
@@ -402,10 +402,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -450,7 +446,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2409,7 +2406,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11481,10 +11478,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index f2f3ac1562..ec9fed24ca 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -27,8 +27,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-11 14:49+0000\n"
-"Last-Translator: Postive_ Cloud <postive12@gmail.com>\n"
+"PO-Revision-Date: 2021-06-20 13:35+0000\n"
+"Last-Translator: Myeongjin Lee <aranet100@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot/ko/>\n"
"Language: ko\n"
@@ -36,7 +36,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -429,12 +429,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "애니메ì´ì…˜ íŠ¸ëž™ì€ ì˜¤ì§ AnimationPlayer 노드만 가리킬 수 있습니다."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"애니메ì´ì…˜ 플레ì´ì–´ëŠ” ìžì‹ ì´ 아닌 다른 플레ì´ì–´ì—ë§Œ 애니메ì´ì…˜ì„ 부여할 수 있"
-"습니다."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "루트 ì—†ì´ ìƒˆ íŠ¸ëž™ì„ ì¶”ê°€í•  수 ì—†ìŒ"
@@ -479,8 +473,9 @@ msgid "Anim Move Keys"
msgstr "애니메ì´ì…˜ 키 ì´ë™"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "í´ë¦½ë³´ë“œê°€ 비었ìŒ"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "í´ë¦½ë³´ë“œê°€ 비었습니다!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1134,7 +1129,7 @@ msgstr "Godot 커뮤니티ì—서 ê°ì‚¬ë“œë¦½ë‹ˆë‹¤!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "í´ë¦­í•˜ì—¬ 복사합니다."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2510,7 +2505,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "ë„기 ì „ì— í•´ë‹¹ ì”¬ì˜ ë³€ê²½ ì‚¬í•­ì„ ì €ìž¥í• ê¹Œìš”?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "프로ì íЏ 매니저를 열기 ì „ì— í•´ë‹¹ ì”¬ì˜ ë³€ê²½ ì‚¬í•­ì„ ì €ìž¥í• ê¹Œìš”?"
#: editor/editor_node.cpp
@@ -11908,10 +11903,6 @@ msgid "Can't copy the function node."
msgstr "함수 노드를 복사할 수 없습니다."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "í´ë¦½ë³´ë“œê°€ 비었습니다!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "비주얼 스í¬ë¦½íЏ 노드 붙여넣기"
@@ -12124,6 +12115,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Debug Keystore, Debug User ë° Debug Password ì„¤ì •ì„ êµ¬ì„±í•˜ê±°ë‚˜ ê·¸ 중 ì–´ëŠ ê²ƒ"
+"ë„ ì—†ì–´ì•¼ 합니다."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12134,6 +12127,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Release Keystore, Release User ë° Release Password ì„¤ì •ì„ êµ¬ì„±í•˜ê±°ë‚˜ ê·¸ 중 ì–´"
+"ëŠ ê²ƒë„ ì—†ì–´ì•¼ 합니다."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13067,6 +13062,14 @@ msgstr "Varyingì€ ê¼­ì§“ì  í•¨ìˆ˜ì—ë§Œ 지정할 수 있습니다."
msgid "Constants cannot be modified."
msgstr "ìƒìˆ˜ëŠ” 수정할 수 없습니다."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "애니메ì´ì…˜ 플레ì´ì–´ëŠ” ìžì‹ ì´ 아닌 다른 플레ì´ì–´ì—ë§Œ 애니메ì´ì…˜ì„ 부여할 "
+#~ "수 있습니다."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "í´ë¦½ë³´ë“œê°€ 비었ìŒ"
+
#~ msgid ""
#~ "Godot editor was built without ray tracing support; lightmaps can't be "
#~ "baked.\n"
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
index d4520d2d76..6df1f44cfb 100644
--- a/editor/translations/lt.po
+++ b/editor/translations/lt.po
@@ -418,10 +418,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animacijos įrašai gali nurodyti į AnimacijosGrotuvo mazgus."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Animacijos grotuvas negali animuoti savęs, tik kitus grotuvus."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Nėra galimybės pridėti naują įrašą be root"
@@ -467,7 +463,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2481,7 +2478,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11833,10 +11830,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12880,6 +12873,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "Animacijos grotuvas negali animuoti savęs, tik kitus grotuvus."
+
#, fuzzy
#~ msgid "Add initial export..."
#~ msgstr "MÄ—gstamiausi:"
diff --git a/editor/translations/lv.po b/editor/translations/lv.po
index 360b8bcb8f..8c8a0011c7 100644
--- a/editor/translations/lv.po
+++ b/editor/translations/lv.po
@@ -413,10 +413,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "AnimÄcijas celiņi var norÄdÄ«t tikai uz AnimationPlayer mezgliem."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "AnimÄcijas atskaņotÄjs nevar animÄ“t pats sevi, tikai citi spÄ“lÄ“tÄji."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Nevar izveidot jaunu celiņu bez saknes"
@@ -461,8 +457,9 @@ msgid "Anim Move Keys"
msgstr "Anim PÄrvietot AtslÄ“gas"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Starpliktuve ir tukša"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2455,7 +2452,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11641,10 +11638,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12677,6 +12670,13 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "AnimÄcijas atskaņotÄjs nevar animÄ“t pats sevi, tikai citi spÄ“lÄ“tÄji."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Starpliktuve ir tukša"
+
#~ msgid "Add initial export..."
#~ msgstr "Pievienot sÄkuma eksportu..."
diff --git a/editor/translations/mi.po b/editor/translations/mi.po
index 17b666c0e6..36a93be0ee 100644
--- a/editor/translations/mi.po
+++ b/editor/translations/mi.po
@@ -394,10 +394,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -442,7 +438,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2401,7 +2398,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11473,10 +11470,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/mk.po b/editor/translations/mk.po
index 0443bd589e..7e5aa06f3c 100644
--- a/editor/translations/mk.po
+++ b/editor/translations/mk.po
@@ -401,10 +401,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -449,7 +445,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2408,7 +2405,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11480,10 +11477,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/ml.po b/editor/translations/ml.po
index a25540d2cd..3919011ade 100644
--- a/editor/translations/ml.po
+++ b/editor/translations/ml.po
@@ -404,10 +404,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -452,7 +448,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2413,7 +2410,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11490,10 +11487,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/mr.po b/editor/translations/mr.po
index 7e6f8f5cc5..4d81595cb1 100644
--- a/editor/translations/mr.po
+++ b/editor/translations/mr.po
@@ -401,10 +401,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -449,7 +445,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2408,7 +2405,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11481,10 +11478,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/ms.po b/editor/translations/ms.po
index 82a4443b24..6226d644a3 100644
--- a/editor/translations/ms.po
+++ b/editor/translations/ms.po
@@ -413,11 +413,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Trek animasi hanya dapat ditujukan kepada nod AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Pemain animasi tidak boleh animasikan dirinya sendiri, hanya pemain lain."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Tidak boleh menambah trek baru tanpa satu akar"
@@ -462,8 +457,9 @@ msgid "Anim Move Keys"
msgstr "Kunci Gerak Anim"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Papan klip kosong"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2514,7 +2510,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Simpan perubahan pada adegan berikut sebelum keluar?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Simpan perubahan adegan berikut sebelum membuka Pengurus Projek?"
#: editor/editor_node.cpp
@@ -11864,10 +11860,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12889,6 +12881,13 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Pemain animasi tidak boleh animasikan dirinya sendiri, hanya pemain lain."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Papan klip kosong"
+
#~ msgid "No"
#~ msgstr "Tidak"
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index f040c4ca0e..042ee8d26f 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -422,11 +422,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animasjonsspor kan kun peke på AnimationPlayer-noder."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"En animansjonsavspiller kan ikke animere seg selv, kun andre avspillere."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Ikke mulig å legge til et nytt spor uten en rot"
@@ -471,8 +466,9 @@ msgid "Anim Move Keys"
msgstr "Anim Flytt Nøkler"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Utklippstavlen er tom"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Utklippsbordet er tomt!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2600,7 +2596,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Lagre endring til følgende scene(r) før avslutting?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Lagre endringer til følgende scene(r) før åpning av Prosjekt-Manager?"
#: editor/editor_node.cpp
@@ -12364,10 +12360,6 @@ msgid "Can't copy the function node."
msgstr "Kan ikke kopiere funksjonsnoden."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Utklippsbordet er tomt!"
-
-#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Paste VisualScript Nodes"
msgstr "Lim inn Noder"
@@ -13420,6 +13412,13 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstanter kan ikke endres."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "En animansjonsavspiller kan ikke animere seg selv, kun andre avspillere."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Utklippstavlen er tom"
+
#~ msgid "No"
#~ msgstr "Nei"
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index 616c3ae69a..2410cd5ad0 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -451,10 +451,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animatiesporen kunnen alleen verwijzen naar AnimatiePlayer-knopen."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Een animatiespeler kan zichzelf niet animeren, alleen andere spelers."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Niet mogelijk om een nieuwe track toe te voegen zonder een root"
@@ -499,8 +495,9 @@ msgid "Anim Move Keys"
msgstr "Anim Verplaats Keys"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Klembord is leeg"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Plakbord is leeg!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2550,7 +2547,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Wijzigen aan de volgende scène(s) opslaan voor het afsluiten?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Wijzigen aan de volgende scène(s) opslaan voor het openen van Projectbeheer?"
@@ -12047,10 +12044,6 @@ msgid "Can't copy the function node."
msgstr "Kan het functieknoop niet kopiëren."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Plakbord is leeg!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Plak VisualScipt knoopen"
@@ -13237,6 +13230,13 @@ msgstr "Varyings kunnen alleen worden toegewezenin vertex functies."
msgid "Constants cannot be modified."
msgstr "Constanten kunnen niet worden aangepast."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Een animatiespeler kan zichzelf niet animeren, alleen andere spelers."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Klembord is leeg"
+
#~ msgid "No"
#~ msgstr "Nee"
diff --git a/editor/translations/or.po b/editor/translations/or.po
index 58214daf10..87528cdac5 100644
--- a/editor/translations/or.po
+++ b/editor/translations/or.po
@@ -400,10 +400,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -448,7 +444,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2407,7 +2404,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11479,10 +11476,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index 9ae69c3d75..3c51593e02 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -17,7 +17,7 @@
# Maksymilian Świąć <maksymilian.swiac@gmail.com>, 2017-2018.
# Mietek Szcześniak <ravaging@go2.pl>, 2016.
# NeverK <neverkoxu@gmail.com>, 2018, 2019, 2020.
-# Rafal Brozio <rafal.brozio@gmail.com>, 2016, 2019, 2020.
+# Rafal Brozio <rafal.brozio@gmail.com>, 2016, 2019, 2020, 2021.
# Rafał Ziemniak <synaptykq@gmail.com>, 2017.
# RM <synaptykq@gmail.com>, 2018, 2020.
# Sebastian Krzyszkowiak <dos@dosowisko.net>, 2017.
@@ -52,8 +52,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-19 20:16+0000\n"
-"Last-Translator: Tomek <kobewi4e@gmail.com>\n"
+"PO-Revision-Date: 2021-07-05 14:32+0000\n"
+"Last-Translator: Rafal Brozio <rafal.brozio@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
"Language: pl\n"
@@ -62,7 +62,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -86,7 +86,7 @@ msgstr "Niewłaściwe dane %i (nie przekazane) w wyrażeniu"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
msgstr ""
-"self nie może być użyte, ponieważ instancja jest nullem (nie przekazano)"
+"self nie może zostać użyte, ponieważ instancja jest nullem (nie przekazana)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -454,11 +454,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Ścieżki animacji mogą wskazywać tylko na węzły AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"AnimationPlayer nie może animować sam siebie, tylko inne węzły tego typu."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Nie da się dodać nowej ścieżki bez korzenia"
@@ -503,8 +498,9 @@ msgid "Anim Move Keys"
msgstr "Przemieść klucze animacji"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Schowek jest pusty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Schowek jest pusty!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1159,7 +1155,7 @@ msgstr "Podziękowania od społeczności Godota!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Kliknij, by skopiować."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2538,7 +2534,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Czy zapisać zmiany w aktualnej scenie/scenach przed wyjściem?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Zapisać zmiany w następujących scenach przed otwarciem menedżera projektów?"
@@ -4700,7 +4696,7 @@ msgstr "Otwórz w inspektorze"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Display list of animations in player."
-msgstr "Wyświetl listę animacji w odtwarzaczu."
+msgstr "Pokaż listę animacji w odtwarzaczu."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Autoplay on Load"
@@ -12019,10 +12015,6 @@ msgid "Can't copy the function node."
msgstr "Nie można skopiować węzła funkcji."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Schowek jest pusty!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Wklej węzeł VisualScript"
@@ -12236,6 +12228,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Albo ustawienia Debug Keystore, Debug User ORAZ Debug Password muszą być "
+"skonfigurowane, ALBO żadne z nich."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12248,6 +12242,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Albo ustawienia Release Keystore, Release User ORAZ Release Password muszÄ… "
+"być skonfigurowane, ALBO żadne z nich."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13219,6 +13215,13 @@ msgstr "Varying może być przypisane tylko w funkcji wierzchołków."
msgid "Constants cannot be modified."
msgstr "Stałe nie mogą być modyfikowane."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "AnimationPlayer nie może animować sam siebie, tylko inne węzły tego typu."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Schowek jest pusty"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index e308deb01b..675c9cf506 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -427,10 +427,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -476,7 +472,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2487,7 +2484,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11907,10 +11904,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Paste VisualScript Nodes"
msgstr "Paste yer Node"
diff --git a/editor/translations/pt.po b/editor/translations/pt.po
index d2db134026..17b1861821 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -18,12 +18,13 @@
# Manuela Silva <mmsrs@sky.com>, 2020.
# Murilo Gama <murilovsky2030@gmail.com>, 2020.
# Ricardo Subtil <ricasubtil@gmail.com>, 2020.
+# André Silva <andre.olivais@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-18 14:51+0000\n"
-"Last-Translator: João Lopes <linux-man@hotmail.com>\n"
+"PO-Revision-Date: 2021-07-03 10:33+0000\n"
+"Last-Translator: André Silva <andre.olivais@gmail.com>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot/pt/>\n"
"Language: pt\n"
@@ -31,7 +32,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -424,12 +425,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Pistas de Animação só podem apontar a nós AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Um reprodutor de animação não se pode animar a ele próprio, apenas a outros "
-"reprodutores."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Não é possível adicionar nova pista sem uma raiz"
@@ -474,8 +469,9 @@ msgid "Anim Move Keys"
msgstr "Anim Mover Chaves"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Ãrea de Transferência está vazia"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Ãrea de Transferência está vazia!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1132,7 +1128,7 @@ msgstr "Agradecimentos da Comunidade Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Clique para copiar."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2516,7 +2512,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Guardar alterações da(s) seguinte(s) cena(s) antes de sair?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Guardar alterações da(s) seguinte(s) cena(s) antes de abrir o Gestor de "
"Projeto?"
@@ -11985,10 +11981,6 @@ msgid "Can't copy the function node."
msgstr "Não consigo copiar o nó função."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Ãrea de Transferência está vazia!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Colar Nós VisualScript"
@@ -13181,6 +13173,14 @@ msgstr "Variações só podem ser atribuídas na função vértice."
msgid "Constants cannot be modified."
msgstr "Constantes não podem ser modificadas."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Um reprodutor de animação não se pode animar a ele próprio, apenas a "
+#~ "outros reprodutores."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Ãrea de Transferência está vazia"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamerda foi descontinuada e será removida no Godot 4.0."
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 1fae91fc0d..e79dd0fa19 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -117,12 +117,13 @@
# Arthur Phillip D. Silva <artphil.dev@gmail.com>, 2021.
# Gustavo HM 102 <gustavohm102@gmail.com>, 2021.
# Douglas Leão <djlsplays@gmail.com>, 2021.
+# PauloFRs <paulofr1@hotmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: 2016-05-30\n"
-"PO-Revision-Date: 2021-06-12 01:23+0000\n"
-"Last-Translator: Douglas Leão <djlsplays@gmail.com>\n"
+"PO-Revision-Date: 2021-06-29 08:04+0000\n"
+"Last-Translator: PauloFRs <paulofr1@hotmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -130,7 +131,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.1-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -153,7 +154,7 @@ msgstr "Entrada inválida %i (não passada) na expressão"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr "self não pode ser usado porque a instância é nula (não passada)"
+msgstr "self não pode ser usado porque sua instância é null (não passado)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -521,11 +522,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Faixas de animação só podem apontar para nós AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Um tocador de animação não pode animar a si mesmo, apenas outros tocadores."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Não é possível adicionar uma nova trilha sem uma raiz"
@@ -571,8 +567,9 @@ msgid "Anim Move Keys"
msgstr "Mover Chaves da Anim"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Ãrea de transferência vazia"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Ãrea de transferência vazia!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1230,7 +1227,7 @@ msgstr "Agradecimentos da comunidade Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Clique para copiar."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1911,7 +1908,7 @@ msgstr "Gerenciar perfis de recurso do editor"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Select Current Folder"
-msgstr "Selecione a Pasta Atual"
+msgstr "Selecionar a Pasta Atual"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
@@ -2612,7 +2609,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Salvar alterações na(s) seguinte(s) cena(s) antes de sair?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Salvar alterações na(s) seguinte(s) cena(s) antes de abrir o Gerenciador de "
"Projetos?"
@@ -12106,10 +12103,6 @@ msgid "Can't copy the function node."
msgstr "Não é possível copiar o nó de função."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Ãrea de transferência vazia!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Colar Nodes VisualScript"
@@ -12328,6 +12321,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"As configurações Debug Keystore, Debug User E Debug Password devem ser "
+"configuradas OU nenhuma delas."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12340,6 +12335,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"As configurações de Release Keystore, Release User AND Release Password "
+"devem ser definidas OU nenhuma delas."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13310,6 +13307,14 @@ msgstr "Variáveis só podem ser atribuídas na função de vértice."
msgid "Constants cannot be modified."
msgstr "Constantes não podem serem modificadas."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Um tocador de animação não pode animar a si mesmo, apenas outros "
+#~ "tocadores."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Ãrea de transferência vazia"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "IntepolatedCamera foi depreciada e será removida no Godot 4.0."
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index ec89b47e96..7ac06fc1b1 100644
--- a/editor/translations/ro.po
+++ b/editor/translations/ro.po
@@ -420,12 +420,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Pistele de animație pot direcționa numai nodurilor AnimațieJucător."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Un player de animatie nu se poate anima insusi, doar alti playeri de "
-"animatie."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Nu este posibil să fie adăugată o nouă pistă fără a avea o rădăcină"
@@ -470,8 +464,9 @@ msgid "Anim Move Keys"
msgstr "Anim Mutați Cheie"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Clip-board de resurse gol"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2520,7 +2515,7 @@ msgstr ""
"Salvezi modificările făcute în urmatoarea(le) scenă(e) înainte să închizi?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Salvezi modificările făcute în urmatoarea(le) scenă(e) înainte să deschizi "
"Managerul de Proiect?"
@@ -12046,10 +12041,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -13088,6 +13079,14 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Un player de animatie nu se poate anima insusi, doar alti playeri de "
+#~ "animatie."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Clip-board de resurse gol"
+
#~ msgid "No"
#~ msgstr "Nu"
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index fe4b510539..4b56d21383 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -95,12 +95,14 @@
# nec-trou <darya.bilyalova@gmail.com>, 2021.
# IindinAndEdresia <kapitan_pol@inbox.ru>, 2021.
# Bualma Show <appleaidar6@gmail.com>, 2021.
+# enderlorde <madel.laboratories@gmail.com>, 2021.
+# Олег Довгер <oleg.a.dovger@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-07 23:43+0000\n"
-"Last-Translator: Bualma Show <appleaidar6@gmail.com>\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"Last-Translator: Danil Alexeev <danil@alexeev.xyz>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
"Language: ru\n"
@@ -109,12 +111,13 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
-msgstr "Ðеверный параметр типа Ð´Ð»Ñ convert(), иÑпользуйте конÑтанты TYPE_*."
+msgstr ""
+"ÐедопуÑтимый аргумент type Ð´Ð»Ñ convert(), иÑпользуйте конÑтанты TYPE_*."
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
@@ -501,10 +504,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Дорожки анимации могут указывать только на узлы типа AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Проигрыватель анимации не может анимировать Ñам ÑебÑ, только других."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ новую дорожку без корневого узла"
@@ -549,8 +548,9 @@ msgid "Anim Move Keys"
msgstr "ПеремеÑтить ключи"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Буфер обмена пуÑÑ‚"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Буфер обмена пуÑÑ‚!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1207,7 +1207,7 @@ msgstr "СпаÑибо от ÑообщеÑтва Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Ðажмите, чтобы Ñкопировать."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2591,7 +2591,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² Ñледующей Ñцене(Ñ‹) перед выходом?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² Ñледующей Ñцене(Ñ‹) перед открытием менеджера проектов?"
@@ -3154,7 +3154,7 @@ msgstr "ИнÑпектор"
#: editor/editor_node.cpp
msgid "Expand Bottom Panel"
-msgstr "РаÑширить боковую панель"
+msgstr "Развернуть нижнюю панель"
#: editor/editor_node.cpp
msgid "Output"
@@ -5813,7 +5813,7 @@ msgstr "Кадрировать выбранное"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Preview Canvas Scale"
-msgstr "ПредпроÑмотр Canvas Scale"
+msgstr "ПредпроÑмотр маÑштаба холÑта"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Translation mask for inserting keys."
@@ -8437,7 +8437,7 @@ msgstr "Приоритет"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Z Index"
-msgstr "Положение по оÑи Z"
+msgstr "Z-индекÑ"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Region Mode"
@@ -12070,10 +12070,6 @@ msgid "Can't copy the function node."
msgstr "Ðе удаётÑÑ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ узел функции."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Буфер обмена пуÑÑ‚!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Ð’Ñтавить узлы VisualScript"
@@ -12287,6 +12283,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"ЛИБО должны быть заданы наÑтройки Debug Keystore, Debug User И Debug "
+"Password, ЛИБО ни одна из них."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12299,6 +12297,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"ЛИБО должны быть заданы наÑтройки Release Keystore, Release User И Release "
+"Password, ЛИБО ни одна из них."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13262,6 +13262,13 @@ msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ быть назначены только Ð
msgid "Constants cannot be modified."
msgstr "КонÑтанты не могут быть изменены."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Проигрыватель анимации не может анимировать Ñам ÑебÑ, только других."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Буфер обмена пуÑÑ‚"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamera уÑтарела и будет удалена в Godot 4.0."
diff --git a/editor/translations/si.po b/editor/translations/si.po
index 89c1b2ffc8..a5586af274 100644
--- a/editor/translations/si.po
+++ b/editor/translations/si.po
@@ -418,10 +418,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "AnimationPlayer පුරුක් සදහ෠පමණක් සජීවීකරණ ලුහුබදින්නන් à¶‘à¶šà·Š à¶šà·… à·„à·à¶š."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -470,7 +466,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2433,7 +2430,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11573,10 +11570,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index 5d5b9cba9b..d97e1321ef 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -11,12 +11,13 @@
# Richard Urban <redasuio1@gmail.com>, 2020.
# Anonymous <noreply@weblate.org>, 2020.
# Mario-projects-dev <m.vitek.mv@gmail.com>, 2021.
+# Eliška Fichnová <eliska@fichna.sk>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-04-11 22:02+0000\n"
-"Last-Translator: Mario-projects-dev <m.vitek.mv@gmail.com>\n"
+"PO-Revision-Date: 2021-07-07 15:34+0000\n"
+"Last-Translator: Eliška Fichnová <eliska@fichna.sk>\n"
"Language-Team: Slovak <https://hosted.weblate.org/projects/godot-engine/"
"godot/sk/>\n"
"Language: sk\n"
@@ -24,7 +25,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-"X-Generator: Weblate 4.6-dev\n"
+"X-Generator: Weblate 4.8-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -414,10 +415,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Track-y Animácií môžu ukazovať iba na node-y AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "Animation player sa nemôže naanimovať sám, iba ostatné player-y."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Není možné pridať nový track bez root-u"
@@ -462,8 +459,9 @@ msgid "Anim Move Keys"
msgstr "Pohybové kľúÄe Animácie"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Schránka je prázdna"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1116,7 +1114,7 @@ msgstr "VÄaka z Godot komunity!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Klikni na skopírovanie."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1610,13 +1608,12 @@ msgstr ""
"Etc' v Nastaveniach Projektu."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. "
"Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings."
msgstr ""
-"Target platforma potrebuje 'ETC2' kompresor textúr pre GLES3. Povoliť'Import "
-"Etc 2' v Nastaveniach Projektu."
+"Cieľová platforma potrebuje 'ETC2' alebo 'PVRTC' kompresor textúr pre GLES3. "
+"Povoľte 'Import Etc 2' alebo 'Import Pvrtc' v Nastaveniach Projektu."
#: editor/editor_export.cpp
#, fuzzy
@@ -2309,6 +2306,8 @@ msgid ""
"An error occurred while trying to save the editor layout.\n"
"Make sure the editor's user data path is writable."
msgstr ""
+"Nastala chyba pri pokuse o uloženie rozloženia editoru.\n"
+"Uistite sa, že cesta uživateľských dát editoru je zapisovateľná."
#: editor/editor_node.cpp
msgid ""
@@ -2316,15 +2315,17 @@ msgid ""
"To restore the Default layout to its base settings, use the Delete Layout "
"option and delete the Default layout."
msgstr ""
+"Prednastavené rozloženie editoru prepísané.\n"
+"Na obnovenie Prednastaveného rozloženia na základné nastavenia, použite "
+"možnosť Vymazať Rozloženie a vymažte Prednastavené rozloženie."
#: editor/editor_node.cpp
msgid "Layout name not found!"
msgstr "Meno Layout-u sa nenašlo!"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restored the Default layout to its base settings."
-msgstr "Obnovené predvolené rozloženie na základné nastavenia."
+msgstr "Predvolené rozloženie bolo obnovené na základné nastavenia."
#: editor/editor_node.cpp
msgid ""
@@ -2381,7 +2382,7 @@ msgstr "Nieje definovaná žiadna scéna na spustenie."
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "Uložiť scénu pred spustením..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2496,7 +2497,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "UložiÅ¥ zmeny do nasledujúcich scén pred ukonÄením?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Uložiť zmeny nasledujúcich scén pred otvorením Manažéra Projektov?"
#: editor/editor_node.cpp
@@ -2525,24 +2526,22 @@ msgstr ""
"Addon plugin nie je možné povoliť pri: '% s' analýze konfigurácie zlyhalo."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Unable to find script field for addon plugin at: '%s'."
-msgstr ""
-"Nepodarilo sa nájsť script field pre addon plugin v: 'res://addons/%s'."
+msgstr "Nepodarilo sa nájsť pole skriptu pre addon plugin v: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
msgstr "Nepodarilo sa naÄítaÅ¥ addon script z cesty: '%s'."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"Unable to load addon script from path: '%s'. This might be due to a code "
"error in that script.\n"
"Disabling the addon at '%s' to prevent further errors."
msgstr ""
-"Nepodarilo sa nájsť addon script z cesty: '%s' Vyzerá to tak že by mohol byť "
-"problém v kóde, prosím skontrolujte syntax."
+"Nebolo možné naÄítaÅ¥ addon skript z cesty: '%s'. Toto môže byÅ¥ spôsobené "
+"chybou kódu v skripte.\n"
+"Deaktivujem addon z '%s', aby sa prediÅ¡lo Äalším chybám."
#: editor/editor_node.cpp
msgid ""
@@ -2985,7 +2984,7 @@ msgstr "O nás"
#: editor/editor_node.cpp
msgid "Support Godot Development"
-msgstr ""
+msgstr "Podporte vývoj Godot"
#: editor/editor_node.cpp
msgid "Play the project."
@@ -3127,21 +3126,22 @@ msgid "Open & Run a Script"
msgstr "Otvoriť a vykonať skript"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"The following files are newer on disk.\n"
"What action should be taken?"
-msgstr "Nasledovné súbory sa nepodarilo extrahovať z balíka:"
+msgstr ""
+"Nasledujúce súbory majú novšiu verziu na disku.\n"
+"Aká akcia sa má vykonať?"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Reload"
-msgstr ""
+msgstr "Znovu naÄítaÅ¥"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Resave"
-msgstr ""
+msgstr "Znovu uložiť"
#: editor/editor_node.cpp
msgid "New Inherited"
@@ -3670,6 +3670,8 @@ msgstr ""
msgid ""
"Importing has been disabled for this file, so it can't be opened for editing."
msgstr ""
+"Importovanie bolo zablokované pre tento súbor, Äiže nemôže byÅ¥ otvorený pre "
+"úpravy."
#: editor/filesystem_dock.cpp
msgid "Cannot move/rename resources root."
@@ -3716,6 +3718,12 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
+"Nasledujúce súbory alebo zložky sú v konflikte s položkami v cieľovom "
+"umiestnení '%s':\n"
+"\n"
+"%s\n"
+"\n"
+"Prajete si ich prepísať?"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
@@ -3796,9 +3804,8 @@ msgid "Duplicate..."
msgstr "Duplikovať..."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Move to Trash"
-msgstr "Presunúť AutoLoad-y"
+msgstr "Presunúť do odpadkov"
#: editor/filesystem_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
msgid "Rename..."
@@ -3909,19 +3916,16 @@ msgid "Searching..."
msgstr "Vyhľadávam..."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d match in %d file."
-msgstr "%d zhody."
+msgstr "%d zhoda v %d súbore."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d file."
-msgstr "%d zhody."
+msgstr "%d zhôd v % súbore."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d files."
-msgstr "%d zhody."
+msgstr "%d zhôd v %d súboroch."
#: editor/groups_editor.cpp
msgid "Add to Group"
@@ -4058,23 +4062,20 @@ msgid "Saving..."
msgstr "Ukladám..."
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Select Importer"
-msgstr "Vybrať Režim"
+msgstr "Vybrať Importér"
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Importer:"
-msgstr "Import"
+msgstr "Importér:"
#: editor/import_defaults_editor.cpp
-#, fuzzy
msgid "Reset to Defaults"
-msgstr "NaÄítaÅ¥ predvolené"
+msgstr "Obnoviť na východzie"
#: editor/import_dock.cpp
msgid "Keep File (No Import)"
-msgstr ""
+msgstr "Ponechať súbor (bez importu)"
#: editor/import_dock.cpp
msgid "%d Files"
@@ -5040,9 +5041,8 @@ msgid "Got:"
msgstr "Má:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Failed SHA-256 hash check"
-msgstr "Zlyhalo sha256 hash check"
+msgstr "Zlyhalo overenie SHA-256 hashu"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -11938,10 +11938,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Paste VisualScript Nodes"
msgstr "Vložiť"
@@ -13001,6 +12997,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "Animation player sa nemôže naanimovať sám, iba ostatné player-y."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Schránka je prázdna"
+
#~ msgid "No"
#~ msgstr "Nie"
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index 2ac453123c..07bd33c389 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -440,10 +440,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -493,7 +489,8 @@ msgid "Anim Move Keys"
msgstr "Animacija Premakni kljuÄ"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2606,7 +2603,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Shranim spremembe na sledeÄih scenah pred zaprtjem?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Shranim spremembe na sledeÄih scenah pred odpiranjem Upravljalnika Projekta?"
@@ -12321,10 +12318,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/sq.po b/editor/translations/sq.po
index 4409a6f48a..49a42b5553 100644
--- a/editor/translations/sq.po
+++ b/editor/translations/sq.po
@@ -407,10 +407,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -455,8 +451,9 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Clipboard-i është bosh"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2548,7 +2545,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Ruaj ndryshimet nga skenat e mëposhtme përpara se të dalësh?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Ruaj ndryshimet ne skenat e mëposhtme para se të hapësh Menaxherin e "
"Projekteve?"
@@ -11927,10 +11924,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -12962,6 +12955,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Clipboard is empty"
+#~ msgstr "Clipboard-i është bosh"
+
#~ msgid "No"
#~ msgstr "Jo"
diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po
index 3ba1c674a3..53fb04b3e4 100644
--- a/editor/translations/sr_Cyrl.po
+++ b/editor/translations/sr_Cyrl.po
@@ -457,11 +457,6 @@ msgstr "Ðнимационе траке могу Ñамо уÑмеравати Ð
#: editor/animation_track_editor.cpp
#, fuzzy
-msgid "An animation player can't animate itself, only other players."
-msgstr "Ðнимациони плејер не може анимирати Ñамог Ñебе, Ñамо друге плејере."
-
-#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Not possible to add a new track without a root"
msgstr "Ðије могуже додати нову траку без корена"
@@ -515,9 +510,9 @@ msgid "Anim Move Keys"
msgstr "Помери кључеве"
#: editor/animation_track_editor.cpp
-#, fuzzy
-msgid "Clipboard is empty"
-msgstr "Ðема реÑурÑа за копирање!"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -2727,7 +2722,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Сачувај промене тренутне Ñцене/а пре излазка?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Сачувај промене тренутне Ñцене/а пре отварање менаџера пројекта?"
#: editor/editor_node.cpp
@@ -13503,10 +13498,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -14817,6 +14808,14 @@ msgstr "Варијације могу Ñамо бити одређене у фу
msgid "Constants cannot be modified."
msgstr "КонÑтанте није могуће мењати."
+#, fuzzy
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "Ðнимациони плејер не може анимирати Ñамог Ñебе, Ñамо друге плејере."
+
+#, fuzzy
+#~ msgid "Clipboard is empty"
+#~ msgstr "Ðема реÑурÑа за копирање!"
+
#~ msgid "No"
#~ msgstr "Ðе"
diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po
index fcab84a2bf..0a90379b41 100644
--- a/editor/translations/sr_Latn.po
+++ b/editor/translations/sr_Latn.po
@@ -422,10 +422,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -473,7 +469,8 @@ msgid "Anim Move Keys"
msgstr "Animacija Pomjeri KljuÄeve"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2446,7 +2443,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11665,10 +11662,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index c5cad10f66..0c5db25a9a 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -22,12 +22,13 @@
# Shaggy <anton_christoffersson@hotmail.com>, 2020.
# Marcus Toftedahl <marcus.toftedahl@his.se>, 2020.
# Alex25820 <Alexander_sjogren@hotmail.se>, 2021.
+# Leon <joel.lundborg@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-03 21:29+0000\n"
-"Last-Translator: Alex25820 <Alexander_sjogren@hotmail.se>\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"Last-Translator: Leon <joel.lundborg@gmail.com>\n"
"Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/"
"godot/sv/>\n"
"Language: sv\n"
@@ -35,7 +36,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -426,11 +427,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animationsspår kan bara peka på AnimationsSpelar noder."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"En animationsspelare kan inte animera sig själv, utan bara andra spelare."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Det är inte möjligt att lägga till ett nytt spår utan en rot-nod"
@@ -475,8 +471,9 @@ msgid "Anim Move Keys"
msgstr "Anim Flytta Nycklar"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Urklipp är tomt"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1134,7 +1131,7 @@ msgstr "Tack från Godot-gemenskapen!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Klicka för att kopiera."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1667,14 +1664,12 @@ msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
msgstr "Den inbäddade PCK får inte vara större än 4 GiB på 32 bitars exporter."
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "3D Editor"
-msgstr "Öppna Skript-Redigerare"
+msgstr "Öppna 3D-redigeraren"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Script Editor"
-msgstr "Öppna Skript-Redigerare"
+msgstr "Öppna Skript-Redigeraren"
#: editor/editor_feature_profile.cpp
msgid "Asset Library"
@@ -1699,18 +1694,16 @@ msgid "Import Dock"
msgstr "Importera"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Erase profile '%s'? (no undo)"
-msgstr "Ersätt Alla"
+msgstr "Rensa profil ‘%s’? (Du kan inte ångra den här åtgärden )"
#: editor/editor_feature_profile.cpp
msgid "Profile must be a valid filename and must not contain '.'"
msgstr "Profilen måste ha ett giltigt filnamn och får inte innehålla '.'"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Profile with this name already exists."
-msgstr "En fil eller mapp med detta namn finns redan."
+msgstr "En profil med detta namn finns redan."
#: editor/editor_feature_profile.cpp
msgid "(Editor Disabled, Properties Disabled)"
@@ -1768,9 +1761,8 @@ msgid "Unset"
msgstr ""
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Current Profile:"
-msgstr "Nuvarande Version:"
+msgstr "Nuvarande Profil:"
#: editor/editor_feature_profile.cpp
msgid "Make Current"
@@ -1792,9 +1784,8 @@ msgid "Export"
msgstr "Exportera"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Available Profiles:"
-msgstr "Tillgängliga Noder:"
+msgstr "Tillgängliga Profiler:"
#: editor/editor_feature_profile.cpp
#, fuzzy
@@ -2561,7 +2552,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Spara ändringar av följande scen(er) innan du avslutar?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Spara ändringar av följande scen(er) innan du öppnar Projekthanteraren?"
@@ -12074,10 +12065,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
@@ -13142,6 +13129,13 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "En animationsspelare kan inte animera sig själv, utan bara andra spelare."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Urklipp är tomt"
+
#~ msgid "No"
#~ msgstr "Nej"
diff --git a/editor/translations/ta.po b/editor/translations/ta.po
index c630966603..0c9022b097 100644
--- a/editor/translations/ta.po
+++ b/editor/translations/ta.po
@@ -421,10 +421,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -472,7 +468,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2437,7 +2434,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11576,10 +11573,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/te.po b/editor/translations/te.po
index f1d857b911..8274d5520f 100644
--- a/editor/translations/te.po
+++ b/editor/translations/te.po
@@ -403,10 +403,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -451,7 +447,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2410,7 +2407,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11483,10 +11480,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/th.po b/editor/translations/th.po
index 0edcf900b9..e9c2a80a49 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -427,10 +427,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "à¹à¸—ร็à¸à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¹ˆà¸™à¸ªà¸²à¸¡à¸²à¸£à¸–ติดไว้บนโหนด AnimationPlayer เท่านั้น"
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "à¹à¸—ร็à¸à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¹ˆà¸™à¹„ม่สามารถเล่นตัวมันเองได้ à¹à¸•่สามารถเล่นตัวเล่นอื่นได้"
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "ไม่สามารถที่จะเพิ่มà¹à¸—ร็à¸à¹ƒà¸«à¸¡à¹ˆà¹‚ดยที่ไม่มีรูท"
@@ -475,8 +471,9 @@ msgid "Anim Move Keys"
msgstr "ย้ายคีย์à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "คลิปบอร์ดว่างเปล่า"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "คลิปบอร์ดว่างเปล่า!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2483,7 +2480,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "บันทึà¸à¸‰à¸²à¸à¸•่อไปนี้à¸à¹ˆà¸­à¸™à¸›à¸´à¸”โปรà¹à¸à¸£à¸¡à¸«à¸£à¸·à¸­à¹„ม่?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "บันทึà¸à¸‰à¸²à¸à¸•่อไปนี้à¸à¹ˆà¸­à¸™à¸à¸¥à¸±à¸šà¸ªà¸¹à¹ˆà¸•ัวจัดà¸à¸²à¸£à¹‚ปรเจà¸à¸•์หรือไม่?"
#: editor/editor_node.cpp
@@ -11801,10 +11798,6 @@ msgid "Can't copy the function node."
msgstr "คัดลอà¸à¹‚หนดฟังà¸à¹Œà¸Šà¸±à¸™à¹„ม่ได้"
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "คลิปบอร์ดว่างเปล่า!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "วางโหนด VisualScript"
@@ -12913,6 +12906,12 @@ msgstr "Varyings สามารถà¸à¸³à¸«à¸™à¸”ในังà¸à¹Œà¸Šà¸±à¸™à¹€
msgid "Constants cannot be modified."
msgstr "ค่าคงที่ไม่สามารถà¹à¸à¹‰à¹„ขได้"
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "à¹à¸—ร็à¸à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¹ˆà¸™à¹„ม่สามารถเล่นตัวมันเองได้ à¹à¸•่สามารถเล่นตัวเล่นอื่นได้"
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "คลิปบอร์ดว่างเปล่า"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamera เลิà¸à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¹à¸¥à¹‰à¸§à¹à¸¥à¸°à¸ˆà¸°à¸–ูà¸à¸¥à¸šà¸­à¸­à¸à¹ƒà¸™ Godot 4.0"
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index 5892850caf..578d7b48d0 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -60,12 +60,13 @@
# Jafar Tarverdiyev <cefertarverdiyevv@gmail.com>, 2021.
# ali aydın <alimxaydin@gmail.com>, 2021.
# Cannur Daşkıran <canndask@gmail.com>, 2021.
+# kahveciderin <kahveciderin@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-29 13:49+0000\n"
-"Last-Translator: ali aydın <alimxaydin@gmail.com>\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"Last-Translator: kahveciderin <kahveciderin@gmail.com>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot/tr/>\n"
"Language: tr\n"
@@ -73,7 +74,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -464,12 +465,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Animasyon izleri sadece AnimasyonOynatıcı düğümlerini işaret edebilir."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Bir animasyon oynatıcı kendisini oynamataz, sadece diğer oynatıcılar "
-"yapaibilir."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Bir kök olmadan yeni bir iz eklemek mümkün değildir"
@@ -514,8 +509,9 @@ msgid "Anim Move Keys"
msgstr "Animasyon Anahtarları Taşı"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Pano boÅŸ"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Pano boÅŸ!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1173,7 +1169,7 @@ msgstr "Godot topluluğundan teşekkürler!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Kopyalamak için tıklayın."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2554,7 +2550,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Çıkmadan önce değişiklikler aşağıdaki sahne(ler)e kaydedilsin mi?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Proje Yöneticisi açılmadan önce değişiklikler aşağıdaki sahneye(lere) "
"kaydedilsin mi?"
@@ -12023,10 +12019,6 @@ msgid "Can't copy the function node."
msgstr "Fonksiyon düğümü kopyalanamıyor."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Pano boÅŸ!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "GörselBetik Düğümleri Yapıştır"
@@ -12238,6 +12230,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Hata Ayıklama Anahtar Deposu, Hata Ayıklama Kullanıcısı VE Hata Ayıklama "
+"Şifresi konfigüre edilmelidir VEYA hiçbiri konfigüre edilmemelidir."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12250,6 +12244,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Yayınlama Anahtar Deposu, Yayınlama Kullanıcısı be Yayınlama Şifresi "
+"ayarları konfigüre edilmeli VEYA hiçbiri konfigüre edilmemelidir."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13215,6 +13211,14 @@ msgstr "varyings yalnızca vertex işlevinde atanabilir."
msgid "Constants cannot be modified."
msgstr "Sabit deÄŸerler deÄŸiÅŸtirilemez."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Bir animasyon oynatıcı kendisini oynamataz, sadece diğer oynatıcılar "
+#~ "yapaibilir."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Pano boÅŸ"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr ""
diff --git a/editor/translations/tt.po b/editor/translations/tt.po
index c0d7e79447..3e63f2369d 100644
--- a/editor/translations/tt.po
+++ b/editor/translations/tt.po
@@ -403,10 +403,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -451,7 +447,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2410,7 +2407,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11482,10 +11479,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/tzm.po b/editor/translations/tzm.po
index 629220c426..0b0ce7d01e 100644
--- a/editor/translations/tzm.po
+++ b/editor/translations/tzm.po
@@ -401,10 +401,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -449,7 +445,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2408,7 +2405,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11480,10 +11477,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 67f369bb15..50508c5df3 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -20,7 +20,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Ukrainian (Godot Engine)\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-18 14:51+0000\n"
+"PO-Revision-Date: 2021-06-20 13:35+0000\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/"
"godot/uk/>\n"
@@ -30,7 +30,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -424,12 +424,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Доріжки анімації можуть вказувати лише на взули AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Відтворювач анімації не може відтворювати Ñам Ñебе, лише інші відтворювачі "
-"анімації."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Ðе можна додавати нові доріжки без кореневого запиÑу"
@@ -476,8 +470,9 @@ msgid "Anim Move Keys"
msgstr "ПереміÑтити ключі анімації"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Буфер обміну порожній"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Буфер обміну порожній!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1137,7 +1132,7 @@ msgstr "СпаÑибі від Ñпільноти Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Клацніть, щоб Ñкопіювати."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2521,7 +2516,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Зберегти зміни в наÑтупній(их) Ñцені(ах) перед тим, Ñк вийти?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
"Зберегти зміни в наÑтупній(их) Ñцені(ах) перед відкриттÑм менеджера проєктів?"
@@ -12025,10 +12020,6 @@ msgid "Can't copy the function node."
msgstr "Ðеможливо Ñкопіювати вузол функції."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Буфер обміну порожній!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Ð’Ñтавити вузли (Візуального Ñкриптингу) VisualScript"
@@ -12244,6 +12235,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Має бути налаштовано діагноÑтику Ñховища ключів, діагноÑтику кориÑтувача ÐБО "
+"діагноÑтику Ð¿Ð°Ñ€Ð¾Ð»Ñ ÐБО не налаштовано діагноÑтику жодного з цих компонентів."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12256,6 +12249,8 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Має бути налаштовано параметри Ñховища ключів випуÑку, кориÑтувача випуÑку Ñ– "
+"Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð²Ð¸Ð¿ÑƒÑку або не налаштовано жоден з цих параметрів."
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -13244,6 +13239,14 @@ msgstr "Змінні величини можна пов'Ñзувати лише
msgid "Constants cannot be modified."
msgstr "Сталі не можна змінювати."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Відтворювач анімації не може відтворювати Ñам Ñебе, лише інші "
+#~ "відтворювачі анімації."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Буфер обміну порожній"
+
#~ msgid ""
#~ "Godot editor was built without ray tracing support; lightmaps can't be "
#~ "baked.\n"
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index 3af1eac2ef..0a213a2bdf 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -410,10 +410,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr ""
@@ -458,7 +454,8 @@ msgid "Anim Move Keys"
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
msgstr ""
#: editor/animation_track_editor.cpp
@@ -2456,7 +2453,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
@@ -11780,10 +11777,6 @@ msgid "Can't copy the function node."
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr ""
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr ""
diff --git a/editor/translations/vi.po b/editor/translations/vi.po
index 8a34f898b8..0104d05502 100644
--- a/editor/translations/vi.po
+++ b/editor/translations/vi.po
@@ -424,11 +424,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "Các bản hoạt ảnh chỉ có thể trỠtới các nút AnimationPlayer."
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-"Animation player không tự tạo hoạt ảnh được, phải thông qua các player khác."
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "Không thể thêm track mới mà không có root"
@@ -473,8 +468,9 @@ msgid "Anim Move Keys"
msgstr "Di chuyển các khoá hoạt cảnh"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "Clipboard rá»—ng"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "Clipboard trống!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -2499,7 +2495,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "Lưu thay đổi trong các scene sau trước khi thoát?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "Lưu thay đổi trong các cảnh sau trước khi mở Quản lí Dự án?"
#: editor/editor_node.cpp
@@ -11888,10 +11884,6 @@ msgid "Can't copy the function node."
msgstr "Không thể sao chép nút chức năng."
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "Clipboard trống!"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "Dán các nút VisualScript"
@@ -13004,6 +12996,14 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Không thể chỉnh sửa hằng số."
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr ""
+#~ "Animation player không tự tạo hoạt ảnh được, phải thông qua các player "
+#~ "khác."
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "Clipboard rá»—ng"
+
#~ msgid "No"
#~ msgstr "Không"
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index 53259bcc6f..4393cb4e08 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -83,7 +83,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Chinese (Simplified) (Godot Engine)\n"
"POT-Creation-Date: 2018-01-20 12:15+0200\n"
-"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
"Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hans/>\n"
@@ -92,7 +92,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -260,7 +260,7 @@ msgstr "修改动画长度"
#: editor/animation_track_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Change Animation Loop"
-msgstr "修改循环"
+msgstr "修改动画循环"
#: editor/animation_track_editor.cpp
msgid "Property Track"
@@ -288,11 +288,11 @@ msgstr "动画播放轨é“"
#: editor/animation_track_editor.cpp
msgid "Animation length (frames)"
-msgstr "动画时长(帧)"
+msgstr "动画长度(帧)"
#: editor/animation_track_editor.cpp
msgid "Animation length (seconds)"
-msgstr "动画时长(秒)"
+msgstr "动画长度(秒)"
#: editor/animation_track_editor.cpp
msgid "Add Track"
@@ -317,15 +317,15 @@ msgstr "动画剪辑:"
#: editor/animation_track_editor.cpp
msgid "Change Track Path"
-msgstr "改å˜è½¨é“路径"
+msgstr "修改轨é“路径"
#: editor/animation_track_editor.cpp
msgid "Toggle this track on/off."
-msgstr "切æ¢å½“å‰è½¨é“开关。"
+msgstr "切æ¢è¯¥è½¨é“的开关。"
#: editor/animation_track_editor.cpp
msgid "Update Mode (How this property is set)"
-msgstr "更新模å¼ï¼ˆå±žæ€§è®¾ç½®æ–¹æ³•)"
+msgstr "更新模å¼ï¼ˆè®¾ç½®å±žæ€§çš„æ–¹å¼ï¼‰"
#: editor/animation_track_editor.cpp
msgid "Interpolation Mode"
@@ -337,7 +337,7 @@ msgstr "æ— ç¼å¾ªçŽ¯æ¨¡å¼ï¼ˆä½¿ç”¨å¾ªçޝ开始æ’值循环结æŸï¼‰"
#: editor/animation_track_editor.cpp
msgid "Remove this track."
-msgstr "移除当å‰è½¨é“。"
+msgstr "移除该轨é“。"
#: editor/animation_track_editor.cpp
msgid "Time (s): "
@@ -378,11 +378,11 @@ msgstr "三次方"
#: editor/animation_track_editor.cpp
msgid "Clamp Loop Interp"
-msgstr "切断循环æ’值器"
+msgstr "切断循环æ’值"
#: editor/animation_track_editor.cpp
msgid "Wrap Loop Interp"
-msgstr "环绕间隔"
+msgstr "环绕循环æ’值"
#: editor/animation_track_editor.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -391,11 +391,11 @@ msgstr "æ’入关键帧"
#: editor/animation_track_editor.cpp
msgid "Duplicate Key(s)"
-msgstr "å¤åˆ¶å¸§"
+msgstr "å¤åˆ¶å…³é”®å¸§"
#: editor/animation_track_editor.cpp
msgid "Delete Key(s)"
-msgstr "删除帧"
+msgstr "删除关键帧"
#: editor/animation_track_editor.cpp
msgid "Change Animation Update Mode"
@@ -411,7 +411,7 @@ msgstr "更改动画循环模å¼"
#: editor/animation_track_editor.cpp
msgid "Remove Anim Track"
-msgstr "移除轨é“"
+msgstr "移除动画轨é“"
#: editor/animation_track_editor.cpp
msgid "Create NEW track for %s and insert key?"
@@ -447,11 +447,11 @@ msgstr "创建并æ’入动画"
#: editor/animation_track_editor.cpp
msgid "Anim Insert Track & Key"
-msgstr "æ’入轨é“和关键帧"
+msgstr "æ’入动画轨é“和关键帧"
#: editor/animation_track_editor.cpp
msgid "Anim Insert Key"
-msgstr "æ’入关键帧"
+msgstr "æ’入动画关键帧"
#: editor/animation_track_editor.cpp
msgid "Change Animation Step"
@@ -463,7 +463,7 @@ msgstr "釿–°æŽ’列轨é“"
#: editor/animation_track_editor.cpp
msgid "Transform tracks only apply to Spatial-based nodes."
-msgstr "å˜æ¢è½¨è¿¹ä»…应用到基于 Spatial 节点。"
+msgstr "å˜æ¢è½¨é“仅应用于基于 Spatial 的节点。"
#: editor/animation_track_editor.cpp
msgid ""
@@ -472,18 +472,14 @@ msgid ""
"-AudioStreamPlayer2D\n"
"-AudioStreamPlayer3D"
msgstr ""
-"音轨åªèƒ½æŒ‡å‘以下类型的节点:\n"
+"音频轨é“åªèƒ½æŒ‡å‘以下类型的节点:\n"
"-AudioStreamPlayer\n"
"-AudioStreamPlayer2D\n"
"-AudioStreamPlayer3D"
#: editor/animation_track_editor.cpp
msgid "Animation tracks can only point to AnimationPlayer nodes."
-msgstr "动画轨迹åªèƒ½æŒ‡å‘ AnimationPlayer 节点。"
-
-#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "动画播放器ä¸èƒ½åŠ¨ç”»åŒ–è‡ªå·±ï¼Œåªèƒ½åŠ¨ç”»åŒ–å…¶ä»–æ’­æ”¾å™¨ã€‚"
+msgstr "动画轨é“åªèƒ½æŒ‡å‘ AnimationPlayer 节点。"
#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
@@ -530,8 +526,9 @@ msgid "Anim Move Keys"
msgstr "移动动画关键帧"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "å‰ªè´´æ¿æ˜¯ç©ºçš„"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "å‰ªè´´æ¿æ˜¯ç©ºçš„ï¼"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1179,7 +1176,7 @@ msgstr "Godot 社区感谢你ï¼"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "点击å¤åˆ¶ã€‚"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2535,7 +2532,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "退出å‰è¦ä¿å­˜ä»¥ä¸‹åœºæ™¯æ›´æ”¹å—?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "打开项目管ç†å™¨å‰è¦ä¿å­˜ä¸‹åˆ—场景更改å—?"
#: editor/editor_node.cpp
@@ -9783,10 +9780,10 @@ msgid ""
"Incompatible with older hardware\n"
"Not recommended for web games"
msgstr ""
-"è§†è§‰è´¨é‡æ›´é«˜\n"
+"视觉质é‡è¾ƒé«˜\n"
"所有功能å¯ç”¨\n"
-"与旧硬件ä¸å…¼å®¹\n"
-"䏿ލè用于网络游æˆ"
+"ä¸å…¼å®¹è¾ƒè€çš„硬件\n"
+"䏿ލè用于网页游æˆ"
#: editor/project_manager.cpp
msgid "OpenGL ES 2.0"
@@ -9802,7 +9799,7 @@ msgstr ""
"视觉质é‡è¾ƒä½Ž\n"
"æŸäº›åŠŸèƒ½ä¸å¯ç”¨\n"
"å¯ç”¨äºŽå¤§å¤šæ•°ç¡¬ä»¶\n"
-"推è用于网络游æˆ"
+"推è用于网页游æˆ"
#: editor/project_manager.cpp
msgid "Renderer can be changed later, but scenes may need to be adjusted."
@@ -9878,7 +9875,7 @@ msgid ""
"the \"Application\" category."
msgstr ""
"无法è¿è¡Œé¡¹ç›®ï¼šæœªå®šä¹‰ä¸»åœºæ™¯ã€‚ \n"
-"请编辑项目并在 “项目设置†中 “Application†类别下设置主场景。"
+"请编辑项目并在 “项目设置†的 “Application†类别下设置主场景。"
#: editor/project_manager.cpp
msgid ""
@@ -9943,7 +9940,7 @@ msgstr "项目"
#: editor/project_manager.cpp
msgid "Loading, please wait..."
-msgstr "正在加载,请ç¨å€™..."
+msgstr "正在加载,请ç¨å€™â€¦â€¦"
#: editor/project_manager.cpp
msgid "Last Modified"
@@ -9971,7 +9968,7 @@ msgstr "模æ¿"
#: editor/project_manager.cpp
msgid "Restart Now"
-msgstr "ç«‹å³é‡æ–°å¯åЍ"
+msgstr "ç«‹å³é‡å¯"
#: editor/project_manager.cpp
msgid "Can't run project"
@@ -9982,7 +9979,7 @@ msgid ""
"You currently don't have any projects.\n"
"Would you like to explore official example projects in the Asset Library?"
msgstr ""
-"ç›®å‰æ²¡æœ‰ä»»ä½•项目。 \n"
+"ç›®å‰æ²¡æœ‰ä»»ä½•项目。\n"
"æ˜¯å¦æŸ¥çœ‹ç´ æåº“中的官方示例项目?"
#: editor/project_manager.cpp
@@ -9996,11 +9993,11 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "Key "
-msgstr "é”® "
+msgstr "按键 "
#: editor/project_settings_editor.cpp
msgid "Joy Button"
-msgstr "手柄按钮"
+msgstr "手柄按键"
#: editor/project_settings_editor.cpp
msgid "Joy Axis"
@@ -10014,11 +10011,11 @@ msgstr "鼠标按键"
msgid ""
"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'"
-msgstr "无效的æ“作å称。æ“作åä¸èƒ½ä¸ºç©ºï¼Œä¹Ÿä¸èƒ½åŒ…å« â€œ/â€, “:â€, “=â€, “\\†或 “\"â€"
+msgstr "无效的动作å称。动作åä¸èƒ½ä¸ºç©ºï¼Œä¹Ÿä¸èƒ½åŒ…å« â€œ/â€, “:â€, “=â€, “\\†或 “\"â€"
#: editor/project_settings_editor.cpp
msgid "An action with the name '%s' already exists."
-msgstr "å为 “%s†的æ“作已存在。"
+msgstr "å为“%sâ€çš„动作已存在。"
#: editor/project_settings_editor.cpp
msgid "Rename Input Action Event"
@@ -10042,11 +10039,11 @@ msgstr "设备"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "Press a Key..."
-msgstr "按下一个键..."
+msgstr "请按键……"
#: editor/project_settings_editor.cpp
msgid "Mouse Button Index:"
-msgstr "鼠标按键:"
+msgstr "鼠标按键索引:"
#: editor/project_settings_editor.cpp
msgid "Left Button"
@@ -10070,11 +10067,11 @@ msgstr "滚轮å‘下"
#: editor/project_settings_editor.cpp
msgid "Wheel Left Button"
-msgstr "滚轮左键"
+msgstr "滚轮å‘å·¦"
#: editor/project_settings_editor.cpp
msgid "Wheel Right Button"
-msgstr "滚轮å³é”®"
+msgstr "滚轮å‘å³"
#: editor/project_settings_editor.cpp
msgid "X Button 1"
@@ -10086,7 +10083,7 @@ msgstr "X 按键 2"
#: editor/project_settings_editor.cpp
msgid "Joypad Axis Index:"
-msgstr "手柄摇æ†åºå·ï¼š"
+msgstr "手柄摇æ†ç´¢å¼•:"
#: editor/project_settings_editor.cpp
msgid "Axis"
@@ -10094,15 +10091,15 @@ msgstr "è½´"
#: editor/project_settings_editor.cpp
msgid "Joypad Button Index:"
-msgstr "手柄按钮:"
+msgstr "手柄按钮索引:"
#: editor/project_settings_editor.cpp
msgid "Erase Input Action"
-msgstr "移除输入事件"
+msgstr "移除输入动作"
#: editor/project_settings_editor.cpp
msgid "Erase Input Action Event"
-msgstr "移除输入事件"
+msgstr "移除输入动作事件"
#: editor/project_settings_editor.cpp
msgid "Add Event"
@@ -10122,7 +10119,7 @@ msgstr "å³é”®ã€‚"
#: editor/project_settings_editor.cpp
msgid "Middle Button."
-msgstr "中键(滚轮)。"
+msgstr "中键。"
#: editor/project_settings_editor.cpp
msgid "Wheel Up."
@@ -10138,15 +10135,15 @@ msgstr "添加全局属性"
#: editor/project_settings_editor.cpp
msgid "Select a setting item first!"
-msgstr "请先选择一个设置项目 ï¼"
+msgstr "请先选择一个设置项ï¼"
#: editor/project_settings_editor.cpp
msgid "No property '%s' exists."
-msgstr "ä¸å­˜åœ¨å±žæ€§ “%sâ€ã€‚"
+msgstr "ä¸å­˜åœ¨å±žæ€§â€œ%sâ€ã€‚"
#: editor/project_settings_editor.cpp
msgid "Setting '%s' is internal, and it can't be deleted."
-msgstr "“%s†是内部设定,无法删除。"
+msgstr "“%sâ€æ˜¯å†…部设定,无法删除。"
#: editor/project_settings_editor.cpp
msgid "Delete Item"
@@ -10157,7 +10154,7 @@ msgid ""
"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
"'\"'."
msgstr ""
-"无效的æ“作å称。åç§°ä¸èƒ½ä¸ºç©ºï¼Œä¹Ÿä¸èƒ½åŒ…å« â€œ/â€, “:â€, “=â€, “\\†或者 “\"â€ã€‚"
+"无效的动作å称。动作ä¸èƒ½ä¸ºç©ºï¼Œä¹Ÿä¸èƒ½åŒ…å« â€œ/â€, “:â€, “=â€, “\\†或者 “\"â€ã€‚"
#: editor/project_settings_editor.cpp
msgid "Add Input Action"
@@ -10173,7 +10170,7 @@ msgstr "ä¿å­˜è®¾ç½®æˆåŠŸã€‚"
#: editor/project_settings_editor.cpp
msgid "Moved Input Action Event"
-msgstr "输入动作事件"
+msgstr "移动输入动作事件"
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
@@ -10209,11 +10206,11 @@ msgstr "移除资æºé‡å®šå‘选项"
#: editor/project_settings_editor.cpp
msgid "Changed Locale Filter"
-msgstr "修改区域设置筛选模å¼"
+msgstr "修改区域设置筛选"
#: editor/project_settings_editor.cpp
msgid "Changed Locale Filter Mode"
-msgstr "更改了区域设置筛选模å¼"
+msgstr "修改区域设置筛选模å¼"
#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
@@ -10237,7 +10234,7 @@ msgstr "键使˜ å°„"
#: editor/project_settings_editor.cpp
msgid "Action:"
-msgstr "动作:"
+msgstr "动作:"
#: editor/project_settings_editor.cpp
msgid "Action"
@@ -10253,7 +10250,7 @@ msgstr "设备:"
#: editor/project_settings_editor.cpp
msgid "Index:"
-msgstr "åºå·ï¼š"
+msgstr "索引:"
#: editor/project_settings_editor.cpp
msgid "Localization"
@@ -10277,7 +10274,7 @@ msgstr "资æºï¼š"
#: editor/project_settings_editor.cpp
msgid "Remaps by Locale:"
-msgstr "ä¾ç…§åŒºåŸŸé‡å®šå‘:"
+msgstr "按区域é‡å®šå‘:"
#: editor/project_settings_editor.cpp
msgid "Locale"
@@ -10329,7 +10326,7 @@ msgstr "缓入缓出"
#: editor/property_editor.cpp
msgid "Easing Out-In"
-msgstr "å缓入缓出"
+msgstr "缓出缓入"
#: editor/property_editor.cpp
msgid "File..."
@@ -11832,10 +11829,6 @@ msgid "Can't copy the function node."
msgstr "无法å¤åˆ¶å‡½æ•°èŠ‚ç‚¹ã€‚"
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "å‰ªè´´æ¿æ˜¯ç©ºçš„ï¼"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "粘贴 VisualScript 节点"
@@ -12043,7 +12036,7 @@ msgstr "未在项目中安装 Android 构建模æ¿ã€‚从项目èœå•安装它。
msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
-msgstr ""
+msgstr "Debug Keystoreã€Debug Userã€Debug Password 必须全部填写或者全部留空。"
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12054,6 +12047,7 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Release Keystoreã€Release Userã€Release Password 必须全部填写或者全部留空。"
#: platform/android/export/export.cpp
msgid "Release keystore incorrectly configured in the export preset."
@@ -12946,6 +12940,12 @@ msgstr "å˜é‡åªèƒ½åœ¨é¡¶ç‚¹å‡½æ•°ä¸­æŒ‡å®šã€‚"
msgid "Constants cannot be modified."
msgstr "ä¸å…许修改常é‡ã€‚"
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "动画播放器ä¸èƒ½åŠ¨ç”»åŒ–è‡ªå·±ï¼Œåªèƒ½åŠ¨ç”»åŒ–å…¶ä»–æ’­æ”¾å™¨ã€‚"
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "å‰ªè´´æ¿æ˜¯ç©ºçš„"
+
#~ msgid ""
#~ "Godot editor was built without ray tracing support; lightmaps can't be "
#~ "baked.\n"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index eee6eb62b7..28a69ee289 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -435,10 +435,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr ""
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr ""
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "沒有ROOT以新增新動畫軌跡"
@@ -486,8 +482,9 @@ msgid "Anim Move Keys"
msgstr "移動動畫幀"
#: editor/animation_track_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
-msgid "Clipboard is empty"
+msgid "Clipboard is empty!"
msgstr "路徑為空"
#: editor/animation_track_editor.cpp
@@ -2575,7 +2572,7 @@ msgstr "離開å‰è¦å…ˆå„²å­˜ä»¥ä¸‹ scene 的任何更改嗎?"
#: editor/editor_node.cpp
#, fuzzy
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "開啟 Project Manager å‰è¦å…ˆå„²å­˜ä»¥ä¸‹ scene 的任何更改嗎?"
#: editor/editor_node.cpp
@@ -12291,11 +12288,6 @@ msgstr ""
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
-msgid "Clipboard is empty!"
-msgstr "路徑為空"
-
-#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
msgstr "貼上"
@@ -13352,6 +13344,10 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#, fuzzy
+#~ msgid "Clipboard is empty"
+#~ msgstr "路徑為空"
+
#~ msgid "No"
#~ msgstr "å¦"
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index 7aee72ee43..f65d628d63 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -25,12 +25,13 @@
# BinotaLIU <binota@protonmail.ch>, 2020.
# BinotaLIU <me@binota.org>, 2020, 2021.
# MintSoda <lionlxh@qq.com>, 2020.
+# meowmeowmeowcat <meowmeowcat1211@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-24 21:36+0000\n"
-"Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n"
+"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"Last-Translator: meowmeowmeowcat <meowmeowcat1211@gmail.com>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hant/>\n"
"Language: zh_TW\n"
@@ -38,7 +39,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -428,10 +429,6 @@ msgid "Animation tracks can only point to AnimationPlayer nodes."
msgstr "å‹•ç•«è»Œåƒ…å¯æŒ‡å‘ AnimationPlayer 節點。"
#: editor/animation_track_editor.cpp
-msgid "An animation player can't animate itself, only other players."
-msgstr "å‹•ç•« Player ç„¡æ³•æ’­æ”¾è‡ªå·±ï¼Œåƒ…å¯æ’­æ”¾å…¶ä»– Player。"
-
-#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
msgstr "沒有根節點時無法新增軌é“"
@@ -476,8 +473,9 @@ msgid "Anim Move Keys"
msgstr "移動動畫關éµç•«æ ¼"
#: editor/animation_track_editor.cpp
-msgid "Clipboard is empty"
-msgstr "剪貼æ¿ç‚ºç©º"
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "剪貼簿為空ï¼"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1125,7 +1123,7 @@ msgstr "Godot 社群感è¬ä½ ï¼"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "按一下以複製。"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2483,7 +2481,7 @@ msgid "Save changes to the following scene(s) before quitting?"
msgstr "退出å‰è¦å…ˆä¿å­˜ä¸‹åˆ—場景嗎?"
#: editor/editor_node.cpp
-msgid "Save changes the following scene(s) before opening Project Manager?"
+msgid "Save changes to the following scene(s) before opening Project Manager?"
msgstr "開啟專案管ç†å“¡å‰è¦å…ˆä¿å­˜ä»¥ä¸‹å ´æ™¯å—Žï¼Ÿ"
#: editor/editor_node.cpp
@@ -11778,10 +11776,6 @@ msgid "Can't copy the function node."
msgstr "無法複製函å¼ç¯€é»žã€‚"
#: modules/visual_script/visual_script_editor.cpp
-msgid "Clipboard is empty!"
-msgstr "剪貼簿為空ï¼"
-
-#: modules/visual_script/visual_script_editor.cpp
msgid "Paste VisualScript Nodes"
msgstr "貼上視覺腳本 (VisualScript) 節點"
@@ -12897,6 +12891,12 @@ msgstr "Varying 變數åªå¯åœ¨é ‚點函å¼ä¸­æŒ‡æ´¾ã€‚"
msgid "Constants cannot be modified."
msgstr "ä¸å¯ä¿®æ”¹å¸¸æ•¸ã€‚"
+#~ msgid "An animation player can't animate itself, only other players."
+#~ msgstr "å‹•ç•« Player ç„¡æ³•æ’­æ”¾è‡ªå·±ï¼Œåƒ…å¯æ’­æ”¾å…¶ä»– Player。"
+
+#~ msgid "Clipboard is empty"
+#~ msgstr "剪貼æ¿ç‚ºç©º"
+
#~ msgid ""
#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
#~ msgstr "InterpolatedCamera å·²åœæ­¢ç¶­è­·ï¼Œä¸”將於 Godot 4.0 中移除。"
diff --git a/main/main.cpp b/main/main.cpp
index f2820fee07..1e5445fd93 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -34,6 +34,7 @@
#include "core/core_string_names.h"
#include "core/crypto/crypto.h"
#include "core/debugger/engine_debugger.h"
+#include "core/extension/extension_api_dump.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
#include "core/io/dir_access.h"
@@ -150,9 +151,9 @@ static bool auto_build_solutions = false;
static DisplayServer::WindowMode window_mode = DisplayServer::WINDOW_MODE_WINDOWED;
static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCREEN_LANDSCAPE;
+static DisplayServer::VSyncMode window_vsync_mode = DisplayServer::VSYNC_ENABLED;
static uint32_t window_flags = 0;
static Size2i window_size = Size2i(1024, 600);
-static bool window_vsync_via_compositor = false;
static int init_screen = -1;
static bool init_fullscreen = false;
@@ -174,7 +175,9 @@ static int frame_delay = 0;
static bool disable_render_loop = false;
static int fixed_fps = -1;
static bool print_fps = false;
-
+#ifdef TOOLS_ENABLED
+static bool dump_extension_api = false;
+#endif
bool profile_gpu = false;
/* Helper methods */
@@ -335,8 +338,6 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n");
OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n");
- OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
- OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
OS::get_singleton()->print(" --tablet-driver Pen tablet input driver.\n");
OS::get_singleton()->print("\n");
@@ -406,6 +407,8 @@ Error Main::test_setup() {
translation_server = memnew(TranslationServer);
+ register_core_extensions();
+
// From `Main::setup2()`.
preregister_module_types();
preregister_server_types();
@@ -546,7 +549,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
translation_server = memnew(TranslationServer);
performance = memnew(Performance);
- ClassDB::register_class<Performance>();
+ GDREGISTER_CLASS(Performance);
engine->add_singleton(Engine::Singleton("Performance", performance));
// Only flush stdout in debug builds by default, as spamming `print()` will
@@ -594,11 +597,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
Vector<String> breakpoints;
bool use_custom_res = true;
bool force_res = false;
- bool saw_vsync_via_compositor_override = false;
#ifdef TOOLS_ENABLED
bool found_project = false;
#endif
- bool use_vsync = false;
packed_data = PackedData::get_singleton();
if (!packed_data) {
@@ -820,12 +821,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "--no-window") { // disable window creation (Windows only)
OS::get_singleton()->set_no_window_mode(true);
- } else if (I->get() == "--enable-vsync-via-compositor") {
- window_vsync_via_compositor = true;
- saw_vsync_via_compositor_override = true;
- } else if (I->get() == "--disable-vsync-via-compositor") {
- window_vsync_via_compositor = false;
- saw_vsync_via_compositor_override = true;
#endif
} else if (I->get() == "--profiling") { // enable profiling
@@ -887,7 +882,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
auto_build_solutions = true;
editor = true;
cmdline_tool = true;
-#ifdef DEBUG_METHODS_ENABLED
+
} else if (I->get() == "--gdnative-generate-json-api" || I->get() == "--gdnative-generate-json-builtin-api") {
// Register as an editor instance to use low-end fallback if relevant.
editor = true;
@@ -895,7 +890,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// We still pass it to the main arguments since the argument handling itself is not done in this function
main_args.push_back(I->get());
-#endif
+ } else if (I->get() == "--dump-extension-api") {
+ // Register as an editor instance to use low-end fallback if relevant.
+ editor = true;
+ cmdline_tool = true;
+ dump_extension_api = true;
+ print_line("dump extension?");
+ main_args.push_back(I->get());
} else if (I->get() == "--export" || I->get() == "--export-debug" ||
I->get() == "--export-pack") { // Export project
// Actually handling is done in start().
@@ -985,11 +986,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "-d" || I->get() == "--debug") {
debug_uri = "local://";
OS::get_singleton()->_debug_stdout = true;
-#if defined(DEBUG_ENABLED) && !defined(SERVER_ENABLED)
+#if defined(DEBUG_ENABLED)
} else if (I->get() == "--debug-collisions") {
debug_collisions = true;
} else if (I->get() == "--debug-navigation") {
debug_navigation = true;
+ } else if (I->get() == "--debug-stringnames") {
+ StringName::set_debug_stringnames(true);
#endif
} else if (I->get() == "--remote-debug") {
if (I->next()) {
@@ -1198,6 +1201,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->set_cmdline(execpath, main_args);
+ register_core_extensions(); //before display
+
GLOBAL_DEF("rendering/driver/driver_name", "Vulkan");
ProjectSettings::get_singleton()->set_custom_property_info("rendering/driver/driver_name",
PropertyInfo(Variant::STRING,
@@ -1274,19 +1279,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
}
- use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true);
- OS::get_singleton()->_use_vsync = use_vsync;
-
- if (!saw_vsync_via_compositor_override) {
- // If one of the command line options to enable/disable vsync via the
- // window compositor ("--enable-vsync-via-compositor" or
- // "--disable-vsync-via-compositor") was present then it overrides the
- // project setting.
- window_vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false);
- }
-
- OS::get_singleton()->_vsync_via_compositor = window_vsync_via_compositor;
-
/* todo restore
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
@@ -1344,7 +1336,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
{
window_orientation = DisplayServer::ScreenOrientation(int(GLOBAL_DEF_BASIC("display/window/handheld/orientation", DisplayServer::ScreenOrientation::SCREEN_LANDSCAPE)));
}
-
+ {
+ window_vsync_mode = DisplayServer::VSyncMode(int(GLOBAL_DEF("display/window/vsync/vsync_mode", DisplayServer::VSyncMode::VSYNC_ENABLED)));
+ }
Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF_BASIC("physics/common/physics_fps", 60));
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps",
PropertyInfo(Variant::INT, "physics/common/physics_fps",
@@ -1537,14 +1531,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
String rendering_driver; // temp broken
Error err;
- display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err);
+ display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_size, err);
if (err != OK || display_server == nullptr) {
//ok i guess we can't use this display server, try other ones
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
if (i == display_driver_idx) {
continue; //don't try the same twice
}
- display_server = DisplayServer::create(i, rendering_driver, window_mode, window_flags, window_size, err);
+ display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_size, err);
if (err == OK && display_server != nullptr) {
break;
}
@@ -2004,6 +1998,11 @@ bool Main::start() {
return false;
}
+
+ if (dump_extension_api) {
+ NativeExtensionAPIDump::generate_extension_json_file("extension_api.json");
+ return false;
+ }
#endif
if (script == "" && game_path == "" && String(GLOBAL_GET("application/run/main_scene")) != "") {
diff --git a/main/performance.cpp b/main/performance.cpp
index a2e53f2ee2..9f5be7b8c4 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -60,16 +60,12 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(OBJECT_RESOURCE_COUNT);
BIND_ENUM_CONSTANT(OBJECT_NODE_COUNT);
BIND_ENUM_CONSTANT(OBJECT_ORPHAN_NODE_COUNT);
- BIND_ENUM_CONSTANT(RENDER_OBJECTS_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_VERTICES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_MATERIAL_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_SHADER_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_SURFACE_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_DRAW_CALLS_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDER_TOTAL_OBJECTS_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDER_TOTAL_PRIMITIVES_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDER_TOTAL_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_VIDEO_MEM_USED);
BIND_ENUM_CONSTANT(RENDER_TEXTURE_MEM_USED);
- BIND_ENUM_CONSTANT(RENDER_VERTEX_MEM_USED);
- BIND_ENUM_CONSTANT(RENDER_USAGE_VIDEO_MEM_TOTAL);
+ BIND_ENUM_CONSTANT(RENDER_BUFFER_MEM_USED);
BIND_ENUM_CONSTANT(PHYSICS_2D_ACTIVE_OBJECTS);
BIND_ENUM_CONSTANT(PHYSICS_2D_COLLISION_PAIRS);
BIND_ENUM_CONSTANT(PHYSICS_2D_ISLAND_COUNT);
@@ -103,16 +99,12 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"object/resources",
"object/nodes",
"object/orphan_nodes",
- "raster/objects_drawn",
- "raster/vertices_drawn",
- "raster/mat_changes",
- "raster/shader_changes",
- "raster/surface_changes",
- "raster/draw_calls",
+ "raster/total_objects_drawn",
+ "raster/total_primitives_drawn",
+ "raster/total_draw_calls",
"video/video_mem",
"video/texture_mem",
- "video/vertex_mem",
- "video/video_mem_max",
+ "video/buffer_mem",
"physics_2d/active_objects",
"physics_2d/collision_pairs",
"physics_2d/islands",
@@ -148,26 +140,18 @@ float Performance::get_monitor(Monitor p_monitor) const {
return _get_node_count();
case OBJECT_ORPHAN_NODE_COUNT:
return Node::orphan_node_count;
- case RENDER_OBJECTS_IN_FRAME:
- return RS::get_singleton()->get_render_info(RS::INFO_OBJECTS_IN_FRAME);
- case RENDER_VERTICES_IN_FRAME:
- return RS::get_singleton()->get_render_info(RS::INFO_VERTICES_IN_FRAME);
- case RENDER_MATERIAL_CHANGES_IN_FRAME:
- return RS::get_singleton()->get_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME);
- case RENDER_SHADER_CHANGES_IN_FRAME:
- return RS::get_singleton()->get_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME);
- case RENDER_SURFACE_CHANGES_IN_FRAME:
- return RS::get_singleton()->get_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME);
- case RENDER_DRAW_CALLS_IN_FRAME:
- return RS::get_singleton()->get_render_info(RS::INFO_DRAW_CALLS_IN_FRAME);
+ case RENDER_TOTAL_OBJECTS_IN_FRAME:
+ return RS::get_singleton()->get_rendering_info(RS::RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME);
+ case RENDER_TOTAL_PRIMITIVES_IN_FRAME:
+ return RS::get_singleton()->get_rendering_info(RS::RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME);
+ case RENDER_TOTAL_DRAW_CALLS_IN_FRAME:
+ return RS::get_singleton()->get_rendering_info(RS::RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME);
case RENDER_VIDEO_MEM_USED:
- return RS::get_singleton()->get_render_info(RS::INFO_VIDEO_MEM_USED);
+ return RS::get_singleton()->get_rendering_info(RS::RENDERING_INFO_VIDEO_MEM_USED);
case RENDER_TEXTURE_MEM_USED:
- return RS::get_singleton()->get_render_info(RS::INFO_TEXTURE_MEM_USED);
- case RENDER_VERTEX_MEM_USED:
- return RS::get_singleton()->get_render_info(RS::INFO_VERTEX_MEM_USED);
- case RENDER_USAGE_VIDEO_MEM_TOTAL:
- return RS::get_singleton()->get_render_info(RS::INFO_USAGE_VIDEO_MEM_TOTAL);
+ return RS::get_singleton()->get_rendering_info(RS::RENDERING_INFO_TEXTURE_MEM_USED);
+ case RENDER_BUFFER_MEM_USED:
+ return RS::get_singleton()->get_rendering_info(RS::RENDERING_INFO_BUFFER_MEM_USED);
case PHYSICS_2D_ACTIVE_OBJECTS:
return PhysicsServer2D::get_singleton()->get_process_info(PhysicsServer2D::INFO_ACTIVE_OBJECTS);
case PHYSICS_2D_COLLISION_PAIRS:
@@ -207,10 +191,6 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
- MONITOR_TYPE_QUANTITY,
- MONITOR_TYPE_QUANTITY,
- MONITOR_TYPE_QUANTITY,
- MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY,
diff --git a/main/performance.h b/main/performance.h
index 122e5a4f9a..174b3500d1 100644
--- a/main/performance.h
+++ b/main/performance.h
@@ -73,16 +73,12 @@ public:
OBJECT_RESOURCE_COUNT,
OBJECT_NODE_COUNT,
OBJECT_ORPHAN_NODE_COUNT,
- RENDER_OBJECTS_IN_FRAME,
- RENDER_VERTICES_IN_FRAME,
- RENDER_MATERIAL_CHANGES_IN_FRAME,
- RENDER_SHADER_CHANGES_IN_FRAME,
- RENDER_SURFACE_CHANGES_IN_FRAME,
- RENDER_DRAW_CALLS_IN_FRAME,
+ RENDER_TOTAL_OBJECTS_IN_FRAME,
+ RENDER_TOTAL_PRIMITIVES_IN_FRAME,
+ RENDER_TOTAL_DRAW_CALLS_IN_FRAME,
RENDER_VIDEO_MEM_USED,
RENDER_TEXTURE_MEM_USED,
- RENDER_VERTEX_MEM_USED,
- RENDER_USAGE_VIDEO_MEM_TOTAL,
+ RENDER_BUFFER_MEM_USED,
PHYSICS_2D_ACTIVE_OBJECTS,
PHYSICS_2D_COLLISION_PAIRS,
PHYSICS_2D_ISLAND_COUNT,
diff --git a/methods.py b/methods.py
index 1afd1ca0d4..fd9978657e 100644
--- a/methods.py
+++ b/methods.py
@@ -231,6 +231,18 @@ def is_module(path):
return True
+def write_disabled_classes(class_list):
+ f = open("core/disabled_classes.gen.h", "w")
+ f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ f.write("#ifndef DISABLED_CLASSES_GEN_H\n")
+ f.write("#define DISABLED_CLASSES_GEN_H\n\n")
+ for c in class_list:
+ cs = c.strip()
+ if cs != "":
+ f.write("#define ClassDB_Disable_" + cs + " 1\n")
+ f.write("\n#endif\n")
+
+
def write_modules(modules):
includes_cpp = ""
preregister_cpp = ""
diff --git a/misc/dist/linux/godot.6 b/misc/dist/linux/godot.6
index 4140094813..3e5bdefdce 100644
--- a/misc/dist/linux/godot.6
+++ b/misc/dist/linux/godot.6
@@ -85,12 +85,6 @@ Force low\-DPI mode (macOS and Windows only).
.TP
\fB\-\-no\-window\fR
Disable window creation (Windows only). Useful together with \fB\-\-script\fR.
-.TP
-\fB\-\-enable\-vsync\-via\-compositor\fR
-When vsync is enabled, vsync via the OS' window compositor (Windows only).
-.TP
-\fB\-\-disable\-vsync\-via\-compositor\fR
-Disable vsync via the OS' window compositor (Windows only).
.SS "Debug options:"
.TP
\fB\-d\fR, \fB\-\-debug\fR
diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion
index 8e14240b53..b29746bfc4 100644
--- a/misc/dist/shell/_godot.zsh-completion
+++ b/misc/dist/shell/_godot.zsh-completion
@@ -51,8 +51,6 @@ _arguments \
'--position[request window position]:position in X,Y format' \
'--low-dpi[force low-DPI mode (macOS and Windows only)]' \
'--no-window[disable window creation (Windows only), useful together with --script]' \
- "--enable-vsync-via-compositor[when Vsync is enabled, Vsync via the OS' window compositor (Windows only)]" \
- "--disable-vsync-via-compositor[disable Vsync via the OS' window compositor (Windows only)]" \
'(-d --debug)'{-d,--debug}'[debug (local stdout debugger)]' \
'(-b --breakpoints)'{-b,--breakpoints}'[specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)]:breakpoint list' \
'--profiling[enable profiling in the script debugger]' \
diff --git a/misc/dist/shell/godot.bash-completion b/misc/dist/shell/godot.bash-completion
index 14f2be37b1..03861e43f8 100644
--- a/misc/dist/shell/godot.bash-completion
+++ b/misc/dist/shell/godot.bash-completion
@@ -54,8 +54,6 @@ _complete_godot_options() {
--position
--low-dpi
--no-window
---enable-vsync-via-compositor
---disable-vsync-via-compositor
--debug
--breakpoints
--profiling
diff --git a/misc/dist/shell/godot.fish b/misc/dist/shell/godot.fish
index a485a1dcdb..1367665bbc 100644
--- a/misc/dist/shell/godot.fish
+++ b/misc/dist/shell/godot.fish
@@ -61,8 +61,6 @@ complete -c godot -l resolution -d "Request window resolution" -x
complete -c godot -l position -d "Request window position" -x
complete -c godot -l low-dpi -d "Force low-DPI mode (macOS and Windows only)"
complete -c godot -l no-window -d "Disable window creation (Windows only), useful together with --script"
-complete -c godot -l enable-vsync-via-compositor -d "When Vsync is enabled, Vsync via the OS' window compositor (Windows only)"
-complete -c godot -l disable-vsync-via-compositor -d "Disable Vsync via the OS' window compositor (Windows only)"
# Debug options:
complete -c godot -s d -l debug -d "Debug (local stdout debugger)"
diff --git a/modules/basis_universal/register_types.cpp b/modules/basis_universal/register_types.cpp
index 23639a4f2f..9a13406900 100644
--- a/modules/basis_universal/register_types.cpp
+++ b/modules/basis_universal/register_types.cpp
@@ -272,7 +272,7 @@ void register_basis_universal_types() {
Image::basis_universal_packer = basis_universal_packer;
#endif
Image::basis_universal_unpacker = basis_universal_unpacker;
- //ClassDB::register_class<TextureBasisU>();
+ //GDREGISTER_CLASS(TextureBasisU);
}
void unregister_basis_universal_types() {
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index e92b6c189c..1fd656c9b4 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -47,17 +47,12 @@ bool godotContactAddedCallback(btManifoldPoint &cp, const btCollisionObjectWrapp
return true;
}
-bool GodotFilterCallback::test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask) {
- return body0_collision_layer & body1_collision_mask || body1_collision_layer & body0_collision_mask;
-}
-
bool GodotFilterCallback::needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const {
- return GodotFilterCallback::test_collision_filters(proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask, proxy1->m_collisionFilterGroup, proxy1->m_collisionFilterMask);
+ return (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) || (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
}
bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
- const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
- if (needs) {
+ if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
@@ -90,8 +85,7 @@ bool GodotAllConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) con
return false;
}
- const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
- if (needs) {
+ if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
if (m_exclude->has(gObj->get_self())) {
@@ -123,8 +117,7 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo
}
bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
- const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
- if (needs) {
+ if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
if (gObj == m_self_object) {
@@ -150,8 +143,7 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox
}
bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
- const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
- if (needs) {
+ if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
@@ -188,8 +180,7 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
return false;
}
- const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
- if (needs) {
+ if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
@@ -244,8 +235,7 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr
return false;
}
- const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
- if (needs) {
+ if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
@@ -287,8 +277,7 @@ btScalar GodotContactPairContactResultCallback::addSingleResult(btManifoldPoint
}
bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
- const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
- if (needs) {
+ if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h
index f92665f3e4..9216322108 100644
--- a/modules/bullet/godot_result_callbacks.h
+++ b/modules/bullet/godot_result_callbacks.h
@@ -47,8 +47,6 @@ bool godotContactAddedCallback(btManifoldPoint &cp, const btCollisionObjectWrapp
/// This class is required to implement custom collision behaviour in the broadphase
struct GodotFilterCallback : public btOverlapFilterCallback {
- static bool test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask);
-
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const;
};
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index 33dd9ef56d..8c286a8629 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -1093,7 +1093,6 @@ private:
const btCollisionObject *self_collision_object;
uint32_t collision_layer = 0;
- uint32_t collision_mask = 0;
struct CompoundLeafCallback : btDbvt::ICollide {
private:
@@ -1123,10 +1122,9 @@ public:
Vector<BroadphaseResult> results;
public:
- RecoverPenetrationBroadPhaseCallback(const btCollisionObject *p_self_collision_object, uint32_t p_collision_layer, uint32_t p_collision_mask, btVector3 p_aabb_min, btVector3 p_aabb_max) :
+ RecoverPenetrationBroadPhaseCallback(const btCollisionObject *p_self_collision_object, uint32_t p_collision_layer, btVector3 p_aabb_min, btVector3 p_aabb_max) :
self_collision_object(p_self_collision_object),
- collision_layer(p_collision_layer),
- collision_mask(p_collision_mask) {
+ collision_layer(p_collision_layer) {
bounds = btDbvtVolume::FromMM(p_aabb_min, p_aabb_max);
}
@@ -1135,7 +1133,7 @@ public:
virtual bool process(const btBroadphaseProxy *proxy) {
btCollisionObject *co = static_cast<btCollisionObject *>(proxy->m_clientObject);
if (co->getInternalType() <= btCollisionObject::CO_RIGID_BODY) {
- if (self_collision_object != proxy->m_clientObject && GodotFilterCallback::test_collision_filters(collision_layer, collision_mask, proxy->m_collisionFilterGroup, proxy->m_collisionFilterMask)) {
+ if (self_collision_object != proxy->m_clientObject && (collision_layer & proxy->m_collisionFilterMask)) {
if (co->getCollisionShape()->isCompound()) {
const btCompoundShape *cs = static_cast<btCompoundShape *>(co->getCollisionShape());
@@ -1218,7 +1216,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
}
// Perform broadphase test
- RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask(), aabb_min, aabb_max);
+ RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), aabb_min, aabb_max);
dynamicsWorld->getBroadphase()->aabbTest(aabb_min, aabb_max, recover_broad_result);
bool penetration = false;
@@ -1409,7 +1407,7 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT
}
// Perform broadphase test
- RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask(), aabb_min, aabb_max);
+ RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), aabb_min, aabb_max);
dynamicsWorld->getBroadphase()->aabbTest(aabb_min, aabb_max, recover_broad_result);
int ray_count = 0;
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 5a37486568..57206ae18b 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -42,7 +42,7 @@ inline static bool is_snapable(const Vector3 &p_point1, const Vector3 &p_point2,
inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2], const Vector2 p_uvs[2], const Vector2 &p_interpolation_point) {
float segment_length = (p_segement_points[1] - p_segement_points[0]).length();
- if (segment_length < CMP_EPSILON) {
+ if (p_segement_points[0].is_equal_approx(p_segement_points[1])) {
return p_uvs[0];
}
@@ -53,13 +53,13 @@ inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2],
}
inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const Vector2 p_uvs[3], const Vector2 &p_interpolation_point) {
- if (p_interpolation_point.distance_squared_to(p_vertices[0]) < CMP_EPSILON2) {
+ if (p_interpolation_point.is_equal_approx(p_vertices[0])) {
return p_uvs[0];
}
- if (p_interpolation_point.distance_squared_to(p_vertices[1]) < CMP_EPSILON2) {
+ if (p_interpolation_point.is_equal_approx(p_vertices[1])) {
return p_uvs[1];
}
- if (p_interpolation_point.distance_squared_to(p_vertices[2]) < CMP_EPSILON2) {
+ if (p_interpolation_point.is_equal_approx(p_vertices[2])) {
return p_uvs[2];
}
@@ -589,7 +589,7 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de
Vector3 intersection_point;
// Check if faces are co-planar.
- if ((current_normal - face_normal).length_squared() < CMP_EPSILON2 &&
+ if (current_normal.is_equal_approx(face_normal) &&
is_point_in_triangle(face_center, current_points)) {
// Only add an intersection if not a B face.
if (!face.from_b) {
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 6b0c2604e3..729dc2f8fc 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -140,7 +140,7 @@ void CSGShape3D::_make_dirty() {
if (parent) {
parent->_make_dirty();
} else if (!dirty) {
- call_deferred("_update_shape");
+ call_deferred(SNAME("_update_shape"));
}
dirty = true;
@@ -778,7 +778,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
}
}
- bool flat = normal[0].distance_to(normal[1]) < CMP_EPSILON && normal[0].distance_to(normal[2]) < CMP_EPSILON;
+ bool flat = normal[0].is_equal_approx(normal[1]) && normal[0].is_equal_approx(normal[2]);
vw[as + j + 0] = vertex[0];
vw[as + j + 1] = vertex[1];
@@ -820,7 +820,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
}
}
- bool flat = normal[0].distance_to(normal[1]) < CMP_EPSILON && normal[0].distance_to(normal[2]) < CMP_EPSILON;
+ bool flat = normal[0].is_equal_approx(normal[1]) && normal[0].is_equal_approx(normal[2]);
vw[as + j + 0] = vertex[0];
vw[as + j + 1] = vertex[1];
@@ -868,7 +868,7 @@ void CSGMesh3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh3D::get_material);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
}
void CSGMesh3D::set_mesh(const Ref<Mesh> &p_mesh) {
@@ -1027,7 +1027,7 @@ void CSGSphere3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
}
void CSGSphere3D::set_radius(const float p_radius) {
@@ -1197,7 +1197,7 @@ void CSGBox3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_material"), &CSGBox3D::get_material);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
}
void CSGBox3D::set_size(const Vector3 &p_size) {
@@ -1373,12 +1373,12 @@ void CSGCylinder3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGCylinder3D::set_smooth_faces);
ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGCylinder3D::get_smooth_faces);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_radius", "get_radius");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_sides", "get_sides");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cone"), "set_cone", "is_cone");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
}
void CSGCylinder3D::set_radius(const float p_radius) {
@@ -1592,12 +1592,12 @@ void CSGTorus3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGTorus3D::set_smooth_faces);
ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGTorus3D::get_smooth_faces);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_inner_radius", "get_inner_radius");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_outer_radius", "get_outer_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_sides", "get_sides");
ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_sides", "get_ring_sides");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
}
void CSGTorus3D::set_inner_radius(const float p_inner_radius) {
@@ -2158,13 +2158,13 @@ void CSGPolygon3D::_notification(int p_what) {
void CSGPolygon3D::_validate_property(PropertyInfo &property) const {
if (property.name.begins_with("spin") && mode != MODE_SPIN) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("path") && mode != MODE_PATH) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "depth" && mode != MODE_DEPTH) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
CSGShape3D::_validate_property(property);
@@ -2224,17 +2224,17 @@ void CSGPolygon3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Depth,Spin,Path"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_depth", "get_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_depth", "get_depth");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spin_degrees", PROPERTY_HINT_RANGE, "1,360,0.1"), "set_spin_degrees", "get_spin_degrees");
ADD_PROPERTY(PropertyInfo(Variant::INT, "spin_sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_spin_sides", "get_spin_sides");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "path_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Path3D"), "set_path_node", "get_path_node");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_interval", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_path_interval", "get_path_interval");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_interval", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_path_interval", "get_path_interval");
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_rotation", PROPERTY_HINT_ENUM, "Polygon,Path,PathFollow"), "set_path_rotation", "get_path_rotation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_local"), "set_path_local", "is_path_local");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_continuous_u"), "set_path_continuous_u", "is_path_continuous_u");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_joined"), "set_path_joined", "is_path_joined");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
BIND_ENUM_CONSTANT(MODE_DEPTH);
BIND_ENUM_CONSTANT(MODE_SPIN);
diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp
index e28f44d1eb..a47390c2b2 100644
--- a/modules/csg/register_types.cpp
+++ b/modules/csg/register_types.cpp
@@ -36,15 +36,15 @@
void register_csg_types() {
#ifndef _3D_DISABLED
- ClassDB::register_virtual_class<CSGShape3D>();
- ClassDB::register_virtual_class<CSGPrimitive3D>();
- ClassDB::register_class<CSGMesh3D>();
- ClassDB::register_class<CSGSphere3D>();
- ClassDB::register_class<CSGBox3D>();
- ClassDB::register_class<CSGCylinder3D>();
- ClassDB::register_class<CSGTorus3D>();
- ClassDB::register_class<CSGPolygon3D>();
- ClassDB::register_class<CSGCombiner3D>();
+ GDREGISTER_VIRTUAL_CLASS(CSGShape3D);
+ GDREGISTER_VIRTUAL_CLASS(CSGPrimitive3D);
+ GDREGISTER_CLASS(CSGMesh3D);
+ GDREGISTER_CLASS(CSGSphere3D);
+ GDREGISTER_CLASS(CSGBox3D);
+ GDREGISTER_CLASS(CSGCylinder3D);
+ GDREGISTER_CLASS(CSGTorus3D);
+ GDREGISTER_CLASS(CSGPolygon3D);
+ GDREGISTER_CLASS(CSGCombiner3D);
#ifdef TOOLS_ENABLED
EditorPlugins::add_by_type<EditorPluginCSG>();
diff --git a/modules/enet/config.py b/modules/enet/config.py
index 5fd343c75d..3662b2d94e 100644
--- a/modules/enet/config.py
+++ b/modules/enet/config.py
@@ -8,7 +8,7 @@ def configure(env):
def get_doc_classes():
return [
- "NetworkedMultiplayerENet",
+ "ENetMultiplayerPeer",
]
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/ENetMultiplayerPeer.xml
index 271cb03c9f..30dec5987b 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/ENetMultiplayerPeer.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" version="4.0">
+<class name="ENetMultiplayerPeer" inherits="MultiplayerPeer" version="4.0">
<brief_description>
PacketPeer implementation using the [url=http://enet.bespin.org/index.html]ENet[/url] library.
</brief_description>
<description>
- A PacketPeer implementation that should be passed to [member SceneTree.network_peer] after being initialized as either a client or server. Events can then be handled by connecting to [SceneTree] signals.
+ A PacketPeer implementation that should be passed to [member MultiplayerAPI.network_peer] after being initialized as either a client or server. Events can then be handled by connecting to [SceneTree] signals.
ENet's purpose is to provide a relatively thin, simple and robust network communication layer on top of UDP (User Datagram Protocol).
[b]Note:[/b] ENet only uses UDP, not TCP. When forwarding the server port to make your server accessible on the public Internet, you only need to forward the server port in UDP. You can use the [UPNP] class to try to forward the server port automatically when starting the server.
</description>
@@ -36,7 +36,7 @@
<argument index="4" name="local_port" type="int" default="0">
</argument>
<description>
- Create client that connects to a server at [code]address[/code] using specified [code]port[/code]. The given address needs to be either a fully qualified domain name (e.g. [code]"www.example.com"[/code]) or an IP address in IPv4 or IPv6 format (e.g. [code]"192.168.1.1"[/code]). The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [constant OK] if a client was created, [constant ERR_ALREADY_IN_USE] if this NetworkedMultiplayerENet instance already has an open connection (in which case you need to call [method close_connection] first) or [constant ERR_CANT_CREATE] if the client could not be created. If [code]local_port[/code] is specified, the client will also listen to the given port; this is useful for some NAT traversal techniques.
+ Create client that connects to a server at [code]address[/code] using specified [code]port[/code]. The given address needs to be either a fully qualified domain name (e.g. [code]"www.example.com"[/code]) or an IP address in IPv4 or IPv6 format (e.g. [code]"192.168.1.1"[/code]). The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [constant OK] if a client was created, [constant ERR_ALREADY_IN_USE] if this ENetMultiplayerPeer instance already has an open connection (in which case you need to call [method close_connection] first) or [constant ERR_CANT_CREATE] if the client could not be created. If [code]local_port[/code] is specified, the client will also listen to the given port; this is useful for some NAT traversal techniques.
</description>
</method>
<method name="create_server">
@@ -51,7 +51,7 @@
<argument index="3" name="out_bandwidth" type="int" default="0">
</argument>
<description>
- Create server that listens to connections via [code]port[/code]. The port needs to be an available, unused port between 0 and 65535. Note that ports below 1024 are privileged and may require elevated permissions depending on the platform. To change the interface the server listens on, use [method set_bind_ip]. The default IP is the wildcard [code]"*"[/code], which listens on all available interfaces. [code]max_clients[/code] is the maximum number of clients that are allowed at once, any number up to 4095 may be used, although the achievable number of simultaneous clients may be far lower and depends on the application. For additional details on the bandwidth parameters, see [method create_client]. Returns [constant OK] if a server was created, [constant ERR_ALREADY_IN_USE] if this NetworkedMultiplayerENet instance already has an open connection (in which case you need to call [method close_connection] first) or [constant ERR_CANT_CREATE] if the server could not be created.
+ Create server that listens to connections via [code]port[/code]. The port needs to be an available, unused port between 0 and 65535. Note that ports below 1024 are privileged and may require elevated permissions depending on the platform. To change the interface the server listens on, use [method set_bind_ip]. The default IP is the wildcard [code]"*"[/code], which listens on all available interfaces. [code]max_clients[/code] is the maximum number of clients that are allowed at once, any number up to 4095 may be used, although the achievable number of simultaneous clients may be far lower and depends on the application. For additional details on the bandwidth parameters, see [method create_client]. Returns [constant OK] if a server was created, [constant ERR_ALREADY_IN_USE] if this ENetMultiplayerPeer instance already has an open connection (in which case you need to call [method close_connection] first) or [constant ERR_CANT_CREATE] if the server could not be created.
</description>
</method>
<method name="disconnect_peer">
@@ -150,13 +150,14 @@
</methods>
<members>
<member name="always_ordered" type="bool" setter="set_always_ordered" getter="is_always_ordered" default="false">
- Enforce ordered packets when using [constant NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE] (thus behaving similarly to [constant NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE_ORDERED]). This is the only way to use ordering with the RPC system.
+ Enforce ordered packets when using [constant MultiplayerPeer.TRANSFER_MODE_UNRELIABLE] (thus behaving similarly to [constant MultiplayerPeer.TRANSFER_MODE_UNRELIABLE_ORDERED]). This is the only way to use ordering with the RPC system.
</member>
<member name="channel_count" type="int" setter="set_channel_count" getter="get_channel_count" default="3">
The number of channels to be used by ENet. Channels are used to separate different kinds of data. In reliable or ordered mode, for example, the packet delivery order is ensured on a per-channel basis. This is done to combat latency and reduces ordering restrictions on packets. The delivery status of a packet in one channel won't stall the delivery of other packets in another channel.
</member>
- <member name="compression_mode" type="int" setter="set_compression_mode" getter="get_compression_mode" enum="NetworkedMultiplayerENet.CompressionMode" default="0">
+ <member name="compression_mode" type="int" setter="set_compression_mode" getter="get_compression_mode" enum="ENetMultiplayerPeer.CompressionMode" default="1">
The compression method used for network packets. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all.
+ [b]Note:[/b] Most games' network design involve sending many small packets frequently (smaller than 4 KB each). If in doubt, it is recommended to keep the default compression algorithm as it works best on these small packets.
</member>
<member name="dtls_verify" type="bool" setter="set_dtls_verify_enabled" getter="is_dtls_verify_enabled" default="true">
Enable or disable certificate verification when [member use_dtls] [code]true[/code].
@@ -168,7 +169,7 @@
<member name="transfer_channel" type="int" setter="set_transfer_channel" getter="get_transfer_channel" default="-1">
Set the default channel to be used to transfer data. By default, this value is [code]-1[/code] which means that ENet will only use 2 channels: one for reliable packets, and one for unreliable packets. The channel [code]0[/code] is reserved and cannot be used. Setting this member to any value between [code]0[/code] and [member channel_count] (excluded) will force ENet to use that channel for sending data. See [member channel_count] for more information about ENet channels.
</member>
- <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="NetworkedMultiplayerPeer.TransferMode" default="2" />
+ <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="MultiplayerPeer.TransferMode" default="2" />
<member name="use_dtls" type="bool" setter="set_dtls_enabled" getter="is_dtls_enabled" default="false">
When enabled, the client or server created by this peer, will use [PacketPeerDTLS] instead of raw UDP sockets for communicating with the remote peer. This will make the communication encrypted with DTLS at the cost of higher resource usage and potentially larger packet size.
Note: When creating a DTLS server, make sure you setup the key/certificate pair via [method set_dtls_key] and [method set_dtls_certificate]. For DTLS clients, have a look at the [member dtls_verify] option, and configure the certificate accordingly via [method set_dtls_certificate].
@@ -176,10 +177,10 @@
</members>
<constants>
<constant name="COMPRESS_NONE" value="0" enum="CompressionMode">
- No compression. This uses the most bandwidth, but has the upside of requiring the fewest CPU resources.
+ No compression. This uses the most bandwidth, but has the upside of requiring the fewest CPU resources. This option may also be used to make network debugging using tools like Wireshark easier.
</constant>
<constant name="COMPRESS_RANGE_CODER" value="1" enum="CompressionMode">
- ENet's built-in range encoding.
+ ENet's built-in range encoding. Works well on small packets, but is not the most efficient algorithm on packets larger than 4 KB.
</constant>
<constant name="COMPRESS_FASTLZ" value="2" enum="CompressionMode">
[url=http://fastlz.org/]FastLZ[/url] compression. This option uses less CPU resources compared to [constant COMPRESS_ZLIB], at the expense of using more bandwidth.
@@ -188,7 +189,7 @@
[url=https://www.zlib.net/]Zlib[/url] compression. This option uses less bandwidth compared to [constant COMPRESS_FASTLZ], at the expense of using more CPU resources.
</constant>
<constant name="COMPRESS_ZSTD" value="4" enum="CompressionMode">
- [url=https://facebook.github.io/zstd/]Zstandard[/url] compression.
+ [url=https://facebook.github.io/zstd/]Zstandard[/url] compression. Note that this algorithm is not very efficient on packets smaller than 4 KB. Therefore, it's recommended to use other compression algorithms in most cases.
</constant>
</constants>
</class>
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/enet_multiplayer_peer.cpp
index 94260e8c13..b4ca93f4d9 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/enet_multiplayer_peer.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* networked_multiplayer_enet.cpp */
+/* enet_multiplayer_peer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,45 +28,45 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "networked_multiplayer_enet.h"
+#include "enet_multiplayer_peer.h"
#include "core/io/ip.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
-void NetworkedMultiplayerENet::set_transfer_mode(TransferMode p_mode) {
+void ENetMultiplayerPeer::set_transfer_mode(TransferMode p_mode) {
transfer_mode = p_mode;
}
-NetworkedMultiplayerPeer::TransferMode NetworkedMultiplayerENet::get_transfer_mode() const {
+MultiplayerPeer::TransferMode ENetMultiplayerPeer::get_transfer_mode() const {
return transfer_mode;
}
-void NetworkedMultiplayerENet::set_target_peer(int p_peer) {
+void ENetMultiplayerPeer::set_target_peer(int p_peer) {
target_peer = p_peer;
}
-int NetworkedMultiplayerENet::get_packet_peer() const {
+int ENetMultiplayerPeer::get_packet_peer() const {
ERR_FAIL_COND_V_MSG(!active, 1, "The multiplayer instance isn't currently active.");
ERR_FAIL_COND_V(incoming_packets.size() == 0, 1);
return incoming_packets.front()->get().from;
}
-int NetworkedMultiplayerENet::get_packet_channel() const {
+int ENetMultiplayerPeer::get_packet_channel() const {
ERR_FAIL_COND_V_MSG(!active, -1, "The multiplayer instance isn't currently active.");
ERR_FAIL_COND_V(incoming_packets.size() == 0, -1);
return incoming_packets.front()->get().channel;
}
-int NetworkedMultiplayerENet::get_last_packet_channel() const {
+int ENetMultiplayerPeer::get_last_packet_channel() const {
ERR_FAIL_COND_V_MSG(!active, -1, "The multiplayer instance isn't currently active.");
ERR_FAIL_COND_V(!current_packet.packet, -1);
return current_packet.channel;
}
-Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) {
+Error ENetMultiplayerPeer::create_server(int p_port, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) {
ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "The multiplayer instance is already active.");
ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");
ERR_FAIL_COND_V_MSG(p_max_clients < 1 || p_max_clients > 4095, ERR_INVALID_PARAMETER, "The number of clients must be set between 1 and 4095 (inclusive).");
@@ -115,7 +115,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int
connection_status = CONNECTION_CONNECTED;
return OK;
}
-Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_port, int p_in_bandwidth, int p_out_bandwidth, int p_local_port) {
+Error ENetMultiplayerPeer::create_client(const String &p_address, int p_port, int p_in_bandwidth, int p_out_bandwidth, int p_local_port) {
ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "The multiplayer instance is already active.");
ERR_FAIL_COND_V_MSG(p_port < 1 || p_port > 65535, ERR_INVALID_PARAMETER, "The remote port number must be between 1 and 65535 (inclusive).");
ERR_FAIL_COND_V_MSG(p_local_port < 0 || p_local_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");
@@ -199,7 +199,7 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por
return OK;
}
-void NetworkedMultiplayerENet::poll() {
+void ENetMultiplayerPeer::poll() {
ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active.");
_pop_current_packet();
@@ -249,7 +249,7 @@ void NetworkedMultiplayerENet::poll() {
connection_status = CONNECTION_CONNECTED; // If connecting, this means it connected to something!
- emit_signal("peer_connected", *new_id);
+ emit_signal(SNAME("peer_connected"), *new_id);
if (server) {
// Do not notify other peers when server_relay is disabled.
@@ -274,7 +274,7 @@ void NetworkedMultiplayerENet::poll() {
enet_peer_send(E->get(), SYSCH_CONFIG, packet);
}
} else {
- emit_signal("connection_succeeded");
+ emit_signal(SNAME("connection_succeeded"));
}
} break;
@@ -285,7 +285,7 @@ void NetworkedMultiplayerENet::poll() {
if (!id) {
if (!server) {
- emit_signal("connection_failed");
+ emit_signal(SNAME("connection_failed"));
}
// Never fully connected.
break;
@@ -293,7 +293,7 @@ void NetworkedMultiplayerENet::poll() {
if (!server) {
// Client just disconnected from server.
- emit_signal("server_disconnected");
+ emit_signal(SNAME("server_disconnected"));
close_connection();
return;
} else if (server_relay) {
@@ -310,7 +310,7 @@ void NetworkedMultiplayerENet::poll() {
}
}
- emit_signal("peer_disconnected", *id);
+ emit_signal(SNAME("peer_disconnected"), *id);
peer_map.erase(*id);
memdelete(id);
} break;
@@ -328,12 +328,12 @@ void NetworkedMultiplayerENet::poll() {
switch (msg) {
case SYSMSG_ADD_PEER: {
peer_map[id] = nullptr;
- emit_signal("peer_connected", id);
+ emit_signal(SNAME("peer_connected"), id);
} break;
case SYSMSG_REMOVE_PEER: {
peer_map.erase(id);
- emit_signal("peer_disconnected", id);
+ emit_signal(SNAME("peer_disconnected"), id);
} break;
}
@@ -426,13 +426,13 @@ void NetworkedMultiplayerENet::poll() {
}
}
-bool NetworkedMultiplayerENet::is_server() const {
+bool ENetMultiplayerPeer::is_server() const {
ERR_FAIL_COND_V_MSG(!active, false, "The multiplayer instance isn't currently active.");
return server;
}
-void NetworkedMultiplayerENet::close_connection(uint32_t wait_usec) {
+void ENetMultiplayerPeer::close_connection(uint32_t wait_usec) {
ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active.");
_pop_current_packet();
@@ -463,7 +463,7 @@ void NetworkedMultiplayerENet::close_connection(uint32_t wait_usec) {
connection_status = CONNECTION_DISCONNECTED;
}
-void NetworkedMultiplayerENet::disconnect_peer(int p_peer, bool now) {
+void ENetMultiplayerPeer::disconnect_peer(int p_peer, bool now) {
ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active.");
ERR_FAIL_COND_MSG(!is_server(), "Can't disconnect a peer when not acting as a server.");
ERR_FAIL_COND_MSG(!peer_map.has(p_peer), vformat("Peer ID %d not found in the list of peers.", p_peer));
@@ -491,18 +491,18 @@ void NetworkedMultiplayerENet::disconnect_peer(int p_peer, bool now) {
memdelete(id);
}
- emit_signal("peer_disconnected", p_peer);
+ emit_signal(SNAME("peer_disconnected"), p_peer);
peer_map.erase(p_peer);
} else {
enet_peer_disconnect_later(peer_map[p_peer], 0);
}
}
-int NetworkedMultiplayerENet::get_available_packet_count() const {
+int ENetMultiplayerPeer::get_available_packet_count() const {
return incoming_packets.size();
}
-Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+Error ENetMultiplayerPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
ERR_FAIL_COND_V_MSG(incoming_packets.size() == 0, ERR_UNAVAILABLE, "No incoming packets available.");
_pop_current_packet();
@@ -516,7 +516,7 @@ Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buff
return OK;
}
-Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+Error ENetMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
ERR_FAIL_COND_V_MSG(!active, ERR_UNCONFIGURED, "The multiplayer instance isn't currently active.");
ERR_FAIL_COND_V_MSG(connection_status != CONNECTION_CONNECTED, ERR_UNCONFIGURED, "The multiplayer instance isn't currently connected to any server or client.");
@@ -591,11 +591,11 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer
return OK;
}
-int NetworkedMultiplayerENet::get_max_packet_size() const {
+int ENetMultiplayerPeer::get_max_packet_size() const {
return 1 << 24; // Anything is good
}
-void NetworkedMultiplayerENet::_pop_current_packet() {
+void ENetMultiplayerPeer::_pop_current_packet() {
if (current_packet.packet) {
enet_packet_destroy(current_packet.packet);
current_packet.packet = nullptr;
@@ -604,11 +604,11 @@ void NetworkedMultiplayerENet::_pop_current_packet() {
}
}
-NetworkedMultiplayerPeer::ConnectionStatus NetworkedMultiplayerENet::get_connection_status() const {
+MultiplayerPeer::ConnectionStatus ENetMultiplayerPeer::get_connection_status() const {
return connection_status;
}
-uint32_t NetworkedMultiplayerENet::_gen_unique_id() const {
+uint32_t ENetMultiplayerPeer::_gen_unique_id() const {
uint32_t hash = 0;
while (hash == 0 || hash == 1) {
@@ -629,12 +629,12 @@ uint32_t NetworkedMultiplayerENet::_gen_unique_id() const {
return hash;
}
-int NetworkedMultiplayerENet::get_unique_id() const {
+int ENetMultiplayerPeer::get_unique_id() const {
ERR_FAIL_COND_V_MSG(!active, 0, "The multiplayer instance isn't currently active.");
return unique_id;
}
-void NetworkedMultiplayerENet::set_refuse_new_connections(bool p_enable) {
+void ENetMultiplayerPeer::set_refuse_new_connections(bool p_enable) {
refuse_connections = p_enable;
#ifdef GODOT_ENET
if (active) {
@@ -643,20 +643,20 @@ void NetworkedMultiplayerENet::set_refuse_new_connections(bool p_enable) {
#endif
}
-bool NetworkedMultiplayerENet::is_refusing_new_connections() const {
+bool ENetMultiplayerPeer::is_refusing_new_connections() const {
return refuse_connections;
}
-void NetworkedMultiplayerENet::set_compression_mode(CompressionMode p_mode) {
+void ENetMultiplayerPeer::set_compression_mode(CompressionMode p_mode) {
compression_mode = p_mode;
}
-NetworkedMultiplayerENet::CompressionMode NetworkedMultiplayerENet::get_compression_mode() const {
+ENetMultiplayerPeer::CompressionMode ENetMultiplayerPeer::get_compression_mode() const {
return compression_mode;
}
-size_t NetworkedMultiplayerENet::enet_compress(void *context, const ENetBuffer *inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
- NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet *)(context);
+size_t ENetMultiplayerPeer::enet_compress(void *context, const ENetBuffer *inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
+ ENetMultiplayerPeer *enet = (ENetMultiplayerPeer *)(context);
if (size_t(enet->src_compressor_mem.size()) < inLimit) {
enet->src_compressor_mem.resize(inLimit);
@@ -709,8 +709,8 @@ size_t NetworkedMultiplayerENet::enet_compress(void *context, const ENetBuffer *
return ret;
}
-size_t NetworkedMultiplayerENet::enet_decompress(void *context, const enet_uint8 *inData, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
- NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet *)(context);
+size_t ENetMultiplayerPeer::enet_decompress(void *context, const enet_uint8 *inData, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
+ ENetMultiplayerPeer *enet = (ENetMultiplayerPeer *)(context);
int ret = -1;
switch (enet->compression_mode) {
case COMPRESS_FASTLZ: {
@@ -732,7 +732,7 @@ size_t NetworkedMultiplayerENet::enet_decompress(void *context, const enet_uint8
}
}
-void NetworkedMultiplayerENet::_setup_compressor() {
+void ENetMultiplayerPeer::_setup_compressor() {
switch (compression_mode) {
case COMPRESS_NONE: {
enet_host_compress(host, nullptr);
@@ -748,11 +748,11 @@ void NetworkedMultiplayerENet::_setup_compressor() {
}
}
-void NetworkedMultiplayerENet::enet_compressor_destroy(void *context) {
+void ENetMultiplayerPeer::enet_compressor_destroy(void *context) {
// Nothing to do
}
-IPAddress NetworkedMultiplayerENet::get_peer_address(int p_peer_id) const {
+IPAddress ENetMultiplayerPeer::get_peer_address(int p_peer_id) const {
ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), IPAddress(), vformat("Peer ID %d not found in the list of peers.", p_peer_id));
ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, IPAddress(), "Can't get the address of peers other than the server (ID -1) when acting as a client.");
ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == nullptr, IPAddress(), vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id));
@@ -767,7 +767,7 @@ IPAddress NetworkedMultiplayerENet::get_peer_address(int p_peer_id) const {
return out;
}
-int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const {
+int ENetMultiplayerPeer::get_peer_port(int p_peer_id) const {
ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), 0, vformat("Peer ID %d not found in the list of peers.", p_peer_id));
ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, 0, "Can't get the address of peers other than the server (ID -1) when acting as a client.");
ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == nullptr, 0, vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id));
@@ -778,12 +778,12 @@ int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const {
#endif
}
-int NetworkedMultiplayerENet::get_local_port() const {
+int ENetMultiplayerPeer::get_local_port() const {
ERR_FAIL_COND_V_MSG(!active || !host, 0, "The multiplayer instance isn't currently active.");
return host->address.port;
}
-void NetworkedMultiplayerENet::set_peer_timeout(int p_peer_id, int p_timeout_limit, int p_timeout_min, int p_timeout_max) {
+void ENetMultiplayerPeer::set_peer_timeout(int p_peer_id, int p_timeout_limit, int p_timeout_min, int p_timeout_max) {
ERR_FAIL_COND_MSG(!peer_map.has(p_peer_id), vformat("Peer ID %d not found in the list of peers.", p_peer_id));
ERR_FAIL_COND_MSG(!is_server() && p_peer_id != 1, "Can't change the timeout of peers other then the server when acting as a client.");
ERR_FAIL_COND_MSG(peer_map[p_peer_id] == nullptr, vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id));
@@ -791,73 +791,73 @@ void NetworkedMultiplayerENet::set_peer_timeout(int p_peer_id, int p_timeout_lim
enet_peer_timeout(peer_map[p_peer_id], p_timeout_limit, p_timeout_min, p_timeout_max);
}
-void NetworkedMultiplayerENet::set_transfer_channel(int p_channel) {
+void ENetMultiplayerPeer::set_transfer_channel(int p_channel) {
ERR_FAIL_COND_MSG(p_channel < -1 || p_channel >= channel_count, vformat("The transfer channel must be set between 0 and %d, inclusive (got %d).", channel_count - 1, p_channel));
ERR_FAIL_COND_MSG(p_channel == SYSCH_CONFIG, vformat("The channel %d is reserved.", SYSCH_CONFIG));
transfer_channel = p_channel;
}
-int NetworkedMultiplayerENet::get_transfer_channel() const {
+int ENetMultiplayerPeer::get_transfer_channel() const {
return transfer_channel;
}
-void NetworkedMultiplayerENet::set_channel_count(int p_channel) {
+void ENetMultiplayerPeer::set_channel_count(int p_channel) {
ERR_FAIL_COND_MSG(active, "The channel count can't be set while the multiplayer instance is active.");
ERR_FAIL_COND_MSG(p_channel < SYSCH_MAX, vformat("The channel count must be greater than or equal to %d to account for reserved channels (got %d).", SYSCH_MAX, p_channel));
channel_count = p_channel;
}
-int NetworkedMultiplayerENet::get_channel_count() const {
+int ENetMultiplayerPeer::get_channel_count() const {
return channel_count;
}
-void NetworkedMultiplayerENet::set_always_ordered(bool p_ordered) {
+void ENetMultiplayerPeer::set_always_ordered(bool p_ordered) {
always_ordered = p_ordered;
}
-bool NetworkedMultiplayerENet::is_always_ordered() const {
+bool ENetMultiplayerPeer::is_always_ordered() const {
return always_ordered;
}
-void NetworkedMultiplayerENet::set_server_relay_enabled(bool p_enabled) {
+void ENetMultiplayerPeer::set_server_relay_enabled(bool p_enabled) {
ERR_FAIL_COND_MSG(active, "Server relaying can't be toggled while the multiplayer instance is active.");
server_relay = p_enabled;
}
-bool NetworkedMultiplayerENet::is_server_relay_enabled() const {
+bool ENetMultiplayerPeer::is_server_relay_enabled() const {
return server_relay;
}
-void NetworkedMultiplayerENet::_bind_methods() {
- ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("create_client", "address", "port", "in_bandwidth", "out_bandwidth", "local_port"), &NetworkedMultiplayerENet::create_client, DEFVAL(0), DEFVAL(0), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("close_connection", "wait_usec"), &NetworkedMultiplayerENet::close_connection, DEFVAL(100));
- ClassDB::bind_method(D_METHOD("disconnect_peer", "id", "now"), &NetworkedMultiplayerENet::disconnect_peer, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("set_compression_mode", "mode"), &NetworkedMultiplayerENet::set_compression_mode);
- ClassDB::bind_method(D_METHOD("get_compression_mode"), &NetworkedMultiplayerENet::get_compression_mode);
- ClassDB::bind_method(D_METHOD("set_bind_ip", "ip"), &NetworkedMultiplayerENet::set_bind_ip);
- ClassDB::bind_method(D_METHOD("set_dtls_enabled", "enabled"), &NetworkedMultiplayerENet::set_dtls_enabled);
- ClassDB::bind_method(D_METHOD("is_dtls_enabled"), &NetworkedMultiplayerENet::is_dtls_enabled);
- ClassDB::bind_method(D_METHOD("set_dtls_key", "key"), &NetworkedMultiplayerENet::set_dtls_key);
- ClassDB::bind_method(D_METHOD("set_dtls_certificate", "certificate"), &NetworkedMultiplayerENet::set_dtls_certificate);
- ClassDB::bind_method(D_METHOD("set_dtls_verify_enabled", "enabled"), &NetworkedMultiplayerENet::set_dtls_verify_enabled);
- ClassDB::bind_method(D_METHOD("is_dtls_verify_enabled"), &NetworkedMultiplayerENet::is_dtls_verify_enabled);
- ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &NetworkedMultiplayerENet::get_peer_address);
- ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &NetworkedMultiplayerENet::get_peer_port);
- ClassDB::bind_method(D_METHOD("get_local_port"), &NetworkedMultiplayerENet::get_local_port);
- ClassDB::bind_method(D_METHOD("set_peer_timeout", "id", "timeout_limit", "timeout_min", "timeout_max"), &NetworkedMultiplayerENet::set_peer_timeout);
-
- ClassDB::bind_method(D_METHOD("get_packet_channel"), &NetworkedMultiplayerENet::get_packet_channel);
- ClassDB::bind_method(D_METHOD("get_last_packet_channel"), &NetworkedMultiplayerENet::get_last_packet_channel);
- ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &NetworkedMultiplayerENet::set_transfer_channel);
- ClassDB::bind_method(D_METHOD("get_transfer_channel"), &NetworkedMultiplayerENet::get_transfer_channel);
- ClassDB::bind_method(D_METHOD("set_channel_count", "channels"), &NetworkedMultiplayerENet::set_channel_count);
- ClassDB::bind_method(D_METHOD("get_channel_count"), &NetworkedMultiplayerENet::get_channel_count);
- ClassDB::bind_method(D_METHOD("set_always_ordered", "ordered"), &NetworkedMultiplayerENet::set_always_ordered);
- ClassDB::bind_method(D_METHOD("is_always_ordered"), &NetworkedMultiplayerENet::is_always_ordered);
- ClassDB::bind_method(D_METHOD("set_server_relay_enabled", "enabled"), &NetworkedMultiplayerENet::set_server_relay_enabled);
- ClassDB::bind_method(D_METHOD("is_server_relay_enabled"), &NetworkedMultiplayerENet::is_server_relay_enabled);
+void ENetMultiplayerPeer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &ENetMultiplayerPeer::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("create_client", "address", "port", "in_bandwidth", "out_bandwidth", "local_port"), &ENetMultiplayerPeer::create_client, DEFVAL(0), DEFVAL(0), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("close_connection", "wait_usec"), &ENetMultiplayerPeer::close_connection, DEFVAL(100));
+ ClassDB::bind_method(D_METHOD("disconnect_peer", "id", "now"), &ENetMultiplayerPeer::disconnect_peer, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_compression_mode", "mode"), &ENetMultiplayerPeer::set_compression_mode);
+ ClassDB::bind_method(D_METHOD("get_compression_mode"), &ENetMultiplayerPeer::get_compression_mode);
+ ClassDB::bind_method(D_METHOD("set_bind_ip", "ip"), &ENetMultiplayerPeer::set_bind_ip);
+ ClassDB::bind_method(D_METHOD("set_dtls_enabled", "enabled"), &ENetMultiplayerPeer::set_dtls_enabled);
+ ClassDB::bind_method(D_METHOD("is_dtls_enabled"), &ENetMultiplayerPeer::is_dtls_enabled);
+ ClassDB::bind_method(D_METHOD("set_dtls_key", "key"), &ENetMultiplayerPeer::set_dtls_key);
+ ClassDB::bind_method(D_METHOD("set_dtls_certificate", "certificate"), &ENetMultiplayerPeer::set_dtls_certificate);
+ ClassDB::bind_method(D_METHOD("set_dtls_verify_enabled", "enabled"), &ENetMultiplayerPeer::set_dtls_verify_enabled);
+ ClassDB::bind_method(D_METHOD("is_dtls_verify_enabled"), &ENetMultiplayerPeer::is_dtls_verify_enabled);
+ ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &ENetMultiplayerPeer::get_peer_address);
+ ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &ENetMultiplayerPeer::get_peer_port);
+ ClassDB::bind_method(D_METHOD("get_local_port"), &ENetMultiplayerPeer::get_local_port);
+ ClassDB::bind_method(D_METHOD("set_peer_timeout", "id", "timeout_limit", "timeout_min", "timeout_max"), &ENetMultiplayerPeer::set_peer_timeout);
+
+ ClassDB::bind_method(D_METHOD("get_packet_channel"), &ENetMultiplayerPeer::get_packet_channel);
+ ClassDB::bind_method(D_METHOD("get_last_packet_channel"), &ENetMultiplayerPeer::get_last_packet_channel);
+ ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &ENetMultiplayerPeer::set_transfer_channel);
+ ClassDB::bind_method(D_METHOD("get_transfer_channel"), &ENetMultiplayerPeer::get_transfer_channel);
+ ClassDB::bind_method(D_METHOD("set_channel_count", "channels"), &ENetMultiplayerPeer::set_channel_count);
+ ClassDB::bind_method(D_METHOD("get_channel_count"), &ENetMultiplayerPeer::get_channel_count);
+ ClassDB::bind_method(D_METHOD("set_always_ordered", "ordered"), &ENetMultiplayerPeer::set_always_ordered);
+ ClassDB::bind_method(D_METHOD("is_always_ordered"), &ENetMultiplayerPeer::is_always_ordered);
+ ClassDB::bind_method(D_METHOD("set_server_relay_enabled", "enabled"), &ENetMultiplayerPeer::set_server_relay_enabled);
+ ClassDB::bind_method(D_METHOD("is_server_relay_enabled"), &ENetMultiplayerPeer::is_server_relay_enabled);
ADD_PROPERTY(PropertyInfo(Variant::INT, "compression_mode", PROPERTY_HINT_ENUM, "None,Range Coder,FastLZ,ZLib,ZStd"), "set_compression_mode", "get_compression_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_channel"), "set_transfer_channel", "get_transfer_channel");
@@ -874,7 +874,7 @@ void NetworkedMultiplayerENet::_bind_methods() {
BIND_ENUM_CONSTANT(COMPRESS_ZSTD);
}
-NetworkedMultiplayerENet::NetworkedMultiplayerENet() {
+ENetMultiplayerPeer::ENetMultiplayerPeer() {
enet_compressor.context = this;
enet_compressor.compress = enet_compress;
enet_compressor.decompress = enet_decompress;
@@ -883,7 +883,7 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() {
bind_ip = IPAddress("*");
}
-NetworkedMultiplayerENet::~NetworkedMultiplayerENet() {
+ENetMultiplayerPeer::~ENetMultiplayerPeer() {
if (active) {
close_connection();
}
@@ -891,36 +891,36 @@ NetworkedMultiplayerENet::~NetworkedMultiplayerENet() {
// Sets IP for ENet to bind when using create_server or create_client
// if no IP is set, then ENet bind to ENET_HOST_ANY
-void NetworkedMultiplayerENet::set_bind_ip(const IPAddress &p_ip) {
+void ENetMultiplayerPeer::set_bind_ip(const IPAddress &p_ip) {
ERR_FAIL_COND_MSG(!p_ip.is_valid() && !p_ip.is_wildcard(), vformat("Invalid bind IP address: %s", String(p_ip)));
bind_ip = p_ip;
}
-void NetworkedMultiplayerENet::set_dtls_enabled(bool p_enabled) {
+void ENetMultiplayerPeer::set_dtls_enabled(bool p_enabled) {
ERR_FAIL_COND(active);
dtls_enabled = p_enabled;
}
-bool NetworkedMultiplayerENet::is_dtls_enabled() const {
+bool ENetMultiplayerPeer::is_dtls_enabled() const {
return dtls_enabled;
}
-void NetworkedMultiplayerENet::set_dtls_verify_enabled(bool p_enabled) {
+void ENetMultiplayerPeer::set_dtls_verify_enabled(bool p_enabled) {
ERR_FAIL_COND(active);
dtls_verify = p_enabled;
}
-bool NetworkedMultiplayerENet::is_dtls_verify_enabled() const {
+bool ENetMultiplayerPeer::is_dtls_verify_enabled() const {
return dtls_verify;
}
-void NetworkedMultiplayerENet::set_dtls_key(Ref<CryptoKey> p_key) {
+void ENetMultiplayerPeer::set_dtls_key(Ref<CryptoKey> p_key) {
ERR_FAIL_COND(active);
dtls_key = p_key;
}
-void NetworkedMultiplayerENet::set_dtls_certificate(Ref<X509Certificate> p_cert) {
+void ENetMultiplayerPeer::set_dtls_certificate(Ref<X509Certificate> p_cert) {
ERR_FAIL_COND(active);
dtls_cert = p_cert;
}
diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/enet_multiplayer_peer.h
index 2d928859fa..63f2ec5870 100644
--- a/modules/enet/networked_multiplayer_enet.h
+++ b/modules/enet/enet_multiplayer_peer.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* networked_multiplayer_enet.h */
+/* enet_multiplayer_peer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -33,12 +33,12 @@
#include "core/crypto/crypto.h"
#include "core/io/compression.h"
-#include "core/io/networked_multiplayer_peer.h"
+#include "core/io/multiplayer_peer.h"
#include <enet/enet.h>
-class NetworkedMultiplayerENet : public NetworkedMultiplayerPeer {
- GDCLASS(NetworkedMultiplayerENet, NetworkedMultiplayerPeer);
+class ENetMultiplayerPeer : public MultiplayerPeer {
+ GDCLASS(ENetMultiplayerPeer, MultiplayerPeer);
public:
enum CompressionMode {
@@ -90,7 +90,7 @@ private:
int channel = 0;
};
- CompressionMode compression_mode = COMPRESS_NONE;
+ CompressionMode compression_mode = COMPRESS_RANGE_CODER;
List<Packet> incoming_packets;
@@ -168,8 +168,8 @@ public:
void set_server_relay_enabled(bool p_enabled);
bool is_server_relay_enabled() const;
- NetworkedMultiplayerENet();
- ~NetworkedMultiplayerENet();
+ ENetMultiplayerPeer();
+ ~ENetMultiplayerPeer();
void set_bind_ip(const IPAddress &p_ip);
void set_dtls_enabled(bool p_enabled);
@@ -180,6 +180,6 @@ public:
void set_dtls_certificate(Ref<X509Certificate> p_cert);
};
-VARIANT_ENUM_CAST(NetworkedMultiplayerENet::CompressionMode);
+VARIANT_ENUM_CAST(ENetMultiplayerPeer::CompressionMode);
#endif // NETWORKED_MULTIPLAYER_ENET_H
diff --git a/modules/enet/register_types.cpp b/modules/enet/register_types.cpp
index 8da2d17e13..38870316e4 100644
--- a/modules/enet/register_types.cpp
+++ b/modules/enet/register_types.cpp
@@ -30,7 +30,7 @@
#include "register_types.h"
#include "core/error/error_macros.h"
-#include "networked_multiplayer_enet.h"
+#include "enet_multiplayer_peer.h"
static bool enet_ok = false;
@@ -41,7 +41,7 @@ void register_enet_types() {
enet_ok = true;
}
- ClassDB::register_class<NetworkedMultiplayerENet>();
+ GDREGISTER_CLASS(ENetMultiplayerPeer);
}
void unregister_enet_types() {
diff --git a/modules/fbx/data/fbx_material.cpp b/modules/fbx/data/fbx_material.cpp
index cf5d70fa5b..fb6c67f7b9 100644
--- a/modules/fbx/data/fbx_material.cpp
+++ b/modules/fbx/data/fbx_material.cpp
@@ -29,6 +29,10 @@
/*************************************************************************/
#include "fbx_material.h"
+
+// FIXME: Shouldn't depend on core_bind.h! Use DirAccessRef like the rest of
+// the engine instead of _Directory.
+#include "core/core_bind.h"
#include "scene/resources/material.h"
#include "scene/resources/texture.h"
#include "tools/validation_tools.h"
diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp
index 0d33b8e7c6..8b4b1e08b3 100644
--- a/modules/fbx/data/fbx_mesh_data.cpp
+++ b/modules/fbx/data/fbx_mesh_data.cpp
@@ -525,7 +525,7 @@ void FBXMeshData::reorganize_vertices(
}
const Vector3 vert_poly_normal = *nrml_arr->getptr(*pid);
- if ((this_vert_poly_normal - vert_poly_normal).length_squared() > CMP_EPSILON) {
+ if (!vert_poly_normal.is_equal_approx(this_vert_poly_normal)) {
// Yes this polygon need duplication.
need_duplication = true;
break;
@@ -586,7 +586,7 @@ void FBXMeshData::reorganize_vertices(
continue;
}
const Vector2 vert_poly_uv = *uvs->getptr(*pid);
- if (((*this_vert_poly_uv) - vert_poly_uv).length_squared() > CMP_EPSILON) {
+ if (!vert_poly_uv.is_equal_approx(*this_vert_poly_uv)) {
// Yes this polygon need duplication.
need_duplication = true;
break;
diff --git a/modules/fbx/data/import_state.h b/modules/fbx/data/import_state.h
index 83bc43faff..9ba60eaacf 100644
--- a/modules/fbx/data/import_state.h
+++ b/modules/fbx/data/import_state.h
@@ -37,7 +37,6 @@
#include "pivot_transform.h"
-#include "core/core_bind.h"
#include "core/io/resource_importer.h"
#include "core/templates/vector.h"
#include "editor/import/resource_importer_scene.h"
diff --git a/modules/fbx/editor_scene_importer_fbx.h b/modules/fbx/editor_scene_importer_fbx.h
index 4bb2c9d21b..4a3b78480b 100644
--- a/modules/fbx/editor_scene_importer_fbx.h
+++ b/modules/fbx/editor_scene_importer_fbx.h
@@ -36,7 +36,6 @@
#include "data/import_state.h"
#include "tools/import_utils.h"
-#include "core/core_bind.h"
#include "core/io/resource_importer.h"
#include "core/string/ustring.h"
#include "core/templates/local_vector.h"
diff --git a/modules/fbx/register_types.cpp b/modules/fbx/register_types.cpp
index b615c91cd2..a75da8f3a9 100644
--- a/modules/fbx/register_types.cpp
+++ b/modules/fbx/register_types.cpp
@@ -46,7 +46,7 @@ void register_fbx_types() {
ClassDB::APIType prev_api = ClassDB::get_current_api();
ClassDB::set_current_api(ClassDB::API_EDITOR);
- ClassDB::register_class<EditorSceneImporterFBX>();
+ GDREGISTER_CLASS(EditorSceneImporterFBX);
ClassDB::set_current_api(prev_api);
diff --git a/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml b/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
index 9f33d32e81..b88f5e7e1e 100644
--- a/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
+++ b/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerPeerGDNative" inherits="NetworkedMultiplayerPeer" version="4.0">
+<class name="MultiplayerPeerGDNative" inherits="MultiplayerPeer" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp
index b4ac0d886e..f965bcd014 100644
--- a/modules/gdnative/gdnative_library_editor_plugin.cpp
+++ b/modules/gdnative/gdnative_library_editor_plugin.cpp
@@ -74,9 +74,9 @@ void GDNativeLibraryEditor::_update_tree() {
platform->set_text(0, E->get().name);
platform->set_metadata(0, E->get().library_extension);
- platform->set_custom_bg_color(0, get_theme_color("prop_category", "Editor"));
- platform->set_custom_bg_color(1, get_theme_color("prop_category", "Editor"));
- platform->set_custom_bg_color(2, get_theme_color("prop_category", "Editor"));
+ platform->set_custom_bg_color(0, get_theme_color(SNAME("prop_category"), SNAME("Editor")));
+ platform->set_custom_bg_color(1, get_theme_color(SNAME("prop_category"), SNAME("Editor")));
+ platform->set_custom_bg_color(2, get_theme_color(SNAME("prop_category"), SNAME("Editor")));
platform->set_selectable(0, false);
platform->set_expand_right(0, true);
@@ -87,31 +87,31 @@ void GDNativeLibraryEditor::_update_tree() {
bit->set_text(0, it->get());
bit->set_metadata(0, target);
bit->set_selectable(0, false);
- bit->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor"));
+ bit->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
- bit->add_button(1, get_theme_icon("Folder", "EditorIcons"), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry"));
+ bit->add_button(1, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry"));
String file = entry_configs[target].library;
if (!file.is_empty()) {
- bit->add_button(1, get_theme_icon("Clear", "EditorIcons"), BUTTON_CLEAR_LIBRARY, false, TTR("Clear"));
+ bit->add_button(1, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), BUTTON_CLEAR_LIBRARY, false, TTR("Clear"));
}
bit->set_text(1, file);
- bit->add_button(2, get_theme_icon("Folder", "EditorIcons"), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry"));
+ bit->add_button(2, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry"));
Array files = entry_configs[target].dependencies;
if (files.size()) {
- bit->add_button(2, get_theme_icon("Clear", "EditorIcons"), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear"));
+ bit->add_button(2, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear"));
}
bit->set_text(2, Variant(files));
- bit->add_button(3, get_theme_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP, false, TTR("Move Up"));
- bit->add_button(3, get_theme_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN, false, TTR("Move Down"));
- bit->add_button(3, get_theme_icon("Remove", "EditorIcons"), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry"));
+ bit->add_button(3, get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")), BUTTON_MOVE_UP, false, TTR("Move Up"));
+ bit->add_button(3, get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")), BUTTON_MOVE_DOWN, false, TTR("Move Down"));
+ bit->add_button(3, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry"));
}
TreeItem *new_arch = tree->create_item(platform);
new_arch->set_text(0, TTR("Double click to create a new entry"));
new_arch->set_text_align(0, TreeItem::ALIGN_CENTER);
- new_arch->set_custom_color(0, get_theme_color("accent_color", "Editor"));
+ new_arch->set_custom_color(0, get_theme_color(SNAME("accent_color"), SNAME("Editor")));
new_arch->set_expand_right(0, true);
new_arch->set_metadata(1, E->key());
@@ -356,12 +356,12 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() {
tree->set_column_titles_visible(true);
tree->set_columns(4);
tree->set_column_expand(0, false);
- tree->set_column_min_width(0, int(200 * EDSCALE));
+ tree->set_column_custom_minimum_width(0, int(200 * EDSCALE));
tree->set_column_title(0, TTR("Platform"));
tree->set_column_title(1, TTR("Dynamic Library"));
tree->set_column_title(2, TTR("Dependencies"));
tree->set_column_expand(3, false);
- tree->set_column_min_width(3, int(110 * EDSCALE));
+ tree->set_column_custom_minimum_width(3, int(110 * EDSCALE));
tree->connect("button_pressed", callable_mp(this, &GDNativeLibraryEditor::_on_item_button));
tree->connect("item_collapsed", callable_mp(this, &GDNativeLibraryEditor::_on_item_collapsed));
tree->connect("item_activated", callable_mp(this, &GDNativeLibraryEditor::_on_item_activated));
diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h
index dd4f76cf57..a88bd2878a 100644
--- a/modules/gdnative/include/gdnative/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -164,7 +164,7 @@ typedef void (*godot_validated_keyed_getter)(const godot_variant *p_base, const
typedef bool (*godot_validated_keyed_checker)(const godot_variant *p_base, const godot_variant *p_key, bool *r_valid);
typedef void (*godot_ptr_keyed_setter)(void *p_base, const void *p_key, const void *p_value);
typedef void (*godot_ptr_keyed_getter)(const void *p_base, const void *p_key, void *r_value);
-typedef bool (*godot_ptr_keyed_checker)(const godot_variant *p_base, const godot_variant *p_key);
+typedef uint32_t (*godot_ptr_keyed_checker)(const godot_variant *p_base, const godot_variant *p_key);
typedef void (*godot_validated_utility_function)(godot_variant *r_return, const godot_variant **p_arguments, int p_argument_count);
typedef void (*godot_ptr_utility_function)(void *r_return, const void **p_arguments, int p_argument_count);
diff --git a/modules/gdnative/include/net/godot_net.h b/modules/gdnative/include/net/godot_net.h
index 2fa576a5bf..94e7739ef9 100644
--- a/modules/gdnative/include/net/godot_net.h
+++ b/modules/gdnative/include/net/godot_net.h
@@ -90,7 +90,7 @@ typedef struct {
godot_int (*get_available_packet_count)(const void *);
godot_int (*get_max_packet_size)(const void *);
- /* This is NetworkedMultiplayerPeer */
+ /* This is MultiplayerPeer */
void (*set_transfer_mode)(void *, godot_int);
godot_int (*get_transfer_mode)(const void *);
// 0 = broadcast, 1 = server, <0 = all but abs(value)
diff --git a/modules/gdnative/include/net/godot_webrtc.h b/modules/gdnative/include/net/godot_webrtc.h
index 25aa72dae1..62b7e3c2c5 100644
--- a/modules/gdnative/include/net/godot_webrtc.h
+++ b/modules/gdnative/include/net/godot_webrtc.h
@@ -101,6 +101,7 @@ typedef struct {
int (*get_max_retransmits)(const void *);
const char *(*get_protocol)(const void *);
bool (*is_negotiated)(const void *);
+ int (*get_buffered_amount)(const void *);
godot_error (*poll)(void *);
void (*close)(void *);
diff --git a/modules/gdnative/include/text/godot_text.h b/modules/gdnative/include/text/godot_text.h
index f3c50e6f87..6428f2f149 100644
--- a/modules/gdnative/include/text/godot_text.h
+++ b/modules/gdnative/include/text/godot_text.h
@@ -143,13 +143,14 @@ typedef struct {
bool (*shaped_text_shape)(void *, godot_rid *);
bool (*shaped_text_update_breaks)(void *, godot_rid *);
bool (*shaped_text_update_justification_ops)(void *, godot_rid *);
+ void (*shaped_text_overrun_trim_to_width)(void *, godot_rid *, float, uint8_t);
bool (*shaped_text_is_ready)(void *, godot_rid *);
godot_packed_glyph_array (*shaped_text_get_glyphs)(void *, godot_rid *);
godot_vector2i (*shaped_text_get_range)(void *, godot_rid *);
godot_packed_glyph_array (*shaped_text_sort_logical)(void *, godot_rid *);
godot_packed_vector2i_array (*shaped_text_get_line_breaks_adv)(void *, godot_rid *, godot_packed_float32_array *, int, bool, uint8_t);
godot_packed_vector2i_array (*shaped_text_get_line_breaks)(void *, godot_rid *, float, int, uint8_t);
- godot_packed_vector2i_array (*shaped_text_get_word_breaks)(void *, godot_rid *);
+ godot_packed_vector2i_array (*shaped_text_get_word_breaks)(void *, godot_rid *, int);
godot_array (*shaped_text_get_objects)(void *, godot_rid *);
godot_rect2 (*shaped_text_get_object_rect)(void *, godot_rid *, const godot_variant *);
godot_vector2 (*shaped_text_get_size)(void *, godot_rid *);
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index 4f696f2a39..477bc9f74d 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -405,7 +405,7 @@ List<ClassAPI> generate_c_api_classes() {
arg_type = Variant::get_type_name(arg_info.type);
}
} else {
- arg_type = Variant::get_type_name(arg_info.type);
+ arg_type = get_type_name(arg_info);
}
method_api.argument_names.push_back(arg_name);
diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp
index b10a747568..70b14836bf 100644
--- a/modules/gdnative/nativescript/godot_nativescript.cpp
+++ b/modules/gdnative/nativescript/godot_nativescript.cpp
@@ -332,7 +332,7 @@ void GDAPI godot_nativescript_unregister_instance_binding_data_functions(int p_i
}
void GDAPI *godot_nativescript_get_instance_binding_data(int p_idx, godot_object *p_object) {
- return NativeScriptLanguage::get_singleton()->get_instance_binding_data(p_idx, (Object *)p_object);
+ return nullptr;
}
void GDAPI godot_nativescript_profiling_add_data(const char *p_signature, uint64_t p_time) {
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index 3695f6b9a3..d7943827c2 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -1258,6 +1258,8 @@ void NativeScriptLanguage::unregister_binding_functions(int p_idx) {
}
void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_object) {
+ return nullptr;
+#if 0
ERR_FAIL_INDEX_V(p_idx, binding_functions.size(), nullptr);
ERR_FAIL_COND_V_MSG(!binding_functions[p_idx].first, nullptr, "Tried to get binding data for a nativescript binding that does not exist.");
@@ -1287,9 +1289,12 @@ void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_objec
}
return (*binding_data)[p_idx];
+#endif
}
void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) {
+ return nullptr;
+#if 0
Vector<void *> *binding_data = new Vector<void *>;
binding_data->resize(binding_functions.size());
@@ -1301,9 +1306,11 @@ void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) {
binding_instances.insert(binding_data);
return (void *)binding_data;
+#endif
}
void NativeScriptLanguage::free_instance_binding_data(void *p_data) {
+#if 0
if (!p_data) {
return;
}
@@ -1323,9 +1330,11 @@ void NativeScriptLanguage::free_instance_binding_data(void *p_data) {
binding_instances.erase(&binding_data);
delete &binding_data;
+#endif
}
void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_object) {
+#if 0
void *data = p_object->get_script_instance_binding(lang_idx);
if (!data) {
@@ -1347,9 +1356,11 @@ void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_objec
binding_functions[i].second.refcount_incremented_instance_binding(binding_data[i], p_object);
}
}
+#endif
}
bool NativeScriptLanguage::refcount_decremented_instance_binding(Object *p_object) {
+#if 0
void *data = p_object->get_script_instance_binding(lang_idx);
if (!data) {
@@ -1375,6 +1386,8 @@ bool NativeScriptLanguage::refcount_decremented_instance_binding(Object *p_objec
}
return can_die;
+#endif
+ return false;
}
void NativeScriptLanguage::set_global_type_tag(int p_idx, StringName p_class_name, const void *p_type_tag) {
diff --git a/modules/gdnative/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp
index 0191cfd809..82a3459517 100644
--- a/modules/gdnative/nativescript/register_types.cpp
+++ b/modules/gdnative/nativescript/register_types.cpp
@@ -45,7 +45,7 @@ Ref<ResourceFormatSaverNativeScript> resource_saver_gdns;
void register_nativescript_types() {
native_script_language = memnew(NativeScriptLanguage);
- ClassDB::register_class<NativeScript>();
+ GDREGISTER_CLASS(NativeScript);
native_script_language->set_language_index(ScriptServer::get_language_count());
ScriptServer::register_language(native_script_language);
diff --git a/modules/gdnative/net/multiplayer_peer_gdnative.cpp b/modules/gdnative/net/multiplayer_peer_gdnative.cpp
index 8b5fc8db5c..8ceba0f339 100644
--- a/modules/gdnative/net/multiplayer_peer_gdnative.cpp
+++ b/modules/gdnative/net/multiplayer_peer_gdnative.cpp
@@ -61,13 +61,13 @@ int MultiplayerPeerGDNative::get_available_packet_count() const {
return interface->get_available_packet_count(interface->data);
}
-/* NetworkedMultiplayerPeer */
+/* MultiplayerPeer */
void MultiplayerPeerGDNative::set_transfer_mode(TransferMode p_mode) {
ERR_FAIL_COND(interface == nullptr);
interface->set_transfer_mode(interface->data, (godot_int)p_mode);
}
-NetworkedMultiplayerPeer::TransferMode MultiplayerPeerGDNative::get_transfer_mode() const {
+MultiplayerPeer::TransferMode MultiplayerPeerGDNative::get_transfer_mode() const {
ERR_FAIL_COND_V(interface == nullptr, TRANSFER_MODE_UNRELIABLE);
return (TransferMode)interface->get_transfer_mode(interface->data);
}
@@ -107,7 +107,7 @@ bool MultiplayerPeerGDNative::is_refusing_new_connections() const {
return interface->is_refusing_new_connections(interface->data);
}
-NetworkedMultiplayerPeer::ConnectionStatus MultiplayerPeerGDNative::get_connection_status() const {
+MultiplayerPeer::ConnectionStatus MultiplayerPeerGDNative::get_connection_status() const {
ERR_FAIL_COND_V(interface == nullptr, CONNECTION_DISCONNECTED);
return (ConnectionStatus)interface->get_connection_status(interface->data);
}
diff --git a/modules/gdnative/net/multiplayer_peer_gdnative.h b/modules/gdnative/net/multiplayer_peer_gdnative.h
index 593b2534dd..7c10ab77f7 100644
--- a/modules/gdnative/net/multiplayer_peer_gdnative.h
+++ b/modules/gdnative/net/multiplayer_peer_gdnative.h
@@ -31,12 +31,12 @@
#ifndef MULTIPLAYER_PEER_GDNATIVE_H
#define MULTIPLAYER_PEER_GDNATIVE_H
-#include "core/io/networked_multiplayer_peer.h"
+#include "core/io/multiplayer_peer.h"
#include "modules/gdnative/gdnative.h"
#include "modules/gdnative/include/net/godot_net.h"
-class MultiplayerPeerGDNative : public NetworkedMultiplayerPeer {
- GDCLASS(MultiplayerPeerGDNative, NetworkedMultiplayerPeer);
+class MultiplayerPeerGDNative : public MultiplayerPeer {
+ GDCLASS(MultiplayerPeerGDNative, MultiplayerPeer);
protected:
static void _bind_methods();
@@ -55,7 +55,7 @@ public:
virtual int get_max_packet_size() const override;
virtual int get_available_packet_count() const override;
- /* Specific to NetworkedMultiplayerPeer */
+ /* Specific to MultiplayerPeer */
virtual void set_transfer_mode(TransferMode p_mode) override;
virtual TransferMode get_transfer_mode() const override;
virtual void set_target_peer(int p_peer_id) override;
diff --git a/modules/gdnative/net/register_types.cpp b/modules/gdnative/net/register_types.cpp
index 645c43b7e3..46c383e5ae 100644
--- a/modules/gdnative/net/register_types.cpp
+++ b/modules/gdnative/net/register_types.cpp
@@ -34,9 +34,9 @@
#include "stream_peer_gdnative.h"
void register_net_types() {
- ClassDB::register_class<MultiplayerPeerGDNative>();
- ClassDB::register_class<PacketPeerGDNative>();
- ClassDB::register_class<StreamPeerGDNative>();
+ GDREGISTER_CLASS(MultiplayerPeerGDNative);
+ GDREGISTER_CLASS(PacketPeerGDNative);
+ GDREGISTER_CLASS(StreamPeerGDNative);
}
void unregister_net_types() {
diff --git a/modules/gdnative/pluginscript/register_types.cpp b/modules/gdnative/pluginscript/register_types.cpp
index 433544178f..7faacfdcb9 100644
--- a/modules/gdnative/pluginscript/register_types.cpp
+++ b/modules/gdnative/pluginscript/register_types.cpp
@@ -107,7 +107,7 @@ void GDAPI godot_pluginscript_register_language(const godot_pluginscript_languag
}
void register_pluginscript_types() {
- ClassDB::register_class<PluginScript>();
+ GDREGISTER_CLASS(PluginScript);
}
void unregister_pluginscript_types() {
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 8e20a2b90d..8e5ae29ed9 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -259,8 +259,8 @@ void register_gdnative_types() {
EditorNode::add_init_callback(editor_init_callback);
#endif
- ClassDB::register_class<GDNativeLibrary>();
- ClassDB::register_class<GDNative>();
+ GDREGISTER_CLASS(GDNativeLibrary);
+ GDREGISTER_CLASS(GDNative);
resource_loader_gdnlib.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_gdnlib);
diff --git a/modules/gdnative/text/text_server_gdnative.cpp b/modules/gdnative/text/text_server_gdnative.cpp
index bc4b1ac134..81dd570bcb 100644
--- a/modules/gdnative/text/text_server_gdnative.cpp
+++ b/modules/gdnative/text/text_server_gdnative.cpp
@@ -498,6 +498,11 @@ bool TextServerGDNative::shaped_text_update_justification_ops(RID p_shaped) {
return interface->shaped_text_update_justification_ops(data, (godot_rid *)&p_shaped);
}
+void TextServerGDNative::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint8_t p_clip_flags) {
+ ERR_FAIL_COND(interface == nullptr);
+ interface->shaped_text_overrun_trim_to_width(data, (godot_rid *)&p_shaped_line, p_width, p_clip_flags);
+};
+
bool TextServerGDNative::shaped_text_is_ready(RID p_shaped) const {
ERR_FAIL_COND_V(interface == nullptr, false);
return interface->shaped_text_is_ready(data, (godot_rid *)&p_shaped);
@@ -550,15 +555,15 @@ Vector<Vector2i> TextServerGDNative::shaped_text_get_line_breaks(RID p_shaped, f
}
}
-Vector<Vector2i> TextServerGDNative::shaped_text_get_word_breaks(RID p_shaped) const {
+Vector<Vector2i> TextServerGDNative::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
ERR_FAIL_COND_V(interface == nullptr, Vector<Vector2i>());
if (interface->shaped_text_get_word_breaks != nullptr) {
- godot_packed_vector2i_array result = interface->shaped_text_get_word_breaks(data, (godot_rid *)&p_shaped);
+ godot_packed_vector2i_array result = interface->shaped_text_get_word_breaks(data, (godot_rid *)&p_shaped, p_grapheme_flags);
Vector<Vector2i> breaks = *(Vector<Vector2i> *)&result;
godot_packed_vector2i_array_destroy(&result);
return breaks;
} else {
- return TextServer::shaped_text_get_word_breaks(p_shaped);
+ return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags);
}
}
diff --git a/modules/gdnative/text/text_server_gdnative.h b/modules/gdnative/text/text_server_gdnative.h
index 7e42b16fe1..7a0725f3d9 100644
--- a/modules/gdnative/text/text_server_gdnative.h
+++ b/modules/gdnative/text/text_server_gdnative.h
@@ -167,6 +167,8 @@ public:
virtual bool shaped_text_update_breaks(RID p_shaped) override;
virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
+ virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_clip_flags) override;
+
virtual bool shaped_text_is_ready(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const override;
@@ -176,7 +178,7 @@ public:
virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) override;
virtual Vector<Vector2i> shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<float> &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint8_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
- virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped) const override;
+ virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
virtual Array shaped_text_get_objects(RID p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override;
diff --git a/modules/gdnative/videodecoder/register_types.cpp b/modules/gdnative/videodecoder/register_types.cpp
index e822d42312..54a577a2b6 100644
--- a/modules/gdnative/videodecoder/register_types.cpp
+++ b/modules/gdnative/videodecoder/register_types.cpp
@@ -39,7 +39,7 @@ void register_videodecoder_types() {
resource_loader_vsgdnative.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_vsgdnative, true);
- ClassDB::register_class<VideoStreamGDNative>();
+ GDREGISTER_CLASS(VideoStreamGDNative);
}
void unregister_videodecoder_types() {
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
index 26b044c0ef..4c9bfb395d 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
@@ -185,7 +185,7 @@ void VideoStreamPlaybackGDNative::update_texture() {
Ref<Image> img = memnew(Image(texture_size.width, texture_size.height, 0, Image::FORMAT_RGBA8, *pba));
- texture->update(img, true);
+ texture->update(img);
}
// ctor and dtor
diff --git a/modules/gdnative/xr/register_types.cpp b/modules/gdnative/xr/register_types.cpp
index b60a04f470..cb043debc5 100644
--- a/modules/gdnative/xr/register_types.cpp
+++ b/modules/gdnative/xr/register_types.cpp
@@ -32,7 +32,7 @@
#include "xr_interface_gdnative.h"
void register_xr_types() {
- ClassDB::register_class<XRInterfaceGDNative>();
+ GDREGISTER_CLASS(XRInterfaceGDNative);
ClassDB::add_compatibility_class("ARVRInterfaceGDNative", "XRInterfaceGDNative");
}
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 79ec9eb65f..9a4c22f49f 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -448,7 +448,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
color_regions.clear();
color_region_cache.clear();
- font_color = text_edit->get_theme_color("font_color");
+ font_color = text_edit->get_theme_color(SNAME("font_color"));
symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
function_color = EDITOR_GET("text_editor/highlighting/function_color");
number_color = EDITOR_GET("text_editor/highlighting/number_color");
diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.h b/modules/gdscript/editor/gdscript_translation_parser_plugin.h
index fcf438422a..caa80fc24c 100644
--- a/modules/gdscript/editor/gdscript_translation_parser_plugin.h
+++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.h
@@ -34,7 +34,6 @@
#include "core/templates/set.h"
#include "editor/editor_translation_parser.h"
#include "modules/gdscript/gdscript_parser.h"
-#include "modules/regex/regex.h"
class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlugin {
GDCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin);
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 397776ba1a..d0b7722847 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1165,15 +1165,11 @@ void GDScript::_init_rpc_methods_properties() {
while (cscript) {
// RPC Methods
for (Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.front(); E; E = E->next()) {
- if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
- MultiplayerAPI::RPCConfig nd;
- nd.name = E->key();
- nd.rpc_mode = E->get()->get_rpc_mode();
- // TODO
- nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
- nd.channel = 0;
- if (-1 == rpc_functions.find(nd)) {
- rpc_functions.push_back(nd);
+ MultiplayerAPI::RPCConfig config = E->get()->get_rpc_config();
+ if (config.rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) {
+ config.name = E->get()->get_name();
+ if (rpc_functions.find(config) == -1) {
+ rpc_functions.push_back(config);
}
}
}
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 078b7a2fd0..24809ad5fd 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -64,7 +64,6 @@ class GDScript : public Script {
int index = 0;
StringName setter;
StringName getter;
- MultiplayerAPI::RPCMode rpc_mode;
GDScriptDataType data_type;
};
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 5a297cc50a..9ff5a342ec 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -155,7 +155,7 @@ void GDScriptByteCodeGenerator::end_parameters() {
function->default_arguments.reverse();
}
-void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCMode p_rpc_mode, const GDScriptDataType &p_return_type) {
+void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) {
function = memnew(GDScriptFunction);
debug_stack = EngineDebugger::is_active();
@@ -170,7 +170,7 @@ void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName
function->_static = p_static;
function->return_type = p_return_type;
- function->rpc_mode = p_rpc_mode;
+ function->rpc_config = p_rpc_config;
function->_argument_count = 0;
}
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index b1f3cd5fb3..3d6fb291ad 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -419,7 +419,7 @@ public:
virtual void start_block() override;
virtual void end_block() override;
- virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCMode p_rpc_mode, const GDScriptDataType &p_return_type) override;
+ virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) override;
virtual GDScriptFunction *write_end() override;
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h
index cac6544f03..ecc86c37f3 100644
--- a/modules/gdscript/gdscript_codegen.h
+++ b/modules/gdscript/gdscript_codegen.h
@@ -80,7 +80,7 @@ public:
virtual void start_block() = 0;
virtual void end_block() = 0;
- virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCMode p_rpc_mode, const GDScriptDataType &p_return_type) = 0;
+ virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) = 0;
virtual GDScriptFunction *write_end() = 0;
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 7fa8e9c067..fbe791a109 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1859,7 +1859,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
StringName func_name;
bool is_static = false;
- MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+ MultiplayerAPI::RPCConfig rpc_config;
GDScriptDataType return_type;
return_type.has_type = true;
return_type.kind = GDScriptDataType::BUILTIN;
@@ -1872,7 +1872,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
func_name = "<anonymous lambda>";
}
is_static = p_func->is_static;
- rpc_mode = p_func->rpc_mode;
+ rpc_config = p_func->rpc_config;
return_type = _gdtype_from_datatype(p_func->get_datatype(), p_script);
} else {
if (p_for_ready) {
@@ -1883,7 +1883,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
}
codegen.function_name = func_name;
- codegen.generator->write_start(p_script, func_name, is_static, rpc_mode, return_type);
+ codegen.generator->write_start(p_script, func_name, is_static, rpc_config, return_type);
int optional_parameters = 0;
@@ -2088,7 +2088,7 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP
return_type = _gdtype_from_datatype(p_variable->get_datatype(), p_script);
}
- codegen.generator->write_start(p_script, func_name, false, p_variable->rpc_mode, return_type);
+ codegen.generator->write_start(p_script, func_name, false, MultiplayerAPI::RPCConfig(), return_type);
if (p_is_setter) {
uint32_t par_addr = codegen.generator->add_parameter(p_variable->setter_parameter->name, false, _gdtype_from_datatype(p_variable->get_datatype()));
@@ -2268,7 +2268,6 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
}
break;
}
- minfo.rpc_mode = variable->rpc_mode;
minfo.data_type = _gdtype_from_datatype(variable->get_datatype(), p_script);
PropertyInfo prop_info = minfo.data_type;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index b149828a2f..c1a7bedbc8 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -3038,9 +3038,9 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
if (!is_function) {
// Guess in autoloads as singletons.
if (ProjectSettings::get_singleton()->has_autoload(p_symbol)) {
- const ProjectSettings::AutoloadInfo &singleton = ProjectSettings::get_singleton()->get_autoload(p_symbol);
- if (singleton.is_singleton) {
- String script = singleton.path;
+ const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(p_symbol);
+ if (autoload.is_singleton) {
+ String script = autoload.path;
if (!script.ends_with(".gd")) {
// Not a script, try find the script anyway,
// may have some success.
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 78399114a5..f300d5a2c9 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -262,9 +262,9 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
if (completed) {
if (first_state.is_valid()) {
- first_state->emit_signal("completed", ret);
+ first_state->emit_signal(SNAME("completed"), ret);
} else {
- emit_signal("completed", ret);
+ emit_signal(SNAME("completed"), ret);
}
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 553c2ecc01..9e5ef0f632 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -472,7 +472,7 @@ private:
int _initial_line = 0;
bool _static = false;
- MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+ MultiplayerAPI::RPCConfig rpc_config;
GDScript *_script = nullptr;
@@ -592,7 +592,7 @@ public:
void disassemble(const Vector<String> &p_code_lines) const;
#endif
- _FORCE_INLINE_ MultiplayerAPI::RPCMode get_rpc_mode() const { return rpc_mode; }
+ _FORCE_INLINE_ MultiplayerAPI::RPCConfig get_rpc_config() const { return rpc_config; }
GDScriptFunction();
~GDScriptFunction();
};
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index ba208ebfe8..df36afc0f0 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -157,7 +157,6 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_multiline"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_MULTILINE_TEXT, Variant::STRING>);
register_annotation(MethodInfo("@export_placeholder"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_PLACEHOLDER_TEXT, Variant::STRING>);
register_annotation(MethodInfo("@export_range", { Variant::FLOAT, "min" }, { Variant::FLOAT, "max" }, { Variant::FLOAT, "step" }, { Variant::STRING, "slider1" }, { Variant::STRING, "slider2" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_RANGE, Variant::FLOAT>, 3);
- register_annotation(MethodInfo("@export_exp_range", { Variant::FLOAT, "min" }, { Variant::FLOAT, "max" }, { Variant::FLOAT, "step" }, { Variant::STRING, "slider1" }, { Variant::STRING, "slider2" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_RANGE, Variant::FLOAT>, 3);
register_annotation(MethodInfo("@export_exp_easing", { Variant::STRING, "hint1" }, { Variant::STRING, "hint2" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_EASING, Variant::FLOAT>, 2);
register_annotation(MethodInfo("@export_color_no_alpha"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_COLOR_NO_ALPHA, Variant::COLOR>);
register_annotation(MethodInfo("@export_node_path", { Variant::STRING, "type" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NODE_PATH_VALID_TYPES, Variant::NODE_PATH>, 1, true);
@@ -169,12 +168,7 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
// Networking.
- register_annotation(MethodInfo("@remote"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_REMOTE>);
- register_annotation(MethodInfo("@master"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_MASTER>);
- register_annotation(MethodInfo("@puppet"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_PUPPET>);
- register_annotation(MethodInfo("@remotesync"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_REMOTESYNC>);
- register_annotation(MethodInfo("@mastersync"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_MASTERSYNC>);
- register_annotation(MethodInfo("@puppetsync"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_PUPPETSYNC>);
+ register_annotation(MethodInfo("@rpc", { Variant::STRING, "mode" }, { Variant::STRING, "sync" }, { Variant::STRING, "transfer_mode" }, { Variant::INT, "transfer_channel" }), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_MASTER>, 4, true);
// TODO: Warning annotations.
}
@@ -3431,27 +3425,60 @@ template <MultiplayerAPI::RPCMode t_mode>
bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Node *p_node) {
ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE && p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to variables and functions.)", p_annotation->name));
- switch (p_node->type) {
- case Node::VARIABLE: {
- VariableNode *variable = static_cast<VariableNode *>(p_node);
- if (variable->rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) {
- push_error(R"(RPC annotations can only be used once per variable.)", p_annotation);
+ MultiplayerAPI::RPCConfig rpc_config;
+ rpc_config.rpc_mode = t_mode;
+ for (int i = 0; i < p_annotation->resolved_arguments.size(); i++) {
+ if (i == 0) {
+ String mode = p_annotation->resolved_arguments[i].operator String();
+ if (mode == "any") {
+ rpc_config.rpc_mode = MultiplayerAPI::RPC_MODE_REMOTE;
+ } else if (mode == "master") {
+ rpc_config.rpc_mode = MultiplayerAPI::RPC_MODE_MASTER;
+ } else if (mode == "puppet") {
+ rpc_config.rpc_mode = MultiplayerAPI::RPC_MODE_PUPPET;
+ } else {
+ push_error(R"(Invalid RPC mode. Must be one of: 'any', 'master', or 'puppet')", p_annotation);
+ return false;
}
- variable->rpc_mode = t_mode;
- break;
+ } else if (i == 1) {
+ String sync = p_annotation->resolved_arguments[i].operator String();
+ if (sync == "sync") {
+ rpc_config.sync = true;
+ } else if (sync == "nosync") {
+ rpc_config.sync = false;
+ } else {
+ push_error(R"(Invalid RPC sync mode. Must be one of: 'sync' or 'nosync')", p_annotation);
+ return false;
+ }
+ } else if (i == 2) {
+ String mode = p_annotation->resolved_arguments[i].operator String();
+ if (mode == "reliable") {
+ rpc_config.transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ } else if (mode == "unreliable") {
+ rpc_config.transfer_mode = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE;
+ } else if (mode == "ordered") {
+ rpc_config.transfer_mode = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED;
+ } else {
+ push_error(R"(Invalid RPC transfer mode. Must be one of: 'reliable', 'unreliable', 'ordered')", p_annotation);
+ return false;
+ }
+ } else if (i == 3) {
+ rpc_config.channel = p_annotation->resolved_arguments[i].operator int();
}
+ }
+ switch (p_node->type) {
case Node::FUNCTION: {
FunctionNode *function = static_cast<FunctionNode *>(p_node);
- if (function->rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) {
+ if (function->rpc_config.rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) {
push_error(R"(RPC annotations can only be used once per function.)", p_annotation);
+ return false;
}
- function->rpc_mode = t_mode;
+ function->rpc_config = rpc_config;
break;
}
default:
return false; // Unreachable.
}
-
return true;
}
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 9e0b60a407..043d87c705 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -729,7 +729,7 @@ public:
SuiteNode *body = nullptr;
bool is_static = false;
bool is_coroutine = false;
- MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+ MultiplayerAPI::RPCConfig rpc_config;
MethodInfo info;
LambdaNode *source_lambda = nullptr;
#ifdef TOOLS_ENABLED
@@ -1117,7 +1117,6 @@ public:
bool exported = false;
bool onready = false;
PropertyInfo export_info;
- MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
int assignments = 0;
int usages = 0;
bool use_conversion_assign = false;
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index f817964a3c..e9a7bf3830 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -695,7 +695,9 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio
ERR_FAIL_NULL_V(p_func, func);
func["name"] = p_func->identifier->name;
func["return_type"] = p_func->get_datatype().to_string();
- func["rpc_mode"] = p_func->rpc_mode;
+ func["rpc_mode"] = p_func->rpc_config.rpc_mode;
+ func["rpc_transfer_mode"] = p_func->rpc_config.transfer_mode;
+ func["rpc_transfer_channel"] = p_func->rpc_config.channel;
Array parameters;
for (int i = 0; i < p_func->parameters.size(); i++) {
Dictionary arg;
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index 969c38eab6..5a2dd55c46 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDSCRIPT_PROTOCAL_SERVER_H
-#define GDSCRIPT_PROTOCAL_SERVER_H
+#ifndef GDSCRIPT_LANGUAGE_PROTOCOL_H
+#define GDSCRIPT_LANGUAGE_PROTOCOL_H
#include "core/io/stream_peer.h"
#include "core/io/stream_peer_tcp.h"
@@ -37,7 +37,13 @@
#include "gdscript_text_document.h"
#include "gdscript_workspace.h"
#include "lsp.hpp"
+
+#include "modules/modules_enabled.gen.h"
+#ifdef MODULE_JSONRPC_ENABLED
#include "modules/jsonrpc/jsonrpc.h"
+#else
+#error "Can't build GDScript LSP without JSONRPC module."
+#endif
#define LSP_MAX_BUFFER_SIZE 4194304
#define LSP_MAX_CLIENTS 8
@@ -108,4 +114,4 @@ public:
GDScriptLanguageProtocol();
};
-#endif
+#endif // GDSCRIPT_LANGUAGE_PROTOCOL_H
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 33597c286f..c47164d95b 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -101,7 +101,7 @@ void GDScriptLanguageServer::stop() {
}
void register_lsp_types() {
- ClassDB::register_class<GDScriptLanguageProtocol>();
- ClassDB::register_class<GDScriptTextDocument>();
- ClassDB::register_class<GDScriptWorkspace>();
+ GDREGISTER_CLASS(GDScriptLanguageProtocol);
+ GDREGISTER_CLASS(GDScriptTextDocument);
+ GDREGISTER_CLASS(GDScriptWorkspace);
}
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 030633274c..55aff618aa 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -40,6 +40,7 @@
void GDScriptTextDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen);
+ ClassDB::bind_method(D_METHOD("didClose"), &GDScriptTextDocument::didClose);
ClassDB::bind_method(D_METHOD("didChange"), &GDScriptTextDocument::didChange);
ClassDB::bind_method(D_METHOD("nativeSymbol"), &GDScriptTextDocument::nativeSymbol);
ClassDB::bind_method(D_METHOD("documentSymbol"), &GDScriptTextDocument::documentSymbol);
@@ -61,6 +62,11 @@ void GDScriptTextDocument::didOpen(const Variant &p_param) {
sync_script_content(doc.uri, doc.text);
}
+void GDScriptTextDocument::didClose(const Variant &p_param) {
+ // Left empty on purpose. Godot does nothing special on closing a document,
+ // but it satisfies LSP clients that require didClose be implemented.
+}
+
void GDScriptTextDocument::didChange(const Variant &p_param) {
lsp::TextDocumentItem doc = load_document_item(p_param);
Dictionary dict = p_param;
@@ -367,7 +373,7 @@ Variant GDScriptTextDocument::declaration(const Dictionary &p_params) {
id = "class_global:" + symbol->native_class + ":" + symbol->name;
break;
}
- call_deferred("show_native_symbol_in_editor", id);
+ call_deferred(SNAME("show_native_symbol_in_editor"), id);
} else {
notify_client_show_symbol(symbol);
}
@@ -404,7 +410,7 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin
}
void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) {
- ScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id);
+ ScriptEditor::get_singleton()->call_deferred(SNAME("_help_class_goto"), p_symbol_id);
DisplayServer::get_singleton()->window_move_to_foreground();
}
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index 17f1d5d5e3..e2987f779c 100644
--- a/modules/gdscript/language_server/gdscript_text_document.h
+++ b/modules/gdscript/language_server/gdscript_text_document.h
@@ -43,6 +43,7 @@ protected:
FileAccess *file_checker;
void didOpen(const Variant &p_param);
+ void didClose(const Variant &p_param);
void didChange(const Variant &p_param);
void sync_script_content(const String &p_path, const String &p_content);
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index ad4ed8bf71..c2b1981f31 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -112,7 +112,7 @@ static void _editor_init() {
#endif // TOOLS_ENABLED
void register_gdscript_types() {
- ClassDB::register_class<GDScript>();
+ GDREGISTER_CLASS(GDScript);
script_language_gd = memnew(GDScriptLanguage);
ScriptServer::register_language(script_language_gd);
diff --git a/modules/gltf/editor_scene_importer_gltf.cpp b/modules/gltf/editor_scene_importer_gltf.cpp
index cef5278f03..eca1c85bf3 100644
--- a/modules/gltf/editor_scene_importer_gltf.cpp
+++ b/modules/gltf/editor_scene_importer_gltf.cpp
@@ -28,22 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "core/crypto/crypto_core.h"
-#include "core/io/file_access.h"
-#include "core/math/disjoint_set.h"
-#include "core/math/math_defs.h"
-#include "core/os/os.h"
-#include "editor/import/resource_importer_scene.h"
-#include "modules/gltf/gltf_state.h"
-#include "modules/regex/regex.h"
-#include "scene/3d/bone_attachment_3d.h"
-#include "scene/3d/camera_3d.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/packed_scene.h"
-#include "scene/resources/surface_tool.h"
+#include "editor_scene_importer_gltf.h"
+
+#include "gltf_document.h"
+#include "gltf_state.h"
-#include "modules/gltf/editor_scene_importer_gltf.h"
+#include "scene/3d/node_3d.h"
+#include "scene/animation/animation_player.h"
+#include "scene/resources/animation.h"
uint32_t EditorSceneImporterGLTF::get_import_flags() const {
return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION;
diff --git a/modules/gltf/editor_scene_importer_gltf.h b/modules/gltf/editor_scene_importer_gltf.h
index 566d5cfd34..7bc5f594ed 100644
--- a/modules/gltf/editor_scene_importer_gltf.h
+++ b/modules/gltf/editor_scene_importer_gltf.h
@@ -31,28 +31,13 @@
#ifndef EDITOR_SCENE_IMPORTER_GLTF_H
#define EDITOR_SCENE_IMPORTER_GLTF_H
-#include "core/config/project_settings.h"
-#include "core/object/object.h"
-#include "core/templates/vector.h"
+#include "gltf_state.h"
+
#include "editor/import/resource_importer_scene.h"
-#include "modules/csg/csg_shape.h"
-#include "modules/gridmap/grid_map.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/multimesh_instance_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/gui/check_box.h"
#include "scene/main/node.h"
#include "scene/resources/packed_scene.h"
-#include "scene/resources/surface_tool.h"
-
-#include "gltf_document.h"
-#include "gltf_state.h"
-class AnimationPlayer;
-class BoneAttachment;
-class EditorSceneImporterMeshNode3D;
+class Animation;
#ifdef TOOLS_ENABLED
class EditorSceneImporterGLTF : public EditorSceneImporter {
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 674403905a..71a9b3667f 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -29,9 +29,7 @@
/*************************************************************************/
#include "gltf_document.h"
-#include "core/error/error_list.h"
-#include "core/error/error_macros.h"
-#include "core/variant/variant.h"
+
#include "gltf_accessor.h"
#include "gltf_animation.h"
#include "gltf_camera.h"
@@ -44,35 +42,33 @@
#include "gltf_state.h"
#include "gltf_texture.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "core/core_bind.h"
#include "core/crypto/crypto_core.h"
+#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/json.h"
#include "core/math/disjoint_set.h"
#include "core/variant/typed_array.h"
+#include "core/variant/variant.h"
#include "core/version.h"
#include "core/version_hash.gen.h"
#include "drivers/png/png_driver_common.h"
#include "editor/import/resource_importer_scene.h"
+#include "scene/2d/node_2d.h"
+#include "scene/3d/camera_3d.h"
+#include "scene/3d/multimesh_instance_3d.h"
+#include "scene/animation/animation_player.h"
+#include "scene/resources/surface_tool.h"
+
+#include "modules/modules_enabled.gen.h"
#ifdef MODULE_CSG_ENABLED
#include "modules/csg/csg_shape.h"
#endif // MODULE_CSG_ENABLED
#ifdef MODULE_GRIDMAP_ENABLED
#include "modules/gridmap/grid_map.h"
#endif // MODULE_GRIDMAP_ENABLED
-#include "scene/2d/node_2d.h"
-#include "scene/3d/bone_attachment_3d.h"
-#include "scene/3d/camera_3d.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/multimesh_instance_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/main/node.h"
-#include "scene/resources/surface_tool.h"
+
+#include <stdio.h>
+#include <stdlib.h>
#include <limits>
Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &p_path) {
@@ -2873,16 +2869,13 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
name = itos(i);
}
name = _gen_unique_name(state, name);
- name = name.pad_zeros(3);
- Ref<_Directory> dir;
- dir.instantiate();
+ name = name.pad_zeros(3) + ".png";
String texture_dir = "textures";
String new_texture_dir = p_path.get_base_dir() + "/" + texture_dir;
- dir->open(p_path.get_base_dir());
- if (!dir->dir_exists(new_texture_dir)) {
- dir->make_dir(new_texture_dir);
+ DirAccessRef da = DirAccess::open(p_path.get_base_dir());
+ if (!da->dir_exists(new_texture_dir)) {
+ da->make_dir(new_texture_dir);
}
- name = name + ".png";
image->save_png(new_texture_dir.plus_file(name));
d["uri"] = texture_dir.plus_file(name);
}
@@ -5537,6 +5530,8 @@ struct EditorSceneImporterGLTFInterpolate<Quaternion> {
template <class T>
T GLTFDocument::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) {
+ ERR_FAIL_COND_V(!p_values.size(), T());
+ ERR_FAIL_COND_V(p_times.size() != p_values.size(), p_values[0]);
//could use binary search, worth it?
int idx = -1;
for (int i = 0; i < p_times.size(); i++) {
@@ -6087,7 +6082,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
Vector3 translation = p_animation->track_get_key_value(p_track_i, key_i);
p_track.translation_track.values.write[key_i] = translation;
}
- } else if (path.find(":rotation_degrees") != -1) {
+ } else if (path.find(":rotation") != -1) {
p_track.rotation_track.times = times;
p_track.rotation_track.interpolation = gltf_interpolation;
@@ -6095,11 +6090,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
p_track.rotation_track.interpolation = gltf_interpolation;
for (int32_t key_i = 0; key_i < key_count; key_i++) {
- Vector3 rotation_degrees = p_animation->track_get_key_value(p_track_i, key_i);
- Vector3 rotation_radian;
- rotation_radian.x = Math::deg2rad(rotation_degrees.x);
- rotation_radian.y = Math::deg2rad(rotation_degrees.y);
- rotation_radian.z = Math::deg2rad(rotation_degrees.z);
+ Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i);
p_track.rotation_track.values.write[key_i] = Quaternion(rotation_radian);
}
} else if (path.find(":scale") != -1) {
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 514373c4f0..3e8ea19045 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -31,11 +31,9 @@
#ifndef GLTF_DOCUMENT_H
#define GLTF_DOCUMENT_H
-#include "editor/import/resource_importer_scene.h"
-#include "editor/import/scene_importer_mesh_node_3d.h"
#include "gltf_animation.h"
-#include "modules/modules_enabled.gen.h"
-#include "scene/2d/node_2d.h"
+
+#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -45,6 +43,8 @@
#include "scene/resources/material.h"
#include "scene/resources/texture.h"
+#include "modules/modules_enabled.gen.h"
+
class GLTFState;
class GLTFSkin;
class GLTFNode;
diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h
index ba6bf8a533..d8209523c5 100644
--- a/modules/gltf/gltf_state.h
+++ b/modules/gltf/gltf_state.h
@@ -31,9 +31,6 @@
#ifndef GLTF_STATE_H
#define GLTF_STATE_H
-#include "core/io/resource.h"
-#include "core/templates/vector.h"
-#include "editor_scene_importer_gltf.h"
#include "gltf_accessor.h"
#include "gltf_animation.h"
#include "gltf_buffer_view.h"
@@ -45,6 +42,9 @@
#include "gltf_skeleton.h"
#include "gltf_skin.h"
#include "gltf_texture.h"
+
+#include "core/io/resource.h"
+#include "core/templates/vector.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/texture.h"
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index d11c7cb9cd..85921490d2 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -62,25 +62,25 @@ void register_gltf_types() {
#ifdef TOOLS_ENABLED
ClassDB::APIType prev_api = ClassDB::get_current_api();
ClassDB::set_current_api(ClassDB::API_EDITOR);
- ClassDB::register_class<EditorSceneImporterGLTF>();
- ClassDB::register_class<GLTFMesh>();
+ GDREGISTER_CLASS(EditorSceneImporterGLTF);
+ GDREGISTER_CLASS(GLTFMesh);
EditorPlugins::add_by_type<SceneExporterGLTFPlugin>();
ClassDB::set_current_api(prev_api);
EditorNode::add_init_callback(_editor_init);
#endif
- ClassDB::register_class<GLTFSpecGloss>();
- ClassDB::register_class<GLTFNode>();
- ClassDB::register_class<GLTFAnimation>();
- ClassDB::register_class<GLTFBufferView>();
- ClassDB::register_class<GLTFAccessor>();
- ClassDB::register_class<GLTFTexture>();
- ClassDB::register_class<GLTFSkeleton>();
- ClassDB::register_class<GLTFSkin>();
- ClassDB::register_class<GLTFCamera>();
- ClassDB::register_class<GLTFLight>();
- ClassDB::register_class<GLTFState>();
- ClassDB::register_class<GLTFDocument>();
- ClassDB::register_class<PackedSceneGLTF>();
+ GDREGISTER_CLASS(GLTFSpecGloss);
+ GDREGISTER_CLASS(GLTFNode);
+ GDREGISTER_CLASS(GLTFAnimation);
+ GDREGISTER_CLASS(GLTFBufferView);
+ GDREGISTER_CLASS(GLTFAccessor);
+ GDREGISTER_CLASS(GLTFTexture);
+ GDREGISTER_CLASS(GLTFSkeleton);
+ GDREGISTER_CLASS(GLTFSkin);
+ GDREGISTER_CLASS(GLTFCamera);
+ GDREGISTER_CLASS(GLTFLight);
+ GDREGISTER_CLASS(GLTFState);
+ GDREGISTER_CLASS(GLTFDocument);
+ GDREGISTER_CLASS(PackedSceneGLTF);
#endif
}
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index c62e7acd62..0cd41133f1 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -221,7 +221,7 @@ void GridMap::set_cell_size(const Vector3 &p_size) {
ERR_FAIL_COND(p_size.x < 0.001 || p_size.y < 0.001 || p_size.z < 0.001);
cell_size = p_size;
_recreate_octant_data();
- emit_signal("cell_size_changed", cell_size);
+ emit_signal(SNAME("cell_size_changed"), cell_size);
}
Vector3 GridMap::get_cell_size() const {
@@ -780,7 +780,7 @@ void GridMap::_update_octants_callback() {
while (to_delete.front()) {
octant_map.erase(to_delete.front()->get());
- to_delete.pop_back();
+ to_delete.pop_front();
}
_update_visibility();
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index a2f570e6a5..046f8c0adb 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -1077,8 +1077,8 @@ void GridMapEditor::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- options->set_icon(get_theme_icon("GridMap", "EditorIcons"));
- search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ options->set_icon(get_theme_icon(SNAME("GridMap"), SNAME("EditorIcons")));
+ search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
@@ -1239,7 +1239,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
mode_thumbnail->set_flat(true);
mode_thumbnail->set_toggle_mode(true);
mode_thumbnail->set_pressed(true);
- mode_thumbnail->set_icon(p_editor->get_gui_base()->get_theme_icon("FileThumbnail", "EditorIcons"));
+ mode_thumbnail->set_icon(p_editor->get_gui_base()->get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
hb->add_child(mode_thumbnail);
mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_THUMBNAIL));
@@ -1247,7 +1247,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
mode_list->set_flat(true);
mode_list->set_toggle_mode(true);
mode_list->set_pressed(false);
- mode_list->set_icon(p_editor->get_gui_base()->get_theme_icon("FileList", "EditorIcons"));
+ mode_list->set_icon(p_editor->get_gui_base()->get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
hb->add_child(mode_list);
mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_LIST));
@@ -1271,7 +1271,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
info_message->set_text(TTR("Give a MeshLibrary resource to this GridMap to use its meshes."));
info_message->set_valign(Label::VALIGN_CENTER);
info_message->set_align(Label::ALIGN_CENTER);
- info_message->set_autowrap(true);
+ info_message->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
mesh_library_palette->add_child(info_message);
diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp
index 5680664213..85739d202e 100644
--- a/modules/gridmap/register_types.cpp
+++ b/modules/gridmap/register_types.cpp
@@ -37,7 +37,7 @@
void register_gridmap_types() {
#ifndef _3D_DISABLED
- ClassDB::register_class<GridMap>();
+ GDREGISTER_CLASS(GridMap);
#ifdef TOOLS_ENABLED
EditorPlugins::add_by_type<GridMapEditorPlugin>();
#endif
diff --git a/modules/jsonrpc/register_types.cpp b/modules/jsonrpc/register_types.cpp
index d6b565ba84..8fdf6fe1aa 100644
--- a/modules/jsonrpc/register_types.cpp
+++ b/modules/jsonrpc/register_types.cpp
@@ -33,7 +33,7 @@
#include "jsonrpc.h"
void register_jsonrpc_types() {
- ClassDB::register_class<JSONRPC>();
+ GDREGISTER_CLASS(JSONRPC);
}
void unregister_jsonrpc_types() {
diff --git a/modules/lightmapper_rd/register_types.cpp b/modules/lightmapper_rd/register_types.cpp
index 191bb3d765..ae9c5fc390 100644
--- a/modules/lightmapper_rd/register_types.cpp
+++ b/modules/lightmapper_rd/register_types.cpp
@@ -54,7 +54,7 @@ void register_lightmapper_rd_types() {
GLOBAL_DEF("rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count", 2048);
GLOBAL_DEF("rendering/lightmapping/bake_performance/max_rays_per_probe_pass", 64);
#ifndef _3D_DISABLED
- ClassDB::register_class<LightmapperRD>();
+ GDREGISTER_CLASS(LightmapperRD);
Lightmapper::create_gpu = create_lightmapper_rd;
#endif
}
diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp
index 774da5a324..2522f1bb11 100644
--- a/modules/mbedtls/crypto_mbedtls.cpp
+++ b/modules/mbedtls/crypto_mbedtls.cpp
@@ -249,6 +249,13 @@ PackedByteArray HMACContextMbedTLS::finish() {
return out;
}
+HMACContextMbedTLS::~HMACContextMbedTLS() {
+ if (ctx != nullptr) {
+ mbedtls_md_free((mbedtls_md_context_t *)ctx);
+ memfree((mbedtls_md_context_t *)ctx);
+ }
+}
+
Crypto *CryptoMbedTLS::create() {
return memnew(CryptoMbedTLS);
}
diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h
index 5ced4d136c..afa1ea7a64 100644
--- a/modules/mbedtls/crypto_mbedtls.h
+++ b/modules/mbedtls/crypto_mbedtls.h
@@ -119,6 +119,7 @@ public:
virtual PackedByteArray finish();
HMACContextMbedTLS() {}
+ ~HMACContextMbedTLS();
};
class CryptoMbedTLS : public Crypto {
diff --git a/modules/mbedtls/tests/test_crypto_mbedtls.cpp b/modules/mbedtls/tests/test_crypto_mbedtls.cpp
index 4217497082..8762838883 100644
--- a/modules/mbedtls/tests/test_crypto_mbedtls.cpp
+++ b/modules/mbedtls/tests/test_crypto_mbedtls.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "modules/mbedtls/tests/test_crypto_mbedtls.h"
+#include "test_crypto_mbedtls.h"
#include "modules/mbedtls/crypto_mbedtls.h"
#include "tests/test_macros.h"
diff --git a/modules/minimp3/register_types.cpp b/modules/minimp3/register_types.cpp
index 27ea512b69..63f2589f42 100644
--- a/modules/minimp3/register_types.cpp
+++ b/modules/minimp3/register_types.cpp
@@ -45,7 +45,7 @@ void register_minimp3_types() {
ResourceFormatImporter::get_singleton()->add_importer(mp3_import);
}
#endif
- ClassDB::register_class<AudioStreamMP3>();
+ GDREGISTER_CLASS(AudioStreamMP3);
}
void unregister_minimp3_types() {
diff --git a/modules/mobile_vr/register_types.cpp b/modules/mobile_vr/register_types.cpp
index 7d138aa4c9..47d1fe482c 100644
--- a/modules/mobile_vr/register_types.cpp
+++ b/modules/mobile_vr/register_types.cpp
@@ -33,7 +33,7 @@
#include "mobile_vr_interface.h"
void register_mobile_vr_types() {
- ClassDB::register_class<MobileVRInterface>();
+ GDREGISTER_CLASS(MobileVRInterface);
if (XRServer::get_singleton()) {
Ref<MobileVRInterface> mobile_vr;
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index 309abfbff7..8e441e7e07 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -101,12 +101,6 @@ def configure(env, env_mono):
mono_lib_names = ["mono-2.0-sgen", "monosgen-2.0"]
- is_travis = os.environ.get("TRAVIS") == "true"
-
- if is_travis:
- # Travis CI may have a Mono version lower than 5.12
- env_mono.Append(CPPDEFINES=["NO_PENDING_EXCEPTIONS"])
-
if is_android and not env["android_arch"] in android_arch_dirs:
raise RuntimeError("This module does not support the specified 'android_arch': " + env["android_arch"])
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index c48230f524..80675feb3b 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1510,6 +1510,7 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
}
void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
+#if 0
RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object);
#ifdef DEBUG_ENABLED
@@ -1544,9 +1545,11 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
gchandle.release();
gchandle = strong_gchandle;
}
+#endif
}
bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
+#if 0
RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object);
#ifdef DEBUG_ENABLED
@@ -1586,6 +1589,8 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
}
return refcount == 0;
+#endif
+ return false;
}
CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle) {
@@ -2264,8 +2269,10 @@ CSharpInstance::~CSharpInstance() {
// Otherwise, the unsafe reference debug checks will incorrectly detect a bug.
bool die = _unreference_owner_unsafe();
CRASH_COND(die); // `owner_keep_alive` holds a reference, so it can't die
-
+#if 0
void *data = owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+
+
CRASH_COND(data == nullptr);
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -2284,6 +2291,7 @@ CSharpInstance::~CSharpInstance() {
// The "instance binding" holds a reference so the refcount should be at least 2 before `scope_keep_owner_alive` goes out of scope
CRASH_COND(rc_owner->reference_get_count() <= 1);
#endif
+#endif
}
if (script.is_valid() && owner) {
@@ -3030,7 +3038,7 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
nd.name = methods[i]->get_name();
nd.rpc_mode = mode;
// TODO Transfer mode, channel
- nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ nd.transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
nd.channel = 0;
if (-1 == p_script->rpc_functions.find(nd)) {
p_script->rpc_functions.push_back(nd);
@@ -3101,7 +3109,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
// Hold it alive. Important if we have to dispose a script instance binding before creating the CSharpInstance.
ref = Ref<RefCounted>(static_cast<RefCounted *>(p_owner));
}
-
+#if 0
// If the object had a script instance binding, dispose it before adding the CSharpInstance
if (p_owner->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index())) {
void *data = p_owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
@@ -3123,7 +3131,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
script_binding.inited = false;
}
}
-
+#endif
CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(this)));
instance->base_ref_counted = p_is_ref_counted;
instance->owner = p_owner;
@@ -3464,15 +3472,6 @@ MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_m
if (p_member->has_attribute(CACHED_CLASS(PuppetAttribute))) {
return MultiplayerAPI::RPC_MODE_PUPPET;
}
- if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute))) {
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- }
- if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute))) {
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- }
- if (p_member->has_attribute(CACHED_CLASS(PuppetSyncAttribute))) {
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- }
return MultiplayerAPI::RPC_MODE_DISABLED;
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index c71c44d79d..1faa6eeac0 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -26,8 +26,6 @@ namespace GodotTools
private PopupMenu menuPopup;
private AcceptDialog errorDialog;
- private AcceptDialog aboutDialog;
- private CheckBox aboutDialogCheckBox;
private Button bottomPanelBtn;
private Button toolBarBuildButton;
@@ -130,13 +128,6 @@ namespace GodotTools
toolBarBuildButton.Show();
}
- private void _ShowAboutDialog()
- {
- bool showOnStart = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
- aboutDialogCheckBox.Pressed = showOnStart;
- aboutDialog.PopupCentered();
- }
-
private void _MenuOptionPressed(int id)
{
switch ((MenuOptions)id)
@@ -144,9 +135,6 @@ namespace GodotTools
case MenuOptions.CreateSln:
CreateProjectSolution();
break;
- case MenuOptions.AboutCSharp:
- _ShowAboutDialog();
- break;
case MenuOptions.SetupGodotNugetFallbackFolder:
{
try
@@ -183,21 +171,11 @@ namespace GodotTools
base._Ready();
MSBuildPanel.BuildOutputView.BuildStateChanged += BuildStateChanged;
-
- bool showInfoDialog = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
- if (showInfoDialog)
- {
- aboutDialog.Exclusive = true;
- _ShowAboutDialog();
- // Once shown a first time, it can be seen again via the Mono menu - it doesn't have to be exclusive from that time on.
- aboutDialog.Exclusive = false;
- }
}
private enum MenuOptions
{
CreateSln,
- AboutCSharp,
SetupGodotNugetFallbackFolder,
}
@@ -439,57 +417,6 @@ namespace GodotTools
AddToolSubmenuItem("C#", menuPopup);
- // TODO: Remove or edit this info dialog once Mono support is no longer in alpha
- {
- menuPopup.AddItem("About C# support".TTR(), (int)MenuOptions.AboutCSharp);
- menuPopup.AddItem("Setup Godot NuGet Offline Packages".TTR(), (int)MenuOptions.SetupGodotNugetFallbackFolder);
- aboutDialog = new AcceptDialog();
- editorBaseControl.AddChild(aboutDialog);
- aboutDialog.Title = "Important: C# support is not feature-complete";
-
- // We don't use DialogText as the default AcceptDialog Label doesn't play well with the TextureRect and CheckBox
- // we'll add. Instead we add containers and a new autowrapped Label inside.
-
- // Main VBoxContainer (icon + label on top, checkbox at bottom)
- var aboutVBox = new VBoxContainer();
- aboutDialog.AddChild(aboutVBox);
-
- // HBoxContainer for icon + label
- var aboutHBox = new HBoxContainer();
- aboutVBox.AddChild(aboutHBox);
-
- var aboutIcon = new TextureRect();
- aboutIcon.Texture = aboutIcon.GetThemeIcon("NodeWarning", "EditorIcons");
- aboutHBox.AddChild(aboutIcon);
-
- var aboutLabel = new Label();
- aboutHBox.AddChild(aboutLabel);
- aboutLabel.RectMinSize = new Vector2(600, 150) * EditorScale;
- aboutLabel.SizeFlagsVertical = (int)Control.SizeFlags.ExpandFill;
- aboutLabel.Autowrap = true;
- aboutLabel.Text =
- "C# support in Godot Engine is in late alpha stage and, while already usable, " +
- "it is not meant for use in production.\n\n" +
- "Projects can be exported to Linux, macOS, Windows, Android, iOS and HTML5, but not yet to UWP. " +
- "Bugs and usability issues will be addressed gradually over future releases, " +
- "potentially including compatibility breaking changes as new features are implemented for a better overall C# experience.\n\n" +
- "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, MSBuild version, IDE, etc.:\n\n" +
- " https://github.com/godotengine/godot/issues\n\n" +
- "Your critical feedback at this stage will play a great role in shaping the C# support in future releases, so thank you!";
-
- EditorDef("mono/editor/show_info_on_start", true);
-
- // CheckBox in main container
- aboutDialogCheckBox = new CheckBox {Text = "Show this warning when starting the editor"};
- aboutDialogCheckBox.Toggled += enabled =>
- {
- bool showOnStart = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
- if (showOnStart != enabled)
- editorSettings.SetSetting("mono/editor/show_info_on_start", enabled);
- };
- aboutVBox.AddChild(aboutDialogCheckBox);
- }
-
toolBarBuildButton = new Button
{
Text = "Build",
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index 21efd58938..8164f459ca 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -241,7 +241,7 @@ MonoBoolean godot_icall_Internal_IsAssembliesReloadingNeeded() {
void godot_icall_Internal_ReloadAssemblies(MonoBoolean p_soft_reload) {
#ifdef GD_MONO_HOT_RELOAD
- _GodotSharp::get_singleton()->call_deferred("_reload_assemblies", (bool)p_soft_reload);
+ _GodotSharp::get_singleton()->call_deferred(SNAME("_reload_assemblies"), (bool)p_soft_reload);
#endif
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
index 8fc430b6bc..6cec8773b2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
@@ -2,21 +2,12 @@ using System;
namespace Godot
{
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
+ [AttributeUsage(AttributeTargets.Method)]
public class RemoteAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
+ [AttributeUsage(AttributeTargets.Method)]
public class MasterAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
+ [AttributeUsage(AttributeTargets.Method)]
public class PuppetAttribute : Attribute {}
-
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class RemoteSyncAttribute : Attribute {}
-
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class MasterSyncAttribute : Attribute {}
-
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class PuppetSyncAttribute : Attribute {}
}
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 2b87c2d9a4..2d04cedb9b 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -64,7 +64,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
return;
}
}
-
+#if 0
void *data = p_ptr->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
if (data) {
@@ -76,6 +76,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
}
}
}
+#endif
}
void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
@@ -84,7 +85,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole
// This is only called with RefCounted derived classes
CRASH_COND(!Object::cast_to<RefCounted>(p_ptr));
#endif
-
+#if 0
RefCounted *rc = static_cast<RefCounted *>(p_ptr);
if (rc->get_script_instance()) {
@@ -124,6 +125,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole
}
}
}
+#endif
}
void godot_icall_Object_ConnectEventSignals(Object *p_ptr) {
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index 341ca88728..0b36796d98 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -143,9 +143,6 @@ void CachedData::clear_godot_api_cache() {
class_RemoteAttribute = nullptr;
class_MasterAttribute = nullptr;
class_PuppetAttribute = nullptr;
- class_RemoteSyncAttribute = nullptr;
- class_MasterSyncAttribute = nullptr;
- class_PuppetSyncAttribute = nullptr;
class_GodotMethodAttribute = nullptr;
field_GodotMethodAttribute_methodName = nullptr;
class_ScriptPathAttribute = nullptr;
@@ -272,9 +269,6 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute));
CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute));
CACHE_CLASS_AND_CHECK(PuppetAttribute, GODOT_API_CLASS(PuppetAttribute));
- CACHE_CLASS_AND_CHECK(RemoteSyncAttribute, GODOT_API_CLASS(RemoteSyncAttribute));
- CACHE_CLASS_AND_CHECK(MasterSyncAttribute, GODOT_API_CLASS(MasterSyncAttribute));
- CACHE_CLASS_AND_CHECK(PuppetSyncAttribute, GODOT_API_CLASS(PuppetSyncAttribute));
CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
CACHE_CLASS_AND_CHECK(ScriptPathAttribute, GODOT_API_CLASS(ScriptPathAttribute));
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 3d867060f5..6d49da0af3 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -114,9 +114,6 @@ struct CachedData {
GDMonoClass *class_RemoteAttribute;
GDMonoClass *class_MasterAttribute;
GDMonoClass *class_PuppetAttribute;
- GDMonoClass *class_RemoteSyncAttribute;
- GDMonoClass *class_MasterSyncAttribute;
- GDMonoClass *class_PuppetSyncAttribute;
GDMonoClass *class_GodotMethodAttribute;
GDMonoField *field_GodotMethodAttribute_methodName;
GDMonoClass *class_ScriptPathAttribute;
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index d7df18d5da..d6545d50ec 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -45,7 +45,7 @@
namespace GDMonoInternals {
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// This method should not fail
-
+#if 0
CRASH_COND(!unmanaged);
// All mono objects created from the managed world (e.g.: 'new Player()')
@@ -108,6 +108,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
CSharpInstance *csharp_instance = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle);
unmanaged->set_script_and_instance(script, csharp_instance);
+#endif
}
void unhandled_exception(MonoException *p_exc) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 0b9a577e01..080398c997 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -54,6 +54,7 @@
namespace GDMonoUtils {
MonoObject *unmanaged_get_managed(Object *unmanaged) {
+#if 0
if (!unmanaged) {
return nullptr;
}
@@ -120,6 +121,8 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
}
return mono_object;
+#endif
+ return nullptr;
}
void set_main_thread(MonoThread *p_thread) {
diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp
index b4a6bfdcd4..2ba89eac55 100644
--- a/modules/mono/register_types.cpp
+++ b/modules/mono/register_types.cpp
@@ -41,11 +41,11 @@ Ref<ResourceFormatSaverCSharpScript> resource_saver_cs;
_GodotSharp *_godotsharp = nullptr;
void register_mono_types() {
- ClassDB::register_class<CSharpScript>();
+ GDREGISTER_CLASS(CSharpScript);
_godotsharp = memnew(_GodotSharp);
- ClassDB::register_class<_GodotSharp>();
+ GDREGISTER_CLASS(_GodotSharp);
Engine::get_singleton()->add_singleton(Engine::Singleton("GodotSharp", _GodotSharp::get_singleton()));
script_language_cs = memnew(CSharpLanguage);
diff --git a/modules/gdnavigation/SCsub b/modules/navigation/SCsub
index 22b5509b32..22b5509b32 100644
--- a/modules/gdnavigation/SCsub
+++ b/modules/navigation/SCsub
diff --git a/modules/gdnavigation/config.py b/modules/navigation/config.py
index d22f9454ed..d22f9454ed 100644
--- a/modules/gdnavigation/config.py
+++ b/modules/navigation/config.py
diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index d5e6e5e69f..fd965674d6 100644
--- a/modules/gdnavigation/gd_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_navigation_server.cpp */
+/* godot_navigation_server.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_navigation_server.h"
+#include "godot_navigation_server.h"
#include "core/os/mutex.h"
@@ -44,96 +44,96 @@
/// an instance of that struct with the submitted parameters.
/// Then, that struct is stored in an array; the `sync` function consume that array.
-#define COMMAND_1(F_NAME, T_0, D_0) \
- struct MERGE(F_NAME, _command) : public SetCommand { \
- T_0 d_0; \
- MERGE(F_NAME, _command) \
- (T_0 p_d_0) : \
- d_0(p_d_0) {} \
- virtual void exec(GdNavigationServer *server) { \
- server->MERGE(_cmd_, F_NAME)(d_0); \
- } \
- }; \
- void GdNavigationServer::F_NAME(T_0 D_0) const { \
- auto cmd = memnew(MERGE(F_NAME, _command)( \
- D_0)); \
- add_command(cmd); \
- } \
- void GdNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0)
-
-#define COMMAND_2(F_NAME, T_0, D_0, T_1, D_1) \
- struct MERGE(F_NAME, _command) : public SetCommand { \
- T_0 d_0; \
- T_1 d_1; \
- MERGE(F_NAME, _command) \
- ( \
- T_0 p_d_0, \
- T_1 p_d_1) : \
- d_0(p_d_0), \
- d_1(p_d_1) {} \
- virtual void exec(GdNavigationServer *server) { \
- server->MERGE(_cmd_, F_NAME)(d_0, d_1); \
- } \
- }; \
- void GdNavigationServer::F_NAME(T_0 D_0, T_1 D_1) const { \
- auto cmd = memnew(MERGE(F_NAME, _command)( \
- D_0, \
- D_1)); \
- add_command(cmd); \
- } \
- void GdNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1)
-
-#define COMMAND_4(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3) \
- struct MERGE(F_NAME, _command) : public SetCommand { \
- T_0 d_0; \
- T_1 d_1; \
- T_2 d_2; \
- T_3 d_3; \
- MERGE(F_NAME, _command) \
- ( \
- T_0 p_d_0, \
- T_1 p_d_1, \
- T_2 p_d_2, \
- T_3 p_d_3) : \
- d_0(p_d_0), \
- d_1(p_d_1), \
- d_2(p_d_2), \
- d_3(p_d_3) {} \
- virtual void exec(GdNavigationServer *server) { \
- server->MERGE(_cmd_, F_NAME)(d_0, d_1, d_2, d_3); \
- } \
- }; \
- void GdNavigationServer::F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) const { \
- auto cmd = memnew(MERGE(F_NAME, _command)( \
- D_0, \
- D_1, \
- D_2, \
- D_3)); \
- add_command(cmd); \
- } \
- void GdNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
-
-GdNavigationServer::GdNavigationServer() :
+#define COMMAND_1(F_NAME, T_0, D_0) \
+ struct MERGE(F_NAME, _command) : public SetCommand { \
+ T_0 d_0; \
+ MERGE(F_NAME, _command) \
+ (T_0 p_d_0) : \
+ d_0(p_d_0) {} \
+ virtual void exec(GodotNavigationServer *server) { \
+ server->MERGE(_cmd_, F_NAME)(d_0); \
+ } \
+ }; \
+ void GodotNavigationServer::F_NAME(T_0 D_0) const { \
+ auto cmd = memnew(MERGE(F_NAME, _command)( \
+ D_0)); \
+ add_command(cmd); \
+ } \
+ void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0)
+
+#define COMMAND_2(F_NAME, T_0, D_0, T_1, D_1) \
+ struct MERGE(F_NAME, _command) : public SetCommand { \
+ T_0 d_0; \
+ T_1 d_1; \
+ MERGE(F_NAME, _command) \
+ ( \
+ T_0 p_d_0, \
+ T_1 p_d_1) : \
+ d_0(p_d_0), \
+ d_1(p_d_1) {} \
+ virtual void exec(GodotNavigationServer *server) { \
+ server->MERGE(_cmd_, F_NAME)(d_0, d_1); \
+ } \
+ }; \
+ void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1) const { \
+ auto cmd = memnew(MERGE(F_NAME, _command)( \
+ D_0, \
+ D_1)); \
+ add_command(cmd); \
+ } \
+ void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1)
+
+#define COMMAND_4(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3) \
+ struct MERGE(F_NAME, _command) : public SetCommand { \
+ T_0 d_0; \
+ T_1 d_1; \
+ T_2 d_2; \
+ T_3 d_3; \
+ MERGE(F_NAME, _command) \
+ ( \
+ T_0 p_d_0, \
+ T_1 p_d_1, \
+ T_2 p_d_2, \
+ T_3 p_d_3) : \
+ d_0(p_d_0), \
+ d_1(p_d_1), \
+ d_2(p_d_2), \
+ d_3(p_d_3) {} \
+ virtual void exec(GodotNavigationServer *server) { \
+ server->MERGE(_cmd_, F_NAME)(d_0, d_1, d_2, d_3); \
+ } \
+ }; \
+ void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) const { \
+ auto cmd = memnew(MERGE(F_NAME, _command)( \
+ D_0, \
+ D_1, \
+ D_2, \
+ D_3)); \
+ add_command(cmd); \
+ } \
+ void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
+
+GodotNavigationServer::GodotNavigationServer() :
NavigationServer3D() {
}
-GdNavigationServer::~GdNavigationServer() {
+GodotNavigationServer::~GodotNavigationServer() {
flush_queries();
}
-void GdNavigationServer::add_command(SetCommand *command) const {
- GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this);
+void GodotNavigationServer::add_command(SetCommand *command) const {
+ GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
{
MutexLock lock(commands_mutex);
mut_this->commands.push_back(command);
}
}
-RID GdNavigationServer::map_create() const {
- GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this);
+RID GodotNavigationServer::map_create() const {
+ GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
- NavMap *space = memnew(NavMap);
- RID rid = map_owner.make_rid(space);
+ RID rid = map_owner.make_rid();
+ NavMap *space = map_owner.getornull(rid);
space->set_self(rid);
return rid;
}
@@ -155,7 +155,7 @@ COMMAND_2(map_set_active, RID, p_map, bool, p_active) {
}
}
-bool GdNavigationServer::map_is_active(RID p_map) const {
+bool GodotNavigationServer::map_is_active(RID p_map) const {
NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, false);
@@ -169,7 +169,7 @@ COMMAND_2(map_set_up, RID, p_map, Vector3, p_up) {
map->set_up(p_up);
}
-Vector3 GdNavigationServer::map_get_up(RID p_map) const {
+Vector3 GodotNavigationServer::map_get_up(RID p_map) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector3());
@@ -183,7 +183,7 @@ COMMAND_2(map_set_cell_size, RID, p_map, real_t, p_cell_size) {
map->set_cell_size(p_cell_size);
}
-real_t GdNavigationServer::map_get_cell_size(RID p_map) const {
+real_t GodotNavigationServer::map_get_cell_size(RID p_map) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, 0);
@@ -197,53 +197,53 @@ COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margi
map->set_edge_connection_margin(p_connection_margin);
}
-real_t GdNavigationServer::map_get_edge_connection_margin(RID p_map) const {
+real_t GodotNavigationServer::map_get_edge_connection_margin(RID p_map) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, 0);
return map->get_edge_connection_margin();
}
-Vector<Vector3> GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
+Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>());
return map->get_path(p_origin, p_destination, p_optimize, p_layers);
}
-Vector3 GdNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
+Vector3 GodotNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector3());
return map->get_closest_point_to_segment(p_from, p_to, p_use_collision);
}
-Vector3 GdNavigationServer::map_get_closest_point(RID p_map, const Vector3 &p_point) const {
+Vector3 GodotNavigationServer::map_get_closest_point(RID p_map, const Vector3 &p_point) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector3());
return map->get_closest_point(p_point);
}
-Vector3 GdNavigationServer::map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const {
+Vector3 GodotNavigationServer::map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector3());
return map->get_closest_point_normal(p_point);
}
-RID GdNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const {
+RID GodotNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, RID());
return map->get_closest_point_owner(p_point);
}
-RID GdNavigationServer::region_create() const {
- GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this);
+RID GodotNavigationServer::region_create() const {
+ GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
- NavRegion *reg = memnew(NavRegion);
- RID rid = region_owner.make_rid(reg);
+ RID rid = region_owner.make_rid();
+ NavRegion *reg = region_owner.getornull(rid);
reg->set_self(rid);
return rid;
}
@@ -284,7 +284,7 @@ COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers) {
region->set_layers(p_layers);
}
-uint32_t GdNavigationServer::region_get_layers(RID p_region) const {
+uint32_t GodotNavigationServer::region_get_layers(RID p_region) const {
NavRegion *region = region_owner.getornull(p_region);
ERR_FAIL_COND_V(region == nullptr, 0);
@@ -298,7 +298,7 @@ COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) {
region->set_mesh(p_nav_mesh);
}
-void GdNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const {
+void GodotNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const {
ERR_FAIL_COND(r_mesh.is_null());
ERR_FAIL_COND(p_node == nullptr);
@@ -308,32 +308,32 @@ void GdNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p
#endif
}
-int GdNavigationServer::region_get_connections_count(RID p_region) const {
+int GodotNavigationServer::region_get_connections_count(RID p_region) const {
NavRegion *region = region_owner.getornull(p_region);
ERR_FAIL_COND_V(!region, 0);
return region->get_connections_count();
}
-Vector3 GdNavigationServer::region_get_connection_pathway_start(RID p_region, int p_connection_id) const {
+Vector3 GodotNavigationServer::region_get_connection_pathway_start(RID p_region, int p_connection_id) const {
NavRegion *region = region_owner.getornull(p_region);
ERR_FAIL_COND_V(!region, Vector3());
return region->get_connection_pathway_start(p_connection_id);
}
-Vector3 GdNavigationServer::region_get_connection_pathway_end(RID p_region, int p_connection_id) const {
+Vector3 GodotNavigationServer::region_get_connection_pathway_end(RID p_region, int p_connection_id) const {
NavRegion *region = region_owner.getornull(p_region);
ERR_FAIL_COND_V(!region, Vector3());
return region->get_connection_pathway_end(p_connection_id);
}
-RID GdNavigationServer::agent_create() const {
- GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this);
+RID GodotNavigationServer::agent_create() const {
+ GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
- RvoAgent *agent = memnew(RvoAgent());
- RID rid = agent_owner.make_rid(agent);
+ RID rid = agent_owner.make_rid();
+ RvoAgent *agent = agent_owner.getornull(rid);
agent->set_self(rid);
return rid;
}
@@ -428,7 +428,7 @@ COMMAND_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore) {
agent->get_agent()->ignore_y_ = p_ignore;
}
-bool GdNavigationServer::agent_is_map_changed(RID p_agent) const {
+bool GodotNavigationServer::agent_is_map_changed(RID p_agent) const {
RvoAgent *agent = agent_owner.getornull(p_agent);
ERR_FAIL_COND_V(agent == nullptr, false);
@@ -472,7 +472,6 @@ COMMAND_1(free, RID, p_object) {
active_maps.remove(map_index);
active_maps_update_id.remove(map_index);
map_owner.free(p_object);
- memdelete(map);
} else if (region_owner.owns(p_object)) {
NavRegion *region = region_owner.getornull(p_object);
@@ -484,7 +483,6 @@ COMMAND_1(free, RID, p_object) {
}
region_owner.free(p_object);
- memdelete(region);
} else if (agent_owner.owns(p_object)) {
RvoAgent *agent = agent_owner.getornull(p_object);
@@ -496,20 +494,19 @@ COMMAND_1(free, RID, p_object) {
}
agent_owner.free(p_object);
- memdelete(agent);
} else {
ERR_FAIL_COND("Invalid ID.");
}
}
-void GdNavigationServer::set_active(bool p_active) const {
- GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this);
+void GodotNavigationServer::set_active(bool p_active) const {
+ GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
mut_this->active = p_active;
}
-void GdNavigationServer::flush_queries() {
+void GodotNavigationServer::flush_queries() {
// In c++ we can't be sure that this is performed in the main thread
// even with mutable functions.
MutexLock lock(commands_mutex);
@@ -521,7 +518,7 @@ void GdNavigationServer::flush_queries() {
commands.clear();
}
-void GdNavigationServer::process(real_t p_delta_time) {
+void GodotNavigationServer::process(real_t p_delta_time) {
flush_queries();
if (!active) {
@@ -539,7 +536,7 @@ void GdNavigationServer::process(real_t p_delta_time) {
// Emit a signal if a map changed.
const uint32_t new_map_update_id = active_maps[i]->get_map_update_id();
if (new_map_update_id != active_maps_update_id[i]) {
- emit_signal("map_changed", active_maps[i]->get_self());
+ emit_signal(SNAME("map_changed"), active_maps[i]->get_self());
active_maps_update_id[i] = new_map_update_id;
}
}
diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 759d15e508..65224493fd 100644
--- a/modules/gdnavigation/gd_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_navigation_server.h */
+/* godot_navigation_server.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_NAVIGATION_SERVER_H
-#define GD_NAVIGATION_SERVER_H
+#ifndef GODOT_NAVIGATION_SERVER_H
+#define GODOT_NAVIGATION_SERVER_H
#include "core/templates/local_vector.h"
#include "core/templates/rid.h"
@@ -61,31 +61,31 @@
virtual void F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3 = D_3_DEF) const; \
void MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
-class GdNavigationServer;
+class GodotNavigationServer;
struct SetCommand {
virtual ~SetCommand() {}
- virtual void exec(GdNavigationServer *server) = 0;
+ virtual void exec(GodotNavigationServer *server) = 0;
};
-class GdNavigationServer : public NavigationServer3D {
+class GodotNavigationServer : public NavigationServer3D {
Mutex commands_mutex;
/// Mutex used to make any operation threadsafe.
Mutex operations_mutex;
std::vector<SetCommand *> commands;
- mutable RID_PtrOwner<NavMap> map_owner;
- mutable RID_PtrOwner<NavRegion> region_owner;
- mutable RID_PtrOwner<RvoAgent> agent_owner;
+ mutable RID_Owner<NavMap> map_owner;
+ mutable RID_Owner<NavRegion> region_owner;
+ mutable RID_Owner<RvoAgent> agent_owner;
bool active = true;
LocalVector<NavMap *> active_maps;
LocalVector<uint32_t> active_maps_update_id;
public:
- GdNavigationServer();
- virtual ~GdNavigationServer();
+ GodotNavigationServer();
+ virtual ~GodotNavigationServer();
void add_command(SetCommand *command) const;
@@ -146,4 +146,4 @@ public:
#undef COMMAND_2
#undef COMMAND_4_DEF
-#endif // GD_NAVIGATION_SERVER_H
+#endif // GODOT_NAVIGATION_SERVER_H
diff --git a/modules/gdnavigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 41306f0687..3150ca0bc8 100644
--- a/modules/gdnavigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -734,7 +734,7 @@ void NavMap::dispatch_callbacks() {
void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const {
Vector3 from = path[path.size() - 1];
- if (from.distance_to(p_to_point) < CMP_EPSILON) {
+ if (from.is_equal_approx(p_to_point)) {
return;
}
Plane cut_plane;
@@ -752,10 +752,10 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys
ERR_FAIL_COND(from_poly->back_navigation_poly_id == -1);
from_poly = &p_navigation_polys[from_poly->back_navigation_poly_id];
- if (pathway_start.distance_to(pathway_end) > CMP_EPSILON) {
+ if (!pathway_start.is_equal_approx(pathway_end)) {
Vector3 inters;
if (cut_plane.intersects_segment(pathway_start, pathway_end, &inters)) {
- if (inters.distance_to(p_to_point) > CMP_EPSILON && inters.distance_to(path[path.size() - 1]) > CMP_EPSILON) {
+ if (!inters.is_equal_approx(p_to_point) && !inters.is_equal_approx(path[path.size() - 1])) {
path.push_back(inters);
}
}
diff --git a/modules/gdnavigation/nav_map.h b/modules/navigation/nav_map.h
index 8e013a72eb..8e013a72eb 100644
--- a/modules/gdnavigation/nav_map.h
+++ b/modules/navigation/nav_map.h
diff --git a/modules/gdnavigation/nav_region.cpp b/modules/navigation/nav_region.cpp
index 81b15a49f5..81b15a49f5 100644
--- a/modules/gdnavigation/nav_region.cpp
+++ b/modules/navigation/nav_region.cpp
diff --git a/modules/gdnavigation/nav_region.h b/modules/navigation/nav_region.h
index f8b067e638..f8b067e638 100644
--- a/modules/gdnavigation/nav_region.h
+++ b/modules/navigation/nav_region.h
diff --git a/modules/gdnavigation/nav_rid.h b/modules/navigation/nav_rid.h
index a0a60a3643..a0a60a3643 100644
--- a/modules/gdnavigation/nav_rid.h
+++ b/modules/navigation/nav_rid.h
diff --git a/modules/gdnavigation/nav_utils.h b/modules/navigation/nav_utils.h
index 35da391eea..35da391eea 100644
--- a/modules/gdnavigation/nav_utils.h
+++ b/modules/navigation/nav_utils.h
diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp b/modules/navigation/navigation_mesh_editor_plugin.cpp
index aa9248d2a1..8f4203e260 100644
--- a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp
+++ b/modules/navigation/navigation_mesh_editor_plugin.cpp
@@ -47,8 +47,8 @@ void NavigationMeshEditor::_node_removed(Node *p_node) {
void NavigationMeshEditor::_notification(int p_option) {
if (p_option == NOTIFICATION_ENTER_TREE) {
- button_bake->set_icon(get_theme_icon("Bake", "EditorIcons"));
- button_reset->set_icon(get_theme_icon("Reload", "EditorIcons"));
+ button_bake->set_icon(get_theme_icon(SNAME("Bake"), SNAME("EditorIcons")));
+ button_reset->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
}
}
diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.h b/modules/navigation/navigation_mesh_editor_plugin.h
index c39269865b..c39269865b 100644
--- a/modules/gdnavigation/navigation_mesh_editor_plugin.h
+++ b/modules/navigation/navigation_mesh_editor_plugin.h
diff --git a/modules/gdnavigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index 0d8330c1da..7aeb9e1858 100644
--- a/modules/gdnavigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -47,12 +47,12 @@
#include "scene/resources/sphere_shape_3d.h"
#include "scene/resources/world_margin_shape_3d.h"
-#include "modules/modules_enabled.gen.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#endif
+#include "modules/modules_enabled.gen.h"
#ifdef MODULE_CSG_ENABLED
#include "modules/csg/csg_shape.h"
#endif
diff --git a/modules/gdnavigation/navigation_mesh_generator.h b/modules/navigation/navigation_mesh_generator.h
index 847c7d097b..847c7d097b 100644
--- a/modules/gdnavigation/navigation_mesh_generator.h
+++ b/modules/navigation/navigation_mesh_generator.h
diff --git a/modules/gdnavigation/register_types.cpp b/modules/navigation/register_types.cpp
index 8443d3d242..97c01d42ab 100644
--- a/modules/gdnavigation/register_types.cpp
+++ b/modules/navigation/register_types.cpp
@@ -31,9 +31,10 @@
#include "register_types.h"
#include "core/config/engine.h"
-#include "gd_navigation_server.h"
#include "servers/navigation_server_3d.h"
+#include "godot_navigation_server.h"
+
#ifndef _3D_DISABLED
#include "navigation_mesh_generator.h"
#endif
@@ -42,38 +43,29 @@
#include "navigation_mesh_editor_plugin.h"
#endif
-/**
- @author AndreaCatania
-*/
-
#ifndef _3D_DISABLED
NavigationMeshGenerator *_nav_mesh_generator = nullptr;
#endif
NavigationServer3D *new_server() {
- return memnew(GdNavigationServer);
+ return memnew(GodotNavigationServer);
}
-void register_gdnavigation_types() {
+void register_navigation_types() {
NavigationServer3DManager::set_default_server(new_server);
#ifndef _3D_DISABLED
_nav_mesh_generator = memnew(NavigationMeshGenerator);
- ClassDB::register_class<NavigationMeshGenerator>();
+ GDREGISTER_CLASS(NavigationMeshGenerator);
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationMeshGenerator", NavigationMeshGenerator::get_singleton()));
#endif
#ifdef TOOLS_ENABLED
EditorPlugins::add_by_type<NavigationMeshEditorPlugin>();
-
- ClassDB::APIType prev_api = ClassDB::get_current_api();
- ClassDB::set_current_api(ClassDB::API_EDITOR);
-
- ClassDB::set_current_api(prev_api);
#endif
}
-void unregister_gdnavigation_types() {
+void unregister_navigation_types() {
#ifndef _3D_DISABLED
if (_nav_mesh_generator) {
memdelete(_nav_mesh_generator);
diff --git a/modules/gdnavigation/register_types.h b/modules/navigation/register_types.h
index c2bb08c649..4737c818eb 100644
--- a/modules/gdnavigation/register_types.h
+++ b/modules/navigation/register_types.h
@@ -28,14 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-/**
- @author AndreaCatania
-*/
+#ifndef NAVIGATION_REGISTER_TYPES_H
+#define NAVIGATION_REGISTER_TYPES_H
-#ifndef GDNAVIGATION_REGISTER_TYPES_H
-#define GDNAVIGATION_REGISTER_TYPES_H
+void register_navigation_types();
+void unregister_navigation_types();
-void register_gdnavigation_types();
-void unregister_gdnavigation_types();
-
-#endif // GDNAVIGATION_REGISTER_TYPES_H
+#endif // NAVIGATION_REGISTER_TYPES_H
diff --git a/modules/gdnavigation/rvo_agent.cpp b/modules/navigation/rvo_agent.cpp
index 21e43d08c1..21e43d08c1 100644
--- a/modules/gdnavigation/rvo_agent.cpp
+++ b/modules/navigation/rvo_agent.cpp
diff --git a/modules/gdnavigation/rvo_agent.h b/modules/navigation/rvo_agent.h
index 369cb1f9a3..369cb1f9a3 100644
--- a/modules/gdnavigation/rvo_agent.h
+++ b/modules/navigation/rvo_agent.h
diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp
index 66c52ffbf9..9db3f3d5fd 100644
--- a/modules/opensimplex/noise_texture.cpp
+++ b/modules/opensimplex/noise_texture.cpp
@@ -109,7 +109,7 @@ void NoiseTexture::_thread_done(const Ref<Image> &p_image) {
void NoiseTexture::_thread_function(void *p_ud) {
NoiseTexture *tex = (NoiseTexture *)p_ud;
- tex->call_deferred("_thread_done", tex->_generate_texture());
+ tex->call_deferred(SNAME("_thread_done"), tex->_generate_texture());
}
void NoiseTexture::_queue_update() {
@@ -118,7 +118,7 @@ void NoiseTexture::_queue_update() {
}
update_queued = true;
- call_deferred("_update_texture");
+ call_deferred(SNAME("_update_texture"));
}
Ref<Image> NoiseTexture::_generate_texture() {
diff --git a/modules/opensimplex/register_types.cpp b/modules/opensimplex/register_types.cpp
index e9735a2cc8..d6f9f3436d 100644
--- a/modules/opensimplex/register_types.cpp
+++ b/modules/opensimplex/register_types.cpp
@@ -33,8 +33,8 @@
#include "open_simplex_noise.h"
void register_opensimplex_types() {
- ClassDB::register_class<OpenSimplexNoise>();
- ClassDB::register_class<NoiseTexture>();
+ GDREGISTER_CLASS(OpenSimplexNoise);
+ GDREGISTER_CLASS(NoiseTexture);
}
void unregister_opensimplex_types() {
diff --git a/modules/pvr/image_compress_pvrtc.cpp b/modules/pvr/image_compress_pvrtc.cpp
index f33912cec0..980cac17d3 100644
--- a/modules/pvr/image_compress_pvrtc.cpp
+++ b/modules/pvr/image_compress_pvrtc.cpp
@@ -43,6 +43,10 @@ static void _compress_pvrtc1_4bpp(Image *p_img) {
if (!img->is_size_po2() || img->get_width() != img->get_height()) {
make_mipmaps = img->has_mipmaps();
img->resize_to_po2(true);
+ // Resizing can fail for some formats
+ if (!img->is_size_po2() || img->get_width() != img->get_height()) {
+ ERR_FAIL_MSG("Failed to resize the image for compression.");
+ }
}
img->convert(Image::FORMAT_RGBA8);
if (!img->has_mipmaps() && make_mipmaps) {
diff --git a/modules/regex/register_types.cpp b/modules/regex/register_types.cpp
index 82f3eaf707..03957f88cf 100644
--- a/modules/regex/register_types.cpp
+++ b/modules/regex/register_types.cpp
@@ -33,8 +33,8 @@
#include "regex.h"
void register_regex_types() {
- ClassDB::register_class<RegExMatch>();
- ClassDB::register_class<RegEx>();
+ GDREGISTER_CLASS(RegExMatch);
+ GDREGISTER_CLASS(RegEx);
}
void unregister_regex_types() {
diff --git a/modules/stb_vorbis/register_types.cpp b/modules/stb_vorbis/register_types.cpp
index d9c6c06d65..bdb1cf69cf 100644
--- a/modules/stb_vorbis/register_types.cpp
+++ b/modules/stb_vorbis/register_types.cpp
@@ -45,7 +45,7 @@ void register_stb_vorbis_types() {
ResourceFormatImporter::get_singleton()->add_importer(ogg_import);
}
#endif
- ClassDB::register_class<AudioStreamOGGVorbis>();
+ GDREGISTER_CLASS(AudioStreamOGGVorbis);
}
void unregister_stb_vorbis_types() {
diff --git a/modules/text_server_adv/dynamic_font_adv.h b/modules/text_server_adv/dynamic_font_adv.h
index 1292966f0c..b3f97bb029 100644
--- a/modules/text_server_adv/dynamic_font_adv.h
+++ b/modules/text_server_adv/dynamic_font_adv.h
@@ -34,7 +34,6 @@
#include "font_adv.h"
#include "modules/modules_enabled.gen.h"
-
#ifdef MODULE_FREETYPE_ENABLED
#include <ft2build.h>
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 906ebe4993..2513039e8e 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -129,6 +129,10 @@ _FORCE_INLINE_ bool is_linebreak(char32_t p_char) {
return (p_char >= 0x000a && p_char <= 0x000d) || (p_char == 0x0085) || (p_char == 0x2028) || (p_char == 0x2029);
}
+_FORCE_INLINE_ bool is_underscore(char32_t p_char) {
+ return (p_char == 0x005F);
+}
+
/*************************************************************************/
String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite";
@@ -1658,6 +1662,161 @@ float TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<float
return 0.f;
}
+void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint8_t p_clip_flags) {
+ _THREAD_SAFE_METHOD_
+ ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped_line);
+ ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid.");
+ if (!sd->valid) {
+ shaped_text_shape(p_shaped_line);
+ }
+
+ bool add_ellipsis = (p_clip_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS;
+ bool cut_per_word = (p_clip_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY;
+ bool enforce_ellipsis = (p_clip_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS;
+
+ Glyph *sd_glyphs = sd->glyphs.ptrw();
+
+ if ((p_clip_flags & OVERRUN_TRIM) == OVERRUN_NO_TRIMMING || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) {
+ return;
+ }
+
+ int sd_size = sd->glyphs.size();
+ RID last_gl_font_rid = sd_glyphs[sd_size - 1].font_rid;
+ int last_gl_font_size = sd_glyphs[sd_size - 1].font_size;
+ uint32_t dot_gl_idx = font_get_glyph_index(last_gl_font_rid, '.');
+ Vector2 dot_adv = font_get_glyph_advance(last_gl_font_rid, dot_gl_idx, last_gl_font_size);
+ uint32_t whitespace_gl_idx = font_get_glyph_index(last_gl_font_rid, ' ');
+ Vector2 whitespace_adv = font_get_glyph_advance(last_gl_font_rid, whitespace_gl_idx, last_gl_font_size);
+
+ int ellipsis_advance = 0;
+ if (add_ellipsis) {
+ ellipsis_advance = 3 * dot_adv.x + font_get_spacing_glyph(last_gl_font_rid) + (cut_per_word ? whitespace_adv.x : 0);
+ }
+
+ int ell_min_characters = 6;
+ float width = sd->width;
+
+ bool is_rtl = sd->direction == DIRECTION_RTL || (sd->direction == DIRECTION_AUTO && sd->para_direction == DIRECTION_RTL);
+
+ int trim_pos = (is_rtl) ? sd_size : 0;
+ int ellipsis_pos = (enforce_ellipsis) ? 0 : -1;
+
+ int last_valid_cut = 0;
+ bool found = false;
+
+ int glyphs_from = (is_rtl) ? 0 : sd_size - 1;
+ int glyphs_to = (is_rtl) ? sd_size - 1 : -1;
+ int glyphs_delta = (is_rtl) ? +1 : -1;
+
+ for (int i = glyphs_from; i != glyphs_to; i += glyphs_delta) {
+ if (!is_rtl) {
+ width -= sd_glyphs[i].advance;
+ }
+ if (sd_glyphs[i].count > 0) {
+ bool above_min_char_treshold = ((is_rtl) ? sd_size - 1 - i : i) >= ell_min_characters;
+
+ if (width + (((above_min_char_treshold && add_ellipsis) || enforce_ellipsis) ? ellipsis_advance : 0) <= p_width) {
+ if (cut_per_word && above_min_char_treshold) {
+ if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
+ last_valid_cut = i;
+ found = true;
+ }
+ } else {
+ last_valid_cut = i;
+ found = true;
+ }
+ if (found) {
+ trim_pos = last_valid_cut;
+
+ if (above_min_char_treshold && width - ellipsis_advance <= p_width) {
+ ellipsis_pos = trim_pos;
+ }
+ break;
+ }
+ }
+ }
+ if (is_rtl) {
+ width -= sd_glyphs[i].advance;
+ }
+ }
+
+ if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis) {
+ int added_glyphs = 0;
+ if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) {
+ // Insert an additional space when cutting word bound for aesthetics.
+ if (cut_per_word && (ellipsis_pos > 0)) {
+ TextServer::Glyph gl;
+ gl.start = sd_glyphs[ellipsis_pos].start;
+ gl.end = sd_glyphs[ellipsis_pos].end;
+ gl.count = 1;
+ gl.advance = whitespace_adv.x;
+ gl.index = whitespace_gl_idx;
+ gl.font_rid = last_gl_font_rid;
+ gl.font_size = last_gl_font_size;
+ gl.flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_BREAK_SOFT | GRAPHEME_IS_VIRTUAL | (is_rtl ? GRAPHEME_IS_RTL : 0);
+
+ // Optimized glyph insertion by replacing a glyph whenever possible.
+ int glyph_idx = trim_pos + ((is_rtl) ? (-added_glyphs - 1) : added_glyphs);
+ if (is_rtl) {
+ if (glyph_idx < 0) {
+ sd->glyphs.insert(0, gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ } else {
+ if (glyph_idx > (sd_size - 1)) {
+ sd->glyphs.append(gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ }
+ added_glyphs++;
+ }
+ // Add ellipsis dots.
+ for (int d = 0; d < 3; d++) {
+ TextServer::Glyph gl;
+ gl.start = sd_glyphs[ellipsis_pos].start;
+ gl.end = sd_glyphs[ellipsis_pos].end;
+ gl.count = 1;
+ gl.advance = dot_adv.x;
+ gl.index = dot_gl_idx;
+ gl.font_rid = last_gl_font_rid;
+ gl.font_size = last_gl_font_size;
+ gl.flags = GRAPHEME_IS_PUNCTUATION | GRAPHEME_IS_VIRTUAL | (is_rtl ? GRAPHEME_IS_RTL : 0);
+
+ // Optimized glyph insertion by replacing a glyph whenever possible.
+ int glyph_idx = trim_pos + ((is_rtl) ? (-added_glyphs - 1) : added_glyphs);
+ if (is_rtl) {
+ if (glyph_idx < 0) {
+ sd->glyphs.insert(0, gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ } else {
+ if (glyph_idx > (sd_size - 1)) {
+ sd->glyphs.append(gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ }
+ added_glyphs++;
+ }
+ }
+
+ // Cut the remaining glyphs off.
+ if (!is_rtl) {
+ sd->glyphs.resize(trim_pos + added_glyphs);
+ } else {
+ if (trim_pos - added_glyphs >= 0) {
+ sd->glyphs = sd->glyphs.subarray(trim_pos - added_glyphs, sd->glyphs.size() - 1);
+ }
+ }
+
+ // Update to correct width.
+ sd->width = width + ((ellipsis_pos != -1) ? ellipsis_advance : 0);
+ }
+}
+
bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
_THREAD_SAFE_METHOD_
ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped);
@@ -1728,7 +1887,10 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
if (is_whitespace(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_SPACE;
}
- if (u_ispunct(c)) {
+ if (is_underscore(c)) {
+ sd_glyphs[i].flags |= GRAPHEME_IS_UNDERSCORE;
+ }
+ if (u_ispunct(c) && c != 0x005F) {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
}
if (breaks.has(sd->glyphs[i].start)) {
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 4ad23ca059..3c4f840bfd 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -229,6 +229,8 @@ public:
virtual bool shaped_text_update_breaks(RID p_shaped) override;
virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
+ virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_clip_flags) override;
+
virtual bool shaped_text_is_ready(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const override;
diff --git a/modules/text_server_fb/dynamic_font_fb.h b/modules/text_server_fb/dynamic_font_fb.h
index b34c8cbed5..82e59fa607 100644
--- a/modules/text_server_fb/dynamic_font_fb.h
+++ b/modules/text_server_fb/dynamic_font_fb.h
@@ -34,7 +34,6 @@
#include "font_fb.h"
#include "modules/modules_enabled.gen.h"
-
#ifdef MODULE_FREETYPE_ENABLED
#include <ft2build.h>
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index a22559efdd..9ad7dabbcc 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -46,7 +46,11 @@ _FORCE_INLINE_ bool is_linebreak(char32_t p_char) {
}
_FORCE_INLINE_ bool is_punct(char32_t p_char) {
- return (p_char >= 0x0020 && p_char <= 0x002F) || (p_char >= 0x003A && p_char <= 0x0040) || (p_char >= 0x005B && p_char <= 0x0060) || (p_char >= 0x007B && p_char <= 0x007E) || (p_char >= 0x2000 && p_char <= 0x206F) || (p_char >= 0x3000 && p_char <= 0x303F);
+ return (p_char >= 0x0020 && p_char <= 0x002F) || (p_char >= 0x003A && p_char <= 0x0040) || (p_char >= 0x005B && p_char <= 0x005E) || (p_char == 0x0060) || (p_char >= 0x007B && p_char <= 0x007E) || (p_char >= 0x2000 && p_char <= 0x206F) || (p_char >= 0x3000 && p_char <= 0x303F);
+}
+
+_FORCE_INLINE_ bool is_underscore(char32_t p_char) {
+ return (p_char == 0x005F);
}
/*************************************************************************/
@@ -1108,6 +1112,9 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
if (is_punct(c)) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_PUNCTUATION;
}
+ if (is_underscore(c)) {
+ sd->glyphs.write[i].flags |= GRAPHEME_IS_UNDERSCORE;
+ }
if (is_whitespace(c) && !is_linebreak(c)) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_SPACE;
sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_SOFT;
@@ -1141,6 +1148,161 @@ bool TextServerFallback::shaped_text_update_justification_ops(RID p_shaped) {
return true;
}
+void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint8_t p_clip_flags) {
+ _THREAD_SAFE_METHOD_
+ ShapedTextData *sd = shaped_owner.getornull(p_shaped_line);
+ ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid.");
+ if (!sd->valid) {
+ shaped_text_shape(p_shaped_line);
+ }
+
+ bool add_ellipsis = (p_clip_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS;
+ bool cut_per_word = (p_clip_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY;
+ bool enforce_ellipsis = (p_clip_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS;
+
+ Glyph *sd_glyphs = sd->glyphs.ptrw();
+
+ if ((p_clip_flags & OVERRUN_TRIM) == OVERRUN_NO_TRIMMING || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) {
+ return;
+ }
+
+ int sd_size = sd->glyphs.size();
+ RID last_gl_font_rid = sd_glyphs[sd_size - 1].font_rid;
+ int last_gl_font_size = sd_glyphs[sd_size - 1].font_size;
+ uint32_t dot_gl_idx = font_get_glyph_index(last_gl_font_rid, '.');
+ Vector2 dot_adv = font_get_glyph_advance(last_gl_font_rid, dot_gl_idx, last_gl_font_size);
+ uint32_t whitespace_gl_idx = font_get_glyph_index(last_gl_font_rid, ' ');
+ Vector2 whitespace_adv = font_get_glyph_advance(last_gl_font_rid, whitespace_gl_idx, last_gl_font_size);
+
+ int ellipsis_advance = 0;
+ if (add_ellipsis) {
+ ellipsis_advance = 3 * dot_adv.x + font_get_spacing_glyph(last_gl_font_rid) + (cut_per_word ? whitespace_adv.x : 0);
+ }
+
+ int ell_min_characters = 6;
+ float width = sd->width;
+
+ bool is_rtl = sd->direction == DIRECTION_RTL || (sd->direction == DIRECTION_AUTO && sd->para_direction == DIRECTION_RTL);
+
+ int trim_pos = (is_rtl) ? sd_size : 0;
+ int ellipsis_pos = (enforce_ellipsis) ? 0 : -1;
+
+ int last_valid_cut = 0;
+ bool found = false;
+
+ int glyphs_from = (is_rtl) ? 0 : sd_size - 1;
+ int glyphs_to = (is_rtl) ? sd_size - 1 : -1;
+ int glyphs_delta = (is_rtl) ? +1 : -1;
+
+ for (int i = glyphs_from; i != glyphs_to; i += glyphs_delta) {
+ if (!is_rtl) {
+ width -= sd_glyphs[i].advance;
+ }
+ if (sd_glyphs[i].count > 0) {
+ bool above_min_char_treshold = ((is_rtl) ? sd_size - 1 - i : i) >= ell_min_characters;
+
+ if (width + (((above_min_char_treshold && add_ellipsis) || enforce_ellipsis) ? ellipsis_advance : 0) <= p_width) {
+ if (cut_per_word && above_min_char_treshold) {
+ if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
+ last_valid_cut = i;
+ found = true;
+ }
+ } else {
+ last_valid_cut = i;
+ found = true;
+ }
+ if (found) {
+ trim_pos = last_valid_cut;
+
+ if (above_min_char_treshold && width - ellipsis_advance <= p_width) {
+ ellipsis_pos = trim_pos;
+ }
+ break;
+ }
+ }
+ }
+ if (is_rtl) {
+ width -= sd_glyphs[i].advance;
+ }
+ }
+
+ if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis) {
+ int added_glyphs = 0;
+ if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) {
+ // Insert an additional space when cutting word bound for aesthetics.
+ if (cut_per_word && (ellipsis_pos > 0)) {
+ TextServer::Glyph gl;
+ gl.start = sd_glyphs[ellipsis_pos].start;
+ gl.end = sd_glyphs[ellipsis_pos].end;
+ gl.count = 1;
+ gl.advance = whitespace_adv.x;
+ gl.index = whitespace_gl_idx;
+ gl.font_rid = last_gl_font_rid;
+ gl.font_size = last_gl_font_size;
+ gl.flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_BREAK_SOFT | GRAPHEME_IS_VIRTUAL | (is_rtl ? GRAPHEME_IS_RTL : 0);
+
+ // Optimized glyph insertion by replacing a glyph whenever possible.
+ int glyph_idx = trim_pos + ((is_rtl) ? -added_glyphs : added_glyphs);
+ if (is_rtl) {
+ if (glyph_idx < 0) {
+ sd->glyphs.insert(0, gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ } else {
+ if (glyph_idx > (sd_size - 1)) {
+ sd->glyphs.append(gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ }
+ added_glyphs++;
+ }
+ // Add ellipsis dots.
+ for (int d = 0; d < 3; d++) {
+ TextServer::Glyph gl;
+ gl.start = sd_glyphs[ellipsis_pos].start;
+ gl.end = sd_glyphs[ellipsis_pos].end;
+ gl.count = 1;
+ gl.advance = dot_adv.x;
+ gl.index = dot_gl_idx;
+ gl.font_rid = last_gl_font_rid;
+ gl.font_size = last_gl_font_size;
+ gl.flags = GRAPHEME_IS_PUNCTUATION | GRAPHEME_IS_VIRTUAL | (is_rtl ? GRAPHEME_IS_RTL : 0);
+
+ // Optimized glyph insertion by replacing a glyph whenever possible.
+ int glyph_idx = trim_pos + ((is_rtl) ? -added_glyphs : added_glyphs);
+ if (is_rtl) {
+ if (glyph_idx < 0) {
+ sd->glyphs.insert(0, gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ } else {
+ if (glyph_idx > (sd_size - 1)) {
+ sd->glyphs.append(gl);
+ } else {
+ sd->glyphs.set(glyph_idx, gl);
+ }
+ }
+ added_glyphs++;
+ }
+ }
+
+ // Cut the remaining glyphs off.
+ if (!is_rtl) {
+ sd->glyphs.resize(trim_pos + added_glyphs);
+ } else {
+ for (int ridx = 0; ridx <= trim_pos - added_glyphs; ridx++) {
+ sd->glyphs.remove(0);
+ }
+ }
+
+ // Update to correct width.
+ sd->width = width + ((ellipsis_pos != -1) ? ellipsis_advance : 0);
+ }
+}
+
bool TextServerFallback::shaped_text_shape(RID p_shaped) {
_THREAD_SAFE_METHOD_
ShapedTextData *sd = shaped_owner.getornull(p_shaped);
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 8f5eb1d315..b70c8f4ec0 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -178,6 +178,8 @@ public:
virtual bool shaped_text_update_breaks(RID p_shaped) override;
virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
+ virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_clip_flags) override;
+
virtual bool shaped_text_is_ready(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const override;
diff --git a/modules/theora/register_types.cpp b/modules/theora/register_types.cpp
index fd6c9dcd3c..55148a6b87 100644
--- a/modules/theora/register_types.cpp
+++ b/modules/theora/register_types.cpp
@@ -38,7 +38,7 @@ void register_theora_types() {
resource_loader_theora.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_theora, true);
- ClassDB::register_class<VideoStreamTheora>();
+ GDREGISTER_CLASS(VideoStreamTheora);
}
void unregister_theora_types() {
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 40be067a91..2f6faec8ec 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -108,7 +108,7 @@ void VideoStreamPlaybackTheora::video_write() {
Ref<Image> img = memnew(Image(size.x, size.y, 0, Image::FORMAT_RGBA8, frame_data)); //zero copy image creation
- texture->update(img, true); //zero copy send to visual server
+ texture->update(img); //zero copy send to visual server
frames_pending = 1;
}
diff --git a/modules/upnp/register_types.cpp b/modules/upnp/register_types.cpp
index a5ee39517f..1e5edd3602 100644
--- a/modules/upnp/register_types.cpp
+++ b/modules/upnp/register_types.cpp
@@ -36,8 +36,8 @@
#include "upnp_device.h"
void register_upnp_types() {
- ClassDB::register_class<UPNP>();
- ClassDB::register_class<UPNPDevice>();
+ GDREGISTER_CLASS(UPNP);
+ GDREGISTER_CLASS(UPNPDevice);
}
void unregister_upnp_types() {
diff --git a/modules/vhacd/register_types.cpp b/modules/vhacd/register_types.cpp
index daad39bdfb..3d7aaee921 100644
--- a/modules/vhacd/register_types.cpp
+++ b/modules/vhacd/register_types.cpp
@@ -32,7 +32,7 @@
#include "scene/resources/mesh.h"
#include "thirdparty/vhacd/public/VHACD.h"
-static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces) {
+static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, int p_max_convex_hulls = -1) {
Vector<float> vertices;
vertices.resize(p_faces.size() * 9);
Vector<uint32_t> indices;
@@ -47,8 +47,12 @@ static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces) {
}
}
- VHACD::IVHACD *decomposer = VHACD::CreateVHACD();
VHACD::IVHACD::Parameters params;
+ if (p_max_convex_hulls > 0) {
+ params.m_maxConvexHulls = p_max_convex_hulls;
+ }
+
+ VHACD::IVHACD *decomposer = VHACD::CreateVHACD();
decomposer->Compute(vertices.ptr(), vertices.size() / 3, indices.ptr(), indices.size() / 3, params);
int hull_count = decomposer->GetNConvexHulls();
diff --git a/modules/visual_script/doc_classes/VisualScriptExpression.xml b/modules/visual_script/doc_classes/VisualScriptExpression.xml
index 5253f7bc7d..223adbbb96 100644
--- a/modules/visual_script/doc_classes/VisualScriptExpression.xml
+++ b/modules/visual_script/doc_classes/VisualScriptExpression.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptExpression" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node that can execute a custom expression.
</brief_description>
<description>
+ A Visual Script node that can execute a custom expression. Values can be provided for the input and the expression result can be retrieved from the output.
</description>
<tutorials>
</tutorials>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunction.xml b/modules/visual_script/doc_classes/VisualScriptFunction.xml
index 873d26a5be..652418bd64 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunction.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptFunction" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node representing a function.
</brief_description>
<description>
+ [VisualScriptFunction] represents a function header. It is the starting point for the function body and can be used to tweak the function's properties (e.g. RPC mode).
</description>
<tutorials>
</tutorials>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
index 48104afcf7..f0b666e57a 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node for calling a function.
</brief_description>
<description>
+ [VisualScriptFunctionCall] is created when you add or drag and drop a function onto the Visual Script graph. It allows to tweak parameters of the call, e.g. what object the function is called on.
</description>
<tutorials>
</tutorials>
@@ -10,46 +12,66 @@
</methods>
<members>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
+ The script to be used when [member call_mode] is set to [constant CALL_MODE_INSTANCE].
</member>
<member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
+ The base type to be used when [member call_mode] is set to [constant CALL_MODE_INSTANCE].
</member>
<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
+ The type to be used when [member call_mode] is set to [constant CALL_MODE_BASIC_TYPE].
</member>
<member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptFunctionCall.CallMode" default="0">
+ [code]call_mode[/code] determines the target object on which the method will be called. See [enum CallMode] for options.
</member>
<member name="function" type="StringName" setter="set_function" getter="get_function" default="&amp;&quot;&quot;">
+ The name of the function to be called.
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+ The node path to use when [member call_mode] is set to [constant CALL_MODE_NODE_PATH].
</member>
<member name="rpc_call_mode" type="int" setter="set_rpc_call_mode" getter="get_rpc_call_mode" enum="VisualScriptFunctionCall.RPCCallMode" default="0">
+ The mode for RPC calls. See [method Node.rpc] for more details and [enum RPCCallMode] for available options.
</member>
<member name="singleton" type="StringName" setter="set_singleton" getter="get_singleton">
+ The singleton to call the method on. Used when [member call_mode] is set to [constant CALL_MODE_SINGLETON].
</member>
<member name="use_default_args" type="int" setter="set_use_default_args" getter="get_use_default_args">
+ Number of default arguments that will be used when calling the function. Can't be higher than the number of available default arguments in the method's declaration.
</member>
<member name="validate" type="bool" setter="set_validate" getter="get_validate" default="true">
+ If [code]false[/code], call errors (e.g. wrong number of arguments) will be ignored.
</member>
</members>
<constants>
<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+ The method will be called on this [Object].
</constant>
<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+ The method will be called on the given [Node] in the scene tree.
</constant>
<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+ The method will be called on an instanced node with the given type and script.
</constant>
<constant name="CALL_MODE_BASIC_TYPE" value="3" enum="CallMode">
+ The method will be called on a GDScript basic type (e.g. [Vector2]).
</constant>
<constant name="CALL_MODE_SINGLETON" value="4" enum="CallMode">
+ The method will be called on a singleton.
</constant>
<constant name="RPC_DISABLED" value="0" enum="RPCCallMode">
+ The method will be called locally.
</constant>
<constant name="RPC_RELIABLE" value="1" enum="RPCCallMode">
+ The method will be called remotely.
</constant>
<constant name="RPC_UNRELIABLE" value="2" enum="RPCCallMode">
+ The method will be called remotely using an unreliable protocol.
</constant>
<constant name="RPC_RELIABLE_TO_ID" value="3" enum="RPCCallMode">
+ The method will be called remotely for the given peer.
</constant>
<constant name="RPC_UNRELIABLE_TO_ID" value="4" enum="RPCCallMode">
+ The method will be called remotely for the given peer, using an unreliable protocol.
</constant>
</constants>
</class>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
index 16c1629fe4..54a02bf270 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptFunctionState" inherits="RefCounted" version="4.0">
<brief_description>
+ A Visual Script node representing a function state.
</brief_description>
<description>
+ [VisualScriptFunctionState] is returned from [VisualScriptYield] and can be used to resume a paused function call.
</description>
<tutorials>
</tutorials>
@@ -17,12 +19,14 @@
<argument index="2" name="args" type="Array">
</argument>
<description>
+ Connects this [VisualScriptFunctionState] to a signal in the given object to automatically resume when it's emitted.
</description>
</method>
<method name="is_valid" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns whether the function state is valid.
</description>
</method>
<method name="resume">
@@ -31,6 +35,7 @@
<argument index="0" name="args" type="Array" default="[]">
</argument>
<description>
+ Resumes the function to run from the point it was yielded.
</description>
</method>
</methods>
diff --git a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
index ef17bd8a28..87fdfd4e53 100644
--- a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node returning a constant from [@GlobalScope].
</brief_description>
<description>
+ A Visual Script node returning a constant from [@GlobalScope].
</description>
<tutorials>
</tutorials>
@@ -10,6 +12,7 @@
</methods>
<members>
<member name="constant" type="int" setter="set_global_constant" getter="get_global_constant" default="0">
+ The constant to be used.
</member>
</members>
<constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
index bb1618a655..b348048298 100644
--- a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptIndexGet" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node for getting a value from an array or a dictionary.
</brief_description>
<description>
+ [VisualScriptIndexGet] will return the value stored in an array or a dictionary under the given index.
</description>
<tutorials>
</tutorials>
diff --git a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
index 4ff96f7211..d7fe7340ad 100644
--- a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptIndexSet" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node for setting a value in an array or a dictionary.
</brief_description>
<description>
+ [VisualScriptIndexSet] will set the value stored in an array or a dictionary under the given index to the provided new value.
</description>
<tutorials>
</tutorials>
diff --git a/modules/visual_script/doc_classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
index 9ca67feacb..d6fa111500 100644
--- a/modules/visual_script/doc_classes/VisualScriptInputAction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptInputAction" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node returning a state of an action.
</brief_description>
<description>
+ [VisualScriptInputAction] can be used to check if an action is pressed or released.
</description>
<tutorials>
</tutorials>
@@ -10,18 +12,24 @@
</methods>
<members>
<member name="action" type="StringName" setter="set_action_name" getter="get_action_name" default="&amp;&quot;&quot;">
+ Name of the action.
</member>
<member name="mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="VisualScriptInputAction.Mode" default="0">
+ State of the action to check. See [enum Mode] for options.
</member>
</members>
<constants>
<constant name="MODE_PRESSED" value="0" enum="Mode">
+ [code]True[/code] if action is pressed.
</constant>
<constant name="MODE_RELEASED" value="1" enum="Mode">
+ [code]True[/code] if action is released (i.e. not pressed).
</constant>
<constant name="MODE_JUST_PRESSED" value="2" enum="Mode">
+ [code]True[/code] on the frame the action was pressed.
</constant>
<constant name="MODE_JUST_RELEASED" value="3" enum="Mode">
+ [code]True[/code] on the frame the action was released.
</constant>
</constants>
</class>
diff --git a/modules/visual_script/doc_classes/VisualScriptLists.xml b/modules/visual_script/doc_classes/VisualScriptLists.xml
index 8a7254b46a..671c427228 100644
--- a/modules/visual_script/doc_classes/VisualScriptLists.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLists.xml
@@ -19,6 +19,7 @@
<argument index="2" name="index" type="int">
</argument>
<description>
+ Adds an input port to the Visual Script node.
</description>
</method>
<method name="add_output_data_port">
@@ -31,6 +32,7 @@
<argument index="2" name="index" type="int">
</argument>
<description>
+ Adds an output port to the Visual Script node.
</description>
</method>
<method name="remove_input_data_port">
@@ -39,6 +41,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Removes an input port from the Visual Script node.
</description>
</method>
<method name="remove_output_data_port">
@@ -47,6 +50,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Removes an output port from the Visual Script node.
</description>
</method>
<method name="set_input_data_port_name">
@@ -57,6 +61,7 @@
<argument index="1" name="name" type="String">
</argument>
<description>
+ Sets the name of an input port.
</description>
</method>
<method name="set_input_data_port_type">
@@ -67,6 +72,7 @@
<argument index="1" name="type" type="int" enum="Variant.Type">
</argument>
<description>
+ Sets the type of an input port.
</description>
</method>
<method name="set_output_data_port_name">
@@ -77,6 +83,7 @@
<argument index="1" name="name" type="String">
</argument>
<description>
+ Sets the name of an output port.
</description>
</method>
<method name="set_output_data_port_type">
@@ -87,6 +94,7 @@
<argument index="1" name="type" type="int" enum="Variant.Type">
</argument>
<description>
+ Sets the type of an output port.
</description>
</method>
</methods>
diff --git a/modules/visual_script/doc_classes/VisualScriptOperator.xml b/modules/visual_script/doc_classes/VisualScriptOperator.xml
index c8ce0f2732..cbbefa7f71 100644
--- a/modules/visual_script/doc_classes/VisualScriptOperator.xml
+++ b/modules/visual_script/doc_classes/VisualScriptOperator.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptOperator" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node that performs an operation on two values.
</brief_description>
<description>
[b]Input Ports:[/b]
@@ -15,8 +16,10 @@
</methods>
<members>
<member name="operator" type="int" setter="set_operator" getter="get_operator" enum="Variant.Operator" default="6">
+ The operation to be performed. See [enum Variant.Operator] for available options.
</member>
<member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type" default="0">
+ The type of the values for this operation. See [enum Variant.Type] for available options.
</member>
</members>
<constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
index ff6c723a3e..c1bf443ea3 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node returning a value of a property from an [Object].
</brief_description>
<description>
+ [VisualScriptPropertyGet] can return a value of any property from the current object or other objects.
</description>
<tutorials>
</tutorials>
@@ -10,28 +12,39 @@
</methods>
<members>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
+ The script to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
</member>
<member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
+ The base type to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
</member>
<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
+ The type to be used when [member set_mode] is set to [constant CALL_MODE_BASIC_TYPE].
</member>
<member name="index" type="StringName" setter="set_index" getter="get_index">
+ The indexed name of the property to retrieve. See [method Object.get_indexed] for details.
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+ The node path to use when [member set_mode] is set to [constant CALL_MODE_NODE_PATH].
</member>
<member name="property" type="StringName" setter="set_property" getter="get_property" default="&amp;&quot;&quot;">
+ The name of the property to retrieve. Changing this will clear [member index].
</member>
<member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertyGet.CallMode" default="0">
+ [code]set_mode[/code] determines the target object from which the property will be retrieved. See [enum CallMode] for options.
</member>
</members>
<constants>
<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+ The property will be retrieved from this [Object].
</constant>
<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+ The property will be retrieved from the given [Node] in the scene tree.
</constant>
<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+ The property will be retrieved from an instanced node with the given type and script.
</constant>
<constant name="CALL_MODE_BASIC_TYPE" value="3" enum="CallMode">
+ The property will be retrieved from a GDScript basic type (e.g. [Vector2]).
</constant>
</constants>
</class>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
index 71bfc4c8a5..75d6a63469 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptPropertySet" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node that sets a property of an [Object].
</brief_description>
<description>
+ [VisualScriptPropertySet] can set the value of any property from the current object or other objects.
</description>
<tutorials>
</tutorials>
@@ -10,52 +12,75 @@
</methods>
<members>
<member name="assign_op" type="int" setter="set_assign_op" getter="get_assign_op" enum="VisualScriptPropertySet.AssignOp" default="0">
+ The additional operation to perform when assigning. See [enum AssignOp] for options.
</member>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
+ The script to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
</member>
<member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
+ The base type to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
</member>
<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
+ The type to be used when [member set_mode] is set to [constant CALL_MODE_BASIC_TYPE].
</member>
<member name="index" type="StringName" setter="set_index" getter="get_index">
+ The indexed name of the property to set. See [method Object.set_indexed] for details.
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+ The node path to use when [member set_mode] is set to [constant CALL_MODE_NODE_PATH].
</member>
<member name="property" type="StringName" setter="set_property" getter="get_property" default="&amp;&quot;&quot;">
+ The name of the property to set. Changing this will clear [member index].
</member>
<member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertySet.CallMode" default="0">
+ [code]set_mode[/code] determines the target object on which the property will be set. See [enum CallMode] for options.
</member>
</members>
<constants>
<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+ The property will be set on this [Object].
</constant>
<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+ The property will be set on the given [Node] in the scene tree.
</constant>
<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+ The property will be set on an instanced node with the given type and script.
</constant>
<constant name="CALL_MODE_BASIC_TYPE" value="3" enum="CallMode">
+ The property will be set on a GDScript basic type (e.g. [Vector2]).
</constant>
<constant name="ASSIGN_OP_NONE" value="0" enum="AssignOp">
+ The property will be assigned regularly.
</constant>
<constant name="ASSIGN_OP_ADD" value="1" enum="AssignOp">
+ The value will be added to the property. Equivalent of doing [code]+=[/code].
</constant>
<constant name="ASSIGN_OP_SUB" value="2" enum="AssignOp">
+ The value will be subtracted from the property. Equivalent of doing [code]-=[/code].
</constant>
<constant name="ASSIGN_OP_MUL" value="3" enum="AssignOp">
+ The property will be multiplied by the value. Equivalent of doing [code]*=[/code].
</constant>
<constant name="ASSIGN_OP_DIV" value="4" enum="AssignOp">
+ The property will be divided by the value. Equivalent of doing [code]/=[/code].
</constant>
<constant name="ASSIGN_OP_MOD" value="5" enum="AssignOp">
+ A modulo operation will be performed on the property and the value. Equivalent of doing [code]%=[/code].
</constant>
<constant name="ASSIGN_OP_SHIFT_LEFT" value="6" enum="AssignOp">
+ The property will be binarly shifted to the left by the given value. Equivalent of doing [code]&lt;&lt;[/code].
</constant>
<constant name="ASSIGN_OP_SHIFT_RIGHT" value="7" enum="AssignOp">
+ The property will be binarly shifted to the right by the given value. Equivalent of doing [code]&gt;&gt;[/code].
</constant>
<constant name="ASSIGN_OP_BIT_AND" value="8" enum="AssignOp">
+ A binary [code]AND[/code] operation will be performed on the property. Equivalent of doing [code]&amp;=[/code].
</constant>
<constant name="ASSIGN_OP_BIT_OR" value="9" enum="AssignOp">
+ A binary [code]OR[/code] operation will be performed on the property. Equivalent of doing [code]|=[/code].
</constant>
<constant name="ASSIGN_OP_BIT_XOR" value="10" enum="AssignOp">
+ A binary [code]XOR[/code] operation will be performed on the property. Equivalent of doing [code]^=[/code].
</constant>
</constants>
</class>
diff --git a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
index 191d4b6977..8cddd02c77 100644
--- a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptSceneTree" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node for accessing [SceneTree] methods.
</brief_description>
<description>
+ A Visual Script node for accessing [SceneTree] methods.
</description>
<tutorials>
</tutorials>
diff --git a/modules/visual_script/doc_classes/VisualScriptSubCall.xml b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
index cb3b04b583..89a10edde4 100644
--- a/modules/visual_script/doc_classes/VisualScriptSubCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptSubCall" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ Calls a method called [code]_subcall[/code] in this object.
</brief_description>
<description>
+ [VisualScriptSubCall] will call method named [code]_subcall[/code] in the current script. It will fail if the method doesn't exist or the provided arguments are wrong.
</description>
<tutorials>
</tutorials>
@@ -13,6 +15,7 @@
<argument index="0" name="arguments" type="Variant">
</argument>
<description>
+ Called by this node.
</description>
</method>
</methods>
diff --git a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
index 9e3e020f2d..5dd1ad3421 100644
--- a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
+++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptTypeCast" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node that casts the given value to another type.
</brief_description>
<description>
+ [VisualScriptTypeCast] will perform a type conversion to an [Object]-derived type.
</description>
<tutorials>
</tutorials>
@@ -10,8 +12,10 @@
</methods>
<members>
<member name="base_script" type="String" setter="set_base_script" getter="get_base_script" default="&quot;&quot;">
+ The target script class to be converted to. If none, only the [member base_type] will be used.
</member>
<member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
+ The target type to be converted to.
</member>
</members>
<constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptYield.xml b/modules/visual_script/doc_classes/VisualScriptYield.xml
index 0a8d529a48..b04ab7b014 100644
--- a/modules/visual_script/doc_classes/VisualScriptYield.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYield.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptYield" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node used to pause a function execution.
</brief_description>
<description>
+ [VisualScriptYield] will pause the function call and return [VisualScriptFunctionState], which can be used to resume the function.
</description>
<tutorials>
</tutorials>
@@ -10,16 +12,21 @@
</methods>
<members>
<member name="mode" type="int" setter="set_yield_mode" getter="get_yield_mode" enum="VisualScriptYield.YieldMode" default="1">
+ The mode to use for yielding. See [enum YieldMode] for available options.
</member>
<member name="wait_time" type="float" setter="set_wait_time" getter="get_wait_time">
+ The time to wait when [member mode] is set to [constant YIELD_WAIT].
</member>
</members>
<constants>
<constant name="YIELD_FRAME" value="1" enum="YieldMode">
+ Yields during an idle frame.
</constant>
<constant name="YIELD_PHYSICS_FRAME" value="2" enum="YieldMode">
+ Yields during a physics frame.
</constant>
<constant name="YIELD_WAIT" value="3" enum="YieldMode">
+ Yields a function and waits the given time.
</constant>
</constants>
</class>
diff --git a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
index c59234433f..c6c3188d08 100644
--- a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" version="4.0">
<brief_description>
+ A Visual Script node yielding for a signal.
</brief_description>
<description>
+ [VisualScriptYieldSignal] will pause the function execution until the provided signal is emitted.
</description>
<tutorials>
</tutorials>
@@ -10,20 +12,27 @@
</methods>
<members>
<member name="base_type" type="StringName" setter="set_base_type" getter="get_base_type" default="&amp;&quot;Object&quot;">
+ The base type to be used when [member call_mode] is set to [constant CALL_MODE_INSTANCE].
</member>
<member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptYieldSignal.CallMode" default="0">
+ [code]call_mode[/code] determines the target object to wait for the signal emission. See [enum CallMode] for options.
</member>
<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+ The node path to use when [member call_mode] is set to [constant CALL_MODE_NODE_PATH].
</member>
<member name="signal" type="StringName" setter="set_signal" getter="get_signal" default="&amp;&quot;&quot;">
+ The signal name to be waited for.
</member>
</members>
<constants>
<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+ A signal from this [Object] will be used.
</constant>
<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+ A signal from the given [Node] in the scene tree will be used.
</constant>
<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+ A signal from an instanced node with the given type will be used.
</constant>
</constants>
</class>
diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp
index 4c7b66e368..f20ef046a3 100644
--- a/modules/visual_script/register_types.cpp
+++ b/modules/visual_script/register_types.cpp
@@ -51,59 +51,59 @@ void register_visual_script_types() {
//script_language_gd->init();
ScriptServer::register_language(visual_script_language);
- ClassDB::register_class<VisualScript>();
- ClassDB::register_virtual_class<VisualScriptNode>();
- ClassDB::register_class<VisualScriptFunctionState>();
- ClassDB::register_class<VisualScriptFunction>();
- ClassDB::register_virtual_class<VisualScriptLists>();
- ClassDB::register_class<VisualScriptComposeArray>();
- ClassDB::register_class<VisualScriptOperator>();
- ClassDB::register_class<VisualScriptVariableSet>();
- ClassDB::register_class<VisualScriptVariableGet>();
- ClassDB::register_class<VisualScriptConstant>();
- ClassDB::register_class<VisualScriptIndexGet>();
- ClassDB::register_class<VisualScriptIndexSet>();
- ClassDB::register_class<VisualScriptGlobalConstant>();
- ClassDB::register_class<VisualScriptClassConstant>();
- ClassDB::register_class<VisualScriptMathConstant>();
- ClassDB::register_class<VisualScriptBasicTypeConstant>();
- ClassDB::register_class<VisualScriptEngineSingleton>();
- ClassDB::register_class<VisualScriptSceneNode>();
- ClassDB::register_class<VisualScriptSceneTree>();
- ClassDB::register_class<VisualScriptResourcePath>();
- ClassDB::register_class<VisualScriptSelf>();
- ClassDB::register_class<VisualScriptCustomNode>();
- ClassDB::register_class<VisualScriptSubCall>();
- ClassDB::register_class<VisualScriptComment>();
- ClassDB::register_class<VisualScriptConstructor>();
- ClassDB::register_class<VisualScriptLocalVar>();
- ClassDB::register_class<VisualScriptLocalVarSet>();
- ClassDB::register_class<VisualScriptInputAction>();
- ClassDB::register_class<VisualScriptDeconstruct>();
- ClassDB::register_class<VisualScriptPreload>();
- ClassDB::register_class<VisualScriptTypeCast>();
-
- ClassDB::register_class<VisualScriptFunctionCall>();
- ClassDB::register_class<VisualScriptPropertySet>();
- ClassDB::register_class<VisualScriptPropertyGet>();
+ GDREGISTER_CLASS(VisualScript);
+ GDREGISTER_VIRTUAL_CLASS(VisualScriptNode);
+ GDREGISTER_CLASS(VisualScriptFunctionState);
+ GDREGISTER_CLASS(VisualScriptFunction);
+ GDREGISTER_VIRTUAL_CLASS(VisualScriptLists);
+ GDREGISTER_CLASS(VisualScriptComposeArray);
+ GDREGISTER_CLASS(VisualScriptOperator);
+ GDREGISTER_CLASS(VisualScriptVariableSet);
+ GDREGISTER_CLASS(VisualScriptVariableGet);
+ GDREGISTER_CLASS(VisualScriptConstant);
+ GDREGISTER_CLASS(VisualScriptIndexGet);
+ GDREGISTER_CLASS(VisualScriptIndexSet);
+ GDREGISTER_CLASS(VisualScriptGlobalConstant);
+ GDREGISTER_CLASS(VisualScriptClassConstant);
+ GDREGISTER_CLASS(VisualScriptMathConstant);
+ GDREGISTER_CLASS(VisualScriptBasicTypeConstant);
+ GDREGISTER_CLASS(VisualScriptEngineSingleton);
+ GDREGISTER_CLASS(VisualScriptSceneNode);
+ GDREGISTER_CLASS(VisualScriptSceneTree);
+ GDREGISTER_CLASS(VisualScriptResourcePath);
+ GDREGISTER_CLASS(VisualScriptSelf);
+ GDREGISTER_CLASS(VisualScriptCustomNode);
+ GDREGISTER_CLASS(VisualScriptSubCall);
+ GDREGISTER_CLASS(VisualScriptComment);
+ GDREGISTER_CLASS(VisualScriptConstructor);
+ GDREGISTER_CLASS(VisualScriptLocalVar);
+ GDREGISTER_CLASS(VisualScriptLocalVarSet);
+ GDREGISTER_CLASS(VisualScriptInputAction);
+ GDREGISTER_CLASS(VisualScriptDeconstruct);
+ GDREGISTER_CLASS(VisualScriptPreload);
+ GDREGISTER_CLASS(VisualScriptTypeCast);
+
+ GDREGISTER_CLASS(VisualScriptFunctionCall);
+ GDREGISTER_CLASS(VisualScriptPropertySet);
+ GDREGISTER_CLASS(VisualScriptPropertyGet);
//ClassDB::register_type<VisualScriptScriptCall>();
- ClassDB::register_class<VisualScriptEmitSignal>();
+ GDREGISTER_CLASS(VisualScriptEmitSignal);
- ClassDB::register_class<VisualScriptReturn>();
- ClassDB::register_class<VisualScriptCondition>();
- ClassDB::register_class<VisualScriptWhile>();
- ClassDB::register_class<VisualScriptIterator>();
- ClassDB::register_class<VisualScriptSequence>();
- //ClassDB::register_class<VisualScriptInputFilter>();
- ClassDB::register_class<VisualScriptSwitch>();
- ClassDB::register_class<VisualScriptSelect>();
+ GDREGISTER_CLASS(VisualScriptReturn);
+ GDREGISTER_CLASS(VisualScriptCondition);
+ GDREGISTER_CLASS(VisualScriptWhile);
+ GDREGISTER_CLASS(VisualScriptIterator);
+ GDREGISTER_CLASS(VisualScriptSequence);
+ //GDREGISTER_CLASS(VisualScriptInputFilter);
+ GDREGISTER_CLASS(VisualScriptSwitch);
+ GDREGISTER_CLASS(VisualScriptSelect);
- ClassDB::register_class<VisualScriptYield>();
- ClassDB::register_class<VisualScriptYieldSignal>();
+ GDREGISTER_CLASS(VisualScriptYield);
+ GDREGISTER_CLASS(VisualScriptYieldSignal);
- ClassDB::register_class<VisualScriptBuiltinFunc>();
+ GDREGISTER_CLASS(VisualScriptBuiltinFunc);
- ClassDB::register_class<VisualScriptExpression>();
+ GDREGISTER_CLASS(VisualScriptExpression);
register_visual_script_nodes();
register_visual_script_func_nodes();
@@ -114,7 +114,7 @@ void register_visual_script_types() {
#ifdef TOOLS_ENABLED
ClassDB::set_current_api(ClassDB::API_EDITOR);
- ClassDB::register_class<_VisualScriptEditor>();
+ GDREGISTER_CLASS(_VisualScriptEditor);
ClassDB::set_current_api(ClassDB::API_CORE);
vs_editor_singleton = memnew(_VisualScriptEditor);
Engine::get_singleton()->add_singleton(Engine::Singleton("VisualScriptEditor", _VisualScriptEditor::get_singleton()));
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index d49060bea8..0de39512ae 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -46,7 +46,7 @@ bool VisualScriptNode::is_breakpoint() const {
}
void VisualScriptNode::ports_changed_notify() {
- emit_signal("ports_changed");
+ emit_signal(SNAME("ports_changed"));
}
void VisualScriptNode::set_default_input_value(int p_port, const Variant &p_value) {
@@ -264,7 +264,7 @@ void VisualScript::_node_ports_changed(int p_id) {
#ifdef TOOLS_ENABLED
set_edited(true); // Something changed, let's set as edited.
- emit_signal("node_ports_changed", p_id);
+ emit_signal(SNAME("node_ports_changed"), p_id);
#endif
}
@@ -1025,7 +1025,7 @@ void VisualScript::_set_data(const Dictionary &p_data) {
MultiplayerAPI::RPCConfig nd;
nd.name = E->get();
nd.rpc_mode = vsf->get_rpc_mode();
- nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO
+ nd.transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO
if (rpc_functions.find(nd) == -1) {
rpc_functions.push_back(nd);
}
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 8858fe9ff1..ed0583a133 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -62,7 +62,7 @@ protected:
void _sig_changed() {
notify_property_list_changed();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool _set(const StringName &p_name, const Variant &p_value) {
@@ -196,10 +196,10 @@ protected:
void _var_changed() {
notify_property_list_changed();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
void _var_value_changed() {
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool _set(const StringName &p_name, const Variant &p_value) {
@@ -611,41 +611,44 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
select_func_text->hide();
Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = {
- Control::get_theme_icon("Variant", "EditorIcons"),
- Control::get_theme_icon("bool", "EditorIcons"),
- Control::get_theme_icon("int", "EditorIcons"),
- Control::get_theme_icon("float", "EditorIcons"),
- Control::get_theme_icon("String", "EditorIcons"),
- Control::get_theme_icon("Vector2", "EditorIcons"),
- Control::get_theme_icon("Vector2i", "EditorIcons"),
- Control::get_theme_icon("Rect2", "EditorIcons"),
- Control::get_theme_icon("Rect2i", "EditorIcons"),
- Control::get_theme_icon("Vector3", "EditorIcons"),
- Control::get_theme_icon("Vector3i", "EditorIcons"),
- Control::get_theme_icon("Transform2D", "EditorIcons"),
- Control::get_theme_icon("Plane", "EditorIcons"),
- Control::get_theme_icon("Quaternion", "EditorIcons"),
- Control::get_theme_icon("AABB", "EditorIcons"),
- Control::get_theme_icon("Basis", "EditorIcons"),
- Control::get_theme_icon("Transform3D", "EditorIcons"),
- Control::get_theme_icon("Color", "EditorIcons"),
- Control::get_theme_icon("NodePath", "EditorIcons"),
- Control::get_theme_icon("RID", "EditorIcons"),
- Control::get_theme_icon("MiniObject", "EditorIcons"),
- Control::get_theme_icon("Callable", "EditorIcons"),
- Control::get_theme_icon("Signal", "EditorIcons"),
- Control::get_theme_icon("Dictionary", "EditorIcons"),
- Control::get_theme_icon("Array", "EditorIcons"),
- Control::get_theme_icon("PackedByteArray", "EditorIcons"),
- Control::get_theme_icon("PackedInt32Array", "EditorIcons"),
- Control::get_theme_icon("PackedFloat32Array", "EditorIcons"),
- Control::get_theme_icon("PackedStringArray", "EditorIcons"),
- Control::get_theme_icon("PackedVector2Array", "EditorIcons"),
- Control::get_theme_icon("PackedVector3Array", "EditorIcons"),
- Control::get_theme_icon("PackedColorArray", "EditorIcons")
+ Control::get_theme_icon(SNAME("Variant"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("bool"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("int"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("String"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector2i"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Rect2"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Rect2i"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector3i"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Transform2D"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Plane"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Quaternion"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("AABB"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Basis"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Color"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("StringName"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("NodePath"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("RID"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("MiniObject"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Callable"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Signal"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Dictionary"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedByteArray"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedInt32Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedInt64Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedFloat32Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedFloat64Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedStringArray"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedVector2Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedVector3Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons"))
};
- Ref<Texture2D> seq_port = Control::get_theme_icon("VisualShaderPort", "EditorIcons");
+ Ref<Texture2D> seq_port = Control::get_theme_icon(SNAME("VisualShaderPort"), SNAME("EditorIcons"));
List<int> node_ids;
script->get_node_list(&node_ids);
@@ -711,7 +714,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
LineEdit *line_edit = memnew(LineEdit);
line_edit->set_text(node->get_text());
line_edit->set_expand_to_text_length_enabled(true);
- line_edit->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
+ line_edit->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
gnode->add_child(line_edit);
line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E->get()));
} else {
@@ -735,7 +738,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
if (node_styles.has(node->get_category())) {
Ref<StyleBoxFlat> sbf = node_styles[node->get_category()];
if (gnode->is_comment()) {
- sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode");
+ sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox(SNAME("comment"), SNAME("GraphNode"));
}
Color c = sbf->get_border_color();
@@ -748,7 +751,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
gnode->add_theme_style_override("frame", sbf);
}
- const Color mono_color = get_theme_color("mono_color", "Editor");
+ const Color mono_color = get_theme_color(SNAME("mono_color"), SNAME("Editor"));
int slot_idx = 0;
@@ -850,7 +853,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
}
Button *rmbtn = memnew(Button);
- rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons"));
+ rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbc->add_child(rmbtn);
rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E->get(), i), CONNECT_DEFERRED);
} else {
@@ -906,7 +909,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
if (right_ok) {
if (is_vslist) {
Button *rmbtn = memnew(Button);
- rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons"));
+ rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbc->add_child(rmbtn);
rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E->get(), i), CONNECT_DEFERRED);
@@ -950,7 +953,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
gnode->add_child(vbc);
- bool dark_theme = get_theme_constant("dark_theme", "Editor");
+ bool dark_theme = get_theme_constant(SNAME("dark_theme"), SNAME("Editor"));
if (i < mixed_seq_ports) {
gnode->set_slot(slot_idx, left_ok, left_type, _color_from_type(left_type, dark_theme), true, TYPE_SEQUENCE, mono_color, Ref<Texture2D>(), seq_port);
} else {
@@ -973,7 +976,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
graph->set_minimap_opacity(graph_minimap_opacity);
// Use default_func instead of default_func for now I think that should be good stop gap solution to ensure not breaking anything.
- graph->call_deferred("set_scroll_ofs", script->get_scroll() * EDSCALE);
+ graph->call_deferred(SNAME("set_scroll_ofs"), script->get_scroll() * EDSCALE);
updating_graph = false;
}
@@ -1037,9 +1040,9 @@ void VisualScriptEditor::_update_members() {
TreeItem *functions = members->create_item(root);
functions->set_selectable(0, false);
functions->set_text(0, TTR("Functions:"));
- functions->add_button(0, Control::get_theme_icon("Override", "EditorIcons"), 1, false, TTR("Override an existing built-in function."));
- functions->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), 0, false, TTR("Create a new function."));
- functions->set_custom_color(0, Control::get_theme_color("mono_color", "Editor"));
+ functions->add_button(0, Control::get_theme_icon(SNAME("Override"), SNAME("EditorIcons")), 1, false, TTR("Override an existing built-in function."));
+ functions->add_button(0, Control::get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), 0, false, TTR("Create a new function."));
+ functions->set_custom_color(0, Control::get_theme_color(SNAME("mono_color"), SNAME("Editor")));
List<StringName> func_names;
script->get_function_list(&func_names);
@@ -1049,7 +1052,7 @@ void VisualScriptEditor::_update_members() {
ti->set_text(0, E->get());
ti->set_selectable(0, true);
ti->set_metadata(0, E->get());
- ti->add_button(0, Control::get_theme_icon("Edit", "EditorIcons"), 0);
+ ti->add_button(0, Control::get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0);
if (selected == E->get()) {
ti->select(0);
}
@@ -1058,42 +1061,42 @@ void VisualScriptEditor::_update_members() {
TreeItem *variables = members->create_item(root);
variables->set_selectable(0, false);
variables->set_text(0, TTR("Variables:"));
- variables->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), -1, false, TTR("Create a new variable."));
- variables->set_custom_color(0, Control::get_theme_color("mono_color", "Editor"));
+ variables->add_button(0, Control::get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), -1, false, TTR("Create a new variable."));
+ variables->set_custom_color(0, Control::get_theme_color(SNAME("mono_color"), SNAME("Editor")));
Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = {
- Control::get_theme_icon("Variant", "EditorIcons"),
- Control::get_theme_icon("bool", "EditorIcons"),
- Control::get_theme_icon("int", "EditorIcons"),
- Control::get_theme_icon("float", "EditorIcons"),
- Control::get_theme_icon("String", "EditorIcons"),
- Control::get_theme_icon("Vector2", "EditorIcons"),
- Control::get_theme_icon("Vector2i", "EditorIcons"),
- Control::get_theme_icon("Rect2", "EditorIcons"),
- Control::get_theme_icon("Rect2i", "EditorIcons"),
- Control::get_theme_icon("Vector3", "EditorIcons"),
- Control::get_theme_icon("Vector3i", "EditorIcons"),
- Control::get_theme_icon("Transform2D", "EditorIcons"),
- Control::get_theme_icon("Plane", "EditorIcons"),
- Control::get_theme_icon("Quaternion", "EditorIcons"),
- Control::get_theme_icon("AABB", "EditorIcons"),
- Control::get_theme_icon("Basis", "EditorIcons"),
- Control::get_theme_icon("Transform3D", "EditorIcons"),
- Control::get_theme_icon("Color", "EditorIcons"),
- Control::get_theme_icon("NodePath", "EditorIcons"),
- Control::get_theme_icon("RID", "EditorIcons"),
- Control::get_theme_icon("MiniObject", "EditorIcons"),
- Control::get_theme_icon("Callable", "EditorIcons"),
- Control::get_theme_icon("Signal", "EditorIcons"),
- Control::get_theme_icon("Dictionary", "EditorIcons"),
- Control::get_theme_icon("Array", "EditorIcons"),
- Control::get_theme_icon("PackedByteArray", "EditorIcons"),
- Control::get_theme_icon("PackedInt32Array", "EditorIcons"),
- Control::get_theme_icon("PackedFloat32Array", "EditorIcons"),
- Control::get_theme_icon("PackedStringArray", "EditorIcons"),
- Control::get_theme_icon("PackedVector2Array", "EditorIcons"),
- Control::get_theme_icon("PackedVector3Array", "EditorIcons"),
- Control::get_theme_icon("PackedColorArray", "EditorIcons")
+ Control::get_theme_icon(SNAME("Variant"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("bool"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("int"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("String"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector2i"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Rect2"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Rect2i"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Vector3i"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Transform2D"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Plane"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Quaternion"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("AABB"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Basis"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Color"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("NodePath"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("RID"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("MiniObject"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Callable"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Signal"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Dictionary"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedByteArray"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedInt32Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedFloat32Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedStringArray"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedVector2Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedVector3Array"), SNAME("EditorIcons")),
+ Control::get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons"))
};
List<StringName> var_names;
@@ -1117,8 +1120,8 @@ void VisualScriptEditor::_update_members() {
TreeItem *_signals = members->create_item(root);
_signals->set_selectable(0, false);
_signals->set_text(0, TTR("Signals:"));
- _signals->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), -1, false, TTR("Create a new signal."));
- _signals->set_custom_color(0, Control::get_theme_color("mono_color", "Editor"));
+ _signals->add_button(0, Control::get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), -1, false, TTR("Create a new signal."));
+ _signals->set_custom_color(0, Control::get_theme_color(SNAME("mono_color"), SNAME("Editor")));
List<StringName> signal_names;
script->get_custom_signal_list(&signal_names);
@@ -1135,12 +1138,12 @@ void VisualScriptEditor::_update_members() {
String base_type = script->get_instance_base_type();
String icon_type = base_type;
- if (!Control::has_theme_icon(base_type, "EditorIcons")) {
+ if (!Control::has_theme_icon(base_type, SNAME("EditorIcons"))) {
icon_type = "Object";
}
base_type_select->set_text(base_type);
- base_type_select->set_icon(Control::get_theme_icon(icon_type, "EditorIcons"));
+ base_type_select->set_icon(Control::get_theme_icon(icon_type, SNAME("EditorIcons")));
updating_members = false;
}
@@ -1366,7 +1369,7 @@ void VisualScriptEditor::_add_func_input() {
hbox->add_child(type_box);
Button *delete_button = memnew(Button);
- delete_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons"));
+ delete_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
delete_button->set_tooltip(vformat(TTR("Delete input port")));
hbox->add_child(delete_button);
@@ -1428,7 +1431,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt
undo_redo->add_do_method(script.ptr(), "add_function", name, fn_id);
undo_redo->add_do_method(script.ptr(), "add_node", fn_id, func_node, pos);
undo_redo->add_undo_method(script.ptr(), "remove_function", name);
- undo_redo->add_do_method(script.ptr(), "remove_node", fn_id);
+ undo_redo->add_undo_method(script.ptr(), "remove_node", fn_id);
undo_redo->add_do_method(this, "_update_members");
undo_redo->add_undo_method(this, "_update_members");
undo_redo->add_do_method(this, "_update_graph");
@@ -2172,6 +2175,11 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
if (String(d["type"]) == "files") {
+#ifdef OSX_ENABLED
+ bool use_preload = Input::get_singleton()->is_key_pressed(KEY_META);
+#else
+ bool use_preload = Input::get_singleton()->is_key_pressed(KEY_CTRL);
+#endif
Vector2 pos = _get_pos_in_graph(p_point);
Array files = d["files"];
@@ -2187,13 +2195,22 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
if (!res.is_valid()) {
continue;
}
+ Ref<Script> drop_script = ResourceLoader::load(files[i]);
+ if (drop_script.is_valid() && drop_script->is_tool() && drop_script->get_instance_base_type() == "VisualScriptCustomNode" && !use_preload) {
+ Ref<VisualScriptCustomNode> vscn;
+ vscn.instantiate();
+ vscn->set_script(drop_script);
+
+ undo_redo->add_do_method(script.ptr(), "add_node", new_id, vscn, pos);
+ undo_redo->add_undo_method(script.ptr(), "remove_node", new_id);
+ } else {
+ Ref<VisualScriptPreload> prnode;
+ prnode.instantiate();
+ prnode->set_preload(res);
- Ref<VisualScriptPreload> prnode;
- prnode.instantiate();
- prnode->set_preload(res);
-
- undo_redo->add_do_method(script.ptr(), "add_node", new_id, prnode, pos);
- undo_redo->add_undo_method(script.ptr(), "remove_node", new_id);
+ undo_redo->add_do_method(script.ptr(), "add_node", new_id, prnode, pos);
+ undo_redo->add_undo_method(script.ptr(), "remove_node", new_id);
+ }
new_ids.push_back(new_id);
new_id++;
pos += Vector2(20, 20);
@@ -2387,7 +2404,7 @@ void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) {
return;
}
- Ref<StyleBox> normal = get_theme_stylebox("normal", "Button");
+ Ref<StyleBox> normal = get_theme_stylebox(SNAME("normal"), SNAME("Button"));
button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color);
}
@@ -2433,7 +2450,7 @@ void VisualScriptEditor::set_edited_resource(const RES &p_res) {
script->connect("node_ports_changed", callable_mp(this, &VisualScriptEditor::_node_ports_changed));
_update_graph();
- call_deferred("_update_members");
+ call_deferred(SNAME("_update_members"));
}
void VisualScriptEditor::enable_editor() {
@@ -2467,7 +2484,7 @@ String VisualScriptEditor::get_name() {
}
Ref<Texture2D> VisualScriptEditor::get_theme_icon() {
- return Control::get_theme_icon("VisualScript", "EditorIcons");
+ return Control::get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons"));
}
bool VisualScriptEditor::is_unsaved() {
@@ -2542,7 +2559,7 @@ void VisualScriptEditor::goto_line(int p_line, bool p_with_error) {
_update_graph();
_update_members();
- call_deferred("call_deferred", "_center_on_node", E->get(), p_line); //editor might be just created and size might not exist yet
+ call_deferred(SNAME("call_deferred"), "_center_on_node", E->get(), p_line); //editor might be just created and size might not exist yet
return;
}
}
@@ -2822,6 +2839,20 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot,
ERR_FAIL_COND(from_seq != to_seq);
+ // Checking to prevent warnings.
+ if (from_seq) {
+ if (script->has_sequence_connection(p_from.to_int(), from_port, p_to.to_int())) {
+ return;
+ }
+ } else if (script->has_data_connection(p_from.to_int(), from_port, p_to.to_int(), to_port)) {
+ return;
+ }
+
+ // Preventing connection to itself.
+ if (p_from.to_int() == p_to.to_int()) {
+ return;
+ }
+
// Do all the checks here.
StringName func; // This the func where we store the one the nodes at the end of the resolution on having multiple nodes.
@@ -2975,7 +3006,7 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac
Ref<VisualScriptNode> node = script->get_node(p_port_action_node);
- if (!node.is_valid()) {
+ if (!node.is_valid() || node->get_output_value_port_count() <= p_port_action_output) {
return tg;
}
@@ -3582,9 +3613,9 @@ void VisualScriptEditor::_notification(int p_what) {
return;
}
- edit_variable_edit->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
- edit_signal_edit->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
- func_input_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ edit_variable_edit->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ edit_signal_edit->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ func_input_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme();
@@ -3607,7 +3638,7 @@ void VisualScriptEditor::_notification(int p_what) {
}
for (Map<StringName, Color>::Element *E = node_colors.front(); E; E = E->next()) {
- const Ref<StyleBoxFlat> sb = tm->get_stylebox("frame", "GraphNode");
+ const Ref<StyleBoxFlat> sb = tm->get_stylebox(SNAME("frame"), SNAME("GraphNode"));
if (!sb.is_null()) {
Ref<StyleBoxFlat> frame_style = sb->duplicate();
@@ -4087,9 +4118,9 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) {
TreeItem *root = members->get_root();
- Ref<Texture2D> del_icon = Control::get_theme_icon("Remove", "EditorIcons");
+ Ref<Texture2D> del_icon = Control::get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
- Ref<Texture2D> edit_icon = Control::get_theme_icon("Edit", "EditorIcons");
+ Ref<Texture2D> edit_icon = Control::get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"));
if (ti->get_parent() == root->get_first_child()) {
member_type = MEMBER_FUNCTION;
@@ -4258,7 +4289,7 @@ VisualScriptEditor::VisualScriptEditor() {
members_section = memnew(VBoxContainer);
// Add but wait until done setting up this.
- ScriptEditor::get_singleton()->get_left_list_split()->call_deferred("add_child", members_section);
+ ScriptEditor::get_singleton()->get_left_list_split()->call_deferred(SNAME("add_child"), members_section);
members_section->set_v_size_flags(SIZE_EXPAND_FILL);
CheckButton *tool_script_check = memnew(CheckButton);
@@ -4519,14 +4550,14 @@ void _VisualScriptEditor::add_custom_node(const String &p_name, const String &p_
String node_name = "custom/" + p_category + "/" + p_name;
custom_nodes.insert(node_name, p_script);
VisualScriptLanguage::singleton->add_register_func(node_name, &_VisualScriptEditor::create_node_custom);
- emit_signal("custom_nodes_updated");
+ emit_signal(SNAME("custom_nodes_updated"));
}
void _VisualScriptEditor::remove_custom_node(const String &p_name, const String &p_category) {
String node_name = "custom/" + p_category + "/" + p_name;
custom_nodes.erase(node_name);
VisualScriptLanguage::singleton->remove_register_func(node_name);
- emit_signal("custom_nodes_updated");
+ emit_signal(SNAME("custom_nodes_updated"));
}
void _VisualScriptEditor::_bind_methods() {
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 98383800ba..7b5ca56dcc 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -520,19 +520,19 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
if (property.name == "base_script") {
if (call_mode != CALL_MODE_INSTANCE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
if (property.name == "basic_type") {
if (call_mode != CALL_MODE_BASIC_TYPE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
if (property.name == "singleton") {
if (call_mode != CALL_MODE_SINGLETON) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
} else {
List<Engine::Singleton> names;
Engine::get_singleton()->get_singletons(&names);
@@ -550,7 +550,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
if (property.name == "node_path") {
if (call_mode != CALL_MODE_NODE_PATH) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
} else {
Node *bnode = _get_base_node();
if (bnode) {
@@ -621,7 +621,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
}
if (mc == 0) {
- property.usage = 0; //do not show
+ property.usage = PROPERTY_USAGE_NONE; //do not show
} else {
property.hint_string = "0," + itos(mc) + ",1";
}
@@ -629,7 +629,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
if (property.name == "rpc_call_mode") {
if (call_mode == CALL_MODE_BASIC_TYPE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
}
@@ -1288,19 +1288,19 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const {
if (property.name == "base_script") {
if (call_mode != CALL_MODE_INSTANCE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
if (property.name == "basic_type") {
if (call_mode != CALL_MODE_BASIC_TYPE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
if (property.name == "node_path") {
if (call_mode != CALL_MODE_NODE_PATH) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
} else {
Node *bnode = _get_base_node();
if (bnode) {
@@ -1362,7 +1362,7 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const {
property.hint_string = options;
property.type = Variant::STRING;
if (options == "") {
- property.usage = 0; //hide if type has no usable index
+ property.usage = PROPERTY_USAGE_NONE; //hide if type has no usable index
}
}
}
@@ -1994,19 +1994,19 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const {
if (property.name == "base_script") {
if (call_mode != CALL_MODE_INSTANCE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
if (property.name == "basic_type") {
if (call_mode != CALL_MODE_BASIC_TYPE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
if (property.name == "node_path") {
if (call_mode != CALL_MODE_NODE_PATH) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
} else {
Node *bnode = _get_base_node();
if (bnode) {
@@ -2067,7 +2067,7 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const {
property.hint_string = options;
property.type = Variant::STRING;
if (options == "") {
- property.usage = 0; //hide if type has no usable index
+ property.usage = PROPERTY_USAGE_NONE; //hide if type has no usable index
}
}
}
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 60392d8f42..2a46051ccf 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -191,7 +191,10 @@ PropertyInfo VisualScriptFunction::get_input_value_port_info(int p_idx) const {
}
PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, arguments.size(), PropertyInfo());
+ // Need to check it without ERR_FAIL_COND, to prevent warnings from appearing on node creation via dragging.
+ if (p_idx < 0 || p_idx >= arguments.size()) {
+ return PropertyInfo();
+ }
PropertyInfo out;
out.type = arguments[p_idx].type;
out.name = arguments[p_idx].name;
@@ -912,39 +915,6 @@ PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const {
return pinfo;
}
-static const char *op_names[] = {
- //comparison
- "Are Equal", //OP_EQUAL,
- "Are Not Equal", //OP_NOT_EQUAL,
- "Less Than", //OP_LESS,
- "Less Than or Equal", //OP_LESS_EQUAL,
- "Greater Than", //OP_GREATER,
- "Greater Than or Equal", //OP_GREATER_EQUAL,
- //mathematic
- "Add", //OP_ADD,
- "Subtract", //OP_SUBTRACT,
- "Multiply", //OP_MULTIPLY,
- "Divide", //OP_DIVIDE,
- "Negate", //OP_NEGATE,
- "Positive", //OP_POSITIVE,
- "Remainder", //OP_MODULE,
- "Concatenate", //OP_STRING_CONCAT,
- //bitwise
- "Bit Shift Left", //OP_SHIFT_LEFT,
- "Bit Shift Right", //OP_SHIFT_RIGHT,
- "Bit And", //OP_BIT_AND,
- "Bit Or", //OP_BIT_OR,
- "Bit Xor", //OP_BIT_XOR,
- "Bit Negate", //OP_BIT_NEGATE,
- //logic
- "And", //OP_AND,
- "Or", //OP_OR,
- "Xor", //OP_XOR,
- "Not", //OP_NOT,
- //containment
- "In", //OP_IN,
-};
-
String VisualScriptOperator::get_caption() const {
switch (op) {
// comparison
@@ -1011,6 +981,71 @@ String VisualScriptOperator::get_caption() const {
}
}
+String VisualScriptOperator::get_operator_name(Variant::Operator p_op) {
+ switch (p_op) {
+ // comparison
+ case Variant::OP_EQUAL:
+ return "Are Equal";
+ case Variant::OP_NOT_EQUAL:
+ return "Are Not Equal";
+ case Variant::OP_LESS:
+ return "Less Than";
+ case Variant::OP_LESS_EQUAL:
+ return "Less Than or Equal";
+ case Variant::OP_GREATER:
+ return "Greater Than";
+ case Variant::OP_GREATER_EQUAL:
+ return "Greater Than or Equal";
+
+ // mathematic
+ case Variant::OP_ADD:
+ return "Add";
+ case Variant::OP_SUBTRACT:
+ return "Subtract";
+ case Variant::OP_MULTIPLY:
+ return "Multiply";
+ case Variant::OP_DIVIDE:
+ return "Divide";
+ case Variant::OP_NEGATE:
+ return "Negate";
+ case Variant::OP_POSITIVE:
+ return "Positive";
+ case Variant::OP_MODULE:
+ return "Remainder";
+
+ // bitwise
+ case Variant::OP_SHIFT_LEFT:
+ return "Bit Shift Left";
+ case Variant::OP_SHIFT_RIGHT:
+ return "Bit Shift Right";
+ case Variant::OP_BIT_AND:
+ return "Bit And";
+ case Variant::OP_BIT_OR:
+ return "Bit Or";
+ case Variant::OP_BIT_XOR:
+ return "Bit Xor";
+ case Variant::OP_BIT_NEGATE:
+ return "Bit Negate";
+
+ // logic
+ case Variant::OP_AND:
+ return "And";
+ case Variant::OP_OR:
+ return "Or";
+ case Variant::OP_XOR:
+ return "Xor";
+ case Variant::OP_NOT:
+ return "Not";
+ case Variant::OP_IN:
+ return "In";
+
+ default: {
+ ERR_FAIL_INDEX_V(p_op, Variant::OP_MAX, "");
+ return "Unknown Operator";
+ }
+ }
+}
+
void VisualScriptOperator::set_operator(Variant::Operator p_op) {
if (op == p_op) {
return;
@@ -1048,7 +1083,7 @@ void VisualScriptOperator::_bind_methods() {
if (i > 0) {
types += ",";
}
- types += op_names[i];
+ types += get_operator_name(static_cast<Variant::Operator>(i));
}
String argt = "Any";
@@ -1081,9 +1116,9 @@ public:
r_error_str = *p_outputs[0];
} else {
if (unary) {
- r_error_str = String(op_names[op]) + RTR(": Invalid argument of type: ") + Variant::get_type_name(p_inputs[0]->get_type());
+ r_error_str = String(Variant::get_operator_name(op)) + RTR(": Invalid argument of type: ") + Variant::get_type_name(p_inputs[0]->get_type());
} else {
- r_error_str = String(op_names[op]) + RTR(": Invalid arguments: ") + "A: " + Variant::get_type_name(p_inputs[0]->get_type()) + " B: " + Variant::get_type_name(p_inputs[1]->get_type());
+ r_error_str = String(Variant::get_operator_name(op)) + RTR(": Invalid arguments: ") + "A: " + Variant::get_type_name(p_inputs[0]->get_type()) + " B: " + Variant::get_type_name(p_inputs[1]->get_type());
}
}
}
@@ -1502,7 +1537,7 @@ void VisualScriptConstant::_validate_property(PropertyInfo &property) const {
if (property.name == "value") {
property.type = type;
if (type == Variant::NIL) {
- property.usage = 0; //do not save if nil
+ property.usage = PROPERTY_USAGE_NONE; //do not save if nil
}
}
}
@@ -2092,7 +2127,7 @@ void VisualScriptBasicTypeConstant::_validate_property(PropertyInfo &property) c
Variant::get_constants_for_type(type, &constants);
if (constants.size() == 0) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
return;
}
property.hint_string = "";
@@ -2955,7 +2990,7 @@ VisualScriptNodeInstance *VisualScriptCustomNode::instantiate(VisualScriptInstan
}
void VisualScriptCustomNode::_script_changed() {
- call_deferred("ports_changed_notify");
+ call_deferred(SNAME("ports_changed_notify"));
}
void VisualScriptCustomNode::_bind_methods() {
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index 551832b002..b599b92b3a 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -227,6 +227,8 @@ public:
void set_typed(Variant::Type p_op);
Variant::Type get_typed() const;
+ static String get_operator_name(Variant::Operator p_op);
+
virtual VisualScriptNodeInstance *instantiate(VisualScriptInstance *p_instance) override;
VisualScriptOperator();
diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp
index 79addc5828..ccb2e2df75 100644
--- a/modules/visual_script/visual_script_property_selector.cpp
+++ b/modules/visual_script/visual_script_property_selector.cpp
@@ -98,35 +98,41 @@ void VisualScriptPropertySelector::_update_search() {
List<PropertyInfo> props;
TreeItem *category = nullptr;
Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = {
- vbc->get_theme_icon("Variant", "EditorIcons"),
- vbc->get_theme_icon("bool", "EditorIcons"),
- vbc->get_theme_icon("int", "EditorIcons"),
- vbc->get_theme_icon("float", "EditorIcons"),
- vbc->get_theme_icon("String", "EditorIcons"),
- vbc->get_theme_icon("Vector2", "EditorIcons"),
- vbc->get_theme_icon("Rect2", "EditorIcons"),
- vbc->get_theme_icon("Vector3", "EditorIcons"),
- vbc->get_theme_icon("Transform2D", "EditorIcons"),
- vbc->get_theme_icon("Plane", "EditorIcons"),
- vbc->get_theme_icon("Quaternion", "EditorIcons"),
- vbc->get_theme_icon("AABB", "EditorIcons"),
- vbc->get_theme_icon("Basis", "EditorIcons"),
- vbc->get_theme_icon("Transform3D", "EditorIcons"),
- vbc->get_theme_icon("Color", "EditorIcons"),
- vbc->get_theme_icon("Path", "EditorIcons"),
- vbc->get_theme_icon("RID", "EditorIcons"),
- vbc->get_theme_icon("Object", "EditorIcons"),
- vbc->get_theme_icon("Dictionary", "EditorIcons"),
- vbc->get_theme_icon("Array", "EditorIcons"),
- vbc->get_theme_icon("PackedByteArray", "EditorIcons"),
- vbc->get_theme_icon("PackedInt32Array", "EditorIcons"),
- vbc->get_theme_icon("PackedFloat32Array", "EditorIcons"),
- vbc->get_theme_icon("PackedInt64Array", "EditorIcons"),
- vbc->get_theme_icon("PackedFloat64Array", "EditorIcons"),
- vbc->get_theme_icon("PackedStringArray", "EditorIcons"),
- vbc->get_theme_icon("PackedVector2Array", "EditorIcons"),
- vbc->get_theme_icon("PackedVector3Array", "EditorIcons"),
- vbc->get_theme_icon("PackedColorArray", "EditorIcons")
+ vbc->get_theme_icon(SNAME("Variant"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("int"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("String"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Vector2i"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Rect2"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Rect2i"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Vector3i"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Transform2D"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Plane"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Quaternion"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("AABB"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Basis"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("StringName"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("NodePath"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("RID"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("MiniObject"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Callable"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Signal"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Dictionary"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("Array"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedByteArray"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedInt32Array"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedInt64Array"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedFloat32Array"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedFloat64Array"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedStringArray"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedVector2Array"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedVector3Array"), SNAME("EditorIcons")),
+ vbc->get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons"))
};
{
String b = String(E->get());
@@ -253,7 +259,7 @@ void VisualScriptPropertySelector::_update_search() {
TreeItem *item = search_options->create_item(category ? category : root);
item->set_text(0, desc);
- item->set_icon(0, vbc->get_theme_icon("MemberMethod", "EditorIcons"));
+ item->set_icon(0, vbc->get_theme_icon(SNAME("MemberMethod"), SNAME("EditorIcons")));
item->set_metadata(0, name);
item->set_selectable(0, true);
@@ -317,7 +323,7 @@ void VisualScriptPropertySelector::create_visualscript_item(const String &name,
if (search_input == String() || text.findn(search_input) != -1) {
TreeItem *item = search_options->create_item(root);
item->set_text(0, text);
- item->set_icon(0, vbc->get_theme_icon("VisualScript", "EditorIcons"));
+ item->set_icon(0, vbc->get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons")));
item->set_metadata(0, name);
item->set_metadata(1, "action");
item->set_selectable(0, true);
@@ -401,7 +407,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
}
item->set_text(0, type_name + String("").join(desc));
- item->set_icon(0, vbc->get_theme_icon("VisualScript", "EditorIcons"));
+ item->set_icon(0, vbc->get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons")));
item->set_selectable(0, true);
item->set_metadata(0, E->get());
item->set_selectable(0, true);
@@ -417,7 +423,7 @@ void VisualScriptPropertySelector::_confirmed() {
if (!ti) {
return;
}
- emit_signal("selected", ti->get_metadata(0), ti->get_metadata(1), ti->get_metadata(2));
+ emit_signal(SNAME("selected"), ti->get_metadata(0), ti->get_metadata(1), ti->get_metadata(2));
set_visible(false);
}
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index 2e1b0a3e99..d8bc926a1d 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -174,7 +174,7 @@ float VisualScriptYield::get_wait_time() {
void VisualScriptYield::_validate_property(PropertyInfo &property) const {
if (property.name == "wait_time") {
if (yield_mode != YIELD_WAIT) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
}
@@ -421,7 +421,7 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const {
if (property.name == "node_path") {
if (call_mode != CALL_MODE_NODE_PATH) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
} else {
Node *bnode = _get_base_node();
if (bnode) {
diff --git a/modules/webm/register_types.cpp b/modules/webm/register_types.cpp
index 9cfaba83c1..8f690a6892 100644
--- a/modules/webm/register_types.cpp
+++ b/modules/webm/register_types.cpp
@@ -38,7 +38,7 @@ void register_webm_types() {
resource_loader_webm.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_webm, true);
- ClassDB::register_class<VideoStreamWebm>();
+ GDREGISTER_CLASS(VideoStreamWebm);
}
void unregister_webm_types() {
diff --git a/modules/webrtc/config.py b/modules/webrtc/config.py
index 0a075ccef1..3281415f38 100644
--- a/modules/webrtc/config.py
+++ b/modules/webrtc/config.py
@@ -10,7 +10,7 @@ def get_doc_classes():
return [
"WebRTCPeerConnection",
"WebRTCDataChannel",
- "WebRTCMultiplayer",
+ "WebRTCMultiplayerPeer",
]
diff --git a/modules/webrtc/doc_classes/WebRTCDataChannel.xml b/modules/webrtc/doc_classes/WebRTCDataChannel.xml
index 5c90038b9a..3435dda982 100644
--- a/modules/webrtc/doc_classes/WebRTCDataChannel.xml
+++ b/modules/webrtc/doc_classes/WebRTCDataChannel.xml
@@ -14,6 +14,13 @@
Closes this data channel, notifying the other peer.
</description>
</method>
+ <method name="get_buffered_amount" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of bytes currently queued to be sent over this channel.
+ </description>
+ </method>
<method name="get_id" qualifiers="const">
<return type="int">
</return>
diff --git a/modules/webrtc/doc_classes/WebRTCMultiplayer.xml b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
index 5b9459bc27..26c5bfa6ce 100644
--- a/modules/webrtc/doc_classes/WebRTCMultiplayer.xml
+++ b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebRTCMultiplayer" inherits="NetworkedMultiplayerPeer" version="4.0">
+<class name="WebRTCMultiplayerPeer" inherits="MultiplayerPeer" version="4.0">
<brief_description>
A simple interface to create a peer-to-peer mesh network composed of [WebRTCPeerConnection] that is compatible with the [MultiplayerAPI].
</brief_description>
<description>
This class constructs a full mesh of [WebRTCPeerConnection] (one connection for each peer) that can be used as a [member MultiplayerAPI.network_peer].
You can add each [WebRTCPeerConnection] via [method add_peer] or remove them via [method remove_peer]. Peers must be added in [constant WebRTCPeerConnection.STATE_NEW] state to allow it to create the appropriate channels. This class will not create offers nor set descriptions, it will only poll them, and notify connections and disconnections.
- [signal NetworkedMultiplayerPeer.connection_succeeded] and [signal NetworkedMultiplayerPeer.server_disconnected] will not be emitted unless [code]server_compatibility[/code] is [code]true[/code] in [method initialize]. Beside that data transfer works like in a [NetworkedMultiplayerPeer].
+ [signal MultiplayerPeer.connection_succeeded] and [signal MultiplayerPeer.server_disconnected] will not be emitted unless [code]server_compatibility[/code] is [code]true[/code] in [method initialize]. Beside that data transfer works like in a [MultiplayerPeer].
</description>
<tutorials>
</tutorials>
@@ -66,8 +66,8 @@
</argument>
<description>
Initialize the multiplayer peer with the given [code]peer_id[/code] (must be between 1 and 2147483647).
- If [code]server_compatibilty[/code] is [code]false[/code] (default), the multiplayer peer will be immediately in state [constant NetworkedMultiplayerPeer.CONNECTION_CONNECTED] and [signal NetworkedMultiplayerPeer.connection_succeeded] will not be emitted.
- If [code]server_compatibilty[/code] is [code]true[/code] the peer will suppress all [signal NetworkedMultiplayerPeer.peer_connected] signals until a peer with id [constant NetworkedMultiplayerPeer.TARGET_PEER_SERVER] connects and then emit [signal NetworkedMultiplayerPeer.connection_succeeded]. After that the signal [signal NetworkedMultiplayerPeer.peer_connected] will be emitted for every already connected peer, and any new peer that might connect. If the server peer disconnects after that, signal [signal NetworkedMultiplayerPeer.server_disconnected] will be emitted and state will become [constant NetworkedMultiplayerPeer.CONNECTION_CONNECTED].
+ If [code]server_compatibilty[/code] is [code]false[/code] (default), the multiplayer peer will be immediately in state [constant MultiplayerPeer.CONNECTION_CONNECTED] and [signal MultiplayerPeer.connection_succeeded] will not be emitted.
+ If [code]server_compatibilty[/code] is [code]true[/code] the peer will suppress all [signal MultiplayerPeer.peer_connected] signals until a peer with id [constant MultiplayerPeer.TARGET_PEER_SERVER] connects and then emit [signal MultiplayerPeer.connection_succeeded]. After that the signal [signal MultiplayerPeer.peer_connected] will be emitted for every already connected peer, and any new peer that might connect. If the server peer disconnects after that, signal [signal MultiplayerPeer.server_disconnected] will be emitted and state will become [constant MultiplayerPeer.CONNECTION_CONNECTED].
</description>
</method>
<method name="remove_peer">
@@ -76,13 +76,13 @@
<argument index="0" name="peer_id" type="int">
</argument>
<description>
- Remove the peer with given [code]peer_id[/code] from the mesh. If the peer was connected, and [signal NetworkedMultiplayerPeer.peer_connected] was emitted for it, then [signal NetworkedMultiplayerPeer.peer_disconnected] will be emitted.
+ Remove the peer with given [code]peer_id[/code] from the mesh. If the peer was connected, and [signal MultiplayerPeer.peer_connected] was emitted for it, then [signal MultiplayerPeer.peer_disconnected] will be emitted.
</description>
</method>
</methods>
<members>
<member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" override="true" default="false" />
- <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="NetworkedMultiplayerPeer.TransferMode" default="2" />
+ <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="MultiplayerPeer.TransferMode" default="2" />
</members>
<constants>
</constants>
diff --git a/modules/webrtc/library_godot_webrtc.js b/modules/webrtc/library_godot_webrtc.js
index 404a116716..a0a6c21be3 100644
--- a/modules/webrtc/library_godot_webrtc.js
+++ b/modules/webrtc/library_godot_webrtc.js
@@ -133,12 +133,12 @@ const GodotRTCDataChannel = {
godot_js_rtc_datachannel_is_ordered__sig: 'ii',
godot_js_rtc_datachannel_is_ordered: function (p_id) {
- return IDHandler.get_prop(p_id, 'ordered', true);
+ return GodotRTCDataChannel.get_prop(p_id, 'ordered', true);
},
godot_js_rtc_datachannel_id_get__sig: 'ii',
godot_js_rtc_datachannel_id_get: function (p_id) {
- return IDHandler.get_prop(p_id, 'id', 65535);
+ return GodotRTCDataChannel.get_prop(p_id, 'id', 65535);
},
godot_js_rtc_datachannel_max_packet_lifetime_get__sig: 'ii',
@@ -158,12 +158,17 @@ const GodotRTCDataChannel = {
godot_js_rtc_datachannel_max_retransmits_get__sig: 'ii',
godot_js_rtc_datachannel_max_retransmits_get: function (p_id) {
- return IDHandler.get_prop(p_id, 'maxRetransmits', 65535);
+ return GodotRTCDataChannel.get_prop(p_id, 'maxRetransmits', 65535);
},
godot_js_rtc_datachannel_is_negotiated__sig: 'ii',
godot_js_rtc_datachannel_is_negotiated: function (p_id) {
- return IDHandler.get_prop(p_id, 'negotiated', 65535);
+ return GodotRTCDataChannel.get_prop(p_id, 'negotiated', 65535);
+ },
+
+ godot_js_rtc_datachannel_get_buffered_amount__sig: 'ii',
+ godot_js_rtc_datachannel_get_buffered_amount: function (p_id) {
+ return GodotRTCDataChannel.get_prop(p_id, 'bufferedAmount', 0);
},
godot_js_rtc_datachannel_label_get__sig: 'ii',
diff --git a/modules/webrtc/register_types.cpp b/modules/webrtc/register_types.cpp
index ecfaed9089..63ecc03a4c 100644
--- a/modules/webrtc/register_types.cpp
+++ b/modules/webrtc/register_types.cpp
@@ -41,7 +41,7 @@
#include "webrtc_data_channel_gdnative.h"
#include "webrtc_peer_connection_gdnative.h"
#endif
-#include "webrtc_multiplayer.h"
+#include "webrtc_multiplayer_peer.h"
void register_webrtc_types() {
#define _SET_HINT(NAME, _VAL_, _MAX_) \
@@ -58,11 +58,11 @@ void register_webrtc_types() {
ClassDB::register_custom_instance_class<WebRTCPeerConnection>();
#ifdef WEBRTC_GDNATIVE_ENABLED
- ClassDB::register_class<WebRTCPeerConnectionGDNative>();
- ClassDB::register_class<WebRTCDataChannelGDNative>();
+ GDREGISTER_CLASS(WebRTCPeerConnectionGDNative);
+ GDREGISTER_CLASS(WebRTCDataChannelGDNative);
#endif
- ClassDB::register_virtual_class<WebRTCDataChannel>();
- ClassDB::register_class<WebRTCMultiplayer>();
+ GDREGISTER_VIRTUAL_CLASS(WebRTCDataChannel);
+ GDREGISTER_CLASS(WebRTCMultiplayerPeer);
}
void unregister_webrtc_types() {}
diff --git a/modules/webrtc/webrtc_data_channel.cpp b/modules/webrtc/webrtc_data_channel.cpp
index 004112f992..ca520a733d 100644
--- a/modules/webrtc/webrtc_data_channel.cpp
+++ b/modules/webrtc/webrtc_data_channel.cpp
@@ -46,6 +46,7 @@ void WebRTCDataChannel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_max_retransmits"), &WebRTCDataChannel::get_max_retransmits);
ClassDB::bind_method(D_METHOD("get_protocol"), &WebRTCDataChannel::get_protocol);
ClassDB::bind_method(D_METHOD("is_negotiated"), &WebRTCDataChannel::is_negotiated);
+ ClassDB::bind_method(D_METHOD("get_buffered_amount"), &WebRTCDataChannel::get_buffered_amount);
ADD_PROPERTY(PropertyInfo(Variant::INT, "write_mode", PROPERTY_HINT_ENUM), "set_write_mode", "get_write_mode");
diff --git a/modules/webrtc/webrtc_data_channel.h b/modules/webrtc/webrtc_data_channel.h
index 20affc513f..809d35c6e3 100644
--- a/modules/webrtc/webrtc_data_channel.h
+++ b/modules/webrtc/webrtc_data_channel.h
@@ -70,6 +70,8 @@ public:
virtual String get_protocol() const = 0;
virtual bool is_negotiated() const = 0;
+ virtual int get_buffered_amount() const = 0;
+
virtual Error poll() = 0;
virtual void close() = 0;
diff --git a/modules/webrtc/webrtc_data_channel_gdnative.cpp b/modules/webrtc/webrtc_data_channel_gdnative.cpp
index d4cf464c7c..10a3367557 100644
--- a/modules/webrtc/webrtc_data_channel_gdnative.cpp
+++ b/modules/webrtc/webrtc_data_channel_gdnative.cpp
@@ -31,6 +31,7 @@
#ifdef WEBRTC_GDNATIVE_ENABLED
#include "webrtc_data_channel_gdnative.h"
+
#include "core/io/resource_loader.h"
#include "modules/gdnative/nativescript/nativescript.h"
@@ -110,6 +111,11 @@ bool WebRTCDataChannelGDNative::is_negotiated() const {
return interface->is_negotiated(interface->data);
}
+int WebRTCDataChannelGDNative::get_buffered_amount() const {
+ ERR_FAIL_COND_V(interface == NULL, 0);
+ return interface->get_buffered_amount(interface->data);
+}
+
Error WebRTCDataChannelGDNative::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED);
return (Error)interface->get_packet(interface->data, r_buffer, &r_buffer_size);
diff --git a/modules/webrtc/webrtc_data_channel_gdnative.h b/modules/webrtc/webrtc_data_channel_gdnative.h
index 7e02a32046..5c80edd48c 100644
--- a/modules/webrtc/webrtc_data_channel_gdnative.h
+++ b/modules/webrtc/webrtc_data_channel_gdnative.h
@@ -60,6 +60,7 @@ public:
virtual int get_max_retransmits() const override;
virtual String get_protocol() const override;
virtual bool is_negotiated() const override;
+ virtual int get_buffered_amount() const override;
virtual Error poll() override;
virtual void close() override;
diff --git a/modules/webrtc/webrtc_data_channel_js.cpp b/modules/webrtc/webrtc_data_channel_js.cpp
index dfbec80c86..31d6a0568c 100644
--- a/modules/webrtc/webrtc_data_channel_js.cpp
+++ b/modules/webrtc/webrtc_data_channel_js.cpp
@@ -46,6 +46,7 @@ extern int godot_js_rtc_datachannel_id_get(int p_id);
extern int godot_js_rtc_datachannel_max_packet_lifetime_get(int p_id);
extern int godot_js_rtc_datachannel_max_retransmits_get(int p_id);
extern int godot_js_rtc_datachannel_is_negotiated(int p_id);
+extern int godot_js_rtc_datachannel_get_buffered_amount(int p_id);
extern char *godot_js_rtc_datachannel_label_get(int p_id); // Must free the returned string.
extern char *godot_js_rtc_datachannel_protocol_get(int p_id); // Must free the returned string.
extern void godot_js_rtc_datachannel_destroy(int p_id);
@@ -181,6 +182,10 @@ bool WebRTCDataChannelJS::is_negotiated() const {
return godot_js_rtc_datachannel_is_negotiated(_js_id);
}
+int WebRTCDataChannelJS::get_buffered_amount() const {
+ return godot_js_rtc_datachannel_get_buffered_amount(_js_id);
+}
+
WebRTCDataChannelJS::WebRTCDataChannelJS() {
}
diff --git a/modules/webrtc/webrtc_data_channel_js.h b/modules/webrtc/webrtc_data_channel_js.h
index db58ebccff..5cd6a32ed9 100644
--- a/modules/webrtc/webrtc_data_channel_js.h
+++ b/modules/webrtc/webrtc_data_channel_js.h
@@ -72,6 +72,7 @@ public:
virtual int get_max_retransmits() const override;
virtual String get_protocol() const override;
virtual bool is_negotiated() const override;
+ virtual int get_buffered_amount() const override;
virtual Error poll() override;
virtual void close() override;
diff --git a/modules/webrtc/webrtc_multiplayer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index 741cad5640..51101e3124 100644
--- a/modules/webrtc/webrtc_multiplayer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* webrtc_multiplayer.cpp */
+/* webrtc_multiplayer_peer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,43 +28,43 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "webrtc_multiplayer.h"
+#include "webrtc_multiplayer_peer.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
-void WebRTCMultiplayer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("initialize", "peer_id", "server_compatibility"), &WebRTCMultiplayer::initialize, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("add_peer", "peer", "peer_id", "unreliable_lifetime"), &WebRTCMultiplayer::add_peer, DEFVAL(1));
- ClassDB::bind_method(D_METHOD("remove_peer", "peer_id"), &WebRTCMultiplayer::remove_peer);
- ClassDB::bind_method(D_METHOD("has_peer", "peer_id"), &WebRTCMultiplayer::has_peer);
- ClassDB::bind_method(D_METHOD("get_peer", "peer_id"), &WebRTCMultiplayer::get_peer);
- ClassDB::bind_method(D_METHOD("get_peers"), &WebRTCMultiplayer::get_peers);
- ClassDB::bind_method(D_METHOD("close"), &WebRTCMultiplayer::close);
+void WebRTCMultiplayerPeer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("initialize", "peer_id", "server_compatibility"), &WebRTCMultiplayerPeer::initialize, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_peer", "peer", "peer_id", "unreliable_lifetime"), &WebRTCMultiplayerPeer::add_peer, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("remove_peer", "peer_id"), &WebRTCMultiplayerPeer::remove_peer);
+ ClassDB::bind_method(D_METHOD("has_peer", "peer_id"), &WebRTCMultiplayerPeer::has_peer);
+ ClassDB::bind_method(D_METHOD("get_peer", "peer_id"), &WebRTCMultiplayerPeer::get_peer);
+ ClassDB::bind_method(D_METHOD("get_peers"), &WebRTCMultiplayerPeer::get_peers);
+ ClassDB::bind_method(D_METHOD("close"), &WebRTCMultiplayerPeer::close);
}
-void WebRTCMultiplayer::set_transfer_mode(TransferMode p_mode) {
+void WebRTCMultiplayerPeer::set_transfer_mode(TransferMode p_mode) {
transfer_mode = p_mode;
}
-NetworkedMultiplayerPeer::TransferMode WebRTCMultiplayer::get_transfer_mode() const {
+MultiplayerPeer::TransferMode WebRTCMultiplayerPeer::get_transfer_mode() const {
return transfer_mode;
}
-void WebRTCMultiplayer::set_target_peer(int p_peer_id) {
+void WebRTCMultiplayerPeer::set_target_peer(int p_peer_id) {
target_peer = p_peer_id;
}
-/* Returns the ID of the NetworkedMultiplayerPeer who sent the most recent packet: */
-int WebRTCMultiplayer::get_packet_peer() const {
+/* Returns the ID of the MultiplayerPeer who sent the most recent packet: */
+int WebRTCMultiplayerPeer::get_packet_peer() const {
return next_packet_peer;
}
-bool WebRTCMultiplayer::is_server() const {
+bool WebRTCMultiplayerPeer::is_server() const {
return unique_id == TARGET_PEER_SERVER;
}
-void WebRTCMultiplayer::poll() {
+void WebRTCMultiplayerPeer::poll() {
if (peer_map.size() == 0) {
return;
}
@@ -123,19 +123,19 @@ void WebRTCMultiplayer::poll() {
// Already connected to server: simply notify new peer.
// NOTE: Mesh is always connected.
if (connection_status == CONNECTION_CONNECTED) {
- emit_signal("peer_connected", E->get());
+ emit_signal(SNAME("peer_connected"), E->get());
}
// Server emulation mode suppresses peer_conencted until server connects.
if (server_compat && E->get() == TARGET_PEER_SERVER) {
// Server connected.
connection_status = CONNECTION_CONNECTED;
- emit_signal("peer_connected", TARGET_PEER_SERVER);
- emit_signal("connection_succeeded");
+ emit_signal(SNAME("peer_connected"), TARGET_PEER_SERVER);
+ emit_signal(SNAME("connection_succeeded"));
// Notify of all previously connected peers
for (Map<int, Ref<ConnectedPeer>>::Element *F = peer_map.front(); F; F = F->next()) {
if (F->key() != 1 && F->get()->connected) {
- emit_signal("peer_connected", F->key());
+ emit_signal(SNAME("peer_connected"), F->key());
}
}
break; // Because we already notified of all newly added peers.
@@ -147,7 +147,7 @@ void WebRTCMultiplayer::poll() {
}
}
-void WebRTCMultiplayer::_find_next_peer() {
+void WebRTCMultiplayerPeer::_find_next_peer() {
Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.find(next_packet_peer);
if (E) {
E = E->next();
@@ -180,19 +180,19 @@ void WebRTCMultiplayer::_find_next_peer() {
next_packet_peer = 0;
}
-void WebRTCMultiplayer::set_refuse_new_connections(bool p_enable) {
+void WebRTCMultiplayerPeer::set_refuse_new_connections(bool p_enable) {
refuse_connections = p_enable;
}
-bool WebRTCMultiplayer::is_refusing_new_connections() const {
+bool WebRTCMultiplayerPeer::is_refusing_new_connections() const {
return refuse_connections;
}
-NetworkedMultiplayerPeer::ConnectionStatus WebRTCMultiplayer::get_connection_status() const {
+MultiplayerPeer::ConnectionStatus WebRTCMultiplayerPeer::get_connection_status() const {
return connection_status;
}
-Error WebRTCMultiplayer::initialize(int p_self_id, bool p_server_compat) {
+Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat) {
ERR_FAIL_COND_V(p_self_id < 0 || p_self_id > ~(1 << 31), ERR_INVALID_PARAMETER);
unique_id = p_self_id;
server_compat = p_server_compat;
@@ -206,12 +206,12 @@ Error WebRTCMultiplayer::initialize(int p_self_id, bool p_server_compat) {
return OK;
}
-int WebRTCMultiplayer::get_unique_id() const {
+int WebRTCMultiplayerPeer::get_unique_id() const {
ERR_FAIL_COND_V(connection_status == CONNECTION_DISCONNECTED, 1);
return unique_id;
}
-void WebRTCMultiplayer::_peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dictionary &r_dict) {
+void WebRTCMultiplayerPeer::_peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dictionary &r_dict) {
Array channels;
for (List<Ref<WebRTCDataChannel>>::Element *F = p_connected_peer->channels.front(); F; F = F->next()) {
channels.push_back(F->get());
@@ -221,18 +221,18 @@ void WebRTCMultiplayer::_peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dicti
r_dict["channels"] = channels;
}
-bool WebRTCMultiplayer::has_peer(int p_peer_id) {
+bool WebRTCMultiplayerPeer::has_peer(int p_peer_id) {
return peer_map.has(p_peer_id);
}
-Dictionary WebRTCMultiplayer::get_peer(int p_peer_id) {
+Dictionary WebRTCMultiplayerPeer::get_peer(int p_peer_id) {
ERR_FAIL_COND_V(!peer_map.has(p_peer_id), Dictionary());
Dictionary out;
_peer_to_dict(peer_map[p_peer_id], out);
return out;
}
-Dictionary WebRTCMultiplayer::get_peers() {
+Dictionary WebRTCMultiplayerPeer::get_peers() {
Dictionary out;
for (Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.front(); E; E = E->next()) {
Dictionary d;
@@ -242,7 +242,7 @@ Dictionary WebRTCMultiplayer::get_peers() {
return out;
}
-Error WebRTCMultiplayer::add_peer(Ref<WebRTCPeerConnection> p_peer, int p_peer_id, int p_unreliable_lifetime) {
+Error WebRTCMultiplayerPeer::add_peer(Ref<WebRTCPeerConnection> p_peer, int p_peer_id, int p_unreliable_lifetime) {
ERR_FAIL_COND_V(p_peer_id < 0 || p_peer_id > ~(1 << 31), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_unreliable_lifetime < 0, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(refuse_connections, ERR_UNAUTHORIZED);
@@ -277,21 +277,21 @@ Error WebRTCMultiplayer::add_peer(Ref<WebRTCPeerConnection> p_peer, int p_peer_i
return OK;
}
-void WebRTCMultiplayer::remove_peer(int p_peer_id) {
+void WebRTCMultiplayerPeer::remove_peer(int p_peer_id) {
ERR_FAIL_COND(!peer_map.has(p_peer_id));
Ref<ConnectedPeer> peer = peer_map[p_peer_id];
peer_map.erase(p_peer_id);
if (peer->connected) {
peer->connected = false;
- emit_signal("peer_disconnected", p_peer_id);
+ emit_signal(SNAME("peer_disconnected"), p_peer_id);
if (server_compat && p_peer_id == TARGET_PEER_SERVER) {
- emit_signal("server_disconnected");
+ emit_signal(SNAME("server_disconnected"));
connection_status = CONNECTION_DISCONNECTED;
}
}
}
-Error WebRTCMultiplayer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+Error WebRTCMultiplayerPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
// Peer not available
if (next_packet_peer == 0 || !peer_map.has(next_packet_peer)) {
_find_next_peer();
@@ -309,7 +309,7 @@ Error WebRTCMultiplayer::get_packet(const uint8_t **r_buffer, int &r_buffer_size
ERR_FAIL_V(ERR_BUG);
}
-Error WebRTCMultiplayer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
ERR_FAIL_COND_V(connection_status == CONNECTION_DISCONNECTED, ERR_UNCONFIGURED);
int ch = CH_RELIABLE;
@@ -351,7 +351,7 @@ Error WebRTCMultiplayer::put_packet(const uint8_t *p_buffer, int p_buffer_size)
return OK;
}
-int WebRTCMultiplayer::get_available_packet_count() const {
+int WebRTCMultiplayerPeer::get_available_packet_count() const {
if (next_packet_peer == 0) {
return 0; // To be sure next call to get_packet works if size > 0 .
}
@@ -364,11 +364,11 @@ int WebRTCMultiplayer::get_available_packet_count() const {
return size;
}
-int WebRTCMultiplayer::get_max_packet_size() const {
+int WebRTCMultiplayerPeer::get_max_packet_size() const {
return 1200;
}
-void WebRTCMultiplayer::close() {
+void WebRTCMultiplayerPeer::close() {
peer_map.clear();
unique_id = 0;
next_packet_peer = 0;
@@ -376,7 +376,7 @@ void WebRTCMultiplayer::close() {
connection_status = CONNECTION_DISCONNECTED;
}
-WebRTCMultiplayer::WebRTCMultiplayer() {
+WebRTCMultiplayerPeer::WebRTCMultiplayerPeer() {
unique_id = 0;
next_packet_peer = 0;
target_peer = 0;
@@ -387,6 +387,6 @@ WebRTCMultiplayer::WebRTCMultiplayer() {
server_compat = false;
}
-WebRTCMultiplayer::~WebRTCMultiplayer() {
+WebRTCMultiplayerPeer::~WebRTCMultiplayerPeer() {
close();
}
diff --git a/modules/webrtc/webrtc_multiplayer.h b/modules/webrtc/webrtc_multiplayer_peer.h
index 2ddb98f656..1d9387b6dc 100644
--- a/modules/webrtc/webrtc_multiplayer.h
+++ b/modules/webrtc/webrtc_multiplayer_peer.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* webrtc_multiplayer.h */
+/* webrtc_multiplayer_peer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -31,11 +31,11 @@
#ifndef WEBRTC_MULTIPLAYER_H
#define WEBRTC_MULTIPLAYER_H
-#include "core/io/networked_multiplayer_peer.h"
+#include "core/io/multiplayer_peer.h"
#include "webrtc_peer_connection.h"
-class WebRTCMultiplayer : public NetworkedMultiplayerPeer {
- GDCLASS(WebRTCMultiplayer, NetworkedMultiplayerPeer);
+class WebRTCMultiplayerPeer : public MultiplayerPeer {
+ GDCLASS(WebRTCMultiplayerPeer, MultiplayerPeer);
protected:
static void _bind_methods();
@@ -77,8 +77,8 @@ private:
void _find_next_peer();
public:
- WebRTCMultiplayer();
- ~WebRTCMultiplayer();
+ WebRTCMultiplayerPeer();
+ ~WebRTCMultiplayerPeer();
Error initialize(int p_self_id, bool p_server_compat = false);
Error add_peer(Ref<WebRTCPeerConnection> p_peer, int p_peer_id, int p_unreliable_lifetime = 1);
@@ -94,7 +94,7 @@ public:
int get_available_packet_count() const override;
int get_max_packet_size() const override;
- // NetworkedMultiplayerPeer
+ // MultiplayerPeer
void set_transfer_mode(TransferMode p_mode) override;
TransferMode get_transfer_mode() const override;
void set_target_peer(int p_peer_id) override;
diff --git a/modules/webrtc/webrtc_peer_connection_js.cpp b/modules/webrtc/webrtc_peer_connection_js.cpp
index 8879f7d6ec..ed3459d5f8 100644
--- a/modules/webrtc/webrtc_peer_connection_js.cpp
+++ b/modules/webrtc/webrtc_peer_connection_js.cpp
@@ -34,17 +34,16 @@
#include "webrtc_data_channel_js.h"
-#include "core/io/json.h"
#include "emscripten.h"
void WebRTCPeerConnectionJS::_on_ice_candidate(void *p_obj, const char *p_mid_name, int p_mline_idx, const char *p_candidate) {
WebRTCPeerConnectionJS *peer = static_cast<WebRTCPeerConnectionJS *>(p_obj);
- peer->emit_signal("ice_candidate_created", String(p_mid_name), p_mline_idx, String(p_candidate));
+ peer->emit_signal(SNAME("ice_candidate_created"), String(p_mid_name), p_mline_idx, String(p_candidate));
}
void WebRTCPeerConnectionJS::_on_session_created(void *p_obj, const char *p_type, const char *p_session) {
WebRTCPeerConnectionJS *peer = static_cast<WebRTCPeerConnectionJS *>(p_obj);
- peer->emit_signal("session_description_created", String(p_type), String(p_session));
+ peer->emit_signal(SNAME("session_description_created"), String(p_type), String(p_session));
}
void WebRTCPeerConnectionJS::_on_connection_state_changed(void *p_obj, int p_state) {
@@ -58,7 +57,7 @@ void WebRTCPeerConnectionJS::_on_error(void *p_obj) {
void WebRTCPeerConnectionJS::_on_data_channel(void *p_obj, int p_id) {
WebRTCPeerConnectionJS *peer = static_cast<WebRTCPeerConnectionJS *>(p_obj);
- peer->emit_signal("data_channel_received", Ref<WebRTCDataChannelJS>(new WebRTCDataChannelJS(p_id)));
+ peer->emit_signal(SNAME("data_channel_received"), Ref<WebRTCDataChannelJS>(new WebRTCDataChannelJS(p_id)));
}
void WebRTCPeerConnectionJS::close() {
@@ -100,7 +99,7 @@ Error WebRTCPeerConnectionJS::initialize(Dictionary p_config) {
}
_conn_state = STATE_NEW;
- String config = JSON::print(p_config);
+ String config = Variant(p_config).to_json_string();
_js_id = godot_js_rtc_pc_create(config.utf8().get_data(), this, &_on_connection_state_changed, &_on_ice_candidate, &_on_data_channel);
return _js_id ? OK : FAILED;
}
@@ -108,7 +107,7 @@ Error WebRTCPeerConnectionJS::initialize(Dictionary p_config) {
Ref<WebRTCDataChannel> WebRTCPeerConnectionJS::create_data_channel(String p_channel, Dictionary p_channel_config) {
ERR_FAIL_COND_V(_conn_state != STATE_NEW, nullptr);
- String config = JSON::print(p_channel_config);
+ String config = Variant(p_channel_config).to_json_string();
int id = godot_js_rtc_pc_datachannel_create(_js_id, p_channel.utf8().get_data(), config.utf8().get_data());
ERR_FAIL_COND_V(id == 0, nullptr);
return memnew(WebRTCDataChannelJS(id));
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index 6af610c689..40c0ad17ad 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -6,7 +6,7 @@
<description>
This class implements a WebSocket client compatible with any RFC 6455-compliant WebSocket server.
This client can be optionally used as a network peer for the [MultiplayerAPI].
- After starting the client ([method connect_to_url]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]).
+ After starting the client ([method connect_to_url]), you will need to [method MultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]).
You will receive appropriate signals when connecting, disconnecting, or when new data is available.
</description>
<tutorials>
diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
index 0679acf78a..ee1b60f739 100644
--- a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
+++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" version="4.0">
+<class name="WebSocketMultiplayerPeer" inherits="MultiplayerPeer" version="4.0">
<brief_description>
Base class for WebSocket server and client.
</brief_description>
@@ -39,7 +39,7 @@
</methods>
<members>
<member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" override="true" default="false" />
- <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="NetworkedMultiplayerPeer.TransferMode" default="2" />
+ <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="MultiplayerPeer.TransferMode" default="2" />
</members>
<signals>
<signal name="peer_packet">
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 78f2832770..5491f7de15 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
This class implements a WebSocket server that can also support the high-level multiplayer API.
- After starting the server ([method listen]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). When clients connect, disconnect, or send data, you will receive the appropriate signal.
+ After starting the server ([method listen]), you will need to [method MultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). When clients connect, disconnect, or send data, you will receive the appropriate signal.
[b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>
@@ -89,6 +89,9 @@
<member name="ca_chain" type="X509Certificate" setter="set_ca_chain" getter="get_ca_chain">
When using SSL (see [member private_key] and [member ssl_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the SSL handshake.
</member>
+ <member name="handshake_timeout" type="float" setter="set_handshake_timeout" getter="get_handshake_timeout" default="3.0">
+ The time in seconds before a pending client (i.e. a client that has not yet finished the HTTP handshake) is considered stale and forcefully disconnected.
+ </member>
<member name="private_key" type="CryptoKey" setter="set_private_key" getter="get_private_key">
When set to a valid [CryptoKey] (along with [member ssl_certificate]) will cause the server to require SSL instead of regular TCP (i.e. the [code]wss://[/code] protocol).
</member>
@@ -113,8 +116,11 @@
</argument>
<argument index="1" name="protocol" type="String">
</argument>
+ <argument index="2" name="resource_name" type="String">
+ </argument>
<description>
- Emitted when a new client connects. "protocol" will be the sub-protocol agreed with the client.
+ Emitted when a new client connects. "protocol" will be the sub-protocol agreed with the client, and "resource_name" will be the resource name of the URI the peer used.
+ "resource_name" is a path (at the very least a single forward slash) and potentially a query string.
</description>
</signal>
<signal name="client_disconnected">
diff --git a/modules/websocket/editor_debugger_server_websocket.cpp b/modules/websocket/editor_debugger_server_websocket.cpp
index b02d212c42..2e61cbfc08 100644
--- a/modules/websocket/editor_debugger_server_websocket.cpp
+++ b/modules/websocket/editor_debugger_server_websocket.cpp
@@ -50,9 +50,9 @@ void EditorDebuggerServerWebSocket::poll() {
Error EditorDebuggerServerWebSocket::start() {
int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port");
- Vector<String> protocols;
- protocols.push_back("binary"); // compatibility with EMSCRIPTEN TCP-to-WebSocket layer.
- return server->listen(remote_port, protocols);
+ Vector<String> compatible_protocols;
+ compatible_protocols.push_back("binary"); // compatibility with EMSCRIPTEN TCP-to-WebSocket layer.
+ return server->listen(remote_port, compatible_protocols);
}
void EditorDebuggerServerWebSocket::stop() {
diff --git a/modules/websocket/editor_debugger_server_websocket.h b/modules/websocket/editor_debugger_server_websocket.h
index 2f73b98c3d..d9543bb647 100644
--- a/modules/websocket/editor_debugger_server_websocket.h
+++ b/modules/websocket/editor_debugger_server_websocket.h
@@ -28,12 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H
-#define SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H
-
-#include "modules/websocket/websocket_server.h"
+#ifndef EDITOR_DEBUGGER_SERVER_WEBSOCKET_H
+#define EDITOR_DEBUGGER_SERVER_WEBSOCKET_H
#include "editor/debugger/editor_debugger_server.h"
+#include "modules/websocket/websocket_server.h"
class EditorDebuggerServerWebSocket : public EditorDebuggerServer {
GDCLASS(EditorDebuggerServerWebSocket, EditorDebuggerServer);
@@ -59,4 +58,4 @@ public:
~EditorDebuggerServerWebSocket();
};
-#endif // SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H
+#endif // EDITOR_DEBUGGER_SERVER_WEBSOCKET_H
diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp
index 626498e1ae..744053b6e2 100644
--- a/modules/websocket/emws_client.cpp
+++ b/modules/websocket/emws_client.cpp
@@ -107,7 +107,7 @@ Ref<WebSocketPeer> EMWSClient::get_peer(int p_peer_id) const {
return _peer;
}
-NetworkedMultiplayerPeer::ConnectionStatus EMWSClient::get_connection_status() const {
+MultiplayerPeer::ConnectionStatus EMWSClient::get_connection_status() const {
if (_peer->is_connected_to_host()) {
if (_is_connecting)
return CONNECTION_CONNECTING;
diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp
index 1ad3bdc825..05f9e12ae1 100644
--- a/modules/websocket/emws_peer.cpp
+++ b/modules/websocket/emws_peer.cpp
@@ -56,7 +56,7 @@ Error EMWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
int is_bin = write_mode == WebSocketPeer::WRITE_MODE_BINARY ? 1 : 0;
godot_js_websocket_send(peer_sock, p_buffer, p_buffer_size, is_bin);
return OK;
-};
+}
Error EMWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
if (_in_buffer.packets_left() == 0)
@@ -70,19 +70,19 @@ Error EMWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
r_buffer_size = read;
return OK;
-};
+}
int EMWSPeer::get_available_packet_count() const {
return _in_buffer.packets_left();
-};
+}
bool EMWSPeer::was_string_packet() const {
return _is_string;
-};
+}
bool EMWSPeer::is_connected_to_host() const {
return peer_sock != -1;
-};
+}
void EMWSPeer::close(int p_code, String p_reason) {
if (peer_sock != -1) {
@@ -91,7 +91,7 @@ void EMWSPeer::close(int p_code, String p_reason) {
_is_string = 0;
_in_buffer.clear();
peer_sock = -1;
-};
+}
IPAddress EMWSPeer::get_connected_host() const {
ERR_FAIL_V_MSG(IPAddress(), "Not supported in HTML5 export.");
@@ -99,7 +99,7 @@ IPAddress EMWSPeer::get_connected_host() const {
uint16_t EMWSPeer::get_connected_port() const {
ERR_FAIL_V_MSG(0, "Not supported in HTML5 export.");
-};
+}
void EMWSPeer::set_no_delay(bool p_enabled) {
ERR_FAIL_MSG("'set_no_delay' is not supported in HTML5 export.");
@@ -107,10 +107,10 @@ void EMWSPeer::set_no_delay(bool p_enabled) {
EMWSPeer::EMWSPeer() {
close();
-};
+}
EMWSPeer::~EMWSPeer() {
close();
-};
+}
#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp
index 5a02509c4a..7c742b1b89 100644
--- a/modules/websocket/register_types.cpp
+++ b/modules/websocket/register_types.cpp
@@ -63,7 +63,7 @@ void register_websocket_types() {
WSLServer::make_default();
#endif
- ClassDB::register_virtual_class<WebSocketMultiplayerPeer>();
+ GDREGISTER_VIRTUAL_CLASS(WebSocketMultiplayerPeer);
ClassDB::register_custom_instance_class<WebSocketServer>();
ClassDB::register_custom_instance_class<WebSocketClient>();
ClassDB::register_custom_instance_class<WebSocketPeer>();
diff --git a/modules/websocket/remote_debugger_peer_websocket.h b/modules/websocket/remote_debugger_peer_websocket.h
index 03c60fb480..590d925dcc 100644
--- a/modules/websocket/remote_debugger_peer_websocket.h
+++ b/modules/websocket/remote_debugger_peer_websocket.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCRIPT_DEBUGGER_WEBSOCKET_H
-#define SCRIPT_DEBUGGER_WEBSOCKET_H
+#ifndef REMOTE_DEBUGGER_PEER_WEBSOCKET_H
+#define REMOTE_DEBUGGER_PEER_WEBSOCKET_H
#ifdef JAVASCRIPT_ENABLED
#include "modules/websocket/emws_client.h"
@@ -62,4 +62,4 @@ public:
RemoteDebuggerPeerWebSocket(Ref<WebSocketPeer> p_peer = Ref<WebSocketPeer>());
};
-#endif // SCRIPT_DEBUGGER_WEBSOCKET_H
+#endif // REMOTE_DEBUGGER_PEER_WEBSOCKET_H
diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp
index 27f0f9af6b..f7a8944745 100644
--- a/modules/websocket/websocket_client.cpp
+++ b/modules/websocket/websocket_client.cpp
@@ -42,9 +42,9 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
_is_multiplayer = gd_mp_api;
String host = p_url;
- String path = "/";
- String scheme = "";
- int port = 80;
+ String path;
+ String scheme;
+ int port = 0;
Error err = p_url.parse_url(scheme, host, port, path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
@@ -55,6 +55,9 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
if (port == 0) {
port = ssl ? 443 : 80;
}
+ if (path.is_empty()) {
+ path = "/";
+ }
return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers);
}
@@ -83,7 +86,7 @@ void WebSocketClient::_on_peer_packet() {
if (_is_multiplayer) {
_process_multiplayer(get_peer(1), 1);
} else {
- emit_signal("data_received");
+ emit_signal(SNAME("data_received"));
}
}
@@ -91,27 +94,27 @@ void WebSocketClient::_on_connect(String p_protocol) {
if (_is_multiplayer) {
// need to wait for ID confirmation...
} else {
- emit_signal("connection_established", p_protocol);
+ emit_signal(SNAME("connection_established"), p_protocol);
}
}
void WebSocketClient::_on_close_request(int p_code, String p_reason) {
- emit_signal("server_close_request", p_code, p_reason);
+ emit_signal(SNAME("server_close_request"), p_code, p_reason);
}
void WebSocketClient::_on_disconnect(bool p_was_clean) {
if (_is_multiplayer) {
- emit_signal("connection_failed");
+ emit_signal(SNAME("connection_failed"));
} else {
- emit_signal("connection_closed", p_was_clean);
+ emit_signal(SNAME("connection_closed"), p_was_clean);
}
}
void WebSocketClient::_on_error() {
if (_is_multiplayer) {
- emit_signal("connection_failed");
+ emit_signal(SNAME("connection_failed"));
} else {
- emit_signal("connection_error");
+ emit_signal(SNAME("connection_error"));
}
}
diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp
index fa0ef7060f..ddd8e190df 100644
--- a/modules/websocket/websocket_multiplayer_peer.cpp
+++ b/modules/websocket/websocket_multiplayer_peer.cpp
@@ -123,13 +123,13 @@ Error WebSocketMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer
}
//
-// NetworkedMultiplayerPeer
+// MultiplayerPeer
//
void WebSocketMultiplayerPeer::set_transfer_mode(TransferMode p_mode) {
// Websocket uses TCP, reliable
}
-NetworkedMultiplayerPeer::TransferMode WebSocketMultiplayerPeer::get_transfer_mode() const {
+MultiplayerPeer::TransferMode WebSocketMultiplayerPeer::get_transfer_mode() const {
// Websocket uses TCP, reliable
return TRANSFER_MODE_RELIABLE;
}
@@ -215,7 +215,7 @@ void WebSocketMultiplayerPeer::_store_pkt(int32_t p_source, int32_t p_dest, cons
packet.destination = p_dest;
memcpy(packet.data, &p_data[PROTO_SIZE], p_data_size);
_incoming_packets.push_back(packet);
- emit_signal("peer_packet", p_source);
+ emit_signal(SNAME("peer_packet"), p_source);
}
Error WebSocketMultiplayerPeer::_server_relay(int32_t p_from, int32_t p_to, const uint8_t *p_buffer, uint32_t p_buffer_size) {
@@ -306,15 +306,15 @@ void WebSocketMultiplayerPeer::_process_multiplayer(Ref<WebSocketPeer> p_peer, u
switch (type) {
case SYS_ADD: // Add peer
_peer_map[id] = Ref<WebSocketPeer>();
- emit_signal("peer_connected", id);
+ emit_signal(SNAME("peer_connected"), id);
if (id == 1) { // We just connected to the server
- emit_signal("connection_succeeded");
+ emit_signal(SNAME("connection_succeeded"));
}
break;
case SYS_DEL: // Remove peer
_peer_map.erase(id);
- emit_signal("peer_disconnected", id);
+ emit_signal(SNAME("peer_disconnected"), id);
break;
case SYS_ID: // Hello, server assigned ID
_peer_id = id;
diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h
index 48a6607d89..e3ccd1a795 100644
--- a/modules/websocket/websocket_multiplayer_peer.h
+++ b/modules/websocket/websocket_multiplayer_peer.h
@@ -32,12 +32,12 @@
#define WEBSOCKET_MULTIPLAYER_PEER_H
#include "core/error/error_list.h"
-#include "core/io/networked_multiplayer_peer.h"
+#include "core/io/multiplayer_peer.h"
#include "core/templates/list.h"
#include "websocket_peer.h"
-class WebSocketMultiplayerPeer : public NetworkedMultiplayerPeer {
- GDCLASS(WebSocketMultiplayerPeer, NetworkedMultiplayerPeer);
+class WebSocketMultiplayerPeer : public MultiplayerPeer {
+ GDCLASS(WebSocketMultiplayerPeer, MultiplayerPeer);
private:
Vector<uint8_t> _make_pkt(uint8_t p_type, int32_t p_from, int32_t p_to, const uint8_t *p_data, uint32_t p_data_size);
@@ -78,7 +78,7 @@ protected:
int _gen_unique_id() const;
public:
- /* NetworkedMultiplayerPeer */
+ /* MultiplayerPeer */
void set_transfer_mode(TransferMode p_mode) override;
TransferMode get_transfer_mode() const override;
void set_target_peer(int p_target_peer) override;
diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp
index dfe4471659..fb838109f3 100644
--- a/modules/websocket/websocket_server.cpp
+++ b/modules/websocket/websocket_server.cpp
@@ -65,9 +65,13 @@ void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ca_chain"), &WebSocketServer::set_ca_chain);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ca_chain", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_ca_chain", "get_ca_chain");
+ ClassDB::bind_method(D_METHOD("get_handshake_timeout"), &WebSocketServer::get_handshake_timeout);
+ ClassDB::bind_method(D_METHOD("set_handshake_timeout", "timeout"), &WebSocketServer::set_handshake_timeout);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handshake_timeout"), "set_handshake_timeout", "get_handshake_timeout");
+
ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason")));
ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close")));
- ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol")));
+ ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol"), PropertyInfo(Variant::STRING, "resource_name")));
ADD_SIGNAL(MethodInfo("data_received", PropertyInfo(Variant::INT, "id")));
}
@@ -108,7 +112,16 @@ void WebSocketServer::set_ca_chain(Ref<X509Certificate> p_ca_chain) {
ca_chain = p_ca_chain;
}
-NetworkedMultiplayerPeer::ConnectionStatus WebSocketServer::get_connection_status() const {
+float WebSocketServer::get_handshake_timeout() const {
+ return handshake_timeout / 1000.0;
+}
+
+void WebSocketServer::set_handshake_timeout(float p_timeout) {
+ ERR_FAIL_COND(p_timeout <= 0.0);
+ handshake_timeout = p_timeout * 1000;
+}
+
+MultiplayerPeer::ConnectionStatus WebSocketServer::get_connection_status() const {
if (is_listening()) {
return CONNECTION_CONNECTED;
}
@@ -124,17 +137,17 @@ void WebSocketServer::_on_peer_packet(int32_t p_peer_id) {
if (_is_multiplayer) {
_process_multiplayer(get_peer(p_peer_id), p_peer_id);
} else {
- emit_signal("data_received", p_peer_id);
+ emit_signal(SNAME("data_received"), p_peer_id);
}
}
-void WebSocketServer::_on_connect(int32_t p_peer_id, String p_protocol) {
+void WebSocketServer::_on_connect(int32_t p_peer_id, String p_protocol, String p_resource_name) {
if (_is_multiplayer) {
// Send add to clients
_send_add(p_peer_id);
- emit_signal("peer_connected", p_peer_id);
+ emit_signal(SNAME("peer_connected"), p_peer_id);
} else {
- emit_signal("client_connected", p_peer_id, p_protocol);
+ emit_signal(SNAME("client_connected"), p_peer_id, p_protocol, p_resource_name);
}
}
@@ -142,12 +155,12 @@ void WebSocketServer::_on_disconnect(int32_t p_peer_id, bool p_was_clean) {
if (_is_multiplayer) {
// Send delete to clients
_send_del(p_peer_id);
- emit_signal("peer_disconnected", p_peer_id);
+ emit_signal(SNAME("peer_disconnected"), p_peer_id);
} else {
- emit_signal("client_disconnected", p_peer_id, p_was_clean);
+ emit_signal(SNAME("client_disconnected"), p_peer_id, p_was_clean);
}
}
void WebSocketServer::_on_close_request(int32_t p_peer_id, int p_code, String p_reason) {
- emit_signal("client_close_request", p_peer_id, p_code, p_reason);
+ emit_signal(SNAME("client_close_request"), p_peer_id, p_code, p_reason);
}
diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h
index bc5e591e7b..c4d651471f 100644
--- a/modules/websocket/websocket_server.h
+++ b/modules/websocket/websocket_server.h
@@ -48,6 +48,7 @@ protected:
Ref<CryptoKey> private_key;
Ref<X509Certificate> ssl_cert;
Ref<X509Certificate> ca_chain;
+ uint32_t handshake_timeout = 3000;
public:
virtual Error listen(int p_port, const Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false) = 0;
@@ -62,7 +63,7 @@ public:
virtual void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = "") = 0;
void _on_peer_packet(int32_t p_peer_id);
- void _on_connect(int32_t p_peer_id, String p_protocol);
+ void _on_connect(int32_t p_peer_id, String p_protocol, String p_resource_name);
void _on_disconnect(int32_t p_peer_id, bool p_was_clean);
void _on_close_request(int32_t p_peer_id, int p_code, String p_reason);
@@ -78,6 +79,9 @@ public:
Ref<X509Certificate> get_ca_chain() const;
void set_ca_chain(Ref<X509Certificate> p_ca_chain);
+ float get_handshake_timeout() const;
+ void set_handshake_timeout(float p_timeout);
+
WebSocketServer();
~WebSocketServer();
};
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index af1bdb532c..49997b42d3 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -158,6 +158,7 @@ bool WSLClient::_verify_headers(String &r_protocol) {
Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
_peer = Ref<WSLPeer>(memnew(WSLPeer));
IPAddress addr;
@@ -287,7 +288,7 @@ Ref<WebSocketPeer> WSLClient::get_peer(int p_peer_id) const {
return _peer;
}
-NetworkedMultiplayerPeer::ConnectionStatus WSLClient::get_connection_status() const {
+MultiplayerPeer::ConnectionStatus WSLClient::get_connection_status() const {
if (_peer->is_connected_to_host()) {
return CONNECTION_CONNECTED;
}
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index 22bb1b6d1a..5f794415af 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -34,7 +34,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
-bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
+bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols, String &r_resource_name) {
Vector<String> psa = String((char *)req_buf).split("\r\n");
int len = psa.size();
ERR_FAIL_COND_V_MSG(len < 4, false, "Not enough response headers, got: " + itos(len) + ", expected >= 4.");
@@ -45,6 +45,7 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
// Wrong protocol
ERR_FAIL_COND_V_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", false, "Invalid method or HTTP version.");
+ r_resource_name = req[1];
Map<String, String> headers;
for (int i = 1; i < len; i++) {
Vector<String> header = psa[i].split(":", false, 1);
@@ -95,28 +96,33 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
return true;
}
-Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols) {
- if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT) {
+Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name) {
+ 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;
}
+
if (use_ssl) {
Ref<StreamPeerSSL> ssl = static_cast<Ref<StreamPeerSSL>>(connection);
if (ssl.is_null()) {
- return FAILED;
+ ERR_FAIL_V_MSG(ERR_BUG, "Couldn't get StreamPeerSSL for WebSocket handshake.");
}
ssl->poll();
if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) {
return ERR_BUSY;
} else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
+ print_verbose(vformat("WebSocket SSL connection error during handshake (StreamPeerSSL status code %d).", ssl->get_status()));
return FAILED;
}
}
+
if (!has_request) {
int read = 0;
while (true) {
- ERR_FAIL_COND_V_MSG(req_pos >= WSL_MAX_HEADER_SIZE, ERR_OUT_OF_MEMORY, "Response headers too big.");
+ ERR_FAIL_COND_V_MSG(req_pos >= WSL_MAX_HEADER_SIZE, ERR_OUT_OF_MEMORY, "WebSocket response headers are too big.");
Error err = connection->get_partial_data(&req_buf[req_pos], 1, read);
if (err != OK) { // Got an error
+ print_verbose(vformat("WebSocket error while getting partial data (StreamPeer error code %d).", err));
return FAILED;
} else if (read != 1) { // Busy, wait next poll
return ERR_BUSY;
@@ -125,7 +131,7 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols) {
int l = req_pos;
if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
r[l - 3] = '\0';
- if (!_parse_request(p_protocols)) {
+ if (!_parse_request(p_protocols, r_resource_name)) {
return FAILED;
}
String s = "HTTP/1.1 101 Switching Protocols\r\n";
@@ -143,17 +149,21 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols) {
req_pos += 1;
}
}
+
if (has_request && response_sent < response.size() - 1) {
int sent = 0;
Error err = connection->put_partial_data((const uint8_t *)response.get_data() + response_sent, response.size() - response_sent - 1, sent);
if (err != OK) {
+ print_verbose(vformat("WebSocket error while putting partial data (StreamPeer error code %d).", err));
return err;
}
response_sent += sent;
}
+
if (response_sent < response.size() - 1) {
return ERR_BUSY;
}
+
return OK;
}
@@ -187,8 +197,9 @@ void WSLServer::poll() {
List<Ref<PendingPeer>> remove_peers;
for (List<Ref<PendingPeer>>::Element *E = _pending.front(); E; E = E->next()) {
+ String resource_name;
Ref<PendingPeer> ppeer = E->get();
- Error err = ppeer->do_handshake(_protocols);
+ Error err = ppeer->do_handshake(_protocols, handshake_timeout, resource_name);
if (err == ERR_BUSY) {
continue;
} else if (err != OK) {
@@ -211,7 +222,7 @@ void WSLServer::poll() {
_peer_map[id] = ws_peer;
remove_peers.push_back(ppeer);
- _on_connect(id, ppeer->protocol);
+ _on_connect(id, ppeer->protocol, resource_name);
}
for (List<Ref<PendingPeer>>::Element *E = remove_peers.front(); E; E = E->next()) {
_pending.erase(E->get());
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index 39177a16a8..93c8bd9604 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -40,15 +40,13 @@
#include "core/io/stream_peer_tcp.h"
#include "core/io/tcp_server.h"
-#define WSL_SERVER_TIMEOUT 1000
-
class WSLServer : public WebSocketServer {
GDCIIMPL(WSLServer, WebSocketServer);
private:
class PendingPeer : public RefCounted {
private:
- bool _parse_request(const Vector<String> p_protocols);
+ bool _parse_request(const Vector<String> p_protocols, String &r_resource_name);
public:
Ref<StreamPeerTCP> tcp;
@@ -64,7 +62,7 @@ private:
CharString response;
int response_sent = 0;
- Error do_handshake(const Vector<String> p_protocols);
+ Error do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name);
};
int _in_buf_size = DEF_BUF_SHIFT;
diff --git a/modules/webxr/register_types.cpp b/modules/webxr/register_types.cpp
index 6df0234811..078a6547cf 100644
--- a/modules/webxr/register_types.cpp
+++ b/modules/webxr/register_types.cpp
@@ -34,7 +34,7 @@
#include "webxr_interface_js.h"
void register_webxr_types() {
- ClassDB::register_virtual_class<WebXRInterface>();
+ GDREGISTER_VIRTUAL_CLASS(WebXRInterface);
#ifdef JAVASCRIPT_ENABLED
Ref<WebXRInterfaceJS> webxr;
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 2eab0cdb07..099e769303 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -35,6 +35,7 @@
#include "core/os/os.h"
#include "emscripten.h"
#include "godot_webxr.h"
+#include "servers/rendering/renderer_compositor.h"
#include <stdlib.h>
void _emwebxr_on_session_supported(char *p_session_mode, int p_supported) {
@@ -45,7 +46,7 @@ void _emwebxr_on_session_supported(char *p_session_mode, int p_supported) {
ERR_FAIL_COND(interface.is_null());
String session_mode = String(p_session_mode);
- interface->emit_signal("session_supported", session_mode, p_supported ? true : false);
+ interface->emit_signal(SNAME("session_supported"), session_mode, p_supported ? true : false);
}
void _emwebxr_on_session_started(char *p_reference_space_type) {
@@ -57,7 +58,7 @@ void _emwebxr_on_session_started(char *p_reference_space_type) {
String reference_space_type = String(p_reference_space_type);
((WebXRInterfaceJS *)interface.ptr())->_set_reference_space_type(reference_space_type);
- interface->emit_signal("session_started");
+ interface->emit_signal(SNAME("session_started"));
}
void _emwebxr_on_session_ended() {
@@ -68,7 +69,7 @@ void _emwebxr_on_session_ended() {
ERR_FAIL_COND(interface.is_null());
interface->uninitialize();
- interface->emit_signal("session_ended");
+ interface->emit_signal(SNAME("session_ended"));
}
void _emwebxr_on_session_failed(char *p_message) {
@@ -81,7 +82,7 @@ void _emwebxr_on_session_failed(char *p_message) {
interface->uninitialize();
String message = String(p_message);
- interface->emit_signal("session_failed", message);
+ interface->emit_signal(SNAME("session_failed"), message);
}
void _emwebxr_on_controller_changed() {
@@ -202,8 +203,8 @@ int WebXRInterfaceJS::get_capabilities() const {
return XRInterface::XR_STEREO | XRInterface::XR_MONO;
};
-bool WebXRInterfaceJS::is_stereo() {
- return godot_webxr_get_view_count() == 2;
+uint32_t WebXRInterfaceJS::get_view_count() {
+ return godot_webxr_get_view_count();
};
bool WebXRInterfaceJS::is_initialized() const {
@@ -376,6 +377,22 @@ void WebXRInterfaceJS::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_targ
return;
}
godot_webxr_commit_for_eye(p_eye);
+}
+
+Vector<BlitToScreen> WebXRInterfaceJS::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+ Vector<BlitToScreen> blit_to_screen;
+
+ if (!initialized) {
+ return blit_to_screen;
+ }
+
+ // @todo Refactor this to be based on "views" rather than "eyes".
+ godot_webxr_commit_for_eye(XRInterface::EYE_LEFT);
+ if (godot_webxr_get_view_count() > 1) {
+ godot_webxr_commit_for_eye(XRInterface::EYE_RIGHT);
+ }
+
+ return blit_to_screen;
};
void WebXRInterfaceJS::process() {
@@ -425,7 +442,7 @@ void WebXRInterfaceJS::_update_tracker(int p_controller_id) {
int *buttons = godot_webxr_get_controller_buttons(p_controller_id);
if (buttons) {
for (int i = 0; i < buttons[0]; i++) {
- input->joy_button(p_controller_id + 100, i, *((float *)buttons + (i + 1)));
+ input->joy_button(p_controller_id + 100, (JoyButton)i, *((float *)buttons + (i + 1)));
}
free(buttons);
}
@@ -436,7 +453,7 @@ void WebXRInterfaceJS::_update_tracker(int p_controller_id) {
Input::JoyAxisValue joy_axis;
joy_axis.min = -1;
joy_axis.value = *((float *)axes + (i + 1));
- input->joy_axis(p_controller_id + 100, i, joy_axis);
+ input->joy_axis(p_controller_id + 100, (JoyAxis)i, joy_axis);
}
free(axes);
}
diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h
index 723ab952cd..f9368582b7 100644
--- a/modules/webxr/webxr_interface_js.h
+++ b/modules/webxr/webxr_interface_js.h
@@ -83,12 +83,13 @@ public:
virtual void uninitialize() override;
virtual Size2 get_render_targetsize() override;
- virtual bool is_stereo() override;
+ virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye) override;
virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
virtual void notification(int p_what) override;
diff --git a/platform/android/api/api.cpp b/platform/android/api/api.cpp
index d3c49c6eb7..03355e4815 100644
--- a/platform/android/api/api.cpp
+++ b/platform/android/api/api.cpp
@@ -44,11 +44,11 @@ void register_android_api() {
// `JNISingleton` registration occurs in
// `platform/android/java_godot_lib_jni.cpp#Java_org_godotengine_godot_GodotLib_setup`
java_class_wrapper = memnew(JavaClassWrapper); // Dummy
- ClassDB::register_class<JNISingleton>();
+ GDREGISTER_CLASS(JNISingleton);
#endif
- ClassDB::register_class<JavaClass>();
- ClassDB::register_class<JavaClassWrapper>();
+ GDREGISTER_CLASS(JavaClass);
+ GDREGISTER_CLASS(JavaClassWrapper);
Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", JavaClassWrapper::get_singleton()));
}
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 66a2013c4e..1fcc3d4a5c 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -358,8 +358,8 @@ Vector<String> DisplayServerAndroid::get_rendering_drivers_func() {
return drivers;
}
-DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver");
}
@@ -377,10 +377,11 @@ void DisplayServerAndroid::reset_window() {
ERR_FAIL_COND(!native_window);
ERR_FAIL_COND(!context_vulkan);
+ VSyncMode last_vsync_mode = context_vulkan->get_vsync_mode(MAIN_WINDOW_ID);
context_vulkan->window_destroy(MAIN_WINDOW_ID);
Size2i display_size = OS_Android::get_singleton()->get_display_size();
- if (context_vulkan->window_create(native_window, display_size.width, display_size.height) == -1) {
+ if (context_vulkan->window_create(native_window, last_vsync_mode, display_size.width, display_size.height) == -1) {
memdelete(context_vulkan);
context_vulkan = nullptr;
ERR_FAIL_MSG("Failed to reset Vulkan window.");
@@ -402,7 +403,7 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {
rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
}
-DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver;
// TODO: rendering_driver is broken, change when different drivers are supported again
@@ -446,7 +447,7 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
}
Size2i display_size = OS_Android::get_singleton()->get_display_size();
- if (context_vulkan->window_create(native_window, display_size.width, display_size.height) == -1) {
+ if (context_vulkan->window_create(native_window, p_vsync_mode, display_size.width, display_size.height) == -1) {
memdelete(context_vulkan);
context_vulkan = nullptr;
ERR_FAIL_MSG("Failed to create Vulkan window.");
@@ -901,3 +902,17 @@ void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape)
DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {
return cursor_shape;
}
+
+void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+#if defined(VULKAN_ENABLED)
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
+}
+
+DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {
+#if defined(VULKAN_ENABLED)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
+}
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index a39271d524..46745f8030 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -92,7 +92,7 @@ private:
1003, //CURSOR_HELP
};
const int CURSOR_TYPE_NULL = 0;
- MouseMode mouse_mode;
+ MouseMode mouse_mode = MouseMode::MOUSE_MODE_VISIBLE;
bool keep_screen_on;
@@ -129,69 +129,84 @@ private:
public:
static DisplayServerAndroid *get_singleton();
- virtual bool has_feature(Feature p_feature) const;
- virtual String get_name() const;
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
- virtual void clipboard_set(const String &p_text);
- virtual String clipboard_get() const;
+ virtual void clipboard_set(const String &p_text) override;
+ virtual String clipboard_get() const override;
- virtual void screen_set_keep_on(bool p_enable);
- virtual bool screen_is_kept_on() const;
+ virtual void screen_set_keep_on(bool p_enable) override;
+ virtual bool screen_is_kept_on() const override;
- virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW);
- virtual ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override;
+ virtual ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual int get_screen_count() const;
- virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual int get_screen_count() const override;
+ virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
- virtual void virtual_keyboard_hide();
- virtual int virtual_keyboard_get_height() const;
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
+ virtual void virtual_keyboard_hide() override;
+ virtual int virtual_keyboard_get_height() const override;
- virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
void send_window_event(WindowEvent p_event) const;
void send_input_event(const Ref<InputEvent> &p_event) const;
void send_input_text(const String &p_text) const;
- virtual Vector<WindowID> get_window_list() const;
- virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
- virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
- virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
- virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
- virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_transient(WindowID p_window, WindowID p_parent);
- virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
- virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
- virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
- virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual bool can_any_window_draw() const;
-
- virtual void alert(const String &p_alert, const String &p_title);
-
- virtual void process_events();
+ virtual Vector<WindowID> get_window_list() const override;
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+
+ virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
+
+ virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
+
+ virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
+
+ virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+
+ virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+
+ virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+
+ virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
+
+ virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
+
+ virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
+
+ virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+
+ virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
+
+ virtual bool can_any_window_draw() const override;
+
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
+
+ virtual void alert(const String &p_alert, const String &p_title) override;
+
+ virtual void process_events() override;
void process_accelerometer(const Vector3 &p_accelerometer);
void process_gravity(const Vector3 &p_gravity);
@@ -205,23 +220,23 @@ public:
void process_joy_event(JoypadEvent p_event);
void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed);
- virtual void cursor_set_shape(CursorShape p_shape);
- virtual CursorShape cursor_get_shape() const;
+ virtual void cursor_set_shape(CursorShape p_shape) override;
+ virtual CursorShape cursor_get_shape() const override;
- void mouse_set_mode(MouseMode p_mode);
- MouseMode mouse_get_mode() const;
+ virtual void mouse_set_mode(MouseMode p_mode) override;
+ virtual MouseMode mouse_get_mode() const override;
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_android_driver();
void reset_window();
void notify_surface_changed(int p_width, int p_height);
- virtual Point2i mouse_get_position() const;
- virtual MouseButton mouse_get_button_state() const;
+ virtual Point2i mouse_get_position() const override;
+ virtual MouseButton mouse_get_button_state() const override;
- DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerAndroid();
};
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index d01232665b..956b59ce80 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -34,6 +34,7 @@
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/image_loader.h"
+#include "core/io/json.h"
#include "core/io/marshalls.h"
#include "core/io/zip_io.h"
#include "core/os/os.h"
@@ -206,6 +207,7 @@ static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v
static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png";
static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png";
static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml";
+static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json";
const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
@@ -277,6 +279,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
EditorProgress *ep = nullptr;
};
+ struct CustomExportData {
+ bool debug;
+ Vector<String> libs;
+ };
+
Vector<PluginConfigAndroid> plugins;
String last_plugin_names;
uint64_t last_custom_build_time = 0;
@@ -757,6 +764,33 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
return OK;
}
+ static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so) {
+ ERR_FAIL_COND_V_MSG(!p_so.path.get_file().begins_with("lib"), FAILED,
+ "Android .so file names must start with \"lib\", but got: " + p_so.path);
+ Vector<String> abis = get_abis();
+ CustomExportData *export_data = (CustomExportData *)p_userdata;
+ bool exported = false;
+ for (int i = 0; i < p_so.tags.size(); ++i) {
+ int abi_index = abis.find(p_so.tags[i]);
+ if (abi_index != -1) {
+ exported = true;
+ String base = "res://android/build/libs";
+ String type = export_data->debug ? "debug" : "release";
+ String abi = abis[abi_index];
+ String filename = p_so.path.get_file();
+ String dst_path = base.plus_file(type).plus_file(abi).plus_file(filename);
+ Vector<uint8_t> data = FileAccess::get_file_as_array(p_so.path);
+ print_verbose("Copying .so file from " + p_so.path + " to " + dst_path);
+ Error err = store_file_at_path(dst_path, data);
+ ERR_FAIL_COND_V_MSG(err, err, "Failed to copy .so file from " + p_so.path + " to " + dst_path);
+ export_data->libs.push_back(dst_path);
+ }
+ }
+ ERR_FAIL_COND_V_MSG(!exported, FAILED,
+ "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + String(" ").join(abis));
+ return OK;
+ }
+
void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
const char **aperms = android_perms;
while (*aperms) {
@@ -858,6 +892,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int xr_mode_index = p_preset->get("xr_features/xr_mode");
bool backup_allowed = p_preset->get("user_data_backup/allow");
+ bool classify_as_game = p_preset->get("package/classify_as_game");
Vector<String> perms;
// Write permissions into the perms variable.
@@ -955,6 +990,10 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
encode_uint32(backup_allowed, &p_manifest.write[iofs + 16]);
}
+ if (tname == "application" && attrname == "isGame") {
+ encode_uint32(classify_as_game, &p_manifest.write[iofs + 16]);
+ }
+
if (tname == "instrumentation" && attrname == "targetPackage") {
string_table.write[attr_value] = get_package_name(package_name);
}
@@ -1673,6 +1712,7 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/classify_as_game"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), ""));
@@ -2024,10 +2064,9 @@ public:
err += template_err;
}
} else {
- r_missing_templates = !exists_export_template("android_source.zip", &err);
-
bool installed_android_build_template = FileAccess::exists("res://android/build/build.gradle");
if (!installed_android_build_template) {
+ r_missing_templates = !exists_export_template("android_source.zip", &err);
err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n";
}
@@ -2380,6 +2419,28 @@ public:
}
}
+ void _remove_copied_libs() {
+ print_verbose("Removing previously installed libraries...");
+ Error error;
+ String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error);
+ if (error || libs_json.is_empty()) {
+ print_verbose("No previously installed libraries found");
+ return;
+ }
+
+ JSON json;
+ error = json.parse(libs_json);
+ 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);
+ for (int i = 0; i < libs.size(); i++) {
+ print_verbose("Removing previously installed library " + libs[i]);
+ da->remove(libs[i]);
+ }
+ da->remove(GDNATIVE_LIBS_PATH);
+ }
+
String join_list(List<String> parts, const String &separator) const {
String ret;
for (int i = 0; i < parts.size(); ++i) {
@@ -2491,13 +2552,22 @@ public:
//stores all the project files inside the Gradle project directory. Also includes all ABIs
_clear_assets_directory();
+ _remove_copied_libs();
if (!apk_expansion) {
print_verbose("Exporting project files..");
- err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, nullptr, ignore_so_file);
+ CustomExportData user_data;
+ user_data.debug = p_debug;
+ err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so);
if (err != OK) {
EditorNode::add_io_error("Could not export project files to gradle project\n");
return err;
}
+ if (user_data.libs.size() > 0) {
+ FileAccessRef 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..");
err = save_apk_expansion_file(p_preset, p_path);
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index 6ab678b8a1..52a7e4c5cf 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -96,14 +96,6 @@ Error create_directory(const String &p_dir) {
return OK;
}
-// Implementation of EditorExportSaveSharedObject.
-// This method will only be called as an input to export_project_files.
-// This method lets the .so files for all ABIs to be copied
-// into the gradle project from the .AAR file
-Error ignore_so_file(void *p_userdata, const SharedObject &p_so) {
- return OK;
-}
-
// Writes p_data into a file at p_path, creating directories if necessary.
// Note: this will overwrite the file at p_path if it already exists.
Error store_file_at_path(const String &p_path, const Vector<uint8_t> &p_data) {
@@ -260,9 +252,13 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
String _get_application_tag(const Ref<EditorExportPreset> &p_preset) {
String manifest_application_text = vformat(
" <application android:label=\"@string/godot_project_name_string\"\n"
- " android:allowBackup=\"%s\" tools:ignore=\"GoogleAppIndexingWarning\"\n"
- " android:icon=\"@mipmap/icon\">\n\n",
- bool_to_string(p_preset->get("user_data_backup/allow")));
+ " android:allowBackup=\"%s\"\n"
+ " android:icon=\"@mipmap/icon\"\n"
+ " android:isGame=\"%s\"\n"
+ " tools:replace=\"android:allowBackup,android:isGame\"\n"
+ " tools:ignore=\"GoogleAppIndexingWarning\">\n\n",
+ bool_to_string(p_preset->get("user_data_backup/allow")),
+ bool_to_string(p_preset->get("package/classify_as_game")));
manifest_application_text += _get_activity_tag(p_preset);
manifest_application_text += " </application>\n";
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 15feea15a4..0874d77645 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -19,8 +19,9 @@
<application
android:label="@string/godot_project_name_string"
android:allowBackup="false"
- tools:ignore="GoogleAppIndexingWarning"
- android:icon="@mipmap/icon" >
+ android:icon="@mipmap/icon"
+ android:isGame="true"
+ tools:ignore="GoogleAppIndexingWarning" >
<!-- Records the version of the Godot editor used for building -->
<meta-data
diff --git a/platform/android/java/app/gradle.properties b/platform/android/java/app/gradle.properties
new file mode 100644
index 0000000000..19587bd81f
--- /dev/null
+++ b/platform/android/java/app/gradle.properties
@@ -0,0 +1,25 @@
+# Godot custom build Gradle settings.
+# These properties apply when running custom build from the Godot editor.
+# NOTE: This should be kept in sync with 'godot/platform/android/java/gradle.properties' except
+# where otherwise specified.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+android.enableJetifier=true
+android.useAndroidX=true
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx4536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+org.gradle.warning.mode=all
+
+# Enable resource optimizations for release build.
+# NOTE: This is turned off for template release build in order to support the build legacy process.
+android.enableResourceOptimizations=true
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index ee24a46d9f..87bb2ea218 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -115,7 +115,7 @@ task zipCustomBuild(type: Zip) {
doFirst {
logger.lifecycle("Generating Godot custom build template")
}
- from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradle.properties', 'gradlew', 'gradlew.bat', 'gradle/**']))
+ from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradlew', 'gradlew.bat', 'gradle/**']))
include '**/*'
archiveFileName = 'android_source.zip'
destinationDirectory = file(binDir)
diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties
index 6b3b62a9da..b51a19a005 100644
--- a/platform/android/java/gradle.properties
+++ b/platform/android/java/gradle.properties
@@ -1,4 +1,6 @@
# Project-wide Gradle settings.
+# NOTE: This should be kept in sync with 'godot/platform/android/java/app/gradle.properties' except
+# where otherwise specified.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
@@ -20,3 +22,7 @@ org.gradle.jvmargs=-Xmx4536m
# org.gradle.parallel=true
org.gradle.warning.mode=all
+
+# Disable resource optimizations for template release build.
+# NOTE: This is turned on for custom build in order to improve the release build.
+android.enableResourceOptimizations=false
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java b/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java
index 0572cf3589..b12844702a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java
@@ -43,10 +43,10 @@ public class Dictionary extends HashMap<String, Object> {
for (String key : keys) {
ret[i] = key;
i++;
- };
+ }
return ret;
- };
+ }
public Object[] get_values() {
Object[] ret = new Object[size()];
@@ -55,21 +55,21 @@ public class Dictionary extends HashMap<String, Object> {
for (String key : keys) {
ret[i] = get(key);
i++;
- };
+ }
return ret;
- };
+ }
public void set_keys(String[] keys) {
keys_cache = keys;
- };
+ }
public void set_values(Object[] vals) {
int i = 0;
for (String key : keys_cache) {
put(key, vals[i]);
i++;
- };
+ }
keys_cache = null;
- };
-};
+ }
+}
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 1ed16e04ca..89497d1526 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
@@ -96,14 +96,6 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God
}
}
- @Override
- public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
- if (godotFragment != null && godotFragment.onKeyMultiple(inKeyCode, repeatCount, event)) {
- return true;
- }
- return super.onKeyMultiple(inKeyCode, repeatCount, event);
- }
-
/**
* Used to initialize the Godot fragment instance in {@link FullScreenGodotApp#onCreate(Bundle)}.
*/
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 0c16214c8a..8ffa4a9249 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -70,10 +70,8 @@ import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings.Secure;
import android.view.Display;
-import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -175,7 +173,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
public static GodotNetUtils netUtils;
public interface ResultCallback {
- public void callback(int requestCode, int resultCode, Intent data);
+ void callback(int requestCode, int resultCode, Intent data);
}
public ResultCallback result_callback;
@@ -220,7 +218,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
for (int i = 0; i < permissions.length; i++) {
GodotLib.requestPermissionResult(permissions[i], grantResults[i] == PackageManager.PERMISSION_GRANTED);
}
- };
+ }
/**
* Invoked on the render thread when the Godot setup is complete.
@@ -281,29 +279,20 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
editText.setView(mRenderView);
io.setEdit(editText);
- view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- Point fullSize = new Point();
- activity.getWindowManager().getDefaultDisplay().getSize(fullSize);
- Rect gameSize = new Rect();
- mRenderView.getView().getWindowVisibleDisplayFrame(gameSize);
-
- final int keyboardHeight = fullSize.y - gameSize.bottom;
- GodotLib.setVirtualKeyboardHeight(keyboardHeight);
- }
+ view.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
+ Point fullSize = new Point();
+ activity.getWindowManager().getDefaultDisplay().getSize(fullSize);
+ Rect gameSize = new Rect();
+ mRenderView.getView().getWindowVisibleDisplayFrame(gameSize);
+ final int keyboardHeight = fullSize.y - gameSize.bottom;
+ GodotLib.setVirtualKeyboardHeight(keyboardHeight);
});
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- // Must occur after GodotLib.setup has completed.
- for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
- plugin.onRegisterPluginWithGodotNative();
- }
-
- setKeepScreenOn("True".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
+ mRenderView.queueOnRenderThread(() -> {
+ for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
+ plugin.onRegisterPluginWithGodotNative();
}
+ setKeepScreenOn("True".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
});
// Include the returned non-null views in the Godot view hierarchy.
@@ -316,14 +305,11 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
}
public void setKeepScreenOn(final boolean p_enabled) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (p_enabled) {
- getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- } else {
- getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
+ runOnUiThread(() -> {
+ if (p_enabled) {
+ getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ } else {
+ getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
});
}
@@ -370,21 +356,14 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
public void alert(final String message, final String title) {
final Activity activity = getActivity();
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setMessage(message).setTitle(title);
- builder.setPositiveButton(
- "OK",
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- }
+ runOnUiThread(() -> {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setMessage(message).setTitle(title);
+ builder.setPositiveButton(
+ "OK",
+ (dialog, id) -> dialog.cancel());
+ AlertDialog dialog = builder.create();
+ dialog.show();
});
}
@@ -534,7 +513,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
String main_pack_md5 = null;
String main_pack_key = null;
- List<String> new_args = new LinkedList<String>();
+ List<String> new_args = new LinkedList<>();
for (int i = 0; i < command_line.length; i++) {
boolean has_extra = i < command_line.length - 1;
@@ -755,19 +734,16 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
public void UiChangeListener() {
final View decorView = getActivity().getWindow().getDecorView();
- decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
- @Override
- public void onSystemUiVisibilityChange(int 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.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);
}
}
});
@@ -780,7 +756,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
int displayRotation = display.getRotation();
float[] adjustedValues = new float[3];
- final int axisSwap[][] = {
+ final int[][] axisSwap = {
{ 1, -1, 0, 1 }, // ROTATION_0
{ -1, -1, 1, 0 }, // ROTATION_90
{ -1, 1, 0, 1 }, // ROTATION_180
@@ -798,21 +774,18 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
final int typeOfSensor = event.sensor.getType();
if (mRenderView != null) {
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) {
- GodotLib.accelerometer(-x, y, -z);
- }
- if (typeOfSensor == Sensor.TYPE_GRAVITY) {
- GodotLib.gravity(-x, y, -z);
- }
- if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) {
- GodotLib.magnetometer(-x, y, -z);
- }
- if (typeOfSensor == Sensor.TYPE_GYROSCOPE) {
- GodotLib.gyroscope(x, -y, z);
- }
+ mRenderView.queueOnRenderThread(() -> {
+ if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) {
+ GodotLib.accelerometer(-x, y, -z);
+ }
+ if (typeOfSensor == Sensor.TYPE_GRAVITY) {
+ GodotLib.gravity(-x, y, -z);
+ }
+ if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) {
+ GodotLib.magnetometer(-x, y, -z);
+ }
+ if (typeOfSensor == Sensor.TYPE_GYROSCOPE) {
+ GodotLib.gyroscope(x, -y, z);
}
});
}
@@ -847,12 +820,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
}
if (shouldQuit && mRenderView != null) {
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- GodotLib.back();
- }
- });
+ mRenderView.queueOnRenderThread(GodotLib::back);
}
}
@@ -897,7 +865,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
byte[] messageDigest = complete.digest();
// Create Hex String
- StringBuffer hexString = new StringBuffer();
+ StringBuilder hexString = new StringBuilder();
for (int i = 0; i < messageDigest.length; i++) {
String s = Integer.toHexString(0xFF & messageDigest[i]);
@@ -918,33 +886,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
}
}
- public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
- String s = event.getCharacters();
- if (s == null || s.length() == 0)
- return false;
-
- final char[] cc = s.toCharArray();
- int cnt = 0;
- for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0)
- ;
- if (cnt == 0)
- return false;
- mRenderView.queueOnRenderThread(new Runnable() {
- // This method will be called on the rendering thread:
- public void run() {
- for (int i = 0, n = cc.length; i < n; i++) {
- int keyCode;
- if ((keyCode = cc[i]) != 0) {
- // Simulate key down and up...
- GodotLib.key(0, 0, keyCode, true);
- GodotLib.key(0, 0, keyCode, false);
- }
- }
- }
- });
- return true;
- }
-
public boolean requestPermission(String p_name) {
return PermissionsUtil.requestPermission(p_name, getActivity());
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index b3ee55ea64..a9d45c943b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -232,13 +232,10 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
public void onResume() {
super.onResume();
- queueEvent(new Runnable() {
- @Override
- public void run() {
- // Resume the renderer
- godotRenderer.onActivityResumed();
- GodotLib.focusin();
- }
+ queueEvent(() -> {
+ // Resume the renderer
+ godotRenderer.onActivityResumed();
+ GodotLib.focusin();
});
}
@@ -246,13 +243,10 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
public void onPause() {
super.onPause();
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.focusout();
- // Pause the renderer
- godotRenderer.onActivityPaused();
- }
+ queueEvent(() -> {
+ GodotLib.focusout();
+ // Pause the renderer
+ godotRenderer.onActivityPaused();
});
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index 12a8bdb90b..66882e8e72 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -34,11 +34,9 @@ import org.godotengine.godot.input.*;
import android.app.Activity;
import android.content.*;
-import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
import android.graphics.Point;
-import android.media.*;
import android.net.Uri;
import android.os.*;
import android.util.DisplayMetrics;
@@ -73,7 +71,7 @@ public class GodotIO {
public int last_file_id = 1;
- class AssetData {
+ static class AssetData {
public boolean eof = false;
public String path;
public InputStream is;
@@ -232,7 +230,7 @@ public class GodotIO {
/// DIRECTORIES
/////////////////////////
- class AssetDir {
+ static class AssetDir {
public String[] files;
public int current;
public String path;
@@ -323,8 +321,8 @@ public class GodotIO {
am = p_activity.getAssets();
activity = p_activity;
//streams = new HashMap<Integer, AssetData>();
- streams = new SparseArray<AssetData>();
- dirs = new SparseArray<AssetDir>();
+ streams = new SparseArray<>();
+ dirs = new SparseArray<>();
}
/////////////////////////
@@ -386,7 +384,7 @@ public class GodotIO {
Point size = new Point();
display.getRealSize(size);
- int result[] = { 0, 0, size.x, size.y };
+ int[] result = { 0, 0, size.x, size.y };
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets();
DisplayCutout cutout = insets.getDisplayCutout();
@@ -408,12 +406,12 @@ public class GodotIO {
//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
//inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
- };
+ }
public void hideKeyboard() {
if (edit != null)
edit.hideKeyboard();
- };
+ }
public void setScreenOrientation(int p_orientation) {
switch (p_orientation) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 8108118388..95870acda1 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -34,7 +34,6 @@ import android.app.Activity;
import android.hardware.SensorEvent;
import android.view.Surface;
-import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
index ac333dd827..79007764a7 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
@@ -35,18 +35,18 @@ import org.godotengine.godot.input.GodotInputHandler;
import android.view.SurfaceView;
public interface GodotRenderView {
- abstract public SurfaceView getView();
+ SurfaceView getView();
- abstract public void initInputDevices();
+ void initInputDevices();
- abstract public void queueOnRenderThread(Runnable event);
+ void queueOnRenderThread(Runnable event);
- abstract public void onActivityPaused();
- abstract public void onActivityResumed();
+ void onActivityPaused();
+ void onActivityResumed();
- abstract public void onBackPressed();
+ void onBackPressed();
- abstract public GodotInputHandler getInputHandler();
+ GodotInputHandler getInputHandler();
- abstract public void setPointerIcon(int pointerType);
+ void setPointerIcon(int pointerType);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
index 59bdbf7f8d..878a119c5c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
@@ -34,7 +34,6 @@ import org.godotengine.godot.plugin.GodotPlugin;
import org.godotengine.godot.plugin.GodotPluginRegistry;
import org.godotengine.godot.utils.GLUtils;
-import android.content.Context;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
index 169c6cf770..6fca7f2a57 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
@@ -39,7 +39,6 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.view.GestureDetector;
-import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
@@ -150,13 +149,10 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
public void onResume() {
super.onResume();
- queueOnVkThread(new Runnable() {
- @Override
- public void run() {
- // Resume the renderer
- mRenderer.onVkResume();
- GodotLib.focusin();
- }
+ queueOnVkThread(() -> {
+ // Resume the renderer
+ mRenderer.onVkResume();
+ GodotLib.focusin();
});
}
@@ -164,13 +160,10 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
public void onPause() {
super.onPause();
- queueOnVkThread(new Runnable() {
- @Override
- public void run() {
- GodotLib.focusout();
- // Pause the renderer
- mRenderer.onVkPause();
- }
+ queueOnVkThread(() -> {
+ GodotLib.focusout();
+ // Pause the renderer
+ mRenderer.onVkPause();
});
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
index 2c39d06832..1d60c21c60 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
@@ -75,12 +75,7 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener
final int x = Math.round(event.getX());
final int y = Math.round(event.getY());
final int buttonMask = event.getButtonState();
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.doubleTap(buttonMask, x, y);
- }
- });
+ queueEvent(() -> GodotLib.doubleTap(buttonMask, x, y));
return true;
}
@@ -89,12 +84,7 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener
//Log.i("GodotGesture", "onScroll");
final int x = Math.round(distanceX);
final int y = Math.round(distanceY);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.scroll(x, y);
- }
- });
+ queueEvent(() -> GodotLib.scroll(x, y));
return true;
}
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 435b8b325f..4dc9157545 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
@@ -45,13 +45,9 @@ import android.view.InputDevice.MotionRange;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
@@ -64,7 +60,7 @@ public class GodotInputHandler implements InputDeviceListener {
private final String tag = this.getClass().getSimpleName();
private final SparseIntArray mJoystickIds = new SparseIntArray(4);
- private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<Joystick>(4);
+ private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<>(4);
public GodotInputHandler(GodotRenderView godotView) {
mRenderView = godotView;
@@ -101,22 +97,12 @@ public class GodotInputHandler implements InputDeviceListener {
final int button = getGodotButton(keyCode);
final int godotJoyId = mJoystickIds.get(deviceId);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joybutton(godotJoyId, button, false);
- }
- });
+ queueEvent(() -> GodotLib.joybutton(godotJoyId, button, false));
}
} else {
final int scanCode = event.getScanCode();
final int chr = event.getUnicodeChar(0);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.key(keyCode, scanCode, chr, false);
- }
- });
+ queueEvent(() -> GodotLib.key(keyCode, scanCode, chr, false));
}
return true;
@@ -147,22 +133,12 @@ public class GodotInputHandler implements InputDeviceListener {
final int button = getGodotButton(keyCode);
final int godotJoyId = mJoystickIds.get(deviceId);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joybutton(godotJoyId, button, true);
- }
- });
+ queueEvent(() -> GodotLib.joybutton(godotJoyId, button, true));
}
} else {
final int scanCode = event.getScanCode();
final int chr = event.getUnicodeChar(0);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.key(keyCode, scanCode, chr, true);
- }
- });
+ queueEvent(() -> GodotLib.key(keyCode, scanCode, chr, true));
}
return true;
@@ -194,19 +170,16 @@ public class GodotInputHandler implements InputDeviceListener {
final int action = event.getActionMasked();
final int pointer_idx = event.getPointerId(event.getActionIndex());
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_MOVE:
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_POINTER_DOWN: {
- GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr);
- } break;
- }
+ mRenderView.queueOnRenderThread(() -> {
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_MOVE:
+ case MotionEvent.ACTION_POINTER_UP:
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr);
+ } break;
}
});
}
@@ -232,13 +205,7 @@ public class GodotInputHandler implements InputDeviceListener {
// save value to prevent repeats
joystick.axesValues.put(axis, value);
final int godotAxisIdx = i;
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyaxis(godotJoyId, godotAxisIdx, value);
- //Log.i(tag, "GodotLib.joyaxis("+godotJoyId+", "+godotAxisIdx+", "+value+");");
- }
- });
+ queueEvent(() -> GodotLib.joyaxis(godotJoyId, godotAxisIdx, value));
}
}
@@ -248,13 +215,7 @@ public class GodotInputHandler implements InputDeviceListener {
if (joystick.hatX != hatX || joystick.hatY != hatY) {
joystick.hatX = hatX;
joystick.hatY = hatY;
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyhat(godotJoyId, hatX, hatY);
- //Log.i(tag, "GodotLib.joyhat("+godotJoyId+", "+hatX+", "+hatY+");");
- }
- });
+ queueEvent(() -> GodotLib.joyhat(godotJoyId, hatX, hatY));
}
}
return true;
@@ -263,12 +224,7 @@ public class GodotInputHandler implements InputDeviceListener {
final float x = event.getX();
final float y = event.getY();
final int type = event.getAction();
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.hover(type, x, y);
- }
- });
+ queueEvent(() -> GodotLib.hover(type, x, y));
return true;
} else if (event.isFromSource(InputDevice.SOURCE_MOUSE) || event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) {
@@ -333,7 +289,7 @@ public class GodotInputHandler implements InputDeviceListener {
//Helps with creating new joypad mappings.
Log.i(tag, "=== New Input Device: " + joystick.name);
- Set<Integer> already = new HashSet<Integer>();
+ Set<Integer> already = new HashSet<>();
for (InputDevice.MotionRange range : device.getMotionRanges()) {
boolean isJoystick = range.isFromSource(InputDevice.SOURCE_JOYSTICK);
boolean isGamepad = range.isFromSource(InputDevice.SOURCE_GAMEPAD);
@@ -360,12 +316,7 @@ public class GodotInputHandler implements InputDeviceListener {
}
mJoysticksDevices.put(deviceId, joystick);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyconnectionchanged(id, true, joystick.name);
- }
- });
+ queueEvent(() -> GodotLib.joyconnectionchanged(id, true, joystick.name));
}
@Override
@@ -378,12 +329,7 @@ public class GodotInputHandler implements InputDeviceListener {
mJoystickIds.delete(deviceId);
mJoysticksDevices.delete(deviceId);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyconnectionchanged(godotJoyId, false, "");
- }
- });
+ queueEvent(() -> GodotLib.joyconnectionchanged(godotJoyId, false, ""));
}
@Override
@@ -472,12 +418,7 @@ public class GodotInputHandler implements InputDeviceListener {
final float x = event.getX();
final float y = event.getY();
final int type = event.getAction();
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.hover(type, x, y);
- }
- });
+ queueEvent(() -> GodotLib.hover(type, x, y));
return true;
}
case MotionEvent.ACTION_BUTTON_PRESS:
@@ -487,12 +428,7 @@ public class GodotInputHandler implements InputDeviceListener {
final float y = event.getY();
final int buttonsMask = event.getButtonState();
final int action = event.getAction();
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask);
- }
- });
+ queueEvent(() -> GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask));
return true;
}
case MotionEvent.ACTION_SCROLL: {
@@ -502,12 +438,7 @@ public class GodotInputHandler implements InputDeviceListener {
final int action = event.getAction();
final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor);
- }
- });
+ queueEvent(() -> GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor));
}
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP: {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index 3e0e6a65fd..020870a110 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -94,17 +94,14 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
//Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < count; ++i) {
- GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true);
- GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false);
-
- if (mHasSelection) {
- mHasSelection = false;
- break;
- }
+ mRenderView.queueOnRenderThread(() -> {
+ for (int i = 0; i < count; ++i) {
+ GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true);
+ GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false);
+
+ if (mHasSelection) {
+ mHasSelection = false;
+ break;
}
}
});
@@ -118,18 +115,15 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
for (int i = start; i < start + count; ++i) {
newChars[i - start] = pCharSequence.charAt(i);
}
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < count; ++i) {
- int key = newChars[i];
- if ((key == '\n') && !mEdit.isMultiline()) {
- // Return keys are handled through action events
- continue;
- }
- GodotLib.key(0, 0, key, true);
- GodotLib.key(0, 0, key, false);
+ mRenderView.queueOnRenderThread(() -> {
+ for (int i = 0; i < count; ++i) {
+ int key = newChars[i];
+ if ((key == '\n') && !mEdit.isMultiline()) {
+ // Return keys are handled through action events
+ continue;
}
+ GodotLib.key(0, 0, key, true);
+ GodotLib.key(0, 0, key, false);
}
});
}
@@ -139,23 +133,21 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
if (mEdit == pTextView && isFullScreenEdit()) {
final String characters = pKeyEvent.getCharacters();
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < characters.length(); i++) {
- final int ch = characters.codePointAt(i);
- GodotLib.key(0, 0, ch, true);
- GodotLib.key(0, 0, ch, false);
- }
+ mRenderView.queueOnRenderThread(() -> {
+ for (int i = 0; i < characters.length(); i++) {
+ final int ch = characters.codePointAt(i);
+ GodotLib.key(0, 0, ch, true);
+ GodotLib.key(0, 0, ch, false);
}
});
}
if (pActionID == EditorInfo.IME_ACTION_DONE) {
// Enter key has been pressed
- GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true);
- GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false);
-
+ mRenderView.queueOnRenderThread(() -> {
+ GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true);
+ GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false);
+ });
mRenderView.getView().requestFocus();
return true;
}
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
index 62810ad3a4..21fdc658bb 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
@@ -28,14 +28,14 @@ public interface InputManagerCompat {
* @param id The device id
* @return The input device or null if not found
*/
- public InputDevice getInputDevice(int id);
+ InputDevice getInputDevice(int id);
/**
* Gets the ids of all input devices in the system.
*
* @return The input device ids.
*/
- public int[] getInputDeviceIds();
+ int[] getInputDeviceIds();
/**
* Registers an input device listener to receive notifications about when
@@ -46,7 +46,7 @@ public interface InputManagerCompat {
* null if the listener should be invoked on the calling thread's
* looper.
*/
- public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
+ void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
Handler handler);
/**
@@ -54,7 +54,7 @@ public interface InputManagerCompat {
*
* @param listener The listener to unregister.
*/
- public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
+ void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
/*
* The following three calls are to simulate V16 behavior on pre-Jellybean
@@ -69,7 +69,7 @@ public interface InputManagerCompat {
*
* @param event the motion event from the app
*/
- public void onGenericMotionEvent(MotionEvent event);
+ void onGenericMotionEvent(MotionEvent event);
/**
* Tell the V9 input manager that it should stop polling for disconnected
@@ -77,7 +77,7 @@ public interface InputManagerCompat {
* might want to call it whenever your game is not active (or whenever you
* don't care about being notified of new input devices)
*/
- public void onPause();
+ void onPause();
/**
* Tell the V9 input manager that it should start polling for disconnected
@@ -85,9 +85,9 @@ public interface InputManagerCompat {
* might want to call it less often (only when the gameplay is actually
* active)
*/
- public void onResume();
+ void onResume();
- public interface InputDeviceListener {
+ 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
@@ -119,7 +119,7 @@ public interface InputManagerCompat {
/**
* Use this to construct a compatible InputManager.
*/
- public static class Factory {
+ class Factory {
/**
* Constructs and returns a compatible InputManger
*
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
index 61828dccae..0dbc13c77b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java
@@ -34,7 +34,7 @@ public class InputManagerV16 implements InputManagerCompat {
public InputManagerV16(Context context) {
mInputManager = (InputManager)context.getSystemService(Context.INPUT_SERVICE);
- mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
+ mListeners = new HashMap<>();
}
@Override
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
index 4b7318c718..bff90d7ce9 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
@@ -41,12 +41,12 @@ import java.util.List;
class Joystick {
int device_id;
String name;
- List<Integer> axes = new ArrayList<Integer>();
+ List<Integer> axes = new ArrayList<>();
protected boolean hasAxisHat = false;
/*
* Keep track of values so we can prevent flooding the engine with useless events.
*/
- protected final SparseArray axesValues = new SparseArray<Float>(4);
+ protected final SparseArray<Float> axesValues = new SparseArray<>(4);
protected int hatX;
protected int hatY;
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
index 6c8a3d4219..2dc8359615 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
@@ -136,7 +136,7 @@ public abstract class GodotPlugin {
nativeRegisterSingleton(pluginName, pluginObject);
Set<Method> filteredMethods = new HashSet<>();
- Class clazz = pluginObject.getClass();
+ Class<?> clazz = pluginObject.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
@@ -157,8 +157,8 @@ public abstract class GodotPlugin {
for (Method method : filteredMethods) {
List<String> ptr = new ArrayList<>();
- Class[] paramTypes = method.getParameterTypes();
- for (Class c : paramTypes) {
+ Class<?>[] paramTypes = method.getParameterTypes();
+ for (Class<?> c : paramTypes) {
ptr.add(c.getName());
}
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 d6e49bb635..2b6e4ad2be 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
@@ -39,10 +39,10 @@ public class Crypt {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(input.getBytes());
- byte messageDigest[] = digest.digest();
+ byte[] messageDigest = digest.digest();
// Create Hex String
- StringBuffer hexString = new StringBuffer();
+ StringBuilder hexString = new StringBuilder();
for (int i = 0; i < messageDigest.length; i++)
hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
return hexString.toString();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
index 71610d2d00..c852e8759a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
@@ -30,7 +30,6 @@
package org.godotengine.godot.xr.regular;
-import org.godotengine.godot.GodotLib;
import org.godotengine.godot.utils.GLUtils;
import android.opengl.GLSurfaceView;
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 4c66789a83..ce7a49e53c 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -157,7 +157,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
}
java_class_wrapper = memnew(JavaClassWrapper(godot_java->get_activity()));
- ClassDB::register_class<JNISingleton>();
+ GDREGISTER_CLASS(JNISingleton);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jobject p_surface, jint p_width, jint p_height) {
@@ -438,8 +438,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
env->DeleteLocalRef(obj);
};
- static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5");
- obj->call_deferred(str_method, args[0], args[1], args[2], args[3], args[4]);
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
+ obj->call_deferred(str_method, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
// something
env->PopLocalFrame(nullptr);
}
@@ -451,7 +451,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResu
}
if (os_android->get_main_loop()) {
- os_android->get_main_loop()->emit_signal("on_request_permissions_result", permission, p_result == JNI_TRUE);
+ os_android->get_main_loop()->emit_signal(SNAME("on_request_permissions_result"), permission, p_result == JNI_TRUE);
}
}
diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp
index cf0c02e2bf..6a20d5eafc 100644
--- a/platform/android/plugin/godot_plugin_jni.cpp
+++ b/platform/android/plugin/godot_plugin_jni.cpp
@@ -126,7 +126,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
env->DeleteLocalRef(j_param);
};
- singleton->emit_signal(signal_name, args, count);
+ singleton->emit_signal(SNAME(signal_name), args, count);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) {
diff --git a/platform/android/vulkan/vulkan_context_android.cpp b/platform/android/vulkan/vulkan_context_android.cpp
index 63f2026fae..a031f3beee 100644
--- a/platform/android/vulkan/vulkan_context_android.cpp
+++ b/platform/android/vulkan/vulkan_context_android.cpp
@@ -36,7 +36,7 @@ const char *VulkanContextAndroid::_get_platform_surface_extension() const {
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
}
-int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, int p_height) {
+int VulkanContextAndroid::window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height) {
VkAndroidSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
@@ -49,7 +49,7 @@ int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, in
ERR_FAIL_V_MSG(-1, "vkCreateAndroidSurfaceKHR failed with error " + itos(err));
}
- return _window_create(DisplayServer::MAIN_WINDOW_ID, surface, p_width, p_height);
+ return _window_create(DisplayServer::MAIN_WINDOW_ID, p_vsync_mode, surface, p_width, p_height);
}
bool VulkanContextAndroid::_use_validation_layers() {
diff --git a/platform/android/vulkan/vulkan_context_android.h b/platform/android/vulkan/vulkan_context_android.h
index 5a84eaf8f3..182ce33c97 100644
--- a/platform/android/vulkan/vulkan_context_android.h
+++ b/platform/android/vulkan/vulkan_context_android.h
@@ -39,7 +39,7 @@ class VulkanContextAndroid : public VulkanContext {
virtual const char *_get_platform_surface_extension() const override;
public:
- int window_create(ANativeWindow *p_window, int p_width, int p_height);
+ int window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height);
VulkanContextAndroid() = default;
~VulkanContextAndroid() override = default;
diff --git a/platform/iphone/display_server_iphone.h b/platform/iphone/display_server_iphone.h
index 34c56382a4..6f64130b23 100644
--- a/platform/iphone/display_server_iphone.h
+++ b/platform/iphone/display_server_iphone.h
@@ -67,7 +67,7 @@ class DisplayServerIPhone : public DisplayServer {
void perform_event(const Ref<InputEvent> &p_event);
- DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerIPhone();
public:
@@ -76,7 +76,7 @@ public:
static DisplayServerIPhone *get_singleton();
static void register_iphone_driver();
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
// MARK: - Events
@@ -176,6 +176,9 @@ public:
virtual bool can_any_window_draw() const override;
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
+
virtual bool screen_is_touchscreen(int p_screen) const override;
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) override;
diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm
index 74d7419715..bd95e2c703 100644
--- a/platform/iphone/display_server_iphone.mm
+++ b/platform/iphone/display_server_iphone.mm
@@ -48,7 +48,7 @@ DisplayServerIPhone *DisplayServerIPhone::get_singleton() {
return (DisplayServerIPhone *)DisplayServer::get_singleton();
}
-DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver;
#if defined(OPENGL_ENABLED)
@@ -108,7 +108,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Displ
}
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
- if (context_vulkan->window_create(MAIN_WINDOW_ID, layer, size.width, size.height) != OK) {
+ if (context_vulkan->window_create(MAIN_WINDOW_ID, p_vsync_mode, layer, size.width, size.height) != OK) {
memdelete(context_vulkan);
context_vulkan = nullptr;
ERR_FAIL_MSG("Failed to create Vulkan window.");
@@ -147,8 +147,8 @@ DisplayServerIPhone::~DisplayServerIPhone() {
#endif
}
-DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
}
Vector<String> DisplayServerIPhone::get_rendering_drivers_func() {
@@ -581,3 +581,19 @@ void DisplayServerIPhone::resize_window(CGSize viewSize) {
Variant resize_rect = Rect2i(Point2i(), size);
_window_callback(window_resize_callback, resize_rect);
}
+
+void DisplayServerIPhone::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
+}
+
+DisplayServer::VSyncMode DisplayServerIPhone::window_get_vsync_mode(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
+}
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 1d1961ac2f..f21a14e84b 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -368,6 +368,8 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false));
}
+ Set<String> plist_keys;
+
for (int i = 0; i < found_plugins.size(); i++) {
// Editable plugin plist values
PluginConfigIOS plugin = found_plugins[i];
@@ -379,7 +381,10 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
switch (item.type) {
case PluginConfigIOS::PlistItemType::STRING_INPUT: {
String preset_name = "plugins_plist/" + key;
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value));
+ if (!plist_keys.has(preset_name)) {
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value));
+ plist_keys.insert(preset_name);
+ }
} break;
default:
continue;
@@ -413,7 +418,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with retina display
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale To Fit,Scale To Fill,Scale"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false));
diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h
index 06770260aa..f9c5d7e51f 100644
--- a/platform/iphone/plugin/godot_plugin_config.h
+++ b/platform/iphone/plugin/godot_plugin_config.h
@@ -252,6 +252,8 @@ static inline PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, co
return plugin_config;
}
+ config_file->clear();
+
Error err = config_file->load(path);
if (err != OK) {
diff --git a/platform/iphone/vulkan_context_iphone.h b/platform/iphone/vulkan_context_iphone.h
index 88764e270e..ec6aaf46e8 100644
--- a/platform/iphone/vulkan_context_iphone.h
+++ b/platform/iphone/vulkan_context_iphone.h
@@ -39,7 +39,7 @@ class VulkanContextIPhone : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
- Error window_create(DisplayServer::WindowID p_window_id, CALayer *p_metal_layer, int p_width, int p_height);
+ Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height);
VulkanContextIPhone();
~VulkanContextIPhone();
diff --git a/platform/iphone/vulkan_context_iphone.mm b/platform/iphone/vulkan_context_iphone.mm
index 08c9007fbb..17f2b167b3 100644
--- a/platform/iphone/vulkan_context_iphone.mm
+++ b/platform/iphone/vulkan_context_iphone.mm
@@ -35,7 +35,7 @@ const char *VulkanContextIPhone::_get_platform_surface_extension() const {
return VK_MVK_IOS_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, CALayer *p_metal_layer, int p_width, int p_height) {
+Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) {
VkIOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = nullptr;
@@ -47,7 +47,7 @@ Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, CA
vkCreateIOSSurfaceMVK(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
- return _window_create(p_window_id, surface, p_width, p_height);
+ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextIPhone::VulkanContextIPhone() {}
diff --git a/platform/javascript/api/api.cpp b/platform/javascript/api/api.cpp
index 5ad2bf56cf..e7c018ba9f 100644
--- a/platform/javascript/api/api.cpp
+++ b/platform/javascript/api/api.cpp
@@ -37,8 +37,8 @@ static JavaScript *javascript_eval;
void register_javascript_api() {
JavaScriptToolsEditorPlugin::initialize();
- ClassDB::register_virtual_class<JavaScriptObject>();
- ClassDB::register_virtual_class<JavaScript>();
+ GDREGISTER_VIRTUAL_CLASS(JavaScriptObject);
+ GDREGISTER_VIRTUAL_CLASS(JavaScript);
javascript_eval = memnew(JavaScript);
Engine::get_singleton()->add_singleton(Engine::Singleton("JavaScript", javascript_eval));
}
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index da6adc4cd8..173b558b6d 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -29,7 +29,7 @@ def get_opts():
from SCons.Variables import BoolVariable
return [
- ("initial_memory", "Initial WASM memory (in MiB)", 16),
+ ("initial_memory", "Initial WASM memory (in MiB)", 32),
BoolVariable("use_assertions", "Use Emscripten runtime assertions", False),
BoolVariable("use_thinlto", "Use ThinLTO", False),
BoolVariable("use_ubsan", "Use Emscripten undefined behavior sanitizer (UBSAN)", False),
@@ -38,7 +38,7 @@ def get_opts():
BoolVariable("use_safe_heap", "Use Emscripten SAFE_HEAP sanitizer", False),
# eval() can be a security concern, so it can be disabled.
BoolVariable("javascript_eval", "Enable JavaScript eval interface", True),
- BoolVariable("threads_enabled", "Enable WebAssembly Threads support (limited browser support)", False),
+ BoolVariable("threads_enabled", "Enable WebAssembly Threads support (limited browser support)", True),
BoolVariable("gdnative_enabled", "Enable WebAssembly GDNative support (produces bigger binaries)", False),
BoolVariable("use_closure_compiler", "Use closure compiler to minimize JavaScript code", False),
]
@@ -130,7 +130,6 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize=leak"])
env.Append(LINKFLAGS=["-fsanitize=leak"])
if env["use_safe_heap"]:
- env.Append(CCFLAGS=["-s", "SAFE_HEAP=1"])
env.Append(LINKFLAGS=["-s", "SAFE_HEAP=1"])
# Closure compiler
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index f1b92264e2..5e2b089c7f 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -229,7 +229,7 @@ EM_BOOL DisplayServerJavaScript::mouse_button_callback(int p_event_type, const E
}
Input *input = Input::get_singleton();
- MouseButton mask = input->get_mouse_button_mask();
+ int mask = input->get_mouse_button_mask();
MouseButton button_flag = MouseButton(1 << (ev->get_button_index() - 1));
if (ev->is_pressed()) {
// Since the event is consumed, focus manually. The containing iframe,
@@ -605,17 +605,17 @@ void DisplayServerJavaScript::process_joypads() {
Input::JoyAxisValue joy_axis;
joy_axis.min = 0;
joy_axis.value = value;
- int a = b == 6 ? JOY_AXIS_TRIGGER_LEFT : JOY_AXIS_TRIGGER_RIGHT;
+ JoyAxis a = b == 6 ? JOY_AXIS_TRIGGER_LEFT : JOY_AXIS_TRIGGER_RIGHT;
input->joy_axis(idx, a, joy_axis);
} else {
- input->joy_button(idx, b, value);
+ input->joy_button(idx, (JoyButton)b, value);
}
}
for (int a = 0; a < s_axes_num; a++) {
Input::JoyAxisValue joy_axis;
joy_axis.min = -1;
joy_axis.value = s_axes[a];
- input->joy_axis(idx, a, joy_axis);
+ input->joy_axis(idx, (JoyAxis)a, joy_axis);
}
}
}
@@ -710,18 +710,18 @@ void DisplayServerJavaScript::_dispatch_input_event(const Ref<InputEvent> &p_eve
}
}
-DisplayServer *DisplayServerJavaScript::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- return memnew(DisplayServerJavaScript(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerJavaScript::create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Size2i &p_resolution, Error &r_error) {
+ return memnew(DisplayServerJavaScript(p_rendering_driver, p_window_mode, p_vsync_mode, p_flags, p_resolution, r_error));
}
-DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Size2i &p_resolution, Error &r_error) {
r_error = OK; // Always succeeds for now.
// Ensure the canvas ID.
godot_js_config_canvas_id_get(canvas_id, 256);
// Handle contextmenu, webglcontextlost
- godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, p_mode == WINDOW_MODE_FULLSCREEN, OS::get_singleton()->is_hidpi_allowed() ? 1 : 0);
+ godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, p_window_mode == WINDOW_MODE_FULLSCREEN, OS::get_singleton()->is_hidpi_allowed() ? 1 : 0);
// Check if it's windows.
swap_cancel_ok = godot_js_display_is_swap_ok_cancel() == 1;
diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h
index ece38f1a95..f8acf30854 100644
--- a/platform/javascript/display_server_javascript.h
+++ b/platform/javascript/display_server_javascript.h
@@ -89,7 +89,7 @@ private:
void process_joypads();
static Vector<String> get_rendering_drivers_func();
- static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static void _dispatch_input_event(const Ref<InputEvent> &p_event);
@@ -109,99 +109,99 @@ public:
bool check_size_force_redraw();
// from DisplayServer
- void alert(const String &p_alert, const String &p_title = "ALERT!") override;
- bool has_feature(Feature p_feature) const override;
- String get_name() const override;
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
// cursor
- void cursor_set_shape(CursorShape p_shape) override;
- CursorShape cursor_get_shape() const override;
- void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
+ virtual void cursor_set_shape(CursorShape p_shape) override;
+ virtual CursorShape cursor_get_shape() const override;
+ virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
// mouse
- void mouse_set_mode(MouseMode p_mode) override;
- MouseMode mouse_get_mode() const override;
+ virtual void mouse_set_mode(MouseMode p_mode) override;
+ virtual MouseMode mouse_get_mode() const override;
// touch
- bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
// clipboard
- void clipboard_set(const String &p_text) override;
- String clipboard_get() const override;
+ virtual void clipboard_set(const String &p_text) override;
+ virtual String clipboard_get() const override;
// screen
- int get_screen_count() const override;
- Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual int get_screen_count() const override;
+ virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
- void virtual_keyboard_hide() override;
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
+ virtual void virtual_keyboard_hide() override;
// windows
- Vector<DisplayServer::WindowID> get_window_list() const override;
- WindowID get_window_at_screen_position(const Point2i &p_position) const override;
+ virtual Vector<DisplayServer::WindowID> get_window_list() const override;
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
- void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
- ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
- int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
- Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
- void window_set_transient(WindowID p_window, WindowID p_parent) override;
+ virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
- void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
- Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
- Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
- Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
- WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
- bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
- bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
- void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
- void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
- bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
- bool can_any_window_draw() const override;
+ virtual bool can_any_window_draw() const override;
// events
- void process_events() override;
+ virtual void process_events() override;
// icon
- void set_icon(const Ref<Image> &p_icon) override;
+ virtual void set_icon(const Ref<Image> &p_icon) override;
// others
- bool get_swap_cancel_ok() override;
- void swap_buffers() override;
+ virtual bool get_swap_cancel_ok() override;
+ virtual void swap_buffers() override;
static void register_javascript_driver();
- DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Size2i &p_resolution, Error &r_error);
~DisplayServerJavaScript();
};
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 51c72e10eb..bf4244eda4 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -450,6 +450,7 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re
}
config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy");
config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard");
+ config["focusCanvas"] = p_preset->get("html/focus_canvas_on_start");
config["gdnativeLibs"] = libs;
config["executable"] = p_name;
config["args"] = args;
@@ -650,6 +651,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "html/canvas_resize_policy", PROPERTY_HINT_ENUM, "None,Project,Adaptive"), 2));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/focus_canvas_on_start"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/experimental_virtual_keyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "progressive_web_app/enabled"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/offline_page", PROPERTY_HINT_FILE, "*.html"), ""));
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index 40771d1882..a3f0dbaa45 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -97,7 +97,7 @@ extern EMSCRIPTEN_KEEPALIVE int godot_js_main(int argc, char *argv[]) {
if (Main::is_project_manager() && FileAccess::exists("/tmp/preload.zip")) {
PackedStringArray ps;
ps.push_back("/tmp/preload.zip");
- os->get_main_loop()->emit_signal("files_dropped", ps, -1);
+ os->get_main_loop()->emit_signal(SNAME("files_dropped"), ps, -1);
}
#endif
emscripten_set_main_loop(main_loop_callback, -1, false);
diff --git a/platform/javascript/javascript_singleton.cpp b/platform/javascript/javascript_singleton.cpp
index 9de2edc9a7..1dd73ef8e9 100644
--- a/platform/javascript/javascript_singleton.cpp
+++ b/platform/javascript/javascript_singleton.cpp
@@ -183,7 +183,7 @@ Variant JavaScriptObjectImpl::_js2variant(int p_type, godot_js_wrapper_ex *p_val
case Variant::FLOAT:
return p_val->r;
case Variant::STRING: {
- String out((const char *)p_val->p);
+ String out = String::utf8((const char *)p_val->p);
free(p_val->p);
return out;
}
diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js
index 6072782875..ba61b14eb7 100644
--- a/platform/javascript/js/engine/config.js
+++ b/platform/javascript/js/engine/config.js
@@ -91,6 +91,14 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
*/
args: [],
/**
+ * When enabled, the game canvas will automatically grab the focus when the engine starts.
+ *
+ * @memberof EngineConfig
+ * @type {boolean}
+ * @default
+ */
+ focusCanvas: true,
+ /**
* When enabled, this will turn on experimental virtual keyboard support on mobile.
*
* @memberof EngineConfig
@@ -238,6 +246,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
this.persistentPaths = parse('persistentPaths', this.persistentPaths);
this.persistentDrops = parse('persistentDrops', this.persistentDrops);
this.experimentalVK = parse('experimentalVK', this.experimentalVK);
+ this.focusCanvas = parse('focusCanvas', this.focusCanvas);
this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs);
this.fileSizes = parse('fileSizes', this.fileSizes);
this.args = parse('args', this.args);
@@ -324,6 +333,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
'locale': locale,
'persistentDrops': this.persistentDrops,
'virtualKeyboard': this.experimentalVK,
+ 'focusCanvas': this.focusCanvas,
'onExecute': this.onExecute,
'onExit': function (p_code) {
cleanup(); // We always need to call the cleanup callback to free memory.
diff --git a/platform/javascript/js/libs/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js
index 7414b8cc47..5aa750757c 100644
--- a/platform/javascript/js/libs/library_godot_os.js
+++ b/platform/javascript/js/libs/library_godot_os.js
@@ -72,6 +72,9 @@ const GodotConfig = {
GodotConfig.persistent_drops = !!p_opts['persistentDrops'];
GodotConfig.on_execute = p_opts['onExecute'];
GodotConfig.on_exit = p_opts['onExit'];
+ if (p_opts['focusCanvas']) {
+ GodotConfig.canvas.focus();
+ }
},
locate_file: function (file) {
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 0b1650076c..260bfad7a5 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -31,13 +31,12 @@
#include "os_javascript.h"
#include "core/debugger/engine_debugger.h"
-#include "core/io/json.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
#include "main/main.h"
-#include "modules/modules_enabled.gen.h"
#include "platform/javascript/display_server_javascript.h"
+#include "modules/modules_enabled.gen.h"
#ifdef MODULE_WEBSOCKET_ENABLED
#include "modules/websocket/remote_debugger_peer_websocket.h"
#endif
@@ -115,7 +114,7 @@ Error OS_JavaScript::create_process(const String &p_path, const List<String> &p_
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
args.push_back(E->get());
}
- String json_args = JSON::print(args);
+ String json_args = Variant(args).to_json_string();
int failed = godot_js_os_execute(json_args.utf8().get_data());
ERR_FAIL_COND_V_MSG(failed, ERR_UNAVAILABLE, "OS::execute() or create_process() must be implemented in JavaScript via 'engine.setOnExecute' if required.");
return OK;
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index 1751d56e71..8aebd57fd2 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -9,6 +9,7 @@ common_linuxbsd = [
"crash_handler_linuxbsd.cpp",
"os_linuxbsd.cpp",
"joypad_linux.cpp",
+ "freedesktop_screensaver.cpp",
]
if "x11" in env and env["x11"]:
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 1487210174..eba672ddcb 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -72,6 +72,7 @@ def get_opts():
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False),
BoolVariable("pulseaudio", "Detect and use PulseAudio", True),
+ BoolVariable("dbus", "Detect and use D-Bus to handle screensaver", True),
BoolVariable("udev", "Use udev for gamepad connection callbacks", True),
BoolVariable("x11", "Enable X11 display", True),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
@@ -347,6 +348,14 @@ def configure(env):
else:
print("PulseAudio development libraries not found, disabling driver")
+ if env["dbus"]:
+ if os.system("pkg-config --exists dbus-1") == 0: # 0 means found
+ print("Enabling D-Bus")
+ env.Append(CPPDEFINES=["DBUS_ENABLED"])
+ env.ParseConfig("pkg-config --cflags --libs dbus-1")
+ else:
+ print("D-Bus development libraries not found, disabling dependent features")
+
if platform.system() == "Linux":
env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
if env["udev"]:
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index d2531cbe50..8f0742041c 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -121,6 +121,9 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
case FEATURE_ICON:
case FEATURE_NATIVE_ICON:
case FEATURE_SWAP_BUFFERS:
+#ifdef DBUS_ENABLED
+ case FEATURE_KEEP_SCREEN_ON:
+#endif
return true;
default: {
}
@@ -822,6 +825,26 @@ bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {
return DisplayServer::screen_is_touchscreen(p_screen);
}
+#ifdef DBUS_ENABLED
+void DisplayServerX11::screen_set_keep_on(bool p_enable) {
+ if (screen_is_kept_on() == p_enable) {
+ return;
+ }
+
+ if (p_enable) {
+ screensaver->inhibit();
+ } else {
+ screensaver->uninhibit();
+ }
+
+ keep_screen_on = p_enable;
+}
+
+bool DisplayServerX11::screen_is_kept_on() const {
+ return keep_screen_on;
+}
+#endif
+
Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
_THREAD_SAFE_METHOD_
@@ -832,10 +855,10 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
return ret;
}
-DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
- WindowID id = _create_window(p_mode, p_flags, p_rect);
+ WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id);
@@ -3618,6 +3641,22 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
XSetErrorHandler(oldHandler);
}
+void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
+}
+
+DisplayServer::VSyncMode DisplayServerX11::window_get_vsync_mode(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
+}
+
Vector<String> DisplayServerX11::get_rendering_drivers_func() {
Vector<String> drivers;
@@ -3631,8 +3670,8 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
return drivers;
}
-DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
"Please update your drivers or if you have a very old or integrated GPU upgrade it.",
@@ -3641,7 +3680,7 @@ DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, W
return ds;
}
-DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
//Create window
long visualMask = VisualScreenMask;
@@ -3805,7 +3844,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
#if defined(VULKAN_ENABLED)
if (context_vulkan) {
- Error err = context_vulkan->window_create(id, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height);
+ Error err = context_vulkan->window_create(id, p_vsync_mode, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window");
}
#endif
@@ -3842,7 +3881,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
return id;
}
-DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
@@ -4078,7 +4117,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
Point2i window_position(
(screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2);
- WindowID main_window = _create_window(p_mode, p_flags, Rect2i(window_position, p_resolution));
+ WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution));
if (main_window == INVALID_WINDOW_ID) {
r_error = ERR_CANT_CREATE;
return;
@@ -4270,6 +4309,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
_update_real_mouse_position(windows[MAIN_WINDOW_ID]);
+#ifdef DBUS_ENABLED
+ screensaver = memnew(FreeDesktopScreenSaver);
+ screen_set_keep_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true));
+#endif
+
r_error = OK;
}
@@ -4334,6 +4378,10 @@ DisplayServerX11::~DisplayServerX11() {
if (xmbstring) {
memfree(xmbstring);
}
+
+#ifdef DBUS_ENABLED
+ memdelete(screensaver);
+#endif
}
void DisplayServerX11::register_x11_driver() {
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 594a38d39e..29c15ca2ba 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -55,6 +55,10 @@
#include "platform/linuxbsd/vulkan_context_x11.h"
#endif
+#if defined(DBUS_ENABLED)
+#include "freedesktop_screensaver.h"
+#endif
+
#include <X11/Xcursor/Xcursor.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
@@ -103,6 +107,11 @@ class DisplayServerX11 : public DisplayServer {
RenderingDeviceVulkan *rendering_device_vulkan;
#endif
+#if defined(DBUS_ENABLED)
+ FreeDesktopScreenSaver *screensaver;
+ bool keep_screen_on = false;
+#endif
+
struct WindowData {
Window x11_window;
::XIC xic;
@@ -143,7 +152,7 @@ class DisplayServerX11 : public DisplayServer {
Map<WindowID, WindowData> windows;
WindowID window_id_counter = MAIN_WINDOW_ID;
- WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect);
+ WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
String internal_clipboard;
Window xdnd_source_window;
@@ -268,113 +277,121 @@ protected:
void _window_changed(XEvent *event);
public:
- virtual bool has_feature(Feature p_feature) const;
- virtual String get_name() const;
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
- virtual void mouse_set_mode(MouseMode p_mode);
- virtual MouseMode mouse_get_mode() const;
+ virtual void mouse_set_mode(MouseMode p_mode) override;
+ virtual MouseMode mouse_get_mode() const override;
- virtual void mouse_warp_to_position(const Point2i &p_to);
- virtual Point2i mouse_get_position() const;
- virtual Point2i mouse_get_absolute_position() const;
- virtual MouseButton mouse_get_button_state() const;
+ virtual void mouse_warp_to_position(const Point2i &p_to) override;
+ virtual Point2i mouse_get_position() const override;
+ virtual Point2i mouse_get_absolute_position() const override;
+ virtual MouseButton mouse_get_button_state() const override;
- virtual void clipboard_set(const String &p_text);
- virtual String clipboard_get() const;
+ virtual void clipboard_set(const String &p_text) override;
+ virtual String clipboard_get() const override;
+
+ virtual int get_screen_count() const override;
+ virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+
+#if defined(DBUS_ENABLED)
+ virtual void screen_set_keep_on(bool p_enable) override;
+ virtual bool screen_is_kept_on() const override;
+#endif
- virtual int get_screen_count() const;
- virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual Vector<DisplayServer::WindowID> get_window_list() const override;
- virtual Vector<DisplayServer::WindowID> get_window_list() const;
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual void show_window(WindowID p_id) override;
+ virtual void delete_sub_window(WindowID p_id) override;
- virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
- virtual void show_window(WindowID p_id);
- virtual void delete_sub_window(WindowID p_id);
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
- virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
- virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
+ virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
- virtual void window_set_transient(WindowID p_window, WindowID p_parent);
+ virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
- virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
- virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
+ virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool can_any_window_draw() const override;
- virtual bool can_any_window_draw() const;
+ virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
- virtual void cursor_set_shape(CursorShape p_shape);
- virtual CursorShape cursor_get_shape() const;
- virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
+ virtual void cursor_set_shape(CursorShape p_shape) override;
+ virtual CursorShape cursor_get_shape() const override;
+ virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) override;
- virtual int keyboard_get_layout_count() const;
- virtual int keyboard_get_current_layout() const;
- virtual void keyboard_set_current_layout(int p_index);
- virtual String keyboard_get_layout_language(int p_index) const;
- virtual String keyboard_get_layout_name(int p_index) const;
+ virtual int keyboard_get_layout_count() const override;
+ virtual int keyboard_get_current_layout() const override;
+ virtual void keyboard_set_current_layout(int p_index) override;
+ virtual String keyboard_get_layout_language(int p_index) const override;
+ virtual String keyboard_get_layout_name(int p_index) const override;
- virtual void process_events();
+ virtual void process_events() override;
- virtual void release_rendering_thread();
- virtual void make_rendering_thread();
- virtual void swap_buffers();
+ virtual void release_rendering_thread() override;
+ virtual void make_rendering_thread() override;
+ virtual void swap_buffers() override;
- virtual void set_context(Context p_context);
+ virtual void set_context(Context p_context) override;
- virtual void set_native_icon(const String &p_filename);
- virtual void set_icon(const Ref<Image> &p_icon);
+ virtual void set_native_icon(const String &p_filename) override;
+ virtual void set_icon(const Ref<Image> &p_icon) override;
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_x11_driver();
- DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerX11();
};
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
new file mode 100644
index 0000000000..a6a3b27d76
--- /dev/null
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -0,0 +1,125 @@
+/*************************************************************************/
+/* freedesktop_screensaver.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "freedesktop_screensaver.h"
+
+#ifdef DBUS_ENABLED
+
+#include "core/config/project_settings.h"
+
+#include <dbus/dbus.h>
+
+#define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver"
+#define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver"
+#define BUS_INTERFACE "org.freedesktop.ScreenSaver"
+
+void FreeDesktopScreenSaver::inhibit() {
+ if (unsupported) {
+ return;
+ }
+
+ DBusError error;
+ dbus_error_init(&error);
+
+ DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
+ if (dbus_error_is_set(&error)) {
+ unsupported = true;
+ return;
+ }
+
+ String app_name_string = ProjectSettings::get_singleton()->get("application/config/name");
+ CharString app_name_utf8 = app_name_string.utf8();
+ const char *app_name = app_name_string.is_empty() ? "Godot Engine" : app_name_utf8.get_data();
+
+ const char *reason = "Running Godot Engine project";
+
+ DBusMessage *message = dbus_message_new_method_call(
+ BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
+ "Inhibit");
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &app_name,
+ DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
+ dbus_message_unref(message);
+ if (dbus_error_is_set(&error)) {
+ dbus_connection_unref(bus);
+ unsupported = false;
+ return;
+ }
+
+ DBusMessageIter reply_iter;
+ dbus_message_iter_init(reply, &reply_iter);
+ dbus_message_iter_get_basic(&reply_iter, &cookie);
+ print_verbose("FreeDesktopScreenSaver: Acquired screensaver inhibition cookie: " + uitos(cookie));
+
+ dbus_message_unref(reply);
+ dbus_connection_unref(bus);
+}
+
+void FreeDesktopScreenSaver::uninhibit() {
+ if (unsupported) {
+ return;
+ }
+
+ DBusError error;
+ dbus_error_init(&error);
+
+ DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
+ if (dbus_error_is_set(&error)) {
+ unsupported = true;
+ return;
+ }
+
+ DBusMessage *message = dbus_message_new_method_call(
+ BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
+ "UnInhibit");
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT32, &cookie,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
+ if (dbus_error_is_set(&error)) {
+ dbus_connection_unref(bus);
+ unsupported = true;
+ return;
+ }
+
+ print_verbose("FreeDesktopScreenSaver: Released screensaver inhibition cookie: " + uitos(cookie));
+
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+ dbus_connection_unref(bus);
+}
+
+#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/freedesktop_screensaver.h b/platform/linuxbsd/freedesktop_screensaver.h
new file mode 100644
index 0000000000..f27e60fce4
--- /dev/null
+++ b/platform/linuxbsd/freedesktop_screensaver.h
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* freedesktop_screensaver.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef DBUS_ENABLED
+
+#include <dbus/dbus.h>
+#include <stdint.h>
+
+class FreeDesktopScreenSaver {
+private:
+ uint32_t cookie = 0;
+ bool unsupported = false;
+
+public:
+ FreeDesktopScreenSaver() {}
+ void inhibit();
+ void uninhibit();
+};
+
+#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index c6a2fa5be7..8cd6ec43c6 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -425,7 +425,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Generates the .trashinfo file
OS::Date date = OS::get_singleton()->get_date(false);
OS::Time time = OS::get_singleton()->get_time(false);
- String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, date.month, date.day, time.hour, time.minute);
+ String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.minute);
timestamp = vformat("%s%02d", timestamp, time.second); // vformat only supports up to 6 arguments.
String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
diff --git a/platform/linuxbsd/vulkan_context_x11.cpp b/platform/linuxbsd/vulkan_context_x11.cpp
index 021db630e0..88cb00a8a1 100644
--- a/platform/linuxbsd/vulkan_context_x11.cpp
+++ b/platform/linuxbsd/vulkan_context_x11.cpp
@@ -35,7 +35,7 @@ const char *VulkanContextX11::_get_platform_surface_extension() const {
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height) {
+Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height) {
VkXlibSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
@@ -46,7 +46,7 @@ Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, ::Win
VkSurfaceKHR surface;
VkResult err = vkCreateXlibSurfaceKHR(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
- return _window_create(p_window_id, surface, p_width, p_height);
+ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextX11::VulkanContextX11() {
diff --git a/platform/linuxbsd/vulkan_context_x11.h b/platform/linuxbsd/vulkan_context_x11.h
index 26472444ad..de4a9c7b90 100644
--- a/platform/linuxbsd/vulkan_context_x11.h
+++ b/platform/linuxbsd/vulkan_context_x11.h
@@ -38,7 +38,7 @@ class VulkanContextX11 : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
- Error window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height);
+ Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height);
VulkanContextX11();
~VulkanContextX11();
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index 5f7f5f84a2..c7b9e411b8 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -145,7 +145,7 @@ public:
WindowID window_id_counter = MAIN_WINDOW_ID;
- WindowID _create_window(WindowMode p_mode, const Rect2i &p_rect);
+ WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect);
void _update_window(WindowData p_wd);
void _send_window_event(const WindowData &wd, WindowEvent p_event);
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
@@ -232,7 +232,7 @@ public:
virtual Vector<int> get_window_list() const override;
- virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override;
@@ -286,6 +286,9 @@ public:
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
+
virtual Point2i ime_get_selection() const override;
virtual String ime_get_text() const override;
@@ -314,12 +317,12 @@ public:
virtual void console_set_visible(bool p_enabled) override;
virtual bool is_console_visible() const override;
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_osx_driver();
- DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerOSX();
};
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 4a672a4b17..dec6da42fe 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -2388,10 +2388,10 @@ Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const {
return ret;
}
-DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
- WindowID id = _create_window(p_mode, p_rect);
+ WindowID id = _create_window(p_mode, p_vsync_mode, p_rect);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id);
@@ -3546,6 +3546,22 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
[nsimg release];
}
+void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
+}
+
+DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
+}
+
Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
Vector<String> drivers;
@@ -3596,15 +3612,15 @@ ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) co
return windows[p_window].instance_id;
}
-DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver");
}
return ds;
}
-DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, const Rect2i &p_rect) {
+DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) {
WindowID id;
const float scale = screen_get_max_scale();
{
@@ -3651,7 +3667,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
if (context_vulkan) {
- Error err = context_vulkan->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
+ Error err = context_vulkan->window_create(window_id_counter, p_vsync_mode, wd.window_view, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan context");
}
}
@@ -3750,7 +3766,7 @@ bool DisplayServerOSX::is_console_visible() const {
return isatty(STDIN_FILENO);
}
-DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
@@ -3886,7 +3902,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
Point2i window_position(
screen_get_position(0).x + (screen_get_size(0).width - p_resolution.width) / 2,
screen_get_position(0).y + (screen_get_size(0).height - p_resolution.height) / 2);
- WindowID main_window = _create_window(p_mode, Rect2i(window_position, p_resolution));
+ WindowID main_window = _create_window(p_mode, p_vsync_mode, Rect2i(window_position, p_resolution));
ERR_FAIL_COND(main_window == INVALID_WINDOW_ID);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index f68ff32012..ea34b8a24e 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -163,9 +163,13 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/replace_existing_signature"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false));
+ if (!Engine::get_singleton()->has_singleton("GodotSharp")) {
+ // These entitlements are required to run managed code, and are always enabled in Mono builds.
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false));
+ }
+
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/disable_library_validation"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/audio_input"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/camera"), false));
@@ -786,18 +790,29 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
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\">");
ent_f->store_line("<dict>");
- if ((bool)p_preset->get("codesign/entitlements/allow_jit_code_execution")) {
+ if (Engine::get_singleton()->has_singleton("GodotSharp")) {
+ // These entitlements are required to run managed code, and are always enabled in Mono builds.
ent_f->store_line("<key>com.apple.security.cs.allow-jit</key>");
ent_f->store_line("<true/>");
- }
- if ((bool)p_preset->get("codesign/entitlements/allow_unsigned_executable_memory")) {
ent_f->store_line("<key>com.apple.security.cs.allow-unsigned-executable-memory</key>");
ent_f->store_line("<true/>");
- }
- if ((bool)p_preset->get("codesign/entitlements/allow_dyld_environment_variables")) {
ent_f->store_line("<key>com.apple.security.cs.allow-dyld-environment-variables</key>");
ent_f->store_line("<true/>");
+ } else {
+ if ((bool)p_preset->get("codesign/entitlements/allow_jit_code_execution")) {
+ ent_f->store_line("<key>com.apple.security.cs.allow-jit</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/allow_unsigned_executable_memory")) {
+ ent_f->store_line("<key>com.apple.security.cs.allow-unsigned-executable-memory</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/allow_dyld_environment_variables")) {
+ ent_f->store_line("<key>com.apple.security.cs.allow-dyld-environment-variables</key>");
+ ent_f->store_line("<true/>");
+ }
}
+
if ((bool)p_preset->get("codesign/entitlements/disable_library_validation")) {
ent_f->store_line("<key>com.apple.security.cs.disable-library-validation</key>");
ent_f->store_line("<true/>");
diff --git a/platform/osx/vulkan_context_osx.h b/platform/osx/vulkan_context_osx.h
index 8b6a75adfb..22d43688a3 100644
--- a/platform/osx/vulkan_context_osx.h
+++ b/platform/osx/vulkan_context_osx.h
@@ -38,7 +38,7 @@ class VulkanContextOSX : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
- Error window_create(DisplayServer::WindowID p_window_id, id p_window, int p_width, int p_height);
+ Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height);
VulkanContextOSX();
~VulkanContextOSX();
diff --git a/platform/osx/vulkan_context_osx.mm b/platform/osx/vulkan_context_osx.mm
index 6b87fbd489..7e18e177c1 100644
--- a/platform/osx/vulkan_context_osx.mm
+++ b/platform/osx/vulkan_context_osx.mm
@@ -35,7 +35,7 @@ const char *VulkanContextOSX::_get_platform_surface_extension() const {
return VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, id p_window, int p_width, int p_height) {
+Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height) {
VkMacOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = nullptr;
@@ -45,7 +45,7 @@ Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, id p_
VkSurfaceKHR surface;
VkResult err = vkCreateMacOSSurfaceMVK(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
- return _window_create(p_window_id, surface, p_width, p_height);
+ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextOSX::VulkanContextOSX() {
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 1075ae38ce..98925fd7fa 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -31,7 +31,6 @@
#include "export.h"
#include "core/config/project_settings.h"
-#include "core/core_bind.h"
#include "core/crypto/crypto_core.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
diff --git a/platform/windows/context_gl_windows.cpp b/platform/windows/context_gl_windows.cpp
index 7cf9738f13..74b12cbb3b 100644
--- a/platform/windows/context_gl_windows.cpp
+++ b/platform/windows/context_gl_windows.cpp
@@ -66,46 +66,13 @@ int ContextGL_Windows::get_window_height() {
return OS::get_singleton()->get_video_mode().height;
}
-bool ContextGL_Windows::should_vsync_via_compositor() {
- if (OS::get_singleton()->is_window_fullscreen() || !OS::get_singleton()->is_vsync_via_compositor_enabled()) {
- return false;
- }
-
- // Note: All Windows versions supported by Godot have a compositor.
- // It can be disabled on earlier Windows versions.
- BOOL dwm_enabled;
-
- if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled))) {
- return dwm_enabled;
- }
-
- return false;
-}
-
void ContextGL_Windows::swap_buffers() {
SwapBuffers(hDC);
-
- if (use_vsync) {
- bool vsync_via_compositor_now = should_vsync_via_compositor();
-
- if (vsync_via_compositor_now && wglGetSwapIntervalEXT() == 0) {
- DwmFlush();
- }
-
- if (vsync_via_compositor_now != vsync_via_compositor) {
- // The previous frame had a different operating mode than this
- // frame. Set the 'vsync_via_compositor' member variable and the
- // OpenGL swap interval to their proper values.
- set_use_vsync(true);
- }
- }
}
void ContextGL_Windows::set_use_vsync(bool p_use) {
- vsync_via_compositor = p_use && should_vsync_via_compositor();
-
if (wglSwapIntervalEXT) {
- int swap_interval = (p_use && !vsync_via_compositor) ? 1 : 0;
+ int swap_interval = p_use ? 1 : 0;
wglSwapIntervalEXT(swap_interval);
}
@@ -210,7 +177,6 @@ ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) {
opengl_3_context = p_opengl_3_context;
hWnd = hwnd;
use_vsync = false;
- vsync_via_compositor = false;
pixel_format = 0;
}
diff --git a/platform/windows/context_gl_windows.h b/platform/windows/context_gl_windows.h
index e44e2945ca..c8e8a0891d 100644
--- a/platform/windows/context_gl_windows.h
+++ b/platform/windows/context_gl_windows.h
@@ -50,13 +50,10 @@ class ContextGL_Windows {
HWND hWnd;
bool opengl_3_context;
bool use_vsync;
- bool vsync_via_compositor;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
- static bool should_vsync_via_compositor();
-
public:
void release_current();
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index f7172598ec..4f64809abc 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -477,10 +477,10 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
return INVALID_WINDOW_ID;
}
-DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
- WindowID window_id = _create_window(p_mode, p_flags, p_rect);
+ WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window.");
WindowData &wd = windows[window_id];
@@ -1697,11 +1697,20 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon);
}
-void DisplayServerWindows::vsync_set_use_via_compositor(bool p_enable) {
+void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
}
-bool DisplayServerWindows::vsync_is_using_via_compositor() const {
- return false;
+DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
}
void DisplayServerWindows::set_context(Context p_context) {
@@ -2968,7 +2977,7 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
}
}
-DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
DWORD dwExStyle;
DWORD dwStyle;
@@ -3030,7 +3039,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
#ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") {
- if (context_vulkan->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) {
+ if (context_vulkan->window_create(id, p_vsync_mode, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) {
memdelete(context_vulkan);
context_vulkan = nullptr;
windows.erase(id);
@@ -3151,7 +3160,7 @@ void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) {
}
}
-DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
drop_events = false;
key_event_pos = 0;
@@ -3270,7 +3279,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
context_gles2->set_use_vsync(video_mode.use_vsync);
- set_vsync_via_compositor(video_mode.vsync_via_compositor);
if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config();
@@ -3286,7 +3294,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
(screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2);
- WindowID main_window = _create_window(p_mode, 0, Rect2i(window_position, p_resolution));
+ WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution));
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
@@ -3347,8 +3355,8 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
return drivers;
}
-DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
"Please update your drivers or if you have a very old or integrated GPU upgrade it.",
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index d71e579c67..aa1d42d6ed 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -389,7 +389,7 @@ class DisplayServerWindows : public DisplayServer {
JoypadWindows *joypad;
- WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect);
+ WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
WindowID window_id_counter = MAIN_WINDOW_ID;
Map<WindowID, WindowData> windows;
@@ -439,135 +439,135 @@ class DisplayServerWindows : public DisplayServer {
public:
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- virtual bool has_feature(Feature p_feature) const;
- virtual String get_name() const;
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
- virtual void mouse_set_mode(MouseMode p_mode);
- virtual MouseMode mouse_get_mode() const;
+ virtual void mouse_set_mode(MouseMode p_mode) override;
+ virtual MouseMode mouse_get_mode() const override;
- virtual void mouse_warp_to_position(const Point2i &p_to);
- virtual Point2i mouse_get_position() const;
- virtual MouseButton mouse_get_button_state() const;
+ virtual void mouse_warp_to_position(const Point2i &p_to) override;
+ virtual Point2i mouse_get_position() const override;
+ virtual MouseButton mouse_get_button_state() const override;
- virtual void clipboard_set(const String &p_text);
- virtual String clipboard_get() const;
+ virtual void clipboard_set(const String &p_text) override;
+ virtual String clipboard_get() const override;
- virtual int get_screen_count() const;
- virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual int get_screen_count() const override;
+ virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW);
+ virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override;
ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual void screen_set_keep_on(bool p_enable); //disable screensaver
- virtual bool screen_is_kept_on() const;
+ virtual void screen_set_keep_on(bool p_enable) override; //disable screensaver
+ virtual bool screen_is_kept_on() const override;
- virtual Vector<DisplayServer::WindowID> get_window_list() const;
+ virtual Vector<DisplayServer::WindowID> get_window_list() const override;
- virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
- virtual void show_window(WindowID p_window);
- virtual void delete_sub_window(WindowID p_window);
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual void show_window(WindowID p_window) override;
+ virtual void delete_sub_window(WindowID p_window) override;
- virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
- virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
- virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
+ virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
+ virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_transient(WindowID p_window, WindowID p_parent);
+ virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
- virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const; //wtf is this? should probable use proper name
+ virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override; //wtf is this? should probable use proper name
- virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
- virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
- virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
- virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool can_any_window_draw() const;
+ virtual bool can_any_window_draw() const override;
- virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void console_set_visible(bool p_enabled);
- virtual bool is_console_visible() const;
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
- virtual void cursor_set_shape(CursorShape p_shape);
- virtual CursorShape cursor_get_shape() const;
- virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
+ virtual void console_set_visible(bool p_enabled) override;
+ virtual bool is_console_visible() const override;
- virtual bool get_swap_cancel_ok();
+ virtual void cursor_set_shape(CursorShape p_shape) override;
+ virtual CursorShape cursor_get_shape() const override;
+ virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
- virtual void enable_for_stealing_focus(OS::ProcessID pid);
+ virtual bool get_swap_cancel_ok() override;
- virtual int keyboard_get_layout_count() const;
- virtual int keyboard_get_current_layout() const;
- virtual void keyboard_set_current_layout(int p_index);
- virtual String keyboard_get_layout_language(int p_index) const;
- virtual String keyboard_get_layout_name(int p_index) const;
+ virtual void enable_for_stealing_focus(OS::ProcessID pid) override;
- virtual int tablet_get_driver_count() const;
- virtual String tablet_get_driver_name(int p_driver) const;
- virtual String tablet_get_current_driver() const;
- virtual void tablet_set_current_driver(const String &p_driver);
+ virtual int keyboard_get_layout_count() const override;
+ virtual int keyboard_get_current_layout() const override;
+ virtual void keyboard_set_current_layout(int p_index) override;
+ virtual String keyboard_get_layout_language(int p_index) const override;
+ virtual String keyboard_get_layout_name(int p_index) const override;
- virtual void process_events();
+ virtual int tablet_get_driver_count() const override;
+ virtual String tablet_get_driver_name(int p_driver) const override;
+ virtual String tablet_get_current_driver() const override;
+ virtual void tablet_set_current_driver(const String &p_driver) override;
- virtual void force_process_and_drop_events();
+ virtual void process_events() override;
- virtual void release_rendering_thread();
- virtual void make_rendering_thread();
- virtual void swap_buffers();
+ virtual void force_process_and_drop_events() override;
- virtual void set_native_icon(const String &p_filename);
- virtual void set_icon(const Ref<Image> &p_icon);
+ virtual void release_rendering_thread() override;
+ virtual void make_rendering_thread() override;
+ virtual void swap_buffers() override;
- virtual void vsync_set_use_via_compositor(bool p_enable);
- virtual bool vsync_is_using_via_compositor() const;
+ virtual void set_native_icon(const String &p_filename) override;
+ virtual void set_icon(const Ref<Image> &p_icon) override;
- virtual void set_context(Context p_context);
+ virtual void set_context(Context p_context) override;
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_windows_driver();
- DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerWindows();
};
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 03093ab6dd..10f953f2ec 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -310,7 +310,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
args.push_back(p_path);
#ifndef WINDOWS_ENABLED
args.push_back("-out");
- args.push_back(p_path);
+ args.push_back(p_path + "_signed");
#endif
String str;
@@ -326,6 +326,16 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
return FAILED;
}
+#ifndef WINDOWS_ENABLED
+ DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
+
+ err = tmp_dir->remove(p_path);
+ ERR_FAIL_COND_V(err != OK, err);
+
+ err = tmp_dir->rename(p_path + "_signed", p_path);
+ ERR_FAIL_COND_V(err != OK, err);
+#endif
+
return OK;
}
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index c956fe49ae..56d673afc3 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -634,13 +634,13 @@ String OS_Windows::get_config_path() const {
// The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
if (has_environment("XDG_CONFIG_HOME")) {
if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
- return get_environment("XDG_CONFIG_HOME");
+ return get_environment("XDG_CONFIG_HOME").replace("\\", "/");
} else {
WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `%APPDATA%` or `.` per the XDG Base Directory specification.");
}
}
if (has_environment("APPDATA")) {
- return get_environment("APPDATA");
+ return get_environment("APPDATA").replace("\\", "/");
}
return ".";
}
@@ -649,7 +649,7 @@ String OS_Windows::get_data_path() const {
// The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
if (has_environment("XDG_DATA_HOME")) {
if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
- return get_environment("XDG_DATA_HOME");
+ return get_environment("XDG_DATA_HOME").replace("\\", "/");
} else {
WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
}
@@ -661,13 +661,13 @@ String OS_Windows::get_cache_path() const {
// The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
if (has_environment("XDG_CACHE_HOME")) {
if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
- return get_environment("XDG_CACHE_HOME");
+ return get_environment("XDG_CACHE_HOME").replace("\\", "/");
} else {
WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%TEMP%` or `get_config_path()` per the XDG Base Directory specification.");
}
}
if (has_environment("TEMP")) {
- return get_environment("TEMP");
+ return get_environment("TEMP").replace("\\", "/");
}
return get_config_path();
}
@@ -710,7 +710,7 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const {
PWSTR szPath;
HRESULT res = SHGetKnownFolderPath(id, 0, nullptr, &szPath);
ERR_FAIL_COND_V(res != S_OK, String());
- String path = String::utf16((const char16_t *)szPath);
+ String path = String::utf16((const char16_t *)szPath).replace("\\", "/");
CoTaskMemFree(szPath);
return path;
}
diff --git a/platform/windows/vulkan_context_win.cpp b/platform/windows/vulkan_context_win.cpp
index e5e176ab93..191792b329 100644
--- a/platform/windows/vulkan_context_win.cpp
+++ b/platform/windows/vulkan_context_win.cpp
@@ -35,18 +35,17 @@ const char *VulkanContextWindows::_get_platform_surface_extension() const {
return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
}
-int VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height) {
+int VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, HWND p_window, HINSTANCE p_instance, int p_width, int p_height) {
VkWin32SurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.hinstance = p_instance;
createInfo.hwnd = p_window;
-
VkSurfaceKHR surface;
VkResult err = vkCreateWin32SurfaceKHR(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, -1);
- return _window_create(p_window_id, surface, p_width, p_height);
+ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextWindows::VulkanContextWindows() {
diff --git a/platform/windows/vulkan_context_win.h b/platform/windows/vulkan_context_win.h
index 4fe987218d..39dd2641fd 100644
--- a/platform/windows/vulkan_context_win.h
+++ b/platform/windows/vulkan_context_win.h
@@ -38,7 +38,7 @@ class VulkanContextWindows : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
- int window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height);
+ int window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, HWND p_window, HINSTANCE p_instance, int p_width, int p_height);
VulkanContextWindows();
~VulkanContextWindows();
diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp
index c1f3827d15..8cab7ca521 100644
--- a/platform/windows/windows_terminal_logger.cpp
+++ b/platform/windows/windows_terminal_logger.cpp
@@ -108,47 +108,47 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR:
- logf("ERROR:");
+ logf_error("ERROR:");
break;
case ERR_WARNING:
- logf("WARNING:");
+ logf_error("WARNING:");
break;
case ERR_SCRIPT:
- logf("SCRIPT ERROR:");
+ logf_error("SCRIPT ERROR:");
break;
case ERR_SHADER:
- logf("SHADER ERROR:");
+ logf_error("SHADER ERROR:");
break;
}
SetConsoleTextAttribute(hCon, basecol);
if (p_rationale && p_rationale[0]) {
- logf(" %s\n", p_rationale);
+ logf_error(" %s\n", p_rationale);
} else {
- logf(" %s\n", p_code);
+ logf_error(" %s\n", p_code);
}
// `FOREGROUND_INTENSITY` alone results in gray text.
SetConsoleTextAttribute(hCon, FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR:
- logf(" at: ");
+ logf_error(" at: ");
break;
case ERR_WARNING:
- logf(" at: ");
+ logf_error(" at: ");
break;
case ERR_SCRIPT:
- logf(" at: ");
+ logf_error(" at: ");
break;
case ERR_SHADER:
- logf(" at: ");
+ logf_error(" at: ");
break;
}
if (p_rationale && p_rationale[0]) {
- logf("(%s:%i)\n", p_file, p_line);
+ logf_error("(%s:%i)\n", p_file, p_line);
} else {
- logf("%s (%s:%i)\n", p_function, p_file, p_line);
+ logf_error("%s (%s:%i)\n", p_function, p_file, p_line);
}
SetConsoleTextAttribute(hCon, sbi.wAttributes);
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 597693aa6a..cf84767151 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -551,7 +551,7 @@ void Area2D::_bind_methods() {
ADD_GROUP("Physics Overrides", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_distance_scale", "get_gravity_distance_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_vec"), "set_gravity_vector", "get_gravity_vector");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-4096,4096,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 127ef6762d..4b96689613 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -255,7 +255,7 @@ void AudioStreamPlayer2D::_notification(int p_what) {
//stop playing if no longer active
if (!active.is_set()) {
set_physics_process_internal(false);
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
}
}
}
@@ -494,7 +494,7 @@ void AudioStreamPlayer2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_EXP_RANGE, "1,4096,1,or_greater"), "set_max_distance", "get_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "1,4096,1,or_greater,exp"), "set_max_distance", "get_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_attenuation", "get_attenuation");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask");
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 926997a715..0e55915957 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -178,20 +178,23 @@ Transform2D Camera2D::get_camera_transform() {
}
Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom);
- if (screen_rect.position.x < limit[SIDE_LEFT]) {
- screen_rect.position.x = limit[SIDE_LEFT];
- }
- if (screen_rect.position.x + screen_rect.size.x > limit[SIDE_RIGHT]) {
- screen_rect.position.x = limit[SIDE_RIGHT] - screen_rect.size.x;
- }
+ if (!limit_smoothing_enabled) {
+ if (screen_rect.position.x < limit[SIDE_LEFT]) {
+ screen_rect.position.x = limit[SIDE_LEFT];
+ }
- if (screen_rect.position.y + screen_rect.size.y > limit[SIDE_BOTTOM]) {
- screen_rect.position.y = limit[SIDE_BOTTOM] - screen_rect.size.y;
- }
+ if (screen_rect.position.x + screen_rect.size.x > limit[SIDE_RIGHT]) {
+ screen_rect.position.x = limit[SIDE_RIGHT] - screen_rect.size.x;
+ }
+
+ if (screen_rect.position.y + screen_rect.size.y > limit[SIDE_BOTTOM]) {
+ screen_rect.position.y = limit[SIDE_BOTTOM] - screen_rect.size.y;
+ }
- if (screen_rect.position.y < limit[SIDE_TOP]) {
- screen_rect.position.y = limit[SIDE_TOP];
+ if (screen_rect.position.y < limit[SIDE_TOP]) {
+ screen_rect.position.y = limit[SIDE_TOP];
+ }
}
if (offset != Vector2()) {
@@ -238,6 +241,10 @@ void Camera2D::_notification(int p_what) {
viewport = get_viewport();
}
+ if (is_current()) {
+ viewport->_camera_2d_set(this);
+ }
+
canvas = get_canvas();
RID vp = viewport->get_viewport_rid();
@@ -256,6 +263,7 @@ void Camera2D::_notification(int p_what) {
if (is_current()) {
if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) {
viewport->set_canvas_transform(Transform2D());
+ clear_current();
}
}
remove_from_group(group_name);
@@ -389,18 +397,29 @@ Camera2D::Camera2DProcessCallback Camera2D::get_process_callback() const {
void Camera2D::_make_current(Object *p_which) {
if (p_which == this) {
current = true;
+ if (is_inside_tree()) {
+ get_viewport()->_camera_2d_set(this);
+ update();
+ }
} else {
current = false;
+ if (is_inside_tree()) {
+ if (get_viewport()->get_camera_2d() == this) {
+ get_viewport()->_camera_2d_set(nullptr);
+ }
+ update();
+ }
}
}
-void Camera2D::_set_current(bool p_current) {
+void Camera2D::set_current(bool p_current) {
if (p_current) {
make_current();
+ } else {
+ if (current) {
+ clear_current();
+ }
}
-
- current = p_current;
- update();
}
bool Camera2D::is_current() const {
@@ -408,18 +427,19 @@ bool Camera2D::is_current() const {
}
void Camera2D::make_current() {
- if (!is_inside_tree()) {
- current = true;
- } else {
+ if (is_inside_tree()) {
get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", this);
+ } else {
+ current = true;
}
_update_scroll();
}
void Camera2D::clear_current() {
- current = false;
if (is_inside_tree()) {
get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", (Object *)nullptr);
+ } else {
+ current = false;
}
}
@@ -656,17 +676,14 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rotating", "rotating"), &Camera2D::set_rotating);
ClassDB::bind_method(D_METHOD("is_rotating"), &Camera2D::is_rotating);
- ClassDB::bind_method(D_METHOD("make_current"), &Camera2D::make_current);
- ClassDB::bind_method(D_METHOD("clear_current"), &Camera2D::clear_current);
- ClassDB::bind_method(D_METHOD("_make_current"), &Camera2D::_make_current);
-
ClassDB::bind_method(D_METHOD("_update_scroll"), &Camera2D::_update_scroll);
ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &Camera2D::set_process_callback);
ClassDB::bind_method(D_METHOD("get_process_callback"), &Camera2D::get_process_callback);
- ClassDB::bind_method(D_METHOD("_set_current", "current"), &Camera2D::_set_current);
+ ClassDB::bind_method(D_METHOD("set_current", "current"), &Camera2D::set_current);
ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current);
+ ClassDB::bind_method(D_METHOD("_make_current"), &Camera2D::_make_current);
ClassDB::bind_method(D_METHOD("set_limit", "margin", "limit"), &Camera2D::set_limit);
ClassDB::bind_method(D_METHOD("get_limit", "margin"), &Camera2D::get_limit);
@@ -722,7 +739,7 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotating"), "set_rotating", "is_rotating");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "_set_current", "is_current");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom"), "set_zoom", "get_zoom");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 7494e526cc..95b49cf076 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -83,7 +83,7 @@ protected:
void _update_scroll();
void _make_current(Object *p_which);
- void _set_current(bool p_current);
+ void set_current(bool p_current);
void _set_old_smoothing(real_t p_enable);
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index a633923be7..3ba3a4eec5 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -31,7 +31,6 @@
#include "collision_object_2d.h"
#include "scene/scene_string_names.h"
-#include "servers/physics_server_2d.h"
void CollisionObject2D::_notification(int p_what) {
switch (p_what) {
@@ -44,16 +43,22 @@ void CollisionObject2D::_notification(int p_what) {
PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform);
}
- RID space = get_world_2d()->get_space();
- if (area) {
- PhysicsServer2D::get_singleton()->area_set_space(rid, space);
- } else {
- PhysicsServer2D::get_singleton()->body_set_space(rid, space);
+ bool disabled = !is_enabled();
+
+ if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
+ _apply_disabled();
}
- _update_pickable();
+ if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
+ RID space = get_world_2d()->get_space();
+ if (area) {
+ PhysicsServer2D::get_singleton()->area_set_space(rid, space);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_space(rid, space);
+ }
+ }
- //get space
+ _update_pickable();
} break;
case NOTIFICATION_ENTER_CANVAS: {
@@ -67,6 +72,7 @@ void CollisionObject2D::_notification(int p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
} break;
+
case NOTIFICATION_TRANSFORM_CHANGED: {
if (only_update_transform_changes) {
return;
@@ -79,15 +85,22 @@ void CollisionObject2D::_notification(int p_what) {
} else {
PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform);
}
-
} break;
+
case NOTIFICATION_EXIT_TREE: {
- if (area) {
- PhysicsServer2D::get_singleton()->area_set_space(rid, RID());
- } else {
- PhysicsServer2D::get_singleton()->body_set_space(rid, RID());
+ bool disabled = !is_enabled();
+
+ if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
+ if (area) {
+ PhysicsServer2D::get_singleton()->area_set_space(rid, RID());
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_space(rid, RID());
+ }
}
+ if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
+ _apply_enabled();
+ }
} break;
case NOTIFICATION_EXIT_CANVAS: {
@@ -97,6 +110,14 @@ void CollisionObject2D::_notification(int p_what) {
PhysicsServer2D::get_singleton()->body_attach_canvas_instance_id(rid, ObjectID());
}
} break;
+
+ case NOTIFICATION_DISABLED: {
+ _apply_disabled();
+ } break;
+
+ case NOTIFICATION_ENABLED: {
+ _apply_enabled();
+ } break;
}
}
@@ -158,6 +179,79 @@ bool CollisionObject2D::get_collision_mask_bit(int p_bit) const {
return get_collision_mask() & (1 << p_bit);
}
+void CollisionObject2D::set_disable_mode(DisableMode p_mode) {
+ if (disable_mode == p_mode) {
+ return;
+ }
+
+ bool disabled = is_inside_tree() && !is_enabled();
+
+ if (disabled) {
+ // Cancel previous disable mode.
+ _apply_enabled();
+ }
+
+ disable_mode = p_mode;
+
+ if (disabled) {
+ // Apply new disable mode.
+ _apply_disabled();
+ }
+}
+
+CollisionObject2D::DisableMode CollisionObject2D::get_disable_mode() const {
+ return disable_mode;
+}
+
+void CollisionObject2D::_apply_disabled() {
+ switch (disable_mode) {
+ case DISABLE_MODE_REMOVE: {
+ if (is_inside_tree()) {
+ if (area) {
+ PhysicsServer2D::get_singleton()->area_set_space(rid, RID());
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_space(rid, RID());
+ }
+ }
+ } break;
+
+ case DISABLE_MODE_MAKE_STATIC: {
+ if (!area && (body_mode != PhysicsServer2D::BODY_MODE_STATIC)) {
+ PhysicsServer2D::get_singleton()->body_set_mode(rid, PhysicsServer2D::BODY_MODE_STATIC);
+ }
+ } break;
+
+ case DISABLE_MODE_KEEP_ACTIVE: {
+ // Nothing to do.
+ } break;
+ }
+}
+
+void CollisionObject2D::_apply_enabled() {
+ switch (disable_mode) {
+ case DISABLE_MODE_REMOVE: {
+ if (is_inside_tree()) {
+ RID space = get_world_2d()->get_space();
+ if (area) {
+ PhysicsServer2D::get_singleton()->area_set_space(rid, space);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_space(rid, space);
+ }
+ }
+ } break;
+
+ case DISABLE_MODE_MAKE_STATIC: {
+ if (!area && (body_mode != PhysicsServer2D::BODY_MODE_STATIC)) {
+ PhysicsServer2D::get_singleton()->body_set_mode(rid, body_mode);
+ }
+ } break;
+
+ case DISABLE_MODE_KEEP_ACTIVE: {
+ // Nothing to do.
+ } break;
+ }
+}
+
uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) {
ShapeData sd;
uint32_t id;
@@ -404,6 +498,20 @@ void CollisionObject2D::_mouse_exit() {
emit_signal(SceneStringNames::get_singleton()->mouse_exited);
}
+void CollisionObject2D::_mouse_shape_enter(int p_shape) {
+ if (get_script_instance()) {
+ get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_shape_enter, p_shape);
+ }
+ emit_signal(SceneStringNames::get_singleton()->mouse_shape_entered, p_shape);
+}
+
+void CollisionObject2D::_mouse_shape_exit(int p_shape) {
+ if (get_script_instance()) {
+ get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_shape_exit, p_shape);
+ }
+ emit_signal(SceneStringNames::get_singleton()->mouse_shape_exited, p_shape);
+}
+
void CollisionObject2D::set_only_update_transform_changes(bool p_enable) {
only_update_transform_changes = p_enable;
}
@@ -412,6 +520,22 @@ bool CollisionObject2D::is_only_update_transform_changes_enabled() const {
return only_update_transform_changes;
}
+void CollisionObject2D::set_body_mode(PhysicsServer2D::BodyMode p_mode) {
+ ERR_FAIL_COND(area);
+
+ if (body_mode == p_mode) {
+ return;
+ }
+
+ body_mode = p_mode;
+
+ if (is_inside_tree() && !is_enabled() && (disable_mode == DISABLE_MODE_MAKE_STATIC)) {
+ return;
+ }
+
+ PhysicsServer2D::get_singleton()->body_set_mode(rid, p_mode);
+}
+
void CollisionObject2D::_update_pickable() {
if (!is_inside_tree()) {
return;
@@ -445,6 +569,8 @@ void CollisionObject2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject2D::get_collision_layer_bit);
ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject2D::set_collision_mask_bit);
ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject2D::get_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &CollisionObject2D::set_disable_mode);
+ ClassDB::bind_method(D_METHOD("get_disable_mode"), &CollisionObject2D::get_disable_mode);
ClassDB::bind_method(D_METHOD("set_pickable", "enabled"), &CollisionObject2D::set_pickable);
ClassDB::bind_method(D_METHOD("is_pickable"), &CollisionObject2D::is_pickable);
ClassDB::bind_method(D_METHOD("create_shape_owner", "owner"), &CollisionObject2D::create_shape_owner);
@@ -472,6 +598,10 @@ void CollisionObject2D::_bind_methods() {
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "viewport", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx")));
ADD_SIGNAL(MethodInfo("mouse_entered"));
ADD_SIGNAL(MethodInfo("mouse_exited"));
+ ADD_SIGNAL(MethodInfo("mouse_shape_entered", PropertyInfo(Variant::INT, "shape_idx")));
+ ADD_SIGNAL(MethodInfo("mouse_shape_exited", PropertyInfo(Variant::INT, "shape_idx")));
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode");
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer");
@@ -479,6 +609,10 @@ void CollisionObject2D::_bind_methods() {
ADD_GROUP("Input", "input_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_pickable"), "set_pickable", "is_pickable");
+
+ BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE);
+ BIND_ENUM_CONSTANT(DISABLE_MODE_MAKE_STATIC);
+ BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE);
}
CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
@@ -493,6 +627,7 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
PhysicsServer2D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id());
} else {
PhysicsServer2D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id());
+ PhysicsServer2D::get_singleton()->body_set_mode(rid, body_mode);
}
}
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index e10f3097d9..eca53eecfc 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -33,10 +33,19 @@
#include "scene/2d/node_2d.h"
#include "scene/resources/shape_2d.h"
+#include "servers/physics_server_2d.h"
class CollisionObject2D : public Node2D {
GDCLASS(CollisionObject2D, Node2D);
+public:
+ enum DisableMode {
+ DISABLE_MODE_REMOVE,
+ DISABLE_MODE_MAKE_STATIC,
+ DISABLE_MODE_KEEP_ACTIVE,
+ };
+
+private:
uint32_t collision_layer = 1;
uint32_t collision_mask = 1;
@@ -44,6 +53,10 @@ class CollisionObject2D : public Node2D {
RID rid;
bool pickable = false;
+ DisableMode disable_mode = DISABLE_MODE_REMOVE;
+
+ PhysicsServer2D::BodyMode body_mode = PhysicsServer2D::BODY_MODE_STATIC;
+
struct ShapeData {
Object *owner = nullptr;
Transform2D xform;
@@ -62,7 +75,10 @@ class CollisionObject2D : public Node2D {
int total_subshapes = 0;
Map<uint32_t, ShapeData> shapes;
- bool only_update_transform_changes = false; //this is used for sync physics in CharacterBody2D
+ bool only_update_transform_changes = false; // This is used for sync to physics.
+
+ void _apply_disabled();
+ void _apply_enabled();
protected:
CollisionObject2D(RID p_rid, bool p_area);
@@ -76,9 +92,14 @@ protected:
void _mouse_enter();
void _mouse_exit();
+ void _mouse_shape_enter(int p_shape);
+ void _mouse_shape_exit(int p_shape);
+
void set_only_update_transform_changes(bool p_enable);
bool is_only_update_transform_changes_enabled() const;
+ void set_body_mode(PhysicsServer2D::BodyMode p_mode);
+
public:
void set_collision_layer(uint32_t p_layer);
uint32_t get_collision_layer() const;
@@ -92,6 +113,9 @@ public:
void set_collision_mask_bit(int p_bit, bool p_value);
bool get_collision_mask_bit(int p_bit) const;
+ void set_disable_mode(DisableMode p_mode);
+ DisableMode get_disable_mode() const;
+
uint32_t create_shape_owner(Object *p_owner);
void remove_shape_owner(uint32_t owner);
void get_shape_owners(List<uint32_t> *r_owners);
@@ -131,4 +155,6 @@ public:
~CollisionObject2D();
};
+VARIANT_ENUM_CAST(CollisionObject2D::DisableMode);
+
#endif // COLLISION_OBJECT_2D_H
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index 1578643d14..a341ba69ac 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -463,32 +463,28 @@ Vector2 CPUParticles2D::get_gravity() const {
}
void CPUParticles2D::_validate_property(PropertyInfo &property) const {
- if (property.name == "color" && color_ramp.is_valid()) {
- property.usage = 0;
- }
-
if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_rect_extents" && emission_shape != EMISSION_SHAPE_RECTANGLE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_normals" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_points" && emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_colors" && emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -1202,7 +1198,7 @@ void CPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("restart"), &CPUParticles2D::restart);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
@@ -1313,7 +1309,7 @@ void CPUParticles2D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING);
ADD_GROUP("Angle", "");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater,degrees"), "set_param", "get_param", PARAM_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGLE);
ADD_GROUP("Scale", "");
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index d7404ff479..adfb94d574 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -451,7 +451,7 @@ void GPUParticles2D::_notification(int p_what) {
RS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid);
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) {
+ if (Engine::get_singleton()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
draw_rect(visibility_rect, Color(0, 0.7, 0.9, 0.4), false);
}
#endif
@@ -531,7 +531,7 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_trail_section_subdivisions"), &GPUParticles2D::get_trail_section_subdivisions);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp
index 8a4ccc2f96..dbba6917b5 100644
--- a/scene/2d/joints_2d.cpp
+++ b/scene/2d/joints_2d.cpp
@@ -274,7 +274,7 @@ void PinJoint2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_softness", "softness"), &PinJoint2D::set_softness);
ClassDB::bind_method(D_METHOD("get_softness"), &PinJoint2D::get_softness);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_EXP_RANGE, "0.00,16,0.01"), "set_softness", "get_softness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_RANGE, "0.00,16,0.01,exp"), "set_softness", "get_softness");
}
PinJoint2D::PinJoint2D() {
@@ -336,8 +336,8 @@ void GrooveJoint2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_initial_offset", "offset"), &GrooveJoint2D::set_initial_offset);
ClassDB::bind_method(D_METHOD("get_initial_offset"), &GrooveJoint2D::get_initial_offset);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_EXP_RANGE, "1,65535,1"), "set_length", "get_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "initial_offset", PROPERTY_HINT_EXP_RANGE, "1,65535,1"), "set_initial_offset", "get_initial_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "1,65535,1,exp"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "initial_offset", PROPERTY_HINT_RANGE, "1,65535,1,exp"), "set_initial_offset", "get_initial_offset");
}
GrooveJoint2D::GrooveJoint2D() {
@@ -433,10 +433,10 @@ void DampedSpringJoint2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_damping", "damping"), &DampedSpringJoint2D::set_damping);
ClassDB::bind_method(D_METHOD("get_damping"), &DampedSpringJoint2D::get_damping);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_EXP_RANGE, "1,65535,1"), "set_length", "get_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rest_length", PROPERTY_HINT_EXP_RANGE, "0,65535,1"), "set_rest_length", "get_rest_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness", PROPERTY_HINT_EXP_RANGE, "0.1,64,0.1"), "set_stiffness", "get_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_EXP_RANGE, "0.01,16,0.01"), "set_damping", "get_damping");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "1,65535,1,exp"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rest_length", PROPERTY_HINT_RANGE, "0,65535,1,exp"), "set_rest_length", "get_rest_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness", PROPERTY_HINT_RANGE, "0.1,64,0.1,exp"), "set_stiffness", "get_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0.01,16,0.01,exp"), "set_damping", "get_damping");
}
DampedSpringJoint2D::DampedSpringJoint2D() {
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index f9cbdbf377..e9a95b680c 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -235,7 +235,7 @@ void NavigationAgent2D::_avoidance_done(Vector3 p_new_velocity) {
}
velocity_submitted = false;
- emit_signal("velocity_computed", velocity);
+ emit_signal(SNAME("velocity_computed"), velocity);
}
TypedArray<String> NavigationAgent2D::get_configuration_warnings() const {
@@ -287,7 +287,7 @@ void NavigationAgent2D::update_navigation() {
navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigable_layers);
navigation_finished = false;
nav_path_index = 0;
- emit_signal("path_changed");
+ emit_signal(SNAME("path_changed"));
}
if (navigation_path.size() == 0) {
@@ -303,7 +303,7 @@ void NavigationAgent2D::update_navigation() {
_check_distance_to_target();
nav_path_index -= 1;
navigation_finished = true;
- emit_signal("navigation_finished");
+ emit_signal(SNAME("navigation_finished"));
break;
}
}
@@ -313,7 +313,7 @@ void NavigationAgent2D::update_navigation() {
void NavigationAgent2D::_check_distance_to_target() {
if (!target_reached) {
if (distance_to_target() < target_desired_distance) {
- emit_signal("target_reached");
+ emit_signal(SNAME("target_reached"));
target_reached = true;
}
}
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 9d86ec88be..6fd383ddab 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -164,14 +164,6 @@ void Node2D::set_skew(real_t p_radians) {
_update_transform();
}
-void Node2D::set_rotation_degrees(real_t p_degrees) {
- set_rotation(Math::deg2rad(p_degrees));
-}
-
-void Node2D::set_skew_degrees(real_t p_degrees) {
- set_skew(Math::deg2rad(p_degrees));
-}
-
void Node2D::set_scale(const Size2 &p_scale) {
if (_xform_dirty) {
((Node2D *)this)->_update_xform_values();
@@ -210,14 +202,6 @@ real_t Node2D::get_skew() const {
return skew;
}
-real_t Node2D::get_rotation_degrees() const {
- return Math::rad2deg(get_rotation());
-}
-
-real_t Node2D::get_skew_degrees() const {
- return Math::rad2deg(get_skew());
-}
-
Size2 Node2D::get_scale() const {
if (_xform_dirty) {
((Node2D *)this)->_update_xform_values();
@@ -293,14 +277,6 @@ void Node2D::set_global_rotation(real_t p_radians) {
}
}
-real_t Node2D::get_global_rotation_degrees() const {
- return Math::rad2deg(get_global_rotation());
-}
-
-void Node2D::set_global_rotation_degrees(real_t p_degrees) {
- set_global_rotation(Math::deg2rad(p_degrees));
-}
-
Size2 Node2D::get_global_scale() const {
return get_global_transform().get_scale();
}
@@ -403,16 +379,12 @@ bool Node2D::is_y_sort_enabled() const {
void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_position", "position"), &Node2D::set_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Node2D::set_rotation);
- ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Node2D::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_skew", "radians"), &Node2D::set_skew);
- ClassDB::bind_method(D_METHOD("set_skew_degrees", "degrees"), &Node2D::set_skew_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node2D::set_scale);
ClassDB::bind_method(D_METHOD("get_position"), &Node2D::get_position);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node2D::get_rotation);
- ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node2D::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_skew"), &Node2D::get_skew);
- ClassDB::bind_method(D_METHOD("get_skew_degrees"), &Node2D::get_skew_degrees);
ClassDB::bind_method(D_METHOD("get_scale"), &Node2D::get_scale);
ClassDB::bind_method(D_METHOD("rotate", "radians"), &Node2D::rotate);
@@ -426,8 +398,6 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_global_position"), &Node2D::get_global_position);
ClassDB::bind_method(D_METHOD("set_global_rotation", "radians"), &Node2D::set_global_rotation);
ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node2D::get_global_rotation);
- ClassDB::bind_method(D_METHOD("set_global_rotation_degrees", "degrees"), &Node2D::set_global_rotation_degrees);
- ClassDB::bind_method(D_METHOD("get_global_rotation_degrees"), &Node2D::get_global_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_global_scale", "scale"), &Node2D::set_global_scale);
ClassDB::bind_method(D_METHOD("get_global_scale"), &Node2D::get_global_scale);
@@ -452,17 +422,14 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent);
ADD_GROUP("Transform", "");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_degrees", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_skew", "get_skew");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew_degrees", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1", PROPERTY_USAGE_EDITOR), "set_skew_degrees", "get_skew_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation", "get_global_rotation");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation_degrees", "get_global_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_scale", "get_global_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 339efd9179..3e66541e32 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -75,9 +75,7 @@ public:
void set_position(const Point2 &p_pos);
void set_rotation(real_t p_radians);
- void set_rotation_degrees(real_t p_degrees);
void set_skew(real_t p_radians);
- void set_skew_degrees(real_t p_radians);
void set_scale(const Size2 &p_scale);
void rotate(real_t p_radians);
@@ -90,20 +88,16 @@ public:
Point2 get_position() const;
real_t get_rotation() const;
real_t get_skew() const;
- real_t get_rotation_degrees() const;
- real_t get_skew_degrees() const;
Size2 get_scale() const;
Point2 get_global_position() const;
real_t get_global_rotation() const;
- real_t get_global_rotation_degrees() const;
Size2 get_global_scale() const;
void set_transform(const Transform2D &p_transform);
void set_global_transform(const Transform2D &p_transform);
void set_global_position(const Point2 &p_pos);
void set_global_rotation(real_t p_radians);
- void set_global_rotation_degrees(real_t p_degrees);
void set_global_scale(const Size2 &p_scale);
void set_z_index(int p_z);
diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp
index 0c1be16174..d547914e16 100644
--- a/scene/2d/physical_bone_2d.cpp
+++ b/scene/2d/physical_bone_2d.cpp
@@ -31,33 +31,37 @@
#include "physical_bone_2d.h"
void PhysicalBone2D::_notification(int p_what) {
- if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
- // Position the RigidBody in the correct position
- if (follow_bone_when_simulating) {
- _position_at_bone2d();
- }
+ switch (p_what) {
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ // Position the RigidBody in the correct position.
+ if (follow_bone_when_simulating) {
+ _position_at_bone2d();
+ }
- // Keep the child joint in the correct position.
- if (child_joint && auto_configure_joint) {
- child_joint->set_global_position(get_global_position());
- }
- } else if (p_what == NOTIFICATION_READY) {
- _find_skeleton_parent();
- _find_joint_child();
+ // Keep the child joint in the correct position.
+ if (child_joint && auto_configure_joint) {
+ child_joint->set_global_position(get_global_position());
+ }
+ } break;
- // Configure joint
- if (child_joint && auto_configure_joint) {
- _auto_configure_joint();
- }
+ case NOTIFICATION_READY: {
+ _find_skeleton_parent();
+ _find_joint_child();
- // Simulate physics if set
- if (simulate_physics) {
- _start_physics_simulation();
- } else {
- _stop_physics_simulation();
- }
+ // Configure joint.
+ if (child_joint && auto_configure_joint) {
+ _auto_configure_joint();
+ }
+
+ // Simulate physics if set.
+ if (simulate_physics) {
+ _start_physics_simulation();
+ } else {
+ _stop_physics_simulation();
+ }
- set_physics_process_internal(true);
+ set_physics_process_internal(true);
+ } break;
}
}
@@ -156,16 +160,16 @@ void PhysicalBone2D::_start_physics_simulation() {
// Apply the correct mode
RigidBody2D::Mode rigid_mode = get_mode();
if (rigid_mode == RigidBody2D::MODE_STATIC) {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
} else if (rigid_mode == RigidBody2D::MODE_DYNAMIC) {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC);
} else if (rigid_mode == RigidBody2D::MODE_KINEMATIC) {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_KINEMATIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
} else if (rigid_mode == RigidBody2D::MODE_DYNAMIC_LOCKED) {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC_LOCKED);
+ set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED);
} else {
- // Default to Rigid
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC);
+ // Default to Dynamic.
+ set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC);
}
_internal_simulate_physics = true;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 6c1cdc2129..5b12da8b57 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -49,7 +49,7 @@ void PhysicsBody2D::_bind_methods() {
PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) :
CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), p_mode);
+ set_body_mode(p_mode);
set_pickable(false);
}
@@ -76,12 +76,50 @@ Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_i
return Ref<KinematicCollision2D>();
}
-bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only) {
+bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only, bool p_cancel_sliding, const Set<RID> &p_exclude) {
if (is_only_update_transform_changes_enabled()) {
ERR_PRINT("Move functions do not work together with 'sync to physics' option. Please read the documentation.");
}
Transform2D gt = get_global_transform();
- bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes);
+ bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes, p_exclude);
+
+ // Restore direction of motion to be along original motion,
+ // in order to avoid sliding due to recovery,
+ // but only if collision depth is low enough to avoid tunneling.
+ if (p_cancel_sliding) {
+ real_t motion_length = p_motion.length();
+ real_t precision = 0.001;
+
+ if (colliding) {
+ // Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
+ // so even in normal resting cases the depth can be a bit more than the margin.
+ precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
+
+ if (r_result.collision_depth > (real_t)p_margin + precision) {
+ p_cancel_sliding = false;
+ }
+ }
+
+ if (p_cancel_sliding) {
+ // When motion is null, recovery is the resulting motion.
+ Vector2 motion_normal;
+ if (motion_length > CMP_EPSILON) {
+ motion_normal = p_motion / motion_length;
+ }
+
+ // Check depth of recovery.
+ real_t projected_length = r_result.motion.dot(motion_normal);
+ Vector2 recovery = r_result.motion - motion_normal * projected_length;
+ real_t recovery_length = recovery.length();
+ // Fixes cases where canceling slide causes the motion to go too deep into the ground,
+ // because we're only taking rest information into account and not general recovery.
+ if (recovery_length < (real_t)p_margin + precision) {
+ // Apply adjustment to motion.
+ r_result.motion = motion_normal * projected_length;
+ r_result.remainder = p_motion - r_result.motion;
+ }
+ }
+ }
if (!p_test_only) {
gt.elements[2] += r_result.motion;
@@ -186,11 +224,18 @@ void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) {
kinematic_motion = p_enabled;
if (kinematic_motion) {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
} else {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
}
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ return;
+ }
+#endif
+
_update_kinematic_motion();
}
@@ -198,29 +243,102 @@ bool StaticBody2D::is_kinematic_motion_enabled() const {
return kinematic_motion;
}
-void StaticBody2D::_notification(int p_what) {
- if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
+void StaticBody2D::set_sync_to_physics(bool p_enable) {
+ if (sync_to_physics == p_enable) {
+ return;
+ }
+
+ sync_to_physics = p_enable;
+
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ return;
+ }
#endif
- ERR_FAIL_COND(!kinematic_motion);
+ if (kinematic_motion) {
+ _update_kinematic_motion();
+ }
+}
- real_t delta_time = get_physics_process_delta_time();
+bool StaticBody2D::is_sync_to_physics_enabled() const {
+ return sync_to_physics;
+}
- Transform2D new_transform = get_global_transform();
+void StaticBody2D::_direct_state_changed(Object *p_state) {
+ if (!sync_to_physics) {
+ return;
+ }
- new_transform.translate(constant_linear_velocity * delta_time);
- new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
+ PhysicsDirectBodyState2D *state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
+ ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument");
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+ last_valid_transform = state->get_transform();
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+}
- // Propagate transform change to node.
- set_block_transform_notify(true);
- set_global_transform(new_transform);
- set_block_transform_notify(false);
+TypedArray<String> StaticBody2D::get_configuration_warnings() const {
+ TypedArray<String> warnings = PhysicsBody2D::get_configuration_warnings();
+
+ if (sync_to_physics && !kinematic_motion) {
+ warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled."));
+ }
+
+ return warnings;
+}
+
+void StaticBody2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ last_valid_transform = get_global_transform();
+ } break;
+
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ // Used by sync to physics, send the new transform to the physics...
+ Transform2D new_transform = get_global_transform();
+
+ real_t delta_time = get_physics_process_delta_time();
+ new_transform.translate(constant_linear_velocity * delta_time);
+ new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
+
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+
+ // ... but then revert changes.
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+ } break;
+
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+
+ ERR_FAIL_COND(!kinematic_motion);
+
+ Transform2D new_transform = get_global_transform();
+
+ real_t delta_time = get_physics_process_delta_time();
+ new_transform.translate(constant_linear_velocity * delta_time);
+ new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
+
+ if (sync_to_physics) {
+ // Propagate transform change to node.
+ set_global_transform(new_transform);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+
+ // Propagate transform change to node.
+ set_block_transform_notify(true);
+ set_global_transform(new_transform);
+ set_block_transform_notify(false);
+ }
+ } break;
}
}
@@ -236,10 +354,14 @@ void StaticBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody2D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody2D::is_sync_to_physics_enabled);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
StaticBody2D::StaticBody2D() :
@@ -263,14 +385,24 @@ void StaticBody2D::_update_kinematic_motion() {
}
#endif
+ if (kinematic_motion && sync_to_physics) {
+ PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &StaticBody2D::_direct_state_changed));
+ set_only_update_transform_changes(true);
+ set_notify_local_transform(true);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
+ }
+
+ bool needs_physics_process = false;
if (kinematic_motion) {
if (!Math::is_zero_approx(constant_angular_velocity) || !constant_linear_velocity.is_equal_approx(Vector2())) {
- set_physics_process_internal(true);
- return;
+ needs_physics_process = true;
}
}
- set_physics_process_internal(false);
+ set_physics_process_internal(needs_physics_process);
}
void RigidBody2D::_body_enter_tree(ObjectID p_id) {
@@ -495,18 +627,18 @@ void RigidBody2D::set_mode(Mode p_mode) {
mode = p_mode;
switch (p_mode) {
case MODE_DYNAMIC: {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC);
} break;
case MODE_STATIC: {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
} break;
case MODE_KINEMATIC: {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC);
+ set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
} break;
case MODE_DYNAMIC_LOCKED: {
- PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED);
+ set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED);
} break;
}
@@ -762,18 +894,19 @@ bool RigidBody2D::is_contact_monitor_enabled() const {
void RigidBody2D::_notification(int p_what) {
#ifdef TOOLS_ENABLED
- if (p_what == NOTIFICATION_ENTER_TREE) {
- if (Engine::get_singleton()->is_editor_hint()) {
- set_notify_local_transform(true); //used for warnings and only in editor
- }
- }
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ set_notify_local_transform(true); //used for warnings and only in editor
+ }
+ } break;
- if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
- if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
- }
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ }
+ } break;
}
-
#endif
}
@@ -855,8 +988,8 @@ void RigidBody2D::_bind_methods() {
BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState2D")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Dynamic,Static,DynamicLocked,Kinematic"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_NONE), "set_inertia", "get_inertia");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp", PROPERTY_USAGE_NONE), "set_inertia", "get_inertia");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
@@ -919,11 +1052,14 @@ void RigidBody2D::_reload_physics_characteristics() {
void CharacterBody2D::move_and_slide() {
Vector2 body_velocity_normal = linear_velocity.normalized();
-
bool was_on_floor = on_floor;
+ // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
+ float delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
+
Vector2 current_floor_velocity = floor_velocity;
- if (on_floor && on_floor_body.is_valid()) {
+
+ if ((on_floor || on_wall) && on_floor_body.is_valid()) {
//this approach makes sure there is less delay between the actual body velocity and the one we saved
PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(on_floor_body);
if (bs) {
@@ -931,26 +1067,38 @@ void CharacterBody2D::move_and_slide() {
}
}
- // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
- Vector2 motion = (current_floor_velocity + linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
-
+ motion_results.clear();
on_floor = false;
- on_floor_body = RID();
on_ceiling = false;
on_wall = false;
- motion_results.clear();
floor_normal = Vector2();
floor_velocity = Vector2();
- int slide_count = max_slides;
- while (slide_count) {
+ if (current_floor_velocity != Vector2()) {
+ PhysicsServer2D::MotionResult floor_result;
+ Set<RID> exclude;
+ exclude.insert(on_floor_body);
+ if (move_and_collide(current_floor_velocity * delta, infinite_inertia, floor_result, true, false, false, false, exclude)) {
+ motion_results.push_back(floor_result);
+ _set_collision_direction(floor_result);
+ }
+ }
+
+ on_floor_body = RID();
+ Vector2 motion = linear_velocity * delta;
+
+ // No sliding on first attempt to keep floor motion stable when possible,
+ // when stop on slope is enabled.
+ bool sliding_enabled = !stop_on_slope;
+
+ for (int iteration = 0; iteration < max_slides; ++iteration) {
PhysicsServer2D::MotionResult result;
bool found_collision = false;
for (int i = 0; i < 2; ++i) {
bool collided;
if (i == 0) { //collide
- collided = move_and_collide(motion, infinite_inertia, result, margin);
+ collided = move_and_collide(motion, infinite_inertia, result, margin, true, false, !sliding_enabled);
if (!collided) {
motion = Vector2(); //clear because no collision happened and motion completed
}
@@ -966,45 +1114,41 @@ void CharacterBody2D::move_and_slide() {
found_collision = true;
motion_results.push_back(result);
- motion = result.remainder;
-
- if (up_direction == Vector2()) {
- //all is a wall
- on_wall = true;
- } else {
- if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
-
- on_floor = true;
- floor_normal = result.collision_normal;
- on_floor_body = result.collider;
- floor_velocity = result.collider_velocity;
-
- if (stop_on_slope) {
- if ((body_velocity_normal + up_direction).length() < 0.01 && result.motion.length() < 1) {
- Transform2D gt = get_global_transform();
- gt.elements[2] -= result.motion.slide(up_direction);
- set_global_transform(gt);
- linear_velocity = Vector2();
- return;
- }
+ _set_collision_direction(result);
+
+ if (on_floor && stop_on_slope) {
+ if ((body_velocity_normal + up_direction).length() < 0.01) {
+ Transform2D gt = get_global_transform();
+ if (result.motion.length() > margin) {
+ gt.elements[2] -= result.motion.slide(up_direction);
+ } else {
+ gt.elements[2] -= result.motion;
}
- } else if (Math::acos(result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
- on_ceiling = true;
- } else {
- on_wall = true;
+ set_global_transform(gt);
+ linear_velocity = Vector2();
+ return;
}
}
- motion = motion.slide(result.collision_normal);
- linear_velocity = linear_velocity.slide(result.collision_normal);
+ if (sliding_enabled || !on_floor) {
+ motion = result.remainder.slide(result.collision_normal);
+ linear_velocity = linear_velocity.slide(result.collision_normal);
+ } else {
+ motion = result.remainder;
+ }
}
+
+ sliding_enabled = true;
}
if (!found_collision || motion == Vector2()) {
break;
}
+ }
- --slide_count;
+ if (!on_floor && !on_wall) {
+ // Add last platform velocity when just left a moving platform.
+ linear_velocity += current_floor_velocity;
}
if (!was_on_floor || snap == Vector2()) {
@@ -1014,7 +1158,7 @@ void CharacterBody2D::move_and_slide() {
// Apply snap.
Transform2D gt = get_global_transform();
PhysicsServer2D::MotionResult result;
- if (move_and_collide(snap, infinite_inertia, result, margin, false, true)) {
+ if (move_and_collide(snap, infinite_inertia, result, margin, false, true, false)) {
bool apply = true;
if (up_direction != Vector2()) {
if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
@@ -1025,9 +1169,12 @@ void CharacterBody2D::move_and_slide() {
if (stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
- result.motion = up_direction * up_direction.dot(result.motion);
+ if (result.motion.length() > margin) {
+ result.motion = up_direction * up_direction.dot(result.motion);
+ } else {
+ result.motion = Vector2();
+ }
}
-
} else {
apply = false;
}
@@ -1040,6 +1187,29 @@ void CharacterBody2D::move_and_slide() {
}
}
+void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
+ on_floor = false;
+ on_ceiling = false;
+ on_wall = false;
+ if (up_direction == Vector2()) {
+ //all is a wall
+ on_wall = true;
+ } else {
+ if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ on_floor = true;
+ floor_normal = p_result.collision_normal;
+ on_floor_body = p_result.collider;
+ floor_velocity = p_result.collider_velocity;
+ } else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ on_ceiling = true;
+ } else {
+ on_wall = true;
+ on_floor_body = p_result.collider;
+ floor_velocity = p_result.collider_velocity;
+ }
+ }
+}
+
bool CharacterBody2D::separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result) {
PhysicsServer2D::SeparationResult sep_res[8]; //max 8 rays
@@ -1128,45 +1298,6 @@ Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) {
return slide_colliders[p_bounce];
}
-void CharacterBody2D::set_sync_to_physics(bool p_enable) {
- if (sync_to_physics == p_enable) {
- return;
- }
- sync_to_physics = p_enable;
-
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-
- if (p_enable) {
- PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &CharacterBody2D::_direct_state_changed));
- set_only_update_transform_changes(true);
- set_notify_local_transform(true);
- } else {
- PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- }
-}
-
-bool CharacterBody2D::is_sync_to_physics_enabled() const {
- return sync_to_physics;
-}
-
-void CharacterBody2D::_direct_state_changed(Object *p_state) {
- if (!sync_to_physics) {
- return;
- }
-
- PhysicsDirectBodyState2D *state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
- ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument");
-
- last_valid_transform = state->get_transform();
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
-}
-
void CharacterBody2D::set_safe_margin(real_t p_margin) {
margin = p_margin;
}
@@ -1207,14 +1338,6 @@ void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
floor_max_angle = p_radians;
}
-real_t CharacterBody2D::get_floor_max_angle_degrees() const {
- return Math::rad2deg(floor_max_angle);
-}
-
-void CharacterBody2D::set_floor_max_angle_degrees(real_t p_degrees) {
- floor_max_angle = Math::deg2rad(p_degrees);
-}
-
const Vector2 &CharacterBody2D::get_snap() const {
return snap;
}
@@ -1232,26 +1355,16 @@ void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
}
void CharacterBody2D::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- last_valid_transform = get_global_transform();
-
- // Reset move_and_slide() data.
- on_floor = false;
- on_floor_body = RID();
- on_ceiling = false;
- on_wall = false;
- motion_results.clear();
- floor_velocity = Vector2();
- }
-
- if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
- //used by sync to physics, send the new transform to the physics
- Transform2D new_transform = get_global_transform();
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
- //but then revert changes
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ // Reset move_and_slide() data.
+ on_floor = false;
+ on_floor_body = RID();
+ on_ceiling = false;
+ on_wall = false;
+ motion_results.clear();
+ floor_velocity = Vector2();
+ } break;
}
}
@@ -1271,8 +1384,6 @@ void CharacterBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle);
- ClassDB::bind_method(D_METHOD("get_floor_max_angle_degrees"), &CharacterBody2D::get_floor_max_angle_degrees);
- ClassDB::bind_method(D_METHOD("set_floor_max_angle_degrees", "degrees"), &CharacterBody2D::set_floor_max_angle_degrees);
ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody2D::get_snap);
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody2D::set_snap);
ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
@@ -1286,19 +1397,14 @@ void CharacterBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_slide_count"), &CharacterBody2D::get_slide_count);
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
- ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &CharacterBody2D::set_sync_to_physics);
- ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &CharacterBody2D::is_sync_to_physics_enabled);
-
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_floor_max_angle", "get_floor_max_angle");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle_degrees", PROPERTY_HINT_RANGE, "0,180,0.1", PROPERTY_USAGE_EDITOR), "set_floor_max_angle_degrees", "get_floor_max_angle_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_floor_max_angle", "get_floor_max_angle");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motion/sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index f084a247aa..7a319aabc9 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -50,7 +50,7 @@ protected:
Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false, real_t p_margin = 0.08);
public:
- bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
+ bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false, bool p_cancel_sliding = true, const Set<RID> &p_exclude = Set<RID>());
bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08);
TypedArray<PhysicsBody2D> get_collision_exceptions();
@@ -69,6 +69,11 @@ class StaticBody2D : public PhysicsBody2D {
Ref<PhysicsMaterial> physics_material_override;
bool kinematic_motion = false;
+ bool sync_to_physics = false;
+
+ Transform2D last_valid_transform;
+
+ void _direct_state_changed(Object *p_state);
protected:
void _notification(int p_what);
@@ -84,6 +89,8 @@ public:
Vector2 get_constant_linear_velocity() const;
real_t get_constant_angular_velocity() const;
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
StaticBody2D();
private:
@@ -93,6 +100,9 @@ private:
void set_kinematic_motion_enabled(bool p_enabled);
bool is_kinematic_motion_enabled() const;
+
+ void set_sync_to_physics(bool p_enable);
+ bool is_sync_to_physics_enabled() const;
};
class RigidBody2D : public PhysicsBody2D {
@@ -243,7 +253,7 @@ public:
TypedArray<Node2D> get_colliding_bodies() const; //function for script
- TypedArray<String> get_configuration_warnings() const override;
+ virtual TypedArray<String> get_configuration_warnings() const override;
RigidBody2D();
~RigidBody2D();
@@ -276,7 +286,6 @@ private:
bool on_floor = false;
bool on_ceiling = false;
bool on_wall = false;
- bool sync_to_physics = false;
Vector<PhysicsServer2D::MotionResult> motion_results;
Vector<Ref<KinematicCollision2D>> slide_colliders;
@@ -285,9 +294,6 @@ private:
bool separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result);
- Transform2D last_valid_transform;
- void _direct_state_changed(Object *p_state);
-
void set_safe_margin(real_t p_margin);
real_t get_safe_margin() const;
@@ -303,14 +309,12 @@ private:
real_t get_floor_max_angle() const;
void set_floor_max_angle(real_t p_radians);
- real_t get_floor_max_angle_degrees() const;
- void set_floor_max_angle_degrees(real_t p_degrees);
-
const Vector2 &get_snap() const;
void set_snap(const Vector2 &p_snap);
const Vector2 &get_up_direction() const;
void set_up_direction(const Vector2 &p_up_direction);
+ void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result);
protected:
void _notification(int p_what);
@@ -331,9 +335,6 @@ public:
int get_slide_count() const;
PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const;
- void set_sync_to_physics(bool p_enable);
- bool is_sync_to_physics_enabled() const;
-
CharacterBody2D();
~CharacterBody2D();
};
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 860e95b51e..7366be5a7d 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -462,14 +462,6 @@ real_t Polygon2D::get_texture_rotation() const {
return tex_rot;
}
-void Polygon2D::set_texture_rotation_degrees(real_t p_rot) {
- set_texture_rotation(Math::deg2rad(p_rot));
-}
-
-real_t Polygon2D::get_texture_rotation_degrees() const {
- return Math::rad2deg(get_texture_rotation());
-}
-
void Polygon2D::set_texture_scale(const Size2 &p_scale) {
tex_scale = p_scale;
update();
@@ -613,9 +605,6 @@ void Polygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_texture_rotation", "texture_rotation"), &Polygon2D::set_texture_rotation);
ClassDB::bind_method(D_METHOD("get_texture_rotation"), &Polygon2D::get_texture_rotation);
- ClassDB::bind_method(D_METHOD("set_texture_rotation_degrees", "texture_rotation"), &Polygon2D::set_texture_rotation_degrees);
- ClassDB::bind_method(D_METHOD("get_texture_rotation_degrees"), &Polygon2D::get_texture_rotation_degrees);
-
ClassDB::bind_method(D_METHOD("set_texture_scale", "texture_scale"), &Polygon2D::set_texture_scale);
ClassDB::bind_method(D_METHOD("get_texture_scale"), &Polygon2D::get_texture_scale);
@@ -657,8 +646,7 @@ void Polygon2D::_bind_methods() {
ADD_GROUP("Texture2D", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_offset"), "set_texture_offset", "get_texture_offset");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale"), "set_texture_scale", "get_texture_scale");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_rotation_degrees", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater"), "set_texture_rotation_degrees", "get_texture_rotation_degrees");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_texture_rotation", "get_texture_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_texture_rotation", "get_texture_rotation");
ADD_GROUP("Skeleton", "");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton2D"), "set_skeleton", "get_skeleton");
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index f9f36ff9a2..bf386b9ace 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -120,9 +120,6 @@ public:
void set_texture_rotation(real_t p_rot);
real_t get_texture_rotation() const;
- void set_texture_rotation_degrees(real_t p_rot);
- real_t get_texture_rotation_degrees() const;
-
void set_texture_scale(const Size2 &p_scale);
Size2 get_texture_scale() const;
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index a7613dc009..e7cef965fe 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -35,7 +35,7 @@ void RemoteTransform2D::_update_cache() {
cache = ObjectID();
if (has_node(remote_node)) {
Node *node = get_node(remote_node);
- if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) {
+ if (!node || this == node || node->is_ancestor_of(this) || this->is_ancestor_of(node)) {
return;
}
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 8f1f5fadbc..15cbdf535e 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -568,7 +568,7 @@ void Skeleton2D::_make_bone_setup_dirty() {
}
bone_setup_dirty = true;
if (is_inside_tree()) {
- call_deferred("_update_bone_setup");
+ call_deferred(SNAME("_update_bone_setup"));
}
}
@@ -597,7 +597,7 @@ void Skeleton2D::_update_bone_setup() {
transform_dirty = true;
_update_transform();
- emit_signal("bone_setup_changed");
+ emit_signal(SNAME("bone_setup_changed"));
}
void Skeleton2D::_make_transform_dirty() {
@@ -606,7 +606,7 @@ void Skeleton2D::_make_transform_dirty() {
}
transform_dirty = true;
if (is_inside_tree()) {
- call_deferred("_update_transform");
+ call_deferred(SNAME("_update_transform"));
}
}
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index e39c8841cd..6d1e27bf1b 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -299,7 +299,7 @@ void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
_recreate_quadrants();
}
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
int TileMap::get_quadrant_size() const {
@@ -311,13 +311,13 @@ void TileMap::set_quadrant_size(int p_size) {
quadrant_size = p_size;
_recreate_quadrants();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
void TileMap::set_collision_visibility_mode(TileMap::VisibilityMode p_show_collision) {
show_collision = p_show_collision;
_recreate_quadrants();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
TileMap::VisibilityMode TileMap::get_collision_visibility_mode() {
@@ -327,7 +327,7 @@ TileMap::VisibilityMode TileMap::get_collision_visibility_mode() {
void TileMap::set_navigation_visibility_mode(TileMap::VisibilityMode p_show_navigation) {
show_navigation = p_show_navigation;
_recreate_quadrants();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() {
@@ -337,7 +337,7 @@ TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() {
void TileMap::set_y_sort_enabled(bool p_enable) {
Node2D::set_y_sort_enabled(p_enable);
_recreate_quadrants();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
void TileMap::update_dirty_quadrants() {
@@ -480,7 +480,7 @@ void TileMap::_make_all_quadrants_dirty(bool p_update) {
return;
}
if (p_update) {
- call_deferred("update_dirty_quadrants");
+ call_deferred(SNAME("update_dirty_quadrants"));
}
}
@@ -500,7 +500,7 @@ void TileMap::_make_quadrant_dirty(Map<Vector2i, TileMapQuadrant>::Element *Q, b
}
if (p_update) {
- call_deferred("update_dirty_quadrants");
+ call_deferred(SNAME("update_dirty_quadrants"));
}
}
@@ -1764,7 +1764,7 @@ void TileMap::_bind_methods() {
}
void TileMap::_tile_set_changed() {
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
_make_all_quadrants_dirty(true);
}
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 0a6393551c..7c345ad377 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -294,7 +294,7 @@ void TouchScreenButton::_press(int p_finger_pressed) {
get_viewport()->input(iea, true);
}
- emit_signal("pressed");
+ emit_signal(SNAME("pressed"));
update();
}
@@ -313,7 +313,7 @@ void TouchScreenButton::_release(bool p_exiting_tree) {
}
if (!p_exiting_tree) {
- emit_signal("released");
+ emit_signal(SNAME("released"));
update();
}
}
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index 44708cddff..cd64a813dd 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -601,7 +601,7 @@ void Area3D::_bind_methods() {
ADD_GROUP("Physics Overrides", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_distance_scale", "get_gravity_distance_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index e05f37c73c..dd8cb1f20d 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -607,7 +607,7 @@ void AudioStreamPlayer3D::_notification(int p_what) {
//stop playing if no longer active
if (!active.is_set()) {
set_physics_process_internal(false);
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
}
}
}
@@ -967,13 +967,13 @@ void AudioStreamPlayer3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,4096,1,or_greater"), "set_max_distance", "get_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,4096,1,or_greater,exp"), "set_max_distance", "get_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "out_of_range_mode", PROPERTY_HINT_ENUM, "Mix,Pause"), "set_out_of_range_mode", "get_out_of_range_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask");
ADD_GROUP("Emission Angle", "emission_angle");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emission_angle_enabled"), "set_emission_angle_enabled", "is_emission_angle_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1"), "set_emission_angle", "get_emission_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1,degrees"), "set_emission_angle", "get_emission_angle");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db");
ADD_GROUP("Attenuation Filter", "attenuation_filter_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz");
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 32006d5e7f..0c38d85a6b 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -85,14 +85,14 @@ void Camera3D::_update_camera() {
// here goes listener stuff
/*
if (viewport_ptr && is_inside_scene() && is_current())
- get_viewport()->_camera_transform_changed_notify();
+ get_viewport()->_camera_3d_transform_changed_notify();
*/
if (get_tree()->is_node_being_edited(this) || !is_current()) {
return;
}
- get_viewport()->_camera_transform_changed_notify();
+ get_viewport()->_camera_3d_transform_changed_notify();
}
void Camera3D::_notification(int p_what) {
@@ -104,9 +104,9 @@ void Camera3D::_notification(int p_what) {
viewport = get_viewport();
ERR_FAIL_COND(!viewport);
- bool first_camera = viewport->_camera_add(this);
+ bool first_camera = viewport->_camera_3d_add(this);
if (current || first_camera) {
- viewport->_camera_set(this);
+ viewport->_camera_3d_set(this);
}
} break;
@@ -128,7 +128,7 @@ void Camera3D::_notification(int p_what) {
}
if (viewport) {
- viewport->_camera_remove(this);
+ viewport->_camera_3d_remove(this);
viewport = nullptr;
}
@@ -220,7 +220,7 @@ void Camera3D::make_current() {
return;
}
- get_viewport()->_camera_set(this);
+ get_viewport()->_camera_3d_set(this);
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this);
}
@@ -231,11 +231,11 @@ void Camera3D::clear_current(bool p_enable_next) {
return;
}
- if (get_viewport()->get_camera() == this) {
- get_viewport()->_camera_set(nullptr);
+ if (get_viewport()->get_camera_3d() == this) {
+ get_viewport()->_camera_3d_set(nullptr);
if (p_enable_next) {
- get_viewport()->_camera_make_next_current(this);
+ get_viewport()->_camera_3d_make_next_current(this);
}
}
}
@@ -250,7 +250,7 @@ void Camera3D::set_current(bool p_current) {
bool Camera3D::is_current() const {
if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
- return get_viewport()->get_camera() == this;
+ return get_viewport()->get_camera_3d() == this;
} else {
return current;
}
@@ -513,11 +513,11 @@ void Camera3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
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"), "set_fov", "get_fov");
+ 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::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.001,10,0.001,or_greater"), "set_near", "get_near");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.01,4000,0.01,or_greater"), "set_far", "get_far");
+ 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");
BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE);
BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL);
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index a04667e53b..dd1f25da68 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -32,7 +32,6 @@
#include "core/config/engine.h"
#include "scene/scene_string_names.h"
-#include "servers/physics_server_3d.h"
void CollisionObject3D::_notification(int p_what) {
switch (p_what) {
@@ -59,18 +58,29 @@ void CollisionObject3D::_notification(int p_what) {
PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
}
- RID space = get_world_3d()->get_space();
- if (area) {
- PhysicsServer3D::get_singleton()->area_set_space(rid, space);
- } else {
- PhysicsServer3D::get_singleton()->body_set_space(rid, space);
+ bool disabled = !is_enabled();
+
+ if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
+ _apply_disabled();
+ }
+
+ if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
+ RID space = get_world_3d()->get_space();
+ if (area) {
+ PhysicsServer3D::get_singleton()->area_set_space(rid, space);
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_space(rid, space);
+ }
}
_update_pickable();
- //get space
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
+ if (only_update_transform_changes) {
+ return;
+ }
+
if (area) {
PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform());
} else {
@@ -78,19 +88,34 @@ void CollisionObject3D::_notification(int p_what) {
}
_on_transform_changed();
-
} break;
+
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
-
} break;
+
case NOTIFICATION_EXIT_WORLD: {
- if (area) {
- PhysicsServer3D::get_singleton()->area_set_space(rid, RID());
- } else {
- PhysicsServer3D::get_singleton()->body_set_space(rid, RID());
+ bool disabled = !is_enabled();
+
+ if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
+ if (area) {
+ PhysicsServer3D::get_singleton()->area_set_space(rid, RID());
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_space(rid, RID());
+ }
+ }
+
+ if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
+ _apply_enabled();
}
+ } break;
+
+ case NOTIFICATION_DISABLED: {
+ _apply_disabled();
+ } break;
+ case NOTIFICATION_ENABLED: {
+ _apply_enabled();
} break;
}
}
@@ -153,6 +178,79 @@ bool CollisionObject3D::get_collision_mask_bit(int p_bit) const {
return get_collision_mask() & (1 << p_bit);
}
+void CollisionObject3D::set_disable_mode(DisableMode p_mode) {
+ if (disable_mode == p_mode) {
+ return;
+ }
+
+ bool disabled = is_inside_tree() && !is_enabled();
+
+ if (disabled) {
+ // Cancel previous disable mode.
+ _apply_enabled();
+ }
+
+ disable_mode = p_mode;
+
+ if (disabled) {
+ // Apply new disable mode.
+ _apply_disabled();
+ }
+}
+
+CollisionObject3D::DisableMode CollisionObject3D::get_disable_mode() const {
+ return disable_mode;
+}
+
+void CollisionObject3D::_apply_disabled() {
+ switch (disable_mode) {
+ case DISABLE_MODE_REMOVE: {
+ if (is_inside_tree()) {
+ if (area) {
+ PhysicsServer3D::get_singleton()->area_set_space(rid, RID());
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_space(rid, RID());
+ }
+ }
+ } break;
+
+ case DISABLE_MODE_MAKE_STATIC: {
+ if (!area && (body_mode != PhysicsServer3D::BODY_MODE_STATIC)) {
+ PhysicsServer3D::get_singleton()->body_set_mode(rid, PhysicsServer3D::BODY_MODE_STATIC);
+ }
+ } break;
+
+ case DISABLE_MODE_KEEP_ACTIVE: {
+ // Nothing to do.
+ } break;
+ }
+}
+
+void CollisionObject3D::_apply_enabled() {
+ switch (disable_mode) {
+ case DISABLE_MODE_REMOVE: {
+ if (is_inside_tree()) {
+ RID space = get_world_3d()->get_space();
+ if (area) {
+ PhysicsServer3D::get_singleton()->area_set_space(rid, space);
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_space(rid, space);
+ }
+ }
+ } break;
+
+ case DISABLE_MODE_MAKE_STATIC: {
+ if (!area && (body_mode != PhysicsServer3D::BODY_MODE_STATIC)) {
+ PhysicsServer3D::get_singleton()->body_set_mode(rid, body_mode);
+ }
+ } break;
+
+ case DISABLE_MODE_KEEP_ACTIVE: {
+ // Nothing to do.
+ } break;
+ }
+}
+
void CollisionObject3D::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
if (get_script_instance()) {
get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape);
@@ -174,6 +272,30 @@ void CollisionObject3D::_mouse_exit() {
emit_signal(SceneStringNames::get_singleton()->mouse_exited);
}
+void CollisionObject3D::set_body_mode(PhysicsServer3D::BodyMode p_mode) {
+ ERR_FAIL_COND(area);
+
+ if (body_mode == p_mode) {
+ return;
+ }
+
+ body_mode = p_mode;
+
+ if (is_inside_tree() && !is_enabled() && (disable_mode == DISABLE_MODE_MAKE_STATIC)) {
+ return;
+ }
+
+ PhysicsServer3D::get_singleton()->body_set_mode(rid, p_mode);
+}
+
+void CollisionObject3D::set_only_update_transform_changes(bool p_enable) {
+ only_update_transform_changes = p_enable;
+}
+
+bool CollisionObject3D::is_only_update_transform_changes_enabled() const {
+ return only_update_transform_changes;
+}
+
void CollisionObject3D::_update_pickable() {
if (!is_inside_tree()) {
return;
@@ -305,6 +427,8 @@ void CollisionObject3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject3D::get_collision_layer_bit);
ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject3D::set_collision_mask_bit);
ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject3D::get_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &CollisionObject3D::set_disable_mode);
+ ClassDB::bind_method(D_METHOD("get_disable_mode"), &CollisionObject3D::get_disable_mode);
ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject3D::set_ray_pickable);
ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject3D::is_ray_pickable);
ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject3D::set_capture_input_on_drag);
@@ -332,6 +456,8 @@ void CollisionObject3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("mouse_entered"));
ADD_SIGNAL(MethodInfo("mouse_exited"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode");
+
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
@@ -339,6 +465,10 @@ void CollisionObject3D::_bind_methods() {
ADD_GROUP("Input", "input_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_ray_pickable"), "set_ray_pickable", "is_ray_pickable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag");
+
+ BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE);
+ BIND_ENUM_CONSTANT(DISABLE_MODE_MAKE_STATIC);
+ BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE);
}
uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) {
@@ -540,8 +670,8 @@ CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) {
PhysicsServer3D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id());
} else {
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id());
+ PhysicsServer3D::get_singleton()->body_set_mode(rid, body_mode);
}
- //set_transform_notify(true);
}
void CollisionObject3D::set_capture_input_on_drag(bool p_capture) {
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index 50a9b4fcd0..7c30a5cd98 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -33,10 +33,19 @@
#include "scene/3d/node_3d.h"
#include "scene/resources/shape_3d.h"
+#include "servers/physics_server_3d.h"
class CollisionObject3D : public Node3D {
GDCLASS(CollisionObject3D, Node3D);
+public:
+ enum DisableMode {
+ DISABLE_MODE_REMOVE,
+ DISABLE_MODE_MAKE_STATIC,
+ DISABLE_MODE_KEEP_ACTIVE,
+ };
+
+private:
uint32_t collision_layer = 1;
uint32_t collision_mask = 1;
@@ -44,6 +53,10 @@ class CollisionObject3D : public Node3D {
RID rid;
+ DisableMode disable_mode = DISABLE_MODE_REMOVE;
+
+ PhysicsServer3D::BodyMode body_mode = PhysicsServer3D::BODY_MODE_STATIC;
+
struct ShapeData {
Object *owner = nullptr;
Transform3D xform;
@@ -61,6 +74,8 @@ class CollisionObject3D : public Node3D {
Map<uint32_t, ShapeData> shapes;
+ bool only_update_transform_changes = false; // This is used for sync to physics.
+
bool capture_input_on_drag = false;
bool ray_pickable = true;
@@ -76,6 +91,9 @@ class CollisionObject3D : public Node3D {
void _update_debug_shapes();
void _clear_debug_shapes();
+ void _apply_disabled();
+ void _apply_enabled();
+
protected:
CollisionObject3D(RID p_rid, bool p_area);
@@ -89,6 +107,11 @@ protected:
virtual void _mouse_enter();
virtual void _mouse_exit();
+ void set_body_mode(PhysicsServer3D::BodyMode p_mode);
+
+ void set_only_update_transform_changes(bool p_enable);
+ bool is_only_update_transform_changes_enabled() const;
+
public:
void set_collision_layer(uint32_t p_layer);
uint32_t get_collision_layer() const;
@@ -102,6 +125,9 @@ public:
void set_collision_mask_bit(int p_bit, bool p_value);
bool get_collision_mask_bit(int p_bit) const;
+ void set_disable_mode(DisableMode p_mode);
+ DisableMode get_disable_mode() const;
+
uint32_t create_shape_owner(Object *p_owner);
void remove_shape_owner(uint32_t owner);
void get_shape_owners(List<uint32_t> *r_owners);
@@ -138,4 +164,6 @@ public:
~CollisionObject3D();
};
+VARIANT_ENUM_CAST(CollisionObject3D::DisableMode);
+
#endif // COLLISION_OBJECT__H
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 2301fef651..9e0bc9f3a1 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -434,28 +434,24 @@ Vector3 CPUParticles3D::get_gravity() const {
}
void CPUParticles3D::_validate_property(PropertyInfo &property) const {
- if (property.name == "color" && color_ramp.is_valid()) {
- property.usage = 0;
- }
-
if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_normals" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -1007,7 +1003,7 @@ void CPUParticles3D::_update_particle_data_buffer() {
sorter.sort(order, pc);
} else if (draw_order == DRAW_ORDER_VIEW_DEPTH) {
ERR_FAIL_NULL(get_viewport());
- Camera3D *c = get_viewport()->get_camera();
+ Camera3D *c = get_viewport()->get_camera_3d();
if (c) {
Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close
@@ -1273,11 +1269,11 @@ void CPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("restart"), &CPUParticles3D::restart);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,exp"), "set_pre_process_time", "get_pre_process_time");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
@@ -1390,7 +1386,7 @@ void CPUParticles3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING);
ADD_GROUP("Angle", "");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater,degrees"), "set_param", "get_param", PARAM_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGLE);
ADD_GROUP("Scale", "");
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index 7d6abe458a..5af7b8ca07 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -45,6 +45,7 @@ void Decal::set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture) {
textures[p_type] = p_texture;
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
RS::get_singleton()->decal_set_texture(decal, RS::DecalTexture(p_type), texture_rid);
+ update_configuration_warnings();
}
Ref<Texture2D> Decal::get_texture(DecalTexture p_type) const {
@@ -137,6 +138,7 @@ float Decal::get_distance_fade_length() const {
void Decal::set_cull_mask(uint32_t p_layers) {
cull_mask = p_layers;
RS::get_singleton()->decal_set_cull_mask(decal, cull_mask);
+ update_configuration_warnings();
}
uint32_t Decal::get_cull_mask() const {
@@ -160,6 +162,27 @@ void Decal::_validate_property(PropertyInfo &property) const {
}
}
+TypedArray<String> Decal::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (textures[TEXTURE_ALBEDO].is_null() && textures[TEXTURE_NORMAL].is_null() && textures[TEXTURE_ORM].is_null() && textures[TEXTURE_EMISSION].is_null()) {
+ warnings.push_back(TTR("The decal has no textures loaded into any of its texture properties, and will therefore not be visible."));
+ }
+
+ if ((textures[TEXTURE_NORMAL].is_valid() || textures[TEXTURE_ORM].is_valid()) && textures[TEXTURE_ALBEDO].is_null()) {
+ warnings.push_back(TTR("The decal has a Normal and/or ORM texture, but no Albedo texture is set.\nAn Albedo texture with an alpha channel is required to blend the normal/ORM maps onto the underlying surface.\nIf you don't want the Albedo texture to be visible, set Albedo Mix to 0."));
+ }
+
+ if (cull_mask == 0) {
+ // NOTE: This warning will not be emitted if none of the 20 checkboxes
+ // exposed in the editor are checked. This is because there are
+ // currently 12 unexposed layers in the editor inspector.
+ warnings.push_back(TTR("The decal's Cull Mask has no bits enabled, which means the decal will not paint objects on any layer.\nTo resolve this, enable at least one bit in the Cull Mask property."));
+ }
+
+ return warnings;
+}
+
void Decal::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &Decal::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &Decal::get_extents);
@@ -207,7 +230,9 @@ void Decal::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_emission_energy", "get_emission_energy");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "albedo_mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_albedo_mix", "get_albedo_mix");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_normal_fade", "get_normal_fade");
+ // A Normal Fade of 1.0 causes the decal to be invisible even if fully perpendicular to a surface.
+ // Due to this, limit Normal Fade to 0.999.
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,0.999,0.001"), "set_normal_fade", "get_normal_fade");
ADD_GROUP("Vertical Fade", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade");
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index ce19e76de1..31a6315213 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -67,6 +67,8 @@ protected:
void _validate_property(PropertyInfo &property) const override;
public:
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index d7f4bfeb4e..f78027e6c7 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -385,7 +385,7 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const {
if (property.name.begins_with("draw_pass_")) {
int index = property.name.get_slicec('_', 2).to_int() - 1;
if (index >= draw_passes.size()) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
return;
}
}
@@ -562,12 +562,12 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_transform_align"), &GPUParticles3D::get_transform_align);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter");
ADD_GROUP("Time", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,exp"), "set_pre_process_time", "get_pre_process_time");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index c1e71b9565..5b88a6ec9f 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -596,7 +596,7 @@ void GPUParticlesCollisionHeightField::_notification(int p_what) {
}
if (follow_camera_mode && get_viewport()) {
- Camera3D *cam = get_viewport()->get_camera();
+ Camera3D *cam = get_viewport()->get_camera_3d();
if (cam) {
Transform3D xform = get_global_transform();
Vector3 x_axis = xform.basis.get_axis(Vector3::AXIS_X).normalized();
diff --git a/scene/3d/immediate_geometry_3d.cpp b/scene/3d/immediate_geometry_3d.cpp
deleted file mode 100644
index d64babaa9d..0000000000
--- a/scene/3d/immediate_geometry_3d.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*************************************************************************/
-/* immediate_geometry_3d.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "immediate_geometry_3d.h"
-
-void ImmediateGeometry3D::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture) {
- RS::get_singleton()->immediate_begin(im, (RS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID());
- if (p_texture.is_valid()) {
- cached_textures.push_back(p_texture);
- }
-}
-
-void ImmediateGeometry3D::set_normal(const Vector3 &p_normal) {
- RS::get_singleton()->immediate_normal(im, p_normal);
-}
-
-void ImmediateGeometry3D::set_tangent(const Plane &p_tangent) {
- RS::get_singleton()->immediate_tangent(im, p_tangent);
-}
-
-void ImmediateGeometry3D::set_color(const Color &p_color) {
- RS::get_singleton()->immediate_color(im, p_color);
-}
-
-void ImmediateGeometry3D::set_uv(const Vector2 &p_uv) {
- RS::get_singleton()->immediate_uv(im, p_uv);
-}
-
-void ImmediateGeometry3D::set_uv2(const Vector2 &p_uv2) {
- RS::get_singleton()->immediate_uv2(im, p_uv2);
-}
-
-void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) {
- RS::get_singleton()->immediate_vertex(im, p_vertex);
- if (empty) {
- aabb.position = p_vertex;
- aabb.size = Vector3();
- empty = false;
- } else {
- aabb.expand_to(p_vertex);
- }
-}
-
-void ImmediateGeometry3D::end() {
- RS::get_singleton()->immediate_end(im);
-}
-
-void ImmediateGeometry3D::clear() {
- RS::get_singleton()->immediate_clear(im);
- empty = true;
- cached_textures.clear();
-}
-
-AABB ImmediateGeometry3D::get_aabb() const {
- return aabb;
-}
-
-Vector<Face3> ImmediateGeometry3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
-void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) {
- const double lat_step = Math_TAU / p_lats;
- const double lon_step = Math_TAU / p_lons;
-
- for (int i = 1; i <= p_lats; i++) {
- double lat0 = lat_step * (i - 1) - Math_TAU / 4;
- double z0 = Math::sin(lat0);
- double zr0 = Math::cos(lat0);
-
- double lat1 = lat_step * i - Math_TAU / 4;
- double z1 = Math::sin(lat1);
- double zr1 = Math::cos(lat1);
-
- for (int j = p_lons; j >= 1; j--) {
- double lng0 = lon_step * (j - 1);
- double x0 = Math::cos(lng0);
- double y0 = Math::sin(lng0);
-
- double lng1 = lon_step * j;
- double x1 = Math::cos(lng1);
- double y1 = Math::sin(lng1);
-
- Vector3 v[4] = {
- Vector3(x1 * zr0, z0, y1 * zr0),
- Vector3(x1 * zr1, z1, y1 * zr1),
- Vector3(x0 * zr1, z1, y0 * zr1),
- Vector3(x0 * zr0, z0, y0 * zr0)
- };
-
-#define ADD_POINT(m_idx) \
- if (p_add_uv) { \
- set_uv(Vector2(Math::atan2(v[m_idx].x, v[m_idx].z) / Math_PI * 0.5 + 0.5, v[m_idx].y * 0.5 + 0.5)); \
- set_tangent(Plane(Vector3(-v[m_idx].z, v[m_idx].y, v[m_idx].x), 1)); \
- } \
- set_normal(v[m_idx]); \
- add_vertex(v[m_idx] * p_radius);
-
- ADD_POINT(0);
- ADD_POINT(1);
- ADD_POINT(2);
-
- ADD_POINT(2);
- ADD_POINT(3);
- ADD_POINT(0);
- }
- }
-}
-
-void ImmediateGeometry3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry3D::begin, DEFVAL(Ref<Texture2D>()));
- ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry3D::set_normal);
- ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry3D::set_tangent);
- ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry3D::set_color);
- ClassDB::bind_method(D_METHOD("set_uv", "uv"), &ImmediateGeometry3D::set_uv);
- ClassDB::bind_method(D_METHOD("set_uv2", "uv"), &ImmediateGeometry3D::set_uv2);
- ClassDB::bind_method(D_METHOD("add_vertex", "position"), &ImmediateGeometry3D::add_vertex);
- ClassDB::bind_method(D_METHOD("add_sphere", "lats", "lons", "radius", "add_uv"), &ImmediateGeometry3D::add_sphere, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("end"), &ImmediateGeometry3D::end);
- ClassDB::bind_method(D_METHOD("clear"), &ImmediateGeometry3D::clear);
-}
-
-ImmediateGeometry3D::ImmediateGeometry3D() {
- im = RenderingServer::get_singleton()->immediate_create();
- set_base(im);
-}
-
-ImmediateGeometry3D::~ImmediateGeometry3D() {
- RenderingServer::get_singleton()->free(im);
-}
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 37881c3332..8478821ba1 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -209,19 +209,19 @@ void Light3D::_validate_property(PropertyInfo &property) const {
}
if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_size") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_specular") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_projector") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (get_light_type() != RS::LIGHT_DIRECTIONAL && property.name == "light_angular_distance") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -375,15 +375,6 @@ DirectionalLight3D::ShadowMode DirectionalLight3D::get_shadow_mode() const {
return shadow_mode;
}
-void DirectionalLight3D::set_shadow_depth_range(ShadowDepthRange p_range) {
- shadow_depth_range = p_range;
- RS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, RS::LightDirectionalShadowDepthRangeMode(p_range));
-}
-
-DirectionalLight3D::ShadowDepthRange DirectionalLight3D::get_shadow_depth_range() const {
- return shadow_depth_range;
-}
-
void DirectionalLight3D::set_blend_splits(bool p_enable) {
blend_splits = p_enable;
RS::get_singleton()->light_directional_set_blend_splits(light, p_enable);
@@ -406,9 +397,6 @@ void DirectionalLight3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight3D::set_shadow_mode);
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight3D::get_shadow_mode);
- ClassDB::bind_method(D_METHOD("set_shadow_depth_range", "mode"), &DirectionalLight3D::set_shadow_depth_range);
- ClassDB::bind_method(D_METHOD("get_shadow_depth_range"), &DirectionalLight3D::get_shadow_depth_range);
-
ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight3D::set_blend_splits);
ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight3D::is_blend_splits_enabled);
@@ -422,18 +410,14 @@ void DirectionalLight3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_EXP_RANGE, "0,1024,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_RANGE, "0,8192,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_RANGE, "0,1024,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_in_sky_only"), "set_sky_only", "is_sky_only");
BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL);
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS);
-
- BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE);
- BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_OPTIMIZED);
}
DirectionalLight3D::DirectionalLight3D() :
@@ -444,7 +428,6 @@ DirectionalLight3D::DirectionalLight3D() :
// Leave normal bias untouched as it doesn't benefit DirectionalLight3D as much as OmniLight3D.
set_param(PARAM_SHADOW_BIAS, 0.05);
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
- set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
blend_splits = false;
}
@@ -472,7 +455,7 @@ void OmniLight3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight3D::get_shadow_mode);
ADD_GROUP("Omni", "omni_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_range", PROPERTY_HINT_RANGE, "0,4096,0.1,or_greater,exp"), "set_param", "get_param", PARAM_RANGE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode");
@@ -504,8 +487,8 @@ TypedArray<String> SpotLight3D::get_configuration_warnings() const {
void SpotLight3D::_bind_methods() {
ADD_GROUP("Spot", "spot_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_RANGE, "0,4096,0.1,or_greater,exp"), "set_param", "get_param", PARAM_RANGE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_param", "get_param", PARAM_SPOT_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), "set_param", "get_param", PARAM_SPOT_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
}
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index e145b08b74..d0308a3025 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -149,15 +149,9 @@ public:
SHADOW_PARALLEL_4_SPLITS,
};
- enum ShadowDepthRange {
- SHADOW_DEPTH_RANGE_STABLE = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE,
- SHADOW_DEPTH_RANGE_OPTIMIZED = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED,
- };
-
private:
bool blend_splits;
ShadowMode shadow_mode;
- ShadowDepthRange shadow_depth_range;
bool sky_only = false;
protected:
@@ -167,9 +161,6 @@ public:
void set_shadow_mode(ShadowMode p_mode);
ShadowMode get_shadow_mode() const;
- void set_shadow_depth_range(ShadowDepthRange p_range);
- ShadowDepthRange get_shadow_depth_range() const;
-
void set_blend_splits(bool p_enable);
bool is_blend_splits_enabled() const;
@@ -180,7 +171,6 @@ public:
};
VARIANT_ENUM_CAST(DirectionalLight3D::ShadowMode)
-VARIANT_ENUM_CAST(DirectionalLight3D::ShadowDepthRange)
class OmniLight3D : public Light3D {
GDCLASS(OmniLight3D, Light3D);
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 74b4269169..3ffb3c0393 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -599,7 +599,7 @@ void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, f
const Vector3 *pp = probe_positions.ptr();
bool exists = false;
for (int j = 0; j < ppcount; j++) {
- if (pp[j].distance_to(real_pos) < CMP_EPSILON) {
+ if (pp[j].is_equal_approx(real_pos)) {
exists = true;
break;
}
@@ -1367,13 +1367,13 @@ LightmapGI::GenerateProbes LightmapGI::get_generate_probes() const {
void LightmapGI::_validate_property(PropertyInfo &property) const {
if (property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 08dec232ab..28ccbd3e68 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -100,7 +100,7 @@ void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
if (mesh.is_valid()) {
for (int i = 0; i < mesh->get_surface_count(); i++) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_material_override/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_material_override/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE));
}
}
}
@@ -241,12 +241,12 @@ void MeshInstance3D::create_trimesh_collision() {
}
}
-Node *MeshInstance3D::create_convex_collision_node() {
+Node *MeshInstance3D::create_convex_collision_node(bool p_clean, bool p_simplify) {
if (mesh.is_null()) {
return nullptr;
}
- Ref<Shape3D> shape = mesh->create_convex_shape();
+ Ref<Shape3D> shape = mesh->create_convex_shape(p_clean, p_simplify);
if (shape.is_null()) {
return nullptr;
}
@@ -258,8 +258,8 @@ Node *MeshInstance3D::create_convex_collision_node() {
return static_body;
}
-void MeshInstance3D::create_convex_collision() {
- StaticBody3D *static_body = Object::cast_to<StaticBody3D>(create_convex_collision_node());
+void MeshInstance3D::create_convex_collision(bool p_clean, bool p_simplify) {
+ StaticBody3D *static_body = Object::cast_to<StaticBody3D>(create_convex_collision_node(p_clean, p_simplify));
ERR_FAIL_COND(!static_body);
static_body->set_name(String(get_name()) + "_col");
@@ -451,7 +451,7 @@ void MeshInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance3D::create_trimesh_collision);
ClassDB::set_method_flags("MeshInstance3D", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
- ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance3D::create_convex_collision);
+ ClassDB::bind_method(D_METHOD("create_convex_collision", "clean", "simplify"), &MeshInstance3D::create_convex_collision, DEFVAL(true), DEFVAL(false));
ClassDB::set_method_flags("MeshInstance3D", "create_convex_collision", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions"), &MeshInstance3D::create_multiple_convex_collisions);
ClassDB::set_method_flags("MeshInstance3D", "create_multiple_convex_collisions", METHOD_FLAGS_DEFAULT);
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 9dea5804e0..e2d20d0a90 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -83,8 +83,8 @@ public:
Node *create_trimesh_collision_node();
void create_trimesh_collision();
- Node *create_convex_collision_node();
- void create_convex_collision();
+ Node *create_convex_collision_node(bool p_clean = true, bool p_simplify = false);
+ void create_convex_collision(bool p_clean = true, bool p_simplify = false);
Node *create_multiple_convex_collisions_node();
void create_multiple_convex_collisions();
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 64cfe4dca7..f890ceeb95 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -242,7 +242,7 @@ void NavigationAgent3D::_avoidance_done(Vector3 p_new_velocity) {
}
velocity_submitted = false;
- emit_signal("velocity_computed", p_new_velocity);
+ emit_signal(SNAME("velocity_computed"), p_new_velocity);
}
TypedArray<String> NavigationAgent3D::get_configuration_warnings() const {
@@ -296,7 +296,7 @@ void NavigationAgent3D::update_navigation() {
navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true);
navigation_finished = false;
nav_path_index = 0;
- emit_signal("path_changed");
+ emit_signal(SNAME("path_changed"));
}
if (navigation_path.size() == 0) {
@@ -312,7 +312,7 @@ void NavigationAgent3D::update_navigation() {
_check_distance_to_target();
nav_path_index -= 1;
navigation_finished = true;
- emit_signal("navigation_finished");
+ emit_signal(SNAME("navigation_finished"));
break;
}
}
@@ -322,7 +322,7 @@ void NavigationAgent3D::update_navigation() {
void NavigationAgent3D::_check_distance_to_target() {
if (!target_reached) {
if (distance_to_target() < target_desired_distance) {
- emit_signal("target_reached");
+ emit_signal(SNAME("target_reached"));
target_reached = true;
}
}
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 0afad62404..19abb3f33a 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -132,7 +132,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
Object::cast_to<MeshInstance3D>(debug_view)->set_mesh(navmesh->get_debug_mesh());
}
- emit_signal("navigation_mesh_changed");
+ emit_signal(SNAME("navigation_mesh_changed"));
update_gizmo();
update_configuration_warnings();
@@ -153,11 +153,11 @@ void _bake_navigation_mesh(void *p_user_data) {
Ref<NavigationMesh> nav_mesh = args->nav_region->get_navigation_mesh()->duplicate();
NavigationServer3D::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_region);
- args->nav_region->call_deferred("_bake_finished", nav_mesh);
+ args->nav_region->call_deferred(SNAME("_bake_finished"), nav_mesh);
memdelete(args);
} else {
ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist");
- args->nav_region->call_deferred("_bake_finished", Ref<NavigationMesh>());
+ args->nav_region->call_deferred(SNAME("_bake_finished"), Ref<NavigationMesh>());
memdelete(args);
}
}
@@ -174,7 +174,7 @@ void NavigationRegion3D::bake_navigation_mesh() {
void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_nav_mesh) {
set_navigation_mesh(p_nav_mesh);
bake_thread.wait_to_finish();
- emit_signal("bake_finished");
+ emit_signal(SNAME("bake_finished"));
}
TypedArray<String> NavigationRegion3D::get_configuration_warnings() const {
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index f78a2ff14e..d6c6ec75b4 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -328,10 +328,6 @@ void Node3D::set_rotation(const Vector3 &p_euler_rad) {
}
}
-void Node3D::set_rotation_degrees(const Vector3 &p_euler_deg) {
- set_rotation(p_euler_deg * (Math_PI / 180.0));
-}
-
void Node3D::set_scale(const Vector3 &p_scale) {
if (data.dirty & DIRTY_VECTORS) {
data.rotation = data.local_transform.basis.get_rotation();
@@ -361,10 +357,6 @@ Vector3 Node3D::get_rotation() const {
return data.rotation;
}
-Vector3 Node3D::get_rotation_degrees() const {
- return get_rotation() * (180.0 / Math_PI);
-}
-
Vector3 Node3D::get_scale() const {
if (data.dirty & DIRTY_VECTORS) {
data.scale = data.local_transform.basis.get_scale();
@@ -749,8 +741,6 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &Node3D::get_position);
ClassDB::bind_method(D_METHOD("set_rotation", "euler"), &Node3D::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node3D::get_rotation);
- ClassDB::bind_method(D_METHOD("set_rotation_degrees", "euler_degrees"), &Node3D::set_rotation_degrees);
- ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node3D::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node3D::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &Node3D::get_scale);
ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Node3D::set_global_transform);
@@ -814,9 +804,8 @@ void Node3D::_bind_methods() {
//ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM3D,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ;
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
ADD_GROUP("Matrix", "");
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index c7e36cf2ec..fe6324c796 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -131,12 +131,10 @@ public:
void set_position(const Vector3 &p_position);
void set_rotation(const Vector3 &p_euler_rad);
- void set_rotation_degrees(const Vector3 &p_euler_deg);
void set_scale(const Vector3 &p_scale);
Vector3 get_position() const;
Vector3 get_rotation() const;
- Vector3 get_rotation_degrees() const;
Vector3 get_scale() const;
void set_transform(const Transform3D &p_transform);
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index b0b9668fd2..7b736e689c 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -174,10 +174,12 @@ void OccluderInstance3D::set_occluder(const Ref<Occluder3D> &p_occluder) {
}
update_gizmo();
+ update_configuration_warnings();
}
void OccluderInstance3D::_occluder_changed() {
update_gizmo();
+ update_configuration_warnings();
}
Ref<Occluder3D> OccluderInstance3D::get_occluder() const {
@@ -186,6 +188,7 @@ Ref<Occluder3D> OccluderInstance3D::get_occluder() const {
void OccluderInstance3D::set_bake_mask(uint32_t p_mask) {
bake_mask = p_mask;
+ update_configuration_warnings();
}
uint32_t OccluderInstance3D::get_bake_mask() const {
@@ -314,6 +317,31 @@ OccluderInstance3D::BakeError OccluderInstance3D::bake(Node *p_from_node, String
return BAKE_ERROR_OK;
}
+TypedArray<String> OccluderInstance3D::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (!bool(GLOBAL_GET("rendering/occlusion_culling/use_occlusion_culling"))) {
+ warnings.push_back(TTR("Occlusion culling is disabled in the Project Settings, which means occlusion culling won't be performed in the root viewport.\nTo resolve this, open the Project Settings and enable Rendering > Occlusion Culling > Use Occlusion Culling."));
+ }
+
+ if (bake_mask == 0) {
+ // NOTE: This warning will not be emitted if none of the 20 checkboxes
+ // exposed in the editor are checked. This is because there are
+ // currently 12 unexposed layers in the editor inspector.
+ warnings.push_back(TTR("The Bake Mask has no bits enabled, which means baking will not produce any occluder meshes for this OccluderInstance3D.\nTo resolve this, enable at least one bit in the Bake Mask property."));
+ }
+
+ if (occluder.is_null()) {
+ warnings.push_back(TTR("No occluder mesh is defined in the Occluder property, so no occlusion culling will be performed using this OccluderInstance3D.\nTo resolve this, select the OccluderInstance3D then use the Bake Occluders button at the top of the 3D editor viewport."));
+ } else if (occluder->get_vertices().size() < 3) {
+ // Using the "New Occluder" dropdown button won't result in a correct occluder,
+ // so warn the user about this.
+ warnings.push_back(TTR("The occluder mesh has less than 3 vertices, so no occlusion culling will be performed using this OccluderInstance3D.\nTo generate a proper occluder mesh, select the OccluderInstance3D then use the Bake Occluders button at the top of the 3D editor viewport."));
+ }
+
+ return warnings;
+}
+
void OccluderInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bake_mask", "mask"), &OccluderInstance3D::set_bake_mask);
ClassDB::bind_method(D_METHOD("get_bake_mask"), &OccluderInstance3D::get_bake_mask);
diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h
index 4bb468274d..d382cd090e 100644
--- a/scene/3d/occluder_instance_3d.h
+++ b/scene/3d/occluder_instance_3d.h
@@ -82,6 +82,8 @@ protected:
static void _bind_methods();
public:
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
enum BakeError {
BAKE_ERROR_OK,
BAKE_ERROR_NO_SAVE_PATH,
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index de115b35e3..54ae2cef75 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -41,7 +41,7 @@ void Path3D::_curve_changed() {
update_gizmo();
}
if (is_inside_tree()) {
- emit_signal("curve_changed");
+ emit_signal(SNAME("curve_changed"));
}
// update the configuration warnings of all children of type PathFollow
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 8e10a37afb..760dbdadca 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -65,7 +65,7 @@ void PhysicsBody3D::_bind_methods() {
PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), p_mode);
+ set_body_mode(p_mode);
}
PhysicsBody3D::~PhysicsBody3D() {
@@ -118,10 +118,48 @@ Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_i
return Ref<KinematicCollision3D>();
}
-bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only) {
+bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only, bool p_cancel_sliding) {
Transform3D gt = get_global_transform();
bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes);
+ // Restore direction of motion to be along original motion,
+ // in order to avoid sliding due to recovery,
+ // but only if collision depth is low enough to avoid tunneling.
+ if (p_cancel_sliding) {
+ real_t motion_length = p_motion.length();
+ real_t precision = 0.001;
+
+ if (colliding) {
+ // Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
+ // so even in normal resting cases the depth can be a bit more than the margin.
+ precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
+
+ if (r_result.collision_depth > (real_t)p_margin + precision) {
+ p_cancel_sliding = false;
+ }
+ }
+
+ if (p_cancel_sliding) {
+ // When motion is null, recovery is the resulting motion.
+ Vector3 motion_normal;
+ if (motion_length > CMP_EPSILON) {
+ motion_normal = p_motion / motion_length;
+ }
+
+ // Check depth of recovery.
+ real_t projected_length = r_result.motion.dot(motion_normal);
+ Vector3 recovery = r_result.motion - motion_normal * projected_length;
+ real_t recovery_length = recovery.length();
+ // Fixes cases where canceling slide causes the motion to go too deep into the ground,
+ // because we're only taking rest information into account and not general recovery.
+ if (recovery_length < (real_t)p_margin + precision) {
+ // Apply adjustment to motion.
+ r_result.motion = motion_normal * projected_length;
+ r_result.remainder = p_motion - r_result.motion;
+ }
+ }
+ }
+
for (int i = 0; i < 3; i++) {
if (locked_axis & (1 << i)) {
r_result.motion[i] = 0;
@@ -200,11 +238,18 @@ void StaticBody3D::set_kinematic_motion_enabled(bool p_enabled) {
kinematic_motion = p_enabled;
if (kinematic_motion) {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
+ set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
} else {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
+ set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
}
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ return;
+ }
+#endif
+
_update_kinematic_motion();
}
@@ -222,6 +267,57 @@ void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
}
}
+void StaticBody3D::set_sync_to_physics(bool p_enable) {
+ if (sync_to_physics == p_enable) {
+ return;
+ }
+
+ sync_to_physics = p_enable;
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ return;
+ }
+#endif
+
+ if (kinematic_motion) {
+ _update_kinematic_motion();
+ }
+}
+
+bool StaticBody3D::is_sync_to_physics_enabled() const {
+ return sync_to_physics;
+}
+
+void StaticBody3D::_direct_state_changed(Object *p_state) {
+ PhysicsDirectBodyState3D *state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
+ ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
+
+ linear_velocity = state->get_linear_velocity();
+ angular_velocity = state->get_angular_velocity();
+
+ if (!sync_to_physics) {
+ return;
+ }
+
+ last_valid_transform = state->get_transform();
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+ _on_transform_changed();
+}
+
+TypedArray<String> StaticBody3D::get_configuration_warnings() const {
+ TypedArray<String> warnings = PhysicsBody3D::get_configuration_warnings();
+
+ if (sync_to_physics && !kinematic_motion) {
+ warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled."));
+ }
+
+ return warnings;
+}
+
void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
constant_angular_velocity = p_vel;
@@ -249,35 +345,70 @@ Vector3 StaticBody3D::get_angular_velocity() const {
}
void StaticBody3D::_notification(int p_what) {
- if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ last_valid_transform = get_global_transform();
+ } break;
+
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ // Used by sync to physics, send the new transform to the physics...
+ Transform3D new_transform = get_global_transform();
+
+ real_t delta_time = get_physics_process_delta_time();
+ new_transform.origin += constant_linear_velocity * delta_time;
+
+ real_t ang_vel = constant_angular_velocity.length();
+ if (!Math::is_zero_approx(ang_vel)) {
+ Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
+ Basis rot(ang_vel_axis, ang_vel * delta_time);
+ new_transform.basis = rot * new_transform.basis;
+ new_transform.orthonormalize();
+ }
+
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
+
+ // ... but then revert changes.
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+ _on_transform_changed();
+ } break;
+
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
#endif
- ERR_FAIL_COND(!kinematic_motion);
+ ERR_FAIL_COND(!kinematic_motion);
- real_t delta_time = get_physics_process_delta_time();
+ Transform3D new_transform = get_global_transform();
- Transform3D new_transform = get_global_transform();
- new_transform.origin += constant_linear_velocity * delta_time;
+ real_t delta_time = get_physics_process_delta_time();
+ new_transform.origin += constant_linear_velocity * delta_time;
- real_t ang_vel = constant_angular_velocity.length();
- if (!Math::is_zero_approx(ang_vel)) {
- Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
- Basis rot(ang_vel_axis, ang_vel * delta_time);
- new_transform.basis = rot * new_transform.basis;
- new_transform.orthonormalize();
- }
+ real_t ang_vel = constant_angular_velocity.length();
+ if (!Math::is_zero_approx(ang_vel)) {
+ Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
+ Basis rot(ang_vel_axis, ang_vel * delta_time);
+ new_transform.basis = rot * new_transform.basis;
+ new_transform.orthonormalize();
+ }
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
+ if (sync_to_physics) {
+ // Propagate transform change to node.
+ set_global_transform(new_transform);
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
- // Propagate transform change to node.
- set_ignore_transform_notification(true);
- set_global_transform(new_transform);
- set_ignore_transform_notification(false);
- _on_transform_changed();
+ // Propagate transform change to node.
+ set_ignore_transform_notification(true);
+ set_global_transform(new_transform);
+ set_ignore_transform_notification(false);
+ _on_transform_changed();
+ }
+ } break;
}
}
@@ -293,22 +424,14 @@ void StaticBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody3D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody3D::is_sync_to_physics_enabled);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
-}
-
-void StaticBody3D::_direct_state_changed(Object *p_state) {
-#ifdef DEBUG_ENABLED
- PhysicsDirectBodyState3D *state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
- ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
-#else
- PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state; //trust it
-#endif
-
- linear_velocity = state->get_linear_velocity();
- angular_velocity = state->get_angular_velocity();
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
StaticBody3D::StaticBody3D() :
@@ -332,18 +455,26 @@ void StaticBody3D::_update_kinematic_motion() {
}
#endif
+ if (kinematic_motion && sync_to_physics) {
+ set_only_update_transform_changes(true);
+ set_notify_local_transform(true);
+ } else {
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
+ }
+
+ bool needs_physics_process = false;
if (kinematic_motion) {
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &StaticBody3D::_direct_state_changed));
if (!constant_angular_velocity.is_equal_approx(Vector3()) || !constant_linear_velocity.is_equal_approx(Vector3())) {
- set_physics_process_internal(true);
- return;
+ needs_physics_process = true;
}
} else {
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
}
- set_physics_process_internal(false);
+ set_physics_process_internal(needs_physics_process);
}
void RigidBody3D::_body_enter_tree(ObjectID p_id) {
@@ -565,18 +696,19 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
void RigidBody3D::_notification(int p_what) {
#ifdef TOOLS_ENABLED
- if (p_what == NOTIFICATION_ENTER_TREE) {
- if (Engine::get_singleton()->is_editor_hint()) {
- set_notify_local_transform(true); //used for warnings and only in editor
- }
- }
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ set_notify_local_transform(true); //used for warnings and only in editor
+ }
+ } break;
- if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
- if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
- }
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ }
+ } break;
}
-
#endif
}
@@ -584,18 +716,16 @@ void RigidBody3D::set_mode(Mode p_mode) {
mode = p_mode;
switch (p_mode) {
case MODE_DYNAMIC: {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC);
+ set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC);
} break;
case MODE_STATIC: {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
-
+ set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
} break;
case MODE_DYNAMIC_LOCKED: {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED);
-
+ set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED);
} break;
case MODE_KINEMATIC: {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
+ set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
} break;
}
update_configuration_warnings();
@@ -902,7 +1032,7 @@ void RigidBody3D::_bind_methods() {
BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState3D")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Dynamic,Static,DynamicLocked,Kinematic"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
@@ -967,6 +1097,15 @@ void CharacterBody3D::move_and_slide() {
}
}
+ Vector3 current_floor_velocity = floor_velocity;
+ if (on_floor && on_floor_body.is_valid()) {
+ //this approach makes sure there is less delay between the actual body velocity and the one we saved
+ PhysicsDirectBodyState3D *bs = PhysicsServer3D::get_singleton()->body_get_direct_state(on_floor_body);
+ if (bs) {
+ current_floor_velocity = bs->get_linear_velocity();
+ }
+ }
+
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
Vector3 motion = (floor_velocity + linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
@@ -978,15 +1117,17 @@ void CharacterBody3D::move_and_slide() {
floor_normal = Vector3();
floor_velocity = Vector3();
- int slide_count = max_slides;
- while (slide_count) {
+ // No sliding on first attempt to keep floor motion stable when possible,
+ // when stop on slope is enabled.
+ bool sliding_enabled = !stop_on_slope;
+ for (int iteration = 0; iteration < max_slides; ++iteration) {
PhysicsServer3D::MotionResult result;
bool found_collision = false;
for (int i = 0; i < 2; ++i) {
bool collided;
if (i == 0) { //collide
- collided = move_and_collide(motion, infinite_inertia, result, margin);
+ collided = move_and_collide(motion, infinite_inertia, result, margin, true, false, !sliding_enabled);
if (!collided) {
motion = Vector3(); //clear because no collision happened and motion completed
}
@@ -1002,7 +1143,6 @@ void CharacterBody3D::move_and_slide() {
found_collision = true;
motion_results.push_back(result);
- motion = result.remainder;
if (up_direction == Vector3()) {
//all is a wall
@@ -1016,9 +1156,13 @@ void CharacterBody3D::move_and_slide() {
floor_velocity = result.collider_velocity;
if (stop_on_slope) {
- if ((body_velocity_normal + up_direction).length() < 0.01 && result.motion.length() < 1) {
+ if ((body_velocity_normal + up_direction).length() < 0.01) {
Transform3D gt = get_global_transform();
- gt.origin -= result.motion.slide(up_direction);
+ if (result.motion.length() > margin) {
+ gt.origin -= result.motion.slide(up_direction);
+ } else {
+ gt.origin -= result.motion;
+ }
set_global_transform(gt);
linear_velocity = Vector3();
return;
@@ -1031,22 +1175,26 @@ void CharacterBody3D::move_and_slide() {
}
}
- motion = motion.slide(result.collision_normal);
- linear_velocity = linear_velocity.slide(result.collision_normal);
+ if (sliding_enabled || !on_floor) {
+ motion = result.remainder.slide(result.collision_normal);
+ linear_velocity = linear_velocity.slide(result.collision_normal);
- for (int j = 0; j < 3; j++) {
- if (locked_axis & (1 << j)) {
- linear_velocity[j] = 0.0;
+ for (int j = 0; j < 3; j++) {
+ if (locked_axis & (1 << j)) {
+ linear_velocity[j] = 0.0;
+ }
}
+ } else {
+ motion = result.remainder;
}
}
+
+ sliding_enabled = true;
}
if (!found_collision || motion == Vector3()) {
break;
}
-
- --slide_count;
}
if (!was_on_floor || snap == Vector3()) {
@@ -1056,7 +1204,7 @@ void CharacterBody3D::move_and_slide() {
// Apply snap.
Transform3D gt = get_global_transform();
PhysicsServer3D::MotionResult result;
- if (move_and_collide(snap, infinite_inertia, result, margin, false, true)) {
+ if (move_and_collide(snap, infinite_inertia, result, margin, false, true, false)) {
bool apply = true;
if (up_direction != Vector3()) {
if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
@@ -1067,7 +1215,11 @@ void CharacterBody3D::move_and_slide() {
if (stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
- result.motion = result.motion.project(up_direction);
+ if (result.motion.length() > margin) {
+ result.motion = result.motion.project(up_direction);
+ } else {
+ result.motion = Vector3();
+ }
}
} else {
apply = false; //snapped with floor direction, but did not snap to a floor, do not snap.
@@ -1208,14 +1360,6 @@ void CharacterBody3D::set_floor_max_angle(real_t p_radians) {
floor_max_angle = p_radians;
}
-real_t CharacterBody3D::get_floor_max_angle_degrees() const {
- return Math::rad2deg(floor_max_angle);
-}
-
-void CharacterBody3D::set_floor_max_angle_degrees(real_t p_degrees) {
- floor_max_angle = Math::deg2rad(p_degrees);
-}
-
const Vector3 &CharacterBody3D::get_snap() const {
return snap;
}
@@ -1233,14 +1377,16 @@ void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) {
}
void CharacterBody3D::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- // Reset move_and_slide() data.
- on_floor = false;
- on_floor_body = RID();
- on_ceiling = false;
- on_wall = false;
- motion_results.clear();
- floor_velocity = Vector3();
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ // Reset move_and_slide() data.
+ on_floor = false;
+ on_floor_body = RID();
+ on_ceiling = false;
+ on_wall = false;
+ motion_results.clear();
+ floor_velocity = Vector3();
+ } break;
}
}
@@ -1260,8 +1406,6 @@ void CharacterBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody3D::set_max_slides);
ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody3D::get_floor_max_angle);
ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody3D::set_floor_max_angle);
- ClassDB::bind_method(D_METHOD("get_floor_max_angle_degrees"), &CharacterBody3D::get_floor_max_angle_degrees);
- ClassDB::bind_method(D_METHOD("set_floor_max_angle_degrees", "degrees"), &CharacterBody3D::set_floor_max_angle_degrees);
ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody3D::get_snap);
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody3D::set_snap);
ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody3D::get_up_direction);
@@ -1280,8 +1424,7 @@ void CharacterBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_floor_max_angle", "get_floor_max_angle");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle_degrees", PROPERTY_HINT_RANGE, "0,180,0.1", PROPERTY_USAGE_EDITOR), "set_floor_max_angle_degrees", "get_floor_max_angle_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "snap"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
@@ -2095,7 +2238,8 @@ void PhysicalBone3D::_notification(int p_what) {
_reload_joint();
}
break;
- case NOTIFICATION_EXIT_TREE:
+
+ case NOTIFICATION_EXIT_TREE: {
if (parent_skeleton) {
if (-1 != bone_id) {
parent_skeleton->unbind_physical_bone_from_bone(bone_id);
@@ -2105,12 +2249,13 @@ void PhysicalBone3D::_notification(int p_what) {
}
parent_skeleton = nullptr;
PhysicsServer3D::get_singleton()->joint_clear(joint);
- break;
- case NOTIFICATION_TRANSFORM_CHANGED:
+ } break;
+
+ case NOTIFICATION_TRANSFORM_CHANGED: {
if (Engine::get_singleton()->is_editor_hint()) {
update_offset();
}
- break;
+ } break;
}
}
@@ -2156,8 +2301,6 @@ void PhysicalBone3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone3D::get_joint_offset);
ClassDB::bind_method(D_METHOD("set_joint_rotation", "euler"), &PhysicalBone3D::set_joint_rotation);
ClassDB::bind_method(D_METHOD("get_joint_rotation"), &PhysicalBone3D::get_joint_rotation);
- ClassDB::bind_method(D_METHOD("set_joint_rotation_degrees", "euler_degrees"), &PhysicalBone3D::set_joint_rotation_degrees);
- ClassDB::bind_method(D_METHOD("get_joint_rotation_degrees"), &PhysicalBone3D::get_joint_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone3D::set_body_offset);
ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone3D::get_body_offset);
@@ -2192,12 +2335,11 @@ void PhysicalBone3D::_bind_methods() {
ADD_GROUP("Joint", "joint_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "joint_offset"), "set_joint_offset", "get_joint_offset");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_joint_rotation_degrees", "get_joint_rotation_degrees");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_joint_rotation", "get_joint_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation", PROPERTY_HINT_RANGE, "-360,360,0.01,or_lesser,or_greater,radians"), "set_joint_rotation", "get_joint_rotation");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "body_offset"), "set_body_offset", "get_body_offset");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale");
@@ -2428,14 +2570,6 @@ Vector3 PhysicalBone3D::get_joint_rotation() const {
return joint_offset.basis.get_rotation();
}
-void PhysicalBone3D::set_joint_rotation_degrees(const Vector3 &p_euler_deg) {
- set_joint_rotation(p_euler_deg * (Math_PI / 180.0));
-}
-
-Vector3 PhysicalBone3D::get_joint_rotation_degrees() const {
- return get_joint_rotation() * (180.0 / Math_PI);
-}
-
const Transform3D &PhysicalBone3D::get_body_offset() const {
return body_offset;
}
@@ -2605,7 +2739,7 @@ void PhysicalBone3D::_start_physics_simulation() {
return;
}
reset_to_rest_position();
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC);
+ set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC);
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_direct_state_changed));
@@ -2618,11 +2752,11 @@ void PhysicalBone3D::_stop_physics_simulation() {
return;
}
if (parent_skeleton->get_animate_physical_bones()) {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
+ set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
} else {
- PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
+ set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), 0);
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0);
}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 7d7adf1624..0ef9c78f3b 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -53,7 +53,7 @@ protected:
Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false, real_t p_margin = 0.001);
public:
- bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
+ bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false, bool p_cancel_sliding = true);
bool test_move(const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001);
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
@@ -82,13 +82,16 @@ class StaticBody3D : public PhysicsBody3D {
Ref<PhysicsMaterial> physics_material_override;
bool kinematic_motion = false;
+ bool sync_to_physics = false;
+
+ Transform3D last_valid_transform;
+
+ void _direct_state_changed(Object *p_state);
protected:
void _notification(int p_what);
static void _bind_methods();
- void _direct_state_changed(Object *p_state);
-
public:
void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
Ref<PhysicsMaterial> get_physics_material_override() const;
@@ -102,6 +105,8 @@ public:
virtual Vector3 get_linear_velocity() const override;
virtual Vector3 get_angular_velocity() const override;
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
StaticBody3D();
private:
@@ -111,6 +116,9 @@ private:
void set_kinematic_motion_enabled(bool p_enabled);
bool is_kinematic_motion_enabled() const;
+
+ void set_sync_to_physics(bool p_enable);
+ bool is_sync_to_physics_enabled() const;
};
class RigidBody3D : public PhysicsBody3D {
@@ -251,7 +259,7 @@ public:
void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
void apply_torque_impulse(const Vector3 &p_impulse);
- TypedArray<String> get_configuration_warnings() const override;
+ virtual TypedArray<String> get_configuration_warnings() const override;
RigidBody3D();
~RigidBody3D();
@@ -307,9 +315,6 @@ private:
real_t get_floor_max_angle() const;
void set_floor_max_angle(real_t p_radians);
- real_t get_floor_max_angle_degrees() const;
- void set_floor_max_angle_degrees(real_t p_degrees);
-
const Vector3 &get_snap() const;
void set_snap(const Vector3 &p_snap);
@@ -551,9 +556,6 @@ public:
void set_joint_rotation(const Vector3 &p_euler_rad);
Vector3 get_joint_rotation() const;
- void set_joint_rotation_degrees(const Vector3 &p_euler_deg);
- Vector3 get_joint_rotation_degrees() const;
-
void set_body_offset(const Transform3D &p_offset);
const Transform3D &get_body_offset() const;
diff --git a/scene/3d/proximity_group_3d.cpp b/scene/3d/proximity_group_3d.cpp
index 9d9fea68b0..037110eaa1 100644
--- a/scene/3d/proximity_group_3d.cpp
+++ b/scene/3d/proximity_group_3d.cpp
@@ -130,7 +130,7 @@ void ProximityGroup3D::_proximity_group_broadcast(String p_method, Variant p_par
if (dispatch_mode == MODE_PROXY) {
get_parent()->call(p_method, p_parameters);
} else {
- emit_signal("broadcast", p_method, p_parameters);
+ emit_signal(SNAME("broadcast"), p_method, p_parameters);
}
}
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index 7762156b4a..c289fc4fd7 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -232,7 +232,7 @@ void ReflectionProbe::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once (Fast),Always (Slow)"), "set_update_mode", "get_update_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,16384,0.1,or_greater"), "set_max_distance", "get_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,16384,0.1,or_greater,exp"), "set_max_distance", "get_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "box_projection"), "set_enable_box_projection", "is_box_projection_enabled");
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index 15c2da3ae0..4bf20c89c5 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -55,7 +55,7 @@ private:
RID probe;
float intensity = 1.0;
float max_distance = 0.0;
- Vector3 extents = Vector3(1, 1, 1);
+ Vector3 extents = Vector3(10, 10, 10);
Vector3 origin_offset = Vector3(0, 0, 0);
bool box_projection = false;
bool enable_shadows = false;
diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp
index a7b3a6f1ec..d5fb1fa6ab 100644
--- a/scene/3d/remote_transform_3d.cpp
+++ b/scene/3d/remote_transform_3d.cpp
@@ -34,7 +34,7 @@ void RemoteTransform3D::_update_cache() {
cache = ObjectID();
if (has_node(remote_node)) {
Node *node = get_node(remote_node);
- if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) {
+ if (!node || this == node || node->is_ancestor_of(this) || this->is_ancestor_of(node)) {
return;
}
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 9592fe5849..05530c39a1 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -81,7 +81,7 @@ void SoftBodyRenderingServerHandler::close() {
}
void SoftBodyRenderingServerHandler::commit_changes() {
- RS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer);
+ RS::get_singleton()->mesh_surface_update_vertex_region(mesh, surface, 0, buffer);
}
void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) {
@@ -266,12 +266,13 @@ void SoftBody3D::_notification(int p_what) {
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space);
prepare_physics_server();
} break;
+
case NOTIFICATION_READY: {
if (!parent_collision_ignore.is_empty()) {
add_collision_exception_with(get_node(parent_collision_ignore));
}
-
} break;
+
case NOTIFICATION_TRANSFORM_CHANGED: {
if (Engine::get_singleton()->is_editor_hint()) {
_reset_points_offsets();
@@ -285,27 +286,36 @@ void SoftBody3D::_notification(int p_what) {
set_as_top_level(true);
set_transform(Transform3D());
set_notify_transform(true);
-
} break;
+
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
-
} break;
+
case NOTIFICATION_EXIT_WORLD: {
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, RID());
-
} break;
- }
-#ifdef TOOLS_ENABLED
+ case NOTIFICATION_DISABLED: {
+ if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
+ prepare_physics_server();
+ }
+ } break;
- if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
- if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
- }
- }
+ case NOTIFICATION_ENABLED: {
+ if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
+ prepare_physics_server();
+ }
+ } break;
+#ifdef TOOLS_ENABLED
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ }
+ } break;
#endif
+ }
}
void SoftBody3D::_bind_methods() {
@@ -326,6 +336,9 @@ void SoftBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody3D::set_parent_collision_ignore);
ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody3D::get_parent_collision_ignore);
+ ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftBody3D::set_disable_mode);
+ ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftBody3D::get_disable_mode);
+
ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody3D::get_collision_exceptions);
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody3D::add_collision_exception_with);
ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody3D::remove_collision_exception_with);
@@ -364,6 +377,11 @@ void SoftBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable");
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,KeepActive"), "set_disable_mode", "get_disable_mode");
+
+ BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE);
+ BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE);
}
TypedArray<String> SoftBody3D::get_configuration_warnings() const {
@@ -407,8 +425,8 @@ void SoftBody3D::_draw_soft_mesh() {
/// Necessary in order to render the mesh correctly (Soft body nodes are in global space)
simulation_started = true;
- call_deferred("set_as_top_level", true);
- call_deferred("set_transform", Transform3D());
+ call_deferred(SNAME("set_as_top_level"), true);
+ call_deferred(SNAME("set_transform"), Transform3D());
}
_update_physics_server();
@@ -421,6 +439,7 @@ void SoftBody3D::_draw_soft_mesh() {
}
void SoftBody3D::prepare_physics_server() {
+#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
if (get_mesh().is_valid()) {
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
@@ -430,8 +449,9 @@ void SoftBody3D::prepare_physics_server() {
return;
}
+#endif
- if (get_mesh().is_valid()) {
+ if (get_mesh().is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) {
become_mesh_owner();
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh));
@@ -527,6 +547,28 @@ bool SoftBody3D::get_collision_layer_bit(int p_bit) const {
return get_collision_layer() & (1 << p_bit);
}
+void SoftBody3D::set_disable_mode(DisableMode p_mode) {
+ if (disable_mode == p_mode) {
+ return;
+ }
+
+ bool inside_tree = is_inside_tree();
+
+ if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) {
+ prepare_physics_server();
+ }
+
+ disable_mode = p_mode;
+
+ if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) {
+ prepare_physics_server();
+ }
+}
+
+SoftBody3D::DisableMode SoftBody3D::get_disable_mode() const {
+ return disable_mode;
+}
+
void SoftBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) {
parent_collision_ignore = p_parent_collision_ignore;
}
diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h
index 0d0d39d48f..81aa0c10c6 100644
--- a/scene/3d/soft_body_3d.h
+++ b/scene/3d/soft_body_3d.h
@@ -67,6 +67,11 @@ class SoftBody3D : public MeshInstance3D {
GDCLASS(SoftBody3D, MeshInstance3D);
public:
+ enum DisableMode {
+ DISABLE_MODE_REMOVE,
+ DISABLE_MODE_KEEP_ACTIVE,
+ };
+
struct PinnedPoint {
int point_index = -1;
NodePath spatial_attachment_path;
@@ -83,6 +88,8 @@ private:
RID physics_rid;
+ DisableMode disable_mode = DISABLE_MODE_REMOVE;
+
bool mesh_owner = false;
uint32_t collision_mask = 1;
uint32_t collision_layer = 1;
@@ -137,6 +144,9 @@ public:
void set_collision_layer_bit(int p_bit, bool p_value);
bool get_collision_layer_bit(int p_bit) const;
+ void set_disable_mode(DisableMode p_mode);
+ DisableMode get_disable_mode() const;
+
void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore);
const NodePath &get_parent_collision_ignore() const;
@@ -192,4 +202,6 @@ private:
int _has_pinned_point(int p_point_index) const;
};
+VARIANT_ENUM_CAST(SoftBody3D::DisableMode);
+
#endif // SOFT_PHYSICS_BODY_H
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 9ec461d973..2a53dd6aca 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -164,6 +164,8 @@ void SpriteBase3D::_im_update() {
_draw();
pending_update = false;
+
+ //texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
}
void SpriteBase3D::_queue_update() {
@@ -204,6 +206,7 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
+
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -313,6 +316,9 @@ void SpriteBase3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect);
ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh);
+ ClassDB::bind_method(D_METHOD("_queue_update"), &SpriteBase3D::_queue_update);
+ ClassDB::bind_method(D_METHOD("_im_update"), &SpriteBase3D::_im_update);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
@@ -343,21 +349,89 @@ SpriteBase3D::SpriteBase3D() {
flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED;
}
- immediate = RenderingServer::get_singleton()->immediate_create();
- set_base(immediate);
+ material = RenderingServer::get_singleton()->material_create();
+ // Set defaults for material, names need to match up those in StandardMaterial3D
+ RS::get_singleton()->material_set_param(material, "albedo", Color(1, 1, 1, 1));
+ RS::get_singleton()->material_set_param(material, "specular", 0.5);
+ RS::get_singleton()->material_set_param(material, "metallic", 0.0);
+ RS::get_singleton()->material_set_param(material, "roughness", 1.0);
+ RS::get_singleton()->material_set_param(material, "uv1_offset", Vector3(0, 0, 0));
+ RS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1));
+ RS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0));
+ RS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1));
+ RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.98);
+
+ mesh = RenderingServer::get_singleton()->mesh_create();
+
+ PackedVector3Array mesh_vertices;
+ PackedVector3Array mesh_normals;
+ PackedFloat32Array mesh_tangents;
+ PackedColorArray mesh_colors;
+ PackedVector2Array mesh_uvs;
+ PackedInt32Array indices;
+
+ mesh_vertices.resize(4);
+ mesh_normals.resize(4);
+ mesh_tangents.resize(16);
+ mesh_colors.resize(4);
+ mesh_uvs.resize(4);
+
+ // create basic mesh and store format information
+ for (int i = 0; i < 4; i++) {
+ mesh_normals.write[i] = Vector3(0.0, 0.0, 0.0);
+ mesh_tangents.write[i * 4 + 0] = 0.0;
+ mesh_tangents.write[i * 4 + 1] = 0.0;
+ mesh_tangents.write[i * 4 + 2] = 0.0;
+ mesh_tangents.write[i * 4 + 3] = 0.0;
+ mesh_colors.write[i] = Color(1.0, 1.0, 1.0, 1.0);
+ mesh_uvs.write[i] = Vector2(0.0, 0.0);
+ mesh_vertices.write[i] = Vector3(0.0, 0.0, 0.0);
+ }
+
+ indices.resize(6);
+ indices.write[0] = 0;
+ indices.write[1] = 1;
+ indices.write[2] = 2;
+ indices.write[3] = 0;
+ indices.write[4] = 2;
+ indices.write[5] = 3;
+
+ Array mesh_array;
+ mesh_array.resize(RS::ARRAY_MAX);
+ mesh_array[RS::ARRAY_VERTEX] = mesh_vertices;
+ mesh_array[RS::ARRAY_NORMAL] = mesh_normals;
+ mesh_array[RS::ARRAY_TANGENT] = mesh_tangents;
+ mesh_array[RS::ARRAY_COLOR] = mesh_colors;
+ mesh_array[RS::ARRAY_TEX_UV] = mesh_uvs;
+ mesh_array[RS::ARRAY_INDEX] = indices;
+
+ RS::SurfaceData sd;
+ RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, mesh_array);
+
+ mesh_surface_format = sd.format;
+ vertex_buffer = sd.vertex_data;
+ attribute_buffer = sd.attribute_data;
+
+ sd.material = material;
+
+ RS::get_singleton()->mesh_surface_make_offsets_from_format(sd.format, sd.vertex_count, sd.index_count, mesh_surface_offsets, vertex_stride, attrib_stride, skin_stride);
+ RS::get_singleton()->mesh_add_surface(mesh, sd);
+ set_base(mesh);
}
SpriteBase3D::~SpriteBase3D() {
- RenderingServer::get_singleton()->free(immediate);
+ RenderingServer::get_singleton()->free(mesh);
+ RenderingServer::get_singleton()->free(material);
}
///////////////////////////////////////////
void Sprite3D::_draw() {
- RID immediate = get_immediate();
-
- RS::get_singleton()->immediate_clear(immediate);
+ if (get_base() != get_mesh()) {
+ set_base(get_mesh());
+ }
if (!texture.is_valid()) {
+ set_base(RID());
return;
}
Vector2 tsize = texture->get_size();
@@ -366,7 +440,7 @@ void Sprite3D::_draw() {
}
Rect2 base_rect;
- if (region_enabled) {
+ if (region) {
base_rect = region_rect;
} else {
base_rect = Rect2(0, 0, texture->get_width(), texture->get_height());
@@ -399,6 +473,7 @@ void Sprite3D::_draw() {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
+
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -426,6 +501,7 @@ void Sprite3D::_draw() {
SWAP(uvs[0], uvs[1]);
SWAP(uvs[2], uvs[3]);
}
+
if (is_flipped_v()) {
SWAP(uvs[0], uvs[3]);
SWAP(uvs[1], uvs[2]);
@@ -442,11 +518,6 @@ void Sprite3D::_draw() {
tangent = Plane(1, 0, 0, 1);
}
- RID mat = StandardMaterial3D::get_material_rid_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);
- RS::get_singleton()->immediate_set_material(immediate, mat);
-
- RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid());
-
int x_axis = ((axis + 1) % 3);
int y_axis = ((axis + 2) % 3);
@@ -466,31 +537,80 @@ void Sprite3D::_draw() {
AABB aabb;
- for (int i = 0; i < 6; i++) {
- static const int index[6] = { 0, 1, 2, 0, 2, 3 };
+ // Everything except position and UV is compressed
+ uint8_t *vertex_write_buffer = vertex_buffer.ptrw();
+ uint8_t *attribute_write_buffer = attribute_buffer.ptrw();
+
+ uint32_t v_normal;
+ {
+ Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
+
+ uint32_t value = 0;
+ value |= CLAMP(int(n.x * 1023.0), 0, 1023);
+ value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
+
+ v_normal = value;
+ }
+ uint32_t v_tangent;
+ {
+ Plane t = tangent;
+ uint32_t value = 0;
+ value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023);
+ value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
+ if (t.d > 0) {
+ value |= 3 << 30;
+ }
+ v_tangent = value;
+ }
- RS::get_singleton()->immediate_normal(immediate, normal);
- RS::get_singleton()->immediate_tangent(immediate, tangent);
- RS::get_singleton()->immediate_color(immediate, color);
- RS::get_singleton()->immediate_uv(immediate, uvs[index[i]]);
+ uint8_t v_color[4] = {
+ uint8_t(CLAMP(color.r * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(color.g * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(color.b * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(color.a * 255.0, 0.0, 255.0))
+ };
+ for (int i = 0; i < 4; i++) {
Vector3 vtx;
- vtx[x_axis] = vertices[index[i]][0];
- vtx[y_axis] = vertices[index[i]][1];
- RS::get_singleton()->immediate_vertex(immediate, vtx);
+ vtx[x_axis] = vertices[i][0];
+ vtx[y_axis] = vertices[i][1];
if (i == 0) {
aabb.position = vtx;
aabb.size = Vector3();
} else {
aabb.expand_to(vtx);
}
+
+ float v_uv[2] = { (float)uvs[i].x, (float)uvs[i].y };
+ memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8);
+
+ float v_vertex[3] = { (float)vtx.x, (float)vtx.y, (float)vtx.z };
+
+ memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
+ memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4);
+ memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4);
+ memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 4);
}
+
+ RID mesh = get_mesh();
+ RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer);
+ RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer);
+
+ RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb);
set_aabb(aabb);
- RS::get_singleton()->immediate_end(immediate);
-}
-void Sprite3D::_texture_changed() {
- _queue_update();
+ 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);
+ if (last_shader != shader_rid) {
+ RS::get_singleton()->material_set_shader(get_material(), shader_rid);
+ last_shader = shader_rid;
+ }
+ if (last_texture != texture->get_rid()) {
+ RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
+ last_texture = texture->get_rid();
+ }
}
void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
@@ -498,38 +618,36 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
return;
}
if (texture.is_valid()) {
- texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
+ texture->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update"));
}
texture = p_texture;
if (texture.is_valid()) {
- texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
+ texture->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update"));
}
_queue_update();
- emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
Ref<Texture2D> Sprite3D::get_texture() const {
return texture;
}
-void Sprite3D::set_region_enabled(bool p_region_enabled) {
- if (p_region_enabled == region_enabled) {
+void Sprite3D::set_region_enabled(bool p_region) {
+ if (p_region == region) {
return;
}
- region_enabled = p_region_enabled;
+ region = p_region;
_queue_update();
- notify_property_list_changed();
}
bool Sprite3D::is_region_enabled() const {
- return region_enabled;
+ return region;
}
void Sprite3D::set_region_rect(const Rect2 &p_region_rect) {
bool changed = region_rect != p_region_rect;
region_rect = p_region_rect;
- if (region_enabled && changed) {
+ if (region && changed) {
_queue_update();
}
}
@@ -596,7 +714,7 @@ Rect2 Sprite3D::get_item_rect() const {
Size2i s;
- if (region_enabled) {
+ if (region) {
s = region_rect.size;
} else {
s = texture->get_size();
@@ -625,10 +743,6 @@ void Sprite3D::_validate_property(PropertyInfo &property) const {
if (property.name == "frame_coords") {
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
-
- if (!region_enabled && property.name == "region_rect") {
- property.usage = PROPERTY_USAGE_NOEDITOR;
- }
}
void Sprite3D::_bind_methods() {
@@ -653,32 +767,28 @@ void Sprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite3D::set_hframes);
ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite3D::get_hframes);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_GROUP("Animation", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
ADD_SIGNAL(MethodInfo("frame_changed"));
- ADD_SIGNAL(MethodInfo("texture_changed"));
}
Sprite3D::Sprite3D() {
- region_enabled = false;
- frame = 0;
- vframes = 1;
- hframes = 1;
}
////////////////////////////////////////
void AnimatedSprite3D::_draw() {
- RID immediate = get_immediate();
- RS::get_singleton()->immediate_clear(immediate);
+ if (get_base() != get_mesh()) {
+ set_base(get_mesh());
+ }
if (frames.is_null()) {
return;
@@ -694,7 +804,8 @@ void AnimatedSprite3D::_draw() {
Ref<Texture2D> texture = frames->get_frame(animation, frame);
if (!texture.is_valid()) {
- return; //no texture no life
+ set_base(RID());
+ return; //no texuture no life
}
Vector2 tsize = texture->get_size();
if (tsize.x == 0 || tsize.y == 0) {
@@ -729,6 +840,7 @@ void AnimatedSprite3D::_draw() {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
+
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -772,12 +884,6 @@ void AnimatedSprite3D::_draw() {
tangent = Plane(1, 0, 0, -1);
}
- RID mat = StandardMaterial3D::get_material_rid_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);
-
- RS::get_singleton()->immediate_set_material(immediate, mat);
-
- RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid());
-
int x_axis = ((axis + 1) % 3);
int y_axis = ((axis + 2) % 3);
@@ -797,30 +903,79 @@ void AnimatedSprite3D::_draw() {
AABB aabb;
- for (int i = 0; i < 6; i++) {
- static const int indices[6] = {
- 0, 1, 2,
- 0, 2, 3
- };
+ // Everything except position and UV is compressed
+ uint8_t *vertex_write_buffer = vertex_buffer.ptrw();
+ uint8_t *attribute_write_buffer = attribute_buffer.ptrw();
+
+ uint32_t v_normal;
+ {
+ Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
+
+ uint32_t value = 0;
+ value |= CLAMP(int(n.x * 1023.0), 0, 1023);
+ value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
+
+ v_normal = value;
+ }
+ uint32_t v_tangent;
+ {
+ Plane t = tangent;
+ uint32_t value = 0;
+ value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023);
+ value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
+ if (t.d > 0) {
+ value |= 3 << 30;
+ }
+ v_tangent = value;
+ }
- RS::get_singleton()->immediate_normal(immediate, normal);
- RS::get_singleton()->immediate_tangent(immediate, tangent);
- RS::get_singleton()->immediate_color(immediate, color);
- RS::get_singleton()->immediate_uv(immediate, uvs[indices[i]]);
+ uint8_t v_color[4] = {
+ uint8_t(CLAMP(color.r * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(color.g * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(color.b * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(color.a * 255.0, 0.0, 255.0))
+ };
+ for (int i = 0; i < 4; i++) {
Vector3 vtx;
- vtx[x_axis] = vertices[indices[i]][0];
- vtx[y_axis] = vertices[indices[i]][1];
- RS::get_singleton()->immediate_vertex(immediate, vtx);
+ vtx[x_axis] = vertices[i][0];
+ vtx[y_axis] = vertices[i][1];
if (i == 0) {
aabb.position = vtx;
aabb.size = Vector3();
} else {
aabb.expand_to(vtx);
}
+
+ float v_uv[2] = { (float)uvs[i].x, (float)uvs[i].y };
+ memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8);
+
+ float v_vertex[3] = { (float)vtx.x, (float)vtx.y, (float)vtx.z };
+ memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
+ memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4);
+ memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4);
+ memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 4);
}
+
+ RID mesh = get_mesh();
+ RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer);
+ RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer);
+
+ RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb);
set_aabb(aabb);
- RS::get_singleton()->immediate_end(immediate);
+
+ 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);
+ if (last_shader != shader_rid) {
+ RS::get_singleton()->material_set_shader(get_material(), shader_rid);
+ last_shader = shader_rid;
+ }
+ if (last_texture != texture->get_rid()) {
+ RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
+ last_texture = texture->get_rid();
+ }
}
void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
@@ -914,11 +1069,11 @@ void AnimatedSprite3D::_notification(int p_what) {
void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
if (frames.is_valid()) {
- frames->disconnect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
+ frames->disconnect("changed", Callable(this, "_res_changed"));
}
frames = p_frames;
if (frames.is_valid()) {
- frames->connect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
+ frames->connect("changed", Callable(this, "_res_changed"));
}
if (!frames.is_valid()) {
@@ -944,9 +1099,8 @@ void AnimatedSprite3D::set_frame(int p_frame) {
if (frames->has_animation(animation)) {
int limit = frames->get_frame_count(animation);
- if (p_frame >= limit) {
+ if (p_frame >= limit)
p_frame = limit - 1;
- }
}
if (p_frame < 0) {
@@ -960,7 +1114,6 @@ void AnimatedSprite3D::set_frame(int p_frame) {
frame = p_frame;
_reset_timeout();
_queue_update();
-
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
@@ -1061,8 +1214,7 @@ StringName AnimatedSprite3D::get_animation() const {
}
TypedArray<String> AnimatedSprite3D::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
-
+ TypedArray<String> warnings = SpriteBase3D::get_configuration_warnings();
if (frames.is_null()) {
warnings.push_back(TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames."));
}
@@ -1087,11 +1239,13 @@ void AnimatedSprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite3D::set_frame);
ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame);
+ ClassDB::bind_method(D_METHOD("_res_changed"), &AnimatedSprite3D::_res_changed);
+
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_SIGNAL(MethodInfo("animation_finished"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames");
- ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing");
}
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index e3dd117804..404ef57e6a 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -31,8 +31,8 @@
#ifndef SPRITE_3D_H
#define SPRITE_3D_H
+#include "scene/2d/animated_sprite_2d.h"
#include "scene/3d/visual_instance_3d.h"
-#include "scene/resources/sprite_frames.h"
class SpriteBase3D : public GeometryInstance3D {
GDCLASS(SpriteBase3D, GeometryInstance3D);
@@ -75,9 +75,10 @@ private:
float pixel_size = 0.01;
AABB aabb;
- RID immediate;
+ RID mesh;
+ RID material;
- bool flags[FLAG_MAX];
+ bool flags[FLAG_MAX] = {};
AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED;
StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
bool pending_update = false;
@@ -91,7 +92,17 @@ protected:
static void _bind_methods();
virtual void _draw() = 0;
_FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; }
- _FORCE_INLINE_ RID &get_immediate() { return immediate; }
+ _FORCE_INLINE_ RID &get_mesh() { return mesh; }
+ _FORCE_INLINE_ RID &get_material() { return material; }
+
+ uint32_t mesh_surface_offsets[RS::ARRAY_MAX];
+ PackedByteArray vertex_buffer;
+ PackedByteArray attribute_buffer;
+ uint32_t vertex_stride;
+ uint32_t attrib_stride;
+ uint32_t skin_stride;
+ uint32_t mesh_surface_format;
+
void _queue_update();
public:
@@ -107,7 +118,7 @@ public:
void set_flip_v(bool p_flip);
bool is_flipped_v() const;
- void set_region_enabled(bool p_region_enabled);
+ void set_region_enabled(bool p_region);
bool is_region_enabled() const;
void set_region_rect(const Rect2 &p_region_rect);
@@ -147,15 +158,16 @@ class Sprite3D : public SpriteBase3D {
GDCLASS(Sprite3D, SpriteBase3D);
Ref<Texture2D> texture;
- bool region_enabled;
+ bool region = false;
Rect2 region_rect;
- int frame;
+ int frame = 0;
- int vframes;
- int hframes;
+ int vframes = 1;
+ int hframes = 1;
- void _texture_changed();
+ RID last_shader;
+ RID last_texture;
protected:
virtual void _draw() override;
@@ -167,7 +179,7 @@ public:
void set_texture(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_texture() const;
- void set_region_enabled(bool p_region_enabled);
+ void set_region_enabled(bool p_region);
bool is_region_enabled() const;
void set_region_rect(const Rect2 &p_region_rect);
@@ -199,14 +211,9 @@ class AnimatedSprite3D : public SpriteBase3D {
StringName animation = "default";
int frame = 0;
- bool centered = true;
-
- float timeout = 0.0;
-
- bool hflip = true;
- bool vflip = true;
+ bool centered = false;
- Color modulate;
+ float timeout = 0;
void _res_changed();
@@ -214,6 +221,9 @@ class AnimatedSprite3D : public SpriteBase3D {
void _set_playing(bool p_playing);
bool _is_playing() const;
+ RID last_shader;
+ RID last_texture;
+
protected:
virtual void _draw() override;
static void _bind_methods();
@@ -236,10 +246,11 @@ public:
virtual Rect2 get_item_rect() const override;
- TypedArray<String> get_configuration_warnings() const override;
+ virtual TypedArray<String> get_configuration_warnings() const override;
AnimatedSprite3D();
};
VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags);
VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode);
+
#endif // SPRITE_3D_H
diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp
index 0d88769b70..b0e37b81a5 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/vehicle_body_3d.cpp
@@ -79,26 +79,29 @@ public:
};
void VehicleWheel3D::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
- if (!cb) {
- return;
- }
- body = cb;
- local_xform = get_transform();
- cb->wheels.push_back(this);
-
- m_chassisConnectionPointCS = get_transform().origin;
- m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized();
- m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized();
- }
- if (p_what == NOTIFICATION_EXIT_TREE) {
- VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
- if (!cb) {
- return;
- }
- cb->wheels.erase(this);
- body = nullptr;
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
+ if (!cb) {
+ return;
+ }
+ body = cb;
+ local_xform = get_transform();
+ cb->wheels.push_back(this);
+
+ m_chassisConnectionPointCS = get_transform().origin;
+ m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized();
+ m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized();
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
+ if (!cb) {
+ return;
+ }
+ cb->wheels.erase(this);
+ body = nullptr;
+ } break;
}
}
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index c16e3c2d78..bd47af8100 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -246,9 +246,9 @@ void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
has_def_value = true;
}
if (instance_uniforms.has(pi.name)) {
- pi.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE | (has_def_value ? (PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED) : 0);
+ pi.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE | (has_def_value ? (PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED) : PROPERTY_USAGE_NONE);
} else {
- pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : 0); //do not save if not changed
+ pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : PROPERTY_USAGE_NONE); //do not save if not changed
}
pi.name = "shader_params/" + pi.name;
@@ -293,7 +293,12 @@ void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform
instance_uniforms.erase(p_value);
} else {
instance_uniforms[p_uniform] = p_value;
- RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value);
+ if (p_value.get_type() == Variant::OBJECT) {
+ RID tex_id = p_value;
+ RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, tex_id);
+ } else {
+ RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value);
+ }
}
}
@@ -389,7 +394,7 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance3D::get_aabb);
ADD_GROUP("Geometry", "");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias");
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index 5558930df8..3da59ac4c0 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -143,15 +143,6 @@ float VoxelGIData::get_propagation() const {
return propagation;
}
-void VoxelGIData::set_anisotropy_strength(float p_anisotropy_strength) {
- RS::get_singleton()->voxel_gi_set_anisotropy_strength(probe, p_anisotropy_strength);
- anisotropy_strength = p_anisotropy_strength;
-}
-
-float VoxelGIData::get_anisotropy_strength() const {
- return anisotropy_strength;
-}
-
void VoxelGIData::set_energy(float p_energy) {
RS::get_singleton()->voxel_gi_set_energy(probe, p_energy);
energy = p_energy;
@@ -161,24 +152,6 @@ float VoxelGIData::get_energy() const {
return energy;
}
-void VoxelGIData::set_ao(float p_ao) {
- RS::get_singleton()->voxel_gi_set_ao(probe, p_ao);
- ao = p_ao;
-}
-
-float VoxelGIData::get_ao() const {
- return ao;
-}
-
-void VoxelGIData::set_ao_size(float p_ao_size) {
- RS::get_singleton()->voxel_gi_set_ao_size(probe, p_ao_size);
- ao_size = p_ao_size;
-}
-
-float VoxelGIData::get_ao_size() const {
- return ao_size;
-}
-
void VoxelGIData::set_bias(float p_bias) {
RS::get_singleton()->voxel_gi_set_bias(probe, p_bias);
bias = p_bias;
@@ -219,15 +192,6 @@ RID VoxelGIData::get_rid() const {
return probe;
}
-void VoxelGIData::_validate_property(PropertyInfo &property) const {
- if (property.name == "anisotropy_strength") {
- bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/global_illumination/voxel_gi/anisotropic");
- if (!anisotropy_enabled) {
- property.usage = PROPERTY_USAGE_NOEDITOR;
- }
- }
-}
-
void VoxelGIData::_bind_methods() {
ClassDB::bind_method(D_METHOD("allocate", "to_cell_xform", "aabb", "octree_size", "octree_cells", "data_cells", "distance_field", "level_counts"), &VoxelGIData::allocate);
@@ -253,15 +217,6 @@ void VoxelGIData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &VoxelGIData::set_propagation);
ClassDB::bind_method(D_METHOD("get_propagation"), &VoxelGIData::get_propagation);
- ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &VoxelGIData::set_anisotropy_strength);
- ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &VoxelGIData::get_anisotropy_strength);
-
- ClassDB::bind_method(D_METHOD("set_ao", "ao"), &VoxelGIData::set_ao);
- ClassDB::bind_method(D_METHOD("get_ao"), &VoxelGIData::get_ao);
-
- ClassDB::bind_method(D_METHOD("set_ao_size", "strength"), &VoxelGIData::set_ao_size);
- ClassDB::bind_method(D_METHOD("get_ao_size"), &VoxelGIData::get_ao_size);
-
ClassDB::bind_method(D_METHOD("set_interior", "interior"), &VoxelGIData::set_interior);
ClassDB::bind_method(D_METHOD("is_interior"), &VoxelGIData::is_interior);
@@ -278,9 +233,6 @@ void VoxelGIData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_bias", "get_bias");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao", "get_ao");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_size", "get_ao_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
}
diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h
index 5b9ee28b33..434d209421 100644
--- a/scene/3d/voxel_gi.h
+++ b/scene/3d/voxel_gi.h
@@ -51,15 +51,11 @@ class VoxelGIData : public Resource {
float bias = 1.5;
float normal_bias = 0.0;
float propagation = 0.7;
- float anisotropy_strength = 0.5;
- float ao = 0.0;
- float ao_size = 0.5;
bool interior = false;
bool use_two_bounces = false;
protected:
static void _bind_methods();
- void _validate_property(PropertyInfo &property) const override;
public:
void allocate(const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
@@ -77,15 +73,6 @@ public:
void set_propagation(float p_propagation);
float get_propagation() const;
- void set_anisotropy_strength(float p_anisotropy_strength);
- float get_anisotropy_strength() const;
-
- void set_ao(float p_ao);
- float get_ao() const;
-
- void set_ao_size(float p_ao_size);
- float get_ao_size() const;
-
void set_energy(float p_energy);
float get_energy() const;
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index 12f055c01d..f1b9708f91 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -36,17 +36,17 @@
#include <stdlib.h>
static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
- if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_vtx[0])) {
r_uv = p_uv[0];
r_normal = p_normal[0];
return;
}
- if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_vtx[1])) {
r_uv = p_uv[1];
r_normal = p_normal[1];
return;
}
- if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_vtx[2])) {
r_uv = p_uv[2];
r_normal = p_normal[2];
return;
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index a91e712b0b..b04c7e2858 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -207,10 +207,10 @@ void XRController3D::_notification(int p_what) {
bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, (JoyButton)i);
if (!was_pressed && is_pressed) {
- emit_signal("button_pressed", i);
+ emit_signal(SNAME("button_pressed"), i);
button_states += mask;
} else if (was_pressed && !is_pressed) {
- emit_signal("button_released", i);
+ emit_signal(SNAME("button_released"), i);
button_states -= mask;
};
@@ -225,7 +225,7 @@ void XRController3D::_notification(int p_what) {
Ref<Mesh> trackerMesh = tracker->get_mesh();
if (mesh != trackerMesh) {
mesh = trackerMesh;
- emit_signal("mesh_updated", mesh);
+ emit_signal(SNAME("mesh_updated"), mesh);
}
};
}; break;
@@ -422,7 +422,7 @@ void XRAnchor3D::_notification(int p_what) {
Ref<Mesh> trackerMesh = tracker->get_mesh();
if (mesh != trackerMesh) {
mesh = trackerMesh;
- emit_signal("mesh_updated", mesh);
+ emit_signal(SNAME("mesh_updated"), mesh);
}
};
}; break;
diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp
index 15f562242f..6e5d964b76 100644
--- a/scene/animation/animation_blend_space_1d.cpp
+++ b/scene/animation/animation_blend_space_1d.cpp
@@ -47,14 +47,14 @@ void AnimationNodeBlendSpace1D::_validate_property(PropertyInfo &property) const
String left = property.name.get_slicec('/', 0);
int idx = left.get_slicec('_', 2).to_int();
if (idx >= blend_points_used) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
AnimationRootNode::_validate_property(property);
}
void AnimationNodeBlendSpace1D::_tree_changed() {
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendSpace1D::_bind_methods() {
@@ -120,7 +120,7 @@ void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_
blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
blend_points_used++;
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendSpace1D::set_blend_point_position(int p_point, float p_position) {
@@ -140,7 +140,7 @@ void AnimationNodeBlendSpace1D::set_blend_point_node(int p_point, const Ref<Anim
blend_points[p_point].node = p_node;
blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
float AnimationNodeBlendSpace1D::get_blend_point_position(int p_point) const {
@@ -164,7 +164,7 @@ void AnimationNodeBlendSpace1D::remove_blend_point(int p_point) {
}
blend_points_used--;
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
int AnimationNodeBlendSpace1D::get_blend_point_count() const {
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index 9c4bc107dd..d88a9badf4 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -34,8 +34,8 @@
void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
r_list->push_back(PropertyInfo(Variant::VECTOR2, blend_position));
- r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "", 0));
- r_list->push_back(PropertyInfo(Variant::FLOAT, length_internal, PROPERTY_HINT_NONE, "", 0));
+ r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, length_internal, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
}
Variant AnimationNodeBlendSpace2D::get_parameter_default_value(const StringName &p_parameter) const {
@@ -84,7 +84,7 @@ void AnimationNodeBlendSpace2D::add_blend_point(const Ref<AnimationRootNode> &p_
_queue_auto_triangles();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendSpace2D::set_blend_point_position(int p_point, const Vector2 &p_position) {
@@ -103,7 +103,7 @@ void AnimationNodeBlendSpace2D::set_blend_point_node(int p_point, const Ref<Anim
blend_points[p_point].node = p_node;
blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
Vector2 AnimationNodeBlendSpace2D::get_blend_point_position(int p_point) const {
@@ -143,7 +143,7 @@ void AnimationNodeBlendSpace2D::remove_blend_point(int p_point) {
blend_points[i] = blend_points[i + 1];
}
blend_points_used--;
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
int AnimationNodeBlendSpace2D::get_blend_point_count() const {
@@ -321,7 +321,7 @@ void AnimationNodeBlendSpace2D::_queue_auto_triangles() {
}
trianges_dirty = true;
- call_deferred("_update_triangles");
+ call_deferred(SNAME("_update_triangles"));
}
void AnimationNodeBlendSpace2D::_update_triangles() {
@@ -332,7 +332,7 @@ void AnimationNodeBlendSpace2D::_update_triangles() {
trianges_dirty = false;
triangles.clear();
if (blend_points_used < 3) {
- emit_signal("triangles_updated");
+ emit_signal(SNAME("triangles_updated"));
return;
}
@@ -347,7 +347,7 @@ void AnimationNodeBlendSpace2D::_update_triangles() {
for (int i = 0; i < triangles.size(); i++) {
add_triangle(triangles[i].points[0], triangles[i].points[1], triangles[i].points[2]);
}
- emit_signal("triangles_updated");
+ emit_signal(SNAME("triangles_updated"));
}
Vector2 AnimationNodeBlendSpace2D::get_closest_point(const Vector2 &p_point) {
@@ -387,19 +387,19 @@ Vector2 AnimationNodeBlendSpace2D::get_closest_point(const Vector2 &p_point) {
}
void AnimationNodeBlendSpace2D::_blend_triangle(const Vector2 &p_pos, const Vector2 *p_points, float *r_weights) {
- if (p_pos.distance_squared_to(p_points[0]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_points[0])) {
r_weights[0] = 1;
r_weights[1] = 0;
r_weights[2] = 0;
return;
}
- if (p_pos.distance_squared_to(p_points[1]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_points[1])) {
r_weights[0] = 0;
r_weights[1] = 1;
r_weights[2] = 0;
return;
}
- if (p_pos.distance_squared_to(p_points[2]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_points[2])) {
r_weights[0] = 0;
r_weights[1] = 0;
r_weights[2] = 1;
@@ -532,10 +532,10 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
float from = 0.0;
if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) {
//see how much animation remains
- from = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, true, 0.0, FILTER_IGNORE, false) - length_internal;
+ from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, 0.0, FILTER_IGNORE, false);
}
- mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false) + from;
+ mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false);
length_internal = from + mind;
closest = new_closest;
@@ -556,13 +556,13 @@ String AnimationNodeBlendSpace2D::get_caption() const {
void AnimationNodeBlendSpace2D::_validate_property(PropertyInfo &property) const {
if (auto_triangles && property.name == "triangles") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("blend_point_")) {
String left = property.name.get_slicec('/', 0);
int idx = left.get_slicec('_', 2).to_int();
if (idx >= blend_points_used) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
AnimationRootNode::_validate_property(property);
@@ -586,7 +586,7 @@ Ref<AnimationNode> AnimationNodeBlendSpace2D::get_child_by_name(const StringName
}
void AnimationNodeBlendSpace2D::_tree_changed() {
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendSpace2D::set_blend_mode(BlendMode p_blend_mode) {
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index ad6115fa16..200a688067 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -43,7 +43,7 @@ StringName AnimationNodeAnimation::get_animation() const {
Vector<String> (*AnimationNodeAnimation::get_editable_animation_list)() = nullptr;
void AnimationNodeAnimation::get_parameter_list(List<PropertyInfo> *r_list) const {
- r_list->push_back(PropertyInfo(Variant::FLOAT, time, PROPERTY_HINT_NONE, "", 0));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, time, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
}
void AnimationNodeAnimation::_validate_property(PropertyInfo &property) const {
@@ -130,10 +130,10 @@ AnimationNodeAnimation::AnimationNodeAnimation() {
void AnimationNodeOneShot::get_parameter_list(List<PropertyInfo> *r_list) const {
r_list->push_back(PropertyInfo(Variant::BOOL, active));
- r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", 0));
- r_list->push_back(PropertyInfo(Variant::FLOAT, time, PROPERTY_HINT_NONE, "", 0));
- r_list->push_back(PropertyInfo(Variant::FLOAT, remaining, PROPERTY_HINT_NONE, "", 0));
- r_list->push_back(PropertyInfo(Variant::FLOAT, time_to_restart, PROPERTY_HINT_NONE, "", 0));
+ r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, time, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, remaining, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, time_to_restart, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
}
Variant AnimationNodeOneShot::get_parameter_default_value(const StringName &p_parameter) const {
@@ -607,10 +607,10 @@ void AnimationNodeTransition::get_parameter_list(List<PropertyInfo> *r_list) con
}
r_list->push_back(PropertyInfo(Variant::INT, current, PROPERTY_HINT_ENUM, anims));
- r_list->push_back(PropertyInfo(Variant::INT, prev_current, PROPERTY_HINT_NONE, "", 0));
- r_list->push_back(PropertyInfo(Variant::INT, prev, PROPERTY_HINT_NONE, "", 0));
- r_list->push_back(PropertyInfo(Variant::FLOAT, time, PROPERTY_HINT_NONE, "", 0));
- r_list->push_back(PropertyInfo(Variant::FLOAT, prev_xfading, PROPERTY_HINT_NONE, "", 0));
+ r_list->push_back(PropertyInfo(Variant::INT, prev_current, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::INT, prev, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, time, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, prev_xfading, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
}
Variant AnimationNodeTransition::get_parameter_default_value(const StringName &p_parameter) const {
@@ -752,7 +752,7 @@ void AnimationNodeTransition::_validate_property(PropertyInfo &property) const {
if (n != "count") {
int idx = n.to_int();
if (idx >= enabled_inputs) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
}
@@ -816,7 +816,7 @@ void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNod
nodes[p_name] = n;
emit_changed();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
p_node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendTree::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
p_node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_name), CONNECT_REFERENCE_COUNTED);
@@ -896,7 +896,7 @@ void AnimationNodeBlendTree::remove_node(const StringName &p_name) {
}
emit_changed();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringName &p_new_name) {
@@ -921,7 +921,7 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN
//connection must be done with new name
nodes[p_new_name].node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_new_name), CONNECT_REFERENCE_COUNTED);
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendTree::connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) {
@@ -1125,11 +1125,11 @@ void AnimationNodeBlendTree::reset_state() {
graph_offset = Vector2();
nodes.clear();
emit_changed();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendTree::_tree_changed() {
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeBlendTree::_node_changed(const StringName &p_node) {
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index f494f5c163..6496331cb0 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -57,7 +57,7 @@ void AnimationNodeStateMachineTransition::set_advance_condition(const StringName
} else {
advance_condition_name = StringName();
}
- emit_signal("advance_condition_changed");
+ emit_signal(SNAME("advance_condition_changed"));
}
StringName AnimationNodeStateMachineTransition::get_advance_condition() const {
@@ -539,7 +539,7 @@ void AnimationNodeStateMachine::add_node(const StringName &p_name, Ref<Animation
states[p_name] = state;
emit_changed();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
}
@@ -559,7 +559,7 @@ void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<Anima
states[p_name].node = p_node;
emit_changed();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
}
@@ -636,7 +636,7 @@ void AnimationNodeStateMachine::remove_node(const StringName &p_name) {
}*/
emit_changed();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeStateMachine::rename_node(const StringName &p_name, const StringName &p_new_name) {
@@ -669,7 +669,7 @@ void AnimationNodeStateMachine::rename_node(const StringName &p_name, const Stri
}*/
//path.clear(); //clear path
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeStateMachine::get_node_list(List<StringName> *r_nodes) const {
@@ -923,7 +923,7 @@ void AnimationNodeStateMachine::reset_state() {
graph_offset = Vector2();
emit_changed();
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeStateMachine::set_node_position(const StringName &p_name, const Vector2 &p_position) {
@@ -937,7 +937,7 @@ Vector2 AnimationNodeStateMachine::get_node_position(const StringName &p_name) c
}
void AnimationNodeStateMachine::_tree_changed() {
- emit_signal("tree_changed");
+ emit_signal(SNAME("tree_changed"));
}
void AnimationNodeStateMachine::_bind_methods() {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 799c81c2ab..14ca325c25 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -513,7 +513,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
}
#endif
- static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)value));
+ static_cast<Node2D *>(pa->object)->set_rotation((double)value);
} break;
case SP_NODE2D_SCALE: {
#ifdef DEBUG_ENABLED
@@ -557,6 +557,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
}
#endif
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
if (can_call) {
if (method_call_mode == ANIMATION_METHOD_CALL_DEFERRED) {
MessageQueue::get_singleton()->push_call(
@@ -566,7 +567,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
s >= 2 ? params[1] : Variant(),
s >= 3 ? params[2] : Variant(),
s >= 4 ? params[3] : Variant(),
- s >= 5 ? params[4] : Variant());
+ s >= 5 ? params[4] : Variant(),
+ s >= 6 ? params[5] : Variant(),
+ s >= 7 ? params[6] : Variant(),
+ s >= 8 ? params[7] : Variant());
} else {
nc->node->call(
method,
@@ -574,7 +578,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
s >= 2 ? params[1] : Variant(),
s >= 3 ? params[2] : Variant(),
s >= 4 ? params[3] : Variant(),
- s >= 5 ? params[4] : Variant());
+ s >= 5 ? params[4] : Variant(),
+ s >= 6 ? params[5] : Variant(),
+ s >= 7 ? params[6] : Variant(),
+ s >= 8 ? params[7] : Variant());
}
}
}
@@ -1325,7 +1332,7 @@ float AnimationPlayer::get_current_animation_length() const {
void AnimationPlayer::_animation_changed() {
clear_caches();
- emit_signal("caches_cleared");
+ emit_signal(SNAME("caches_cleared"));
if (is_playing()) {
playback.seeked = true; //need to restart stuff, like audio
}
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 6fac70bdd5..72448fc4f7 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -385,7 +385,7 @@ void AnimationNode::_set_filters(const Array &p_filters) {
void AnimationNode::_validate_property(PropertyInfo &property) const {
if (!has_filter() && (property.name == "filter_enabled" || property.name == "filters")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -985,6 +985,7 @@ void AnimationTree::_process_graph(float p_delta) {
int s = params.size();
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
ERR_CONTINUE(s > VARIANT_ARG_MAX);
if (can_call) {
t->object->call_deferred(
@@ -993,7 +994,10 @@ void AnimationTree::_process_graph(float p_delta) {
s >= 2 ? params[1] : Variant(),
s >= 3 ? params[2] : Variant(),
s >= 4 ? params[3] : Variant(),
- s >= 5 ? params[4] : Variant());
+ s >= 5 ? params[4] : Variant(),
+ s >= 6 ? params[5] : Variant(),
+ s >= 7 ? params[6] : Variant(),
+ s >= 8 ? params[7] : Variant());
}
}
@@ -1327,7 +1331,7 @@ void AnimationTree::_tree_changed() {
return;
}
- call_deferred("_update_properties");
+ call_deferred(SNAME("_update_properties"));
properties_dirty = true;
}
diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp
index b963cf5702..770996820d 100644
--- a/scene/animation/root_motion_view.cpp
+++ b/scene/animation/root_motion_view.cpp
@@ -77,7 +77,7 @@ bool RootMotionView::get_zero_y() const {
void RootMotionView::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- RS::get_singleton()->immediate_set_material(immediate, StandardMaterial3D::get_material_rid_for_2d(false, true, false, false, false));
+ immediate_material = StandardMaterial3D::get_material_for_2d(false, true, false, false, false);
first = true;
}
@@ -119,11 +119,12 @@ void RootMotionView::_notification(int p_what) {
}
accumulated.origin.z = Math::fposmod(accumulated.origin.z, cell_size);
- RS::get_singleton()->immediate_clear(immediate);
+ immediate->clear_surfaces();
int cells_in_radius = int((radius / cell_size) + 1.0);
- RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_LINES);
+ immediate->surface_begin(Mesh::PRIMITIVE_LINES, immediate_material);
+
for (int i = -cells_in_radius; i < cells_in_radius; i++) {
for (int j = -cells_in_radius; j < cells_in_radius; j++) {
Vector3 from(i * cell_size, 0, j * cell_size);
@@ -138,21 +139,21 @@ void RootMotionView::_notification(int p_what) {
c_i.a *= MAX(0, 1.0 - from_i.length() / radius);
c_j.a *= MAX(0, 1.0 - from_j.length() / radius);
- RS::get_singleton()->immediate_color(immediate, c);
- RS::get_singleton()->immediate_vertex(immediate, from);
+ immediate->surface_set_color(c);
+ immediate->surface_add_vertex(from);
- RS::get_singleton()->immediate_color(immediate, c_i);
- RS::get_singleton()->immediate_vertex(immediate, from_i);
+ immediate->surface_set_color(c_i);
+ immediate->surface_add_vertex(from_i);
- RS::get_singleton()->immediate_color(immediate, c);
- RS::get_singleton()->immediate_vertex(immediate, from);
+ immediate->surface_set_color(c);
+ immediate->surface_add_vertex(from);
- RS::get_singleton()->immediate_color(immediate, c_j);
- RS::get_singleton()->immediate_vertex(immediate, from_j);
+ immediate->surface_set_color(c_j);
+ immediate->surface_add_vertex(from_j);
}
}
- RS::get_singleton()->immediate_end(immediate);
+ immediate->surface_end();
}
}
@@ -188,12 +189,13 @@ void RootMotionView::_bind_methods() {
}
RootMotionView::RootMotionView() {
- set_process_internal(true);
- immediate = RenderingServer::get_singleton()->immediate_create();
- set_base(immediate);
+ if (Engine::get_singleton()->is_editor_hint()) {
+ set_process_internal(true);
+ }
+ immediate.instantiate();
+ set_base(immediate->get_rid());
}
RootMotionView::~RootMotionView() {
set_base(RID());
- RenderingServer::get_singleton()->free(immediate);
}
diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h
index 4cd3c7b443..55fd2d2b73 100644
--- a/scene/animation/root_motion_view.h
+++ b/scene/animation/root_motion_view.h
@@ -32,12 +32,12 @@
#define ROOT_MOTION_VIEW_H
#include "scene/3d/visual_instance_3d.h"
-
+#include "scene/resources/immediate_mesh.h"
class RootMotionView : public VisualInstance3D {
GDCLASS(RootMotionView, VisualInstance3D);
public:
- RID immediate;
+ Ref<ImmediateMesh> immediate;
NodePath path;
float cell_size = 1.0;
float radius = 10.0;
@@ -46,6 +46,8 @@ public:
bool first = true;
bool zero_y = true;
+ Ref<Material> immediate_material;
+
Transform3D accumulated;
private:
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 7bf616e602..761046c14a 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -264,7 +264,7 @@ bool Tween::step(float p_delta) {
rem_delta = step_delta;
if (!step_active) {
- emit_signal("step_finished", current_step);
+ emit_signal(SNAME("step_finished"), current_step);
current_step++;
if (current_step == tweeners.size()) {
@@ -272,9 +272,9 @@ bool Tween::step(float p_delta) {
if (loops_done == loops) {
running = false;
dead = true;
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
} else {
- emit_signal("loop_finished", loops_done);
+ emit_signal(SNAME("loop_finished"), loops_done);
current_step = 0;
start_tweeners();
}
@@ -690,7 +690,7 @@ bool PropertyTweener::step(float &r_delta) {
} else {
finished = true;
r_delta = elapsed_time - delay - duration;
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
return false;
}
}
@@ -745,7 +745,7 @@ bool IntervalTweener::step(float &r_delta) {
} else {
finished = true;
r_delta = elapsed_time - duration;
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
return false;
}
}
@@ -784,7 +784,7 @@ bool CallbackTweener::step(float &r_delta) {
finished = true;
r_delta = elapsed_time - delay;
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
return false;
}
@@ -854,7 +854,7 @@ bool MethodTweener::step(float &r_delta) {
} else {
finished = true;
r_delta = elapsed_time - delay - duration;
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
return false;
}
}
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index 1478cbf69e..298d75b668 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -146,7 +146,7 @@ void AudioStreamPlayer::_notification(int p_what) {
if (!active.is_set() || (setseek.get() < 0 && !stream_playback->is_playing())) {
active.clear();
set_process_internal(false);
- emit_signal("finished");
+ emit_signal(SNAME("finished"));
}
}
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index 1bf841be04..fd5637be11 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -145,12 +145,12 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]);
} else if (p_msg == "live_node_call") {
- ERR_FAIL_COND_V(p_args.size() < 7, ERR_INVALID_DATA);
- live_editor->_node_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6]);
+ ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA);
+ live_editor->_node_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]);
} else if (p_msg == "live_res_call") {
- ERR_FAIL_COND_V(p_args.size() < 7, ERR_INVALID_DATA);
- live_editor->_res_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6]);
+ ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA);
+ live_editor->_res_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]);
} else if (p_msg == "live_create_node") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
@@ -525,7 +525,7 @@ void LiveEditor::_node_set_func(int p_id, const StringName &p_prop, const Varian
for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -569,7 +569,7 @@ void LiveEditor::_node_call_func(int p_id, const StringName &p_method, VARIANT_A
for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -652,7 +652,7 @@ void LiveEditor::_create_node_func(const NodePath &p_parent, const String &p_typ
for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -696,7 +696,7 @@ void LiveEditor::_instance_node_func(const NodePath &p_parent, const String &p_p
for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -736,7 +736,7 @@ void LiveEditor::_remove_node_func(const NodePath &p_at) {
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -772,7 +772,7 @@ void LiveEditor::_remove_and_keep_node_func(const NodePath &p_at, ObjectID p_kee
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -811,7 +811,7 @@ void LiveEditor::_restore_node_func(ObjectID p_id, const NodePath &p_at, int p_a
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -862,7 +862,7 @@ void LiveEditor::_duplicate_node_func(const NodePath &p_at, const String &p_new_
for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
@@ -901,7 +901,7 @@ void LiveEditor::_reparent_node_func(const NodePath &p_at, const NodePath &p_new
for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
Node *n = F->get();
- if (base && !base->is_a_parent_of(n)) {
+ if (base && !base->is_ancestor_of(n)) {
continue;
}
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 66155958cf..75a4464a40 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -125,7 +125,7 @@ void BaseButton::_pressed() {
get_script_instance()->call(SceneStringNames::get_singleton()->_pressed);
}
pressed();
- emit_signal("pressed");
+ emit_signal(SNAME("pressed"));
}
void BaseButton::_toggled(bool p_pressed) {
@@ -133,14 +133,14 @@ void BaseButton::_toggled(bool p_pressed) {
get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, p_pressed);
}
toggled(p_pressed);
- emit_signal("toggled", p_pressed);
+ emit_signal(SNAME("toggled"), p_pressed);
}
void BaseButton::on_action_event(Ref<InputEvent> p_event) {
if (p_event->is_pressed()) {
status.press_attempt = true;
status.pressing_inside = true;
- emit_signal("button_down");
+ emit_signal(SNAME("button_down"));
}
if (status.press_attempt && status.pressing_inside) {
@@ -153,7 +153,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
status.pressed = !status.pressed;
_unpress_group();
if (button_group.is_valid()) {
- button_group->emit_signal("pressed", this);
+ button_group->emit_signal(SNAME("pressed"), this);
}
_toggled(status.pressed);
_pressed();
@@ -174,7 +174,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
}
status.press_attempt = false;
status.pressing_inside = false;
- emit_signal("button_up");
+ emit_signal(SNAME("button_up"));
}
update();
@@ -218,7 +218,7 @@ void BaseButton::set_pressed(bool p_pressed) {
if (p_pressed) {
_unpress_group();
if (button_group.is_valid()) {
- button_group->emit_signal("pressed", this);
+ button_group->emit_signal(SNAME("pressed"), this);
}
}
_toggled(status.pressed);
@@ -226,6 +226,18 @@ void BaseButton::set_pressed(bool p_pressed) {
update();
}
+void BaseButton::set_pressed_no_signal(bool p_pressed) {
+ if (!toggle_mode) {
+ return;
+ }
+ if (status.pressed == p_pressed) {
+ return;
+ }
+ status.pressed = p_pressed;
+
+ update();
+}
+
bool BaseButton::is_pressing() const {
return status.press_attempt;
}
@@ -391,7 +403,7 @@ bool BaseButton::_is_focus_owner_in_shorcut_context() const {
Control *vp_focus = get_focus_owner();
// If the context is valid and the viewport focus is valid, check if the context is the focus or is a parent of it.
- return ctx_node && vp_focus && (ctx_node == vp_focus || ctx_node->is_a_parent_of(vp_focus));
+ return ctx_node && vp_focus && (ctx_node == vp_focus || ctx_node->is_ancestor_of(vp_focus));
}
void BaseButton::_bind_methods() {
@@ -399,6 +411,7 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &BaseButton::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed);
ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed);
+ ClassDB::bind_method(D_METHOD("set_pressed_no_signal", "pressed"), &BaseButton::set_pressed_no_signal);
ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered);
ClassDB::bind_method(D_METHOD("set_toggle_mode", "enabled"), &BaseButton::set_toggle_mode);
ClassDB::bind_method(D_METHOD("is_toggle_mode"), &BaseButton::is_toggle_mode);
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 6c7a8f3433..d86b35daf0 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -98,7 +98,8 @@ public:
bool is_pressing() const; ///< return whether button is pressed (toggled in)
bool is_hovered() const;
- void set_pressed(bool p_pressed); ///only works in toggle mode
+ void set_pressed(bool p_pressed); // Only works in toggle mode.
+ void set_pressed_no_signal(bool p_pressed);
void set_toggle_mode(bool p_on);
bool is_toggle_mode() const;
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index 7407ad5b8f..a2f1d2b15a 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -43,7 +43,7 @@ void BoxContainer::_resort() {
Size2i new_size = get_size();
- int sep = get_theme_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer");
+ int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
bool rtl = is_layout_rtl();
bool first = true;
@@ -247,7 +247,7 @@ Size2 BoxContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- int sep = get_theme_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer");
+ int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
bool first = true;
@@ -349,6 +349,7 @@ void BoxContainer::_bind_methods() {
MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control *p_control, bool p_expand) {
Label *l = memnew(Label);
+ l->set_theme_type_variation("HeaderSmall");
l->set_text(p_label);
add_child(l);
MarginContainer *mc = memnew(MarginContainer);
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 595d712eb8..4b6c0ef697 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -41,27 +41,32 @@ Size2 Button::get_minimum_size() const {
if (!expand_icon) {
Ref<Texture2D> _icon;
- if (icon.is_null() && has_theme_icon("icon")) {
- _icon = Control::get_theme_icon("icon");
+ if (icon.is_null() && has_theme_icon(SNAME("icon"))) {
+ _icon = Control::get_theme_icon(SNAME("icon"));
} else {
_icon = icon;
}
if (!_icon.is_null()) {
minsize.height = MAX(minsize.height, _icon->get_height());
- minsize.width += _icon->get_width();
- if (xl_text != "") {
- minsize.width += get_theme_constant("hseparation");
+
+ if (icon_align != ALIGN_CENTER) {
+ minsize.width += _icon->get_width();
+ if (xl_text != "") {
+ minsize.width += get_theme_constant(SNAME("hseparation"));
+ }
+ } else {
+ minsize.width = MAX(minsize.width, _icon->get_width());
}
}
}
- Ref<Font> font = get_theme_font("font");
- float font_height = font->get_height(get_theme_font_size("font_size"));
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ float font_height = font->get_height(get_theme_font_size(SNAME("font_size")));
minsize.height = MAX(font_height, minsize.height);
- return get_theme_stylebox("normal")->get_minimum_size() + minsize;
+ return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize;
}
void Button::_set_internal_margin(Side p_side, float p_value) {
@@ -92,43 +97,43 @@ void Button::_notification(int p_what) {
Color color;
Color color_icon(1, 1, 1, 1);
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
bool rtl = is_layout_rtl();
switch (get_draw_mode()) {
case DRAW_NORMAL: {
- if (rtl && has_theme_stylebox("normal_mirrored")) {
- style = get_theme_stylebox("normal_mirrored");
+ if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
+ style = get_theme_stylebox(SNAME("normal_mirrored"));
} else {
- style = get_theme_stylebox("normal");
+ style = get_theme_stylebox(SNAME("normal"));
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- color = get_theme_color("font_color");
- if (has_theme_color("icon_normal_color")) {
- color_icon = get_theme_color("icon_normal_color");
+ color = get_theme_color(SNAME("font_color"));
+ if (has_theme_color(SNAME("icon_normal_color"))) {
+ color_icon = get_theme_color(SNAME("icon_normal_color"));
}
} break;
case DRAW_HOVER_PRESSED: {
- if (has_theme_stylebox("hover_pressed") && has_theme_stylebox_override("hover_pressed")) {
- if (rtl && has_theme_stylebox("hover_pressed_mirrored")) {
- style = get_theme_stylebox("hover_pressed_mirrored");
+ if (has_theme_stylebox(SNAME("hover_pressed")) && has_theme_stylebox_override("hover_pressed")) {
+ if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
+ style = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
} else {
- style = get_theme_stylebox("hover_pressed");
+ style = get_theme_stylebox(SNAME("hover_pressed"));
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- if (has_theme_color("font_hover_pressed_color")) {
- color = get_theme_color("font_hover_pressed_color");
+ if (has_theme_color(SNAME("font_hover_pressed_color"))) {
+ color = get_theme_color(SNAME("font_hover_pressed_color"));
} else {
- color = get_theme_color("font_color");
+ color = get_theme_color(SNAME("font_color"));
}
- if (has_theme_color("icon_hover_pressed_color")) {
- color_icon = get_theme_color("icon_hover_pressed_color");
+ if (has_theme_color(SNAME("icon_hover_pressed_color"))) {
+ color_icon = get_theme_color(SNAME("icon_hover_pressed_color"));
}
break;
@@ -136,72 +141,87 @@ void Button::_notification(int p_what) {
[[fallthrough]];
}
case DRAW_PRESSED: {
- if (rtl && has_theme_stylebox("pressed_mirrored")) {
- style = get_theme_stylebox("pressed_mirrored");
+ if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
+ style = get_theme_stylebox(SNAME("pressed_mirrored"));
} else {
- style = get_theme_stylebox("pressed");
+ style = get_theme_stylebox(SNAME("pressed"));
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- if (has_theme_color("font_pressed_color")) {
- color = get_theme_color("font_pressed_color");
+ if (has_theme_color(SNAME("font_pressed_color"))) {
+ color = get_theme_color(SNAME("font_pressed_color"));
} else {
- color = get_theme_color("font_color");
+ color = get_theme_color(SNAME("font_color"));
}
- if (has_theme_color("icon_pressed_color")) {
- color_icon = get_theme_color("icon_pressed_color");
+ if (has_theme_color(SNAME("icon_pressed_color"))) {
+ color_icon = get_theme_color(SNAME("icon_pressed_color"));
}
} break;
case DRAW_HOVER: {
- if (rtl && has_theme_stylebox("hover_mirrored")) {
- style = get_theme_stylebox("hover_mirrored");
+ if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
+ style = get_theme_stylebox(SNAME("hover_mirrored"));
} else {
- style = get_theme_stylebox("hover");
+ style = get_theme_stylebox(SNAME("hover"));
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- color = get_theme_color("font_hover_color");
- if (has_theme_color("icon_hover_color")) {
- color_icon = get_theme_color("icon_hover_color");
+ color = get_theme_color(SNAME("font_hover_color"));
+ if (has_theme_color(SNAME("icon_hover_color"))) {
+ color_icon = get_theme_color(SNAME("icon_hover_color"));
}
} break;
case DRAW_DISABLED: {
- if (rtl && has_theme_stylebox("disabled_mirrored")) {
- style = get_theme_stylebox("disabled_mirrored");
+ if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
+ style = get_theme_stylebox(SNAME("disabled_mirrored"));
} else {
- style = get_theme_stylebox("disabled");
+ style = get_theme_stylebox(SNAME("disabled"));
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- color = get_theme_color("font_disabled_color");
- if (has_theme_color("icon_disabled_color")) {
- color_icon = get_theme_color("icon_disabled_color");
+ color = get_theme_color(SNAME("font_disabled_color"));
+ if (has_theme_color(SNAME("icon_disabled_color"))) {
+ color_icon = get_theme_color(SNAME("icon_disabled_color"));
}
} break;
}
if (has_focus()) {
- Ref<StyleBox> style2 = get_theme_stylebox("focus");
+ Ref<StyleBox> style2 = get_theme_stylebox(SNAME("focus"));
style2->draw(ci, Rect2(Point2(), size));
}
Ref<Texture2D> _icon;
- if (icon.is_null() && has_theme_icon("icon")) {
- _icon = Control::get_theme_icon("icon");
+ if (icon.is_null() && has_theme_icon(SNAME("icon"))) {
+ _icon = Control::get_theme_icon(SNAME("icon"));
} else {
_icon = icon;
}
Rect2 icon_region = Rect2();
+ TextAlign icon_align_rtl_checked = icon_align;
+ TextAlign align_rtl_checked = align;
+ // Swap icon and text alignment sides if right-to-left layout is set.
+ if (rtl) {
+ if (icon_align == ALIGN_RIGHT) {
+ icon_align_rtl_checked = ALIGN_LEFT;
+ } else if (icon_align == ALIGN_LEFT) {
+ icon_align_rtl_checked = ALIGN_RIGHT;
+ }
+ if (align == ALIGN_RIGHT) {
+ align_rtl_checked = ALIGN_LEFT;
+ } else if (align == ALIGN_LEFT) {
+ align_rtl_checked = ALIGN_RIGHT;
+ }
+ }
if (!_icon.is_null()) {
int valign = size.height - style->get_minimum_size().y;
if (is_disabled()) {
@@ -209,20 +229,27 @@ void Button::_notification(int p_what) {
}
float icon_ofs_region = 0.0;
- if (rtl) {
- if (_internal_margin[SIDE_RIGHT] > 0) {
- icon_ofs_region = _internal_margin[SIDE_RIGHT] + get_theme_constant("hseparation");
- }
- } else {
+ Point2 style_offset;
+ Size2 icon_size = _icon->get_size();
+ if (icon_align_rtl_checked == ALIGN_LEFT) {
+ style_offset.x = style->get_margin(SIDE_LEFT);
if (_internal_margin[SIDE_LEFT] > 0) {
- icon_ofs_region = _internal_margin[SIDE_LEFT] + get_theme_constant("hseparation");
+ icon_ofs_region = _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("hseparation"));
+ }
+ } else if (icon_align_rtl_checked == ALIGN_CENTER) {
+ style_offset.x = 0.0;
+ } else if (icon_align_rtl_checked == ALIGN_RIGHT) {
+ style_offset.x = -style->get_margin(SIDE_RIGHT);
+ if (_internal_margin[SIDE_RIGHT] > 0) {
+ icon_ofs_region = -_internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("hseparation"));
}
}
+ style_offset.y = style->get_margin(SIDE_TOP);
if (expand_icon) {
Size2 _size = get_size() - style->get_offset() * 2;
- _size.width -= get_theme_constant("hseparation") + icon_ofs_region;
- if (!clip_text) {
+ _size.width -= get_theme_constant(SNAME("hseparation")) + icon_ofs_region;
+ if (!clip_text && icon_align_rtl_checked != ALIGN_CENTER) {
_size.width -= text_buf->get_size().width;
}
float icon_width = _icon->get_width() * _size.height / _icon->get_height();
@@ -233,49 +260,49 @@ void Button::_notification(int p_what) {
icon_height = _icon->get_height() * icon_width / _icon->get_width();
}
- if (rtl) {
- icon_region = Rect2(Point2(size.width - (icon_ofs_region + icon_width + style->get_margin(SIDE_RIGHT)), style->get_margin(SIDE_TOP) + (_size.height - icon_height) / 2), Size2(icon_width, icon_height));
- } else {
- icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, (_size.height - icon_height) / 2), Size2(icon_width, icon_height));
- }
+ icon_size = Size2(icon_width, icon_height);
+ }
+
+ if (icon_align_rtl_checked == ALIGN_LEFT) {
+ icon_region = Rect2(style_offset + Point2(icon_ofs_region, Math::floor((valign - icon_size.y) * 0.5)), icon_size);
+ } else if (icon_align_rtl_checked == ALIGN_CENTER) {
+ icon_region = Rect2(style_offset + Point2(icon_ofs_region + Math::floor((size.x - icon_size.x) * 0.5), Math::floor((valign - icon_size.y) * 0.5)), icon_size);
} else {
- if (rtl) {
- icon_region = Rect2(Point2(size.width - (icon_ofs_region + _icon->get_size().width + style->get_margin(SIDE_RIGHT)), style->get_margin(SIDE_TOP) + Math::floor((valign - _icon->get_height()) / 2.0)), _icon->get_size());
- } else {
- icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, Math::floor((valign - _icon->get_height()) / 2.0)), _icon->get_size());
- }
+ icon_region = Rect2(style_offset + Point2(icon_ofs_region + size.x - icon_size.x, Math::floor((valign - icon_size.y) * 0.5)), icon_size);
+ }
+
+ if (icon_region.size.width > 0) {
+ draw_texture_rect_region(_icon, icon_region, Rect2(Point2(), _icon->get_size()), color_icon);
}
}
- Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant("hseparation"), 0) : Point2();
+ Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant(SNAME("hseparation")), 0) : Point2();
+ if (align_rtl_checked == ALIGN_CENTER && icon_align_rtl_checked == ALIGN_CENTER) {
+ icon_ofs.x = 0.0;
+ }
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
text_buf->set_width(clip_text ? text_clip : -1);
int text_width = clip_text ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x;
if (_internal_margin[SIDE_LEFT] > 0) {
- text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant("hseparation");
+ text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("hseparation"));
}
if (_internal_margin[SIDE_RIGHT] > 0) {
- text_clip -= _internal_margin[SIDE_RIGHT] + get_theme_constant("hseparation");
+ text_clip -= _internal_margin[SIDE_RIGHT] + get_theme_constant(SNAME("hseparation"));
}
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - text_buf->get_size() - Point2(_internal_margin[SIDE_RIGHT] - _internal_margin[SIDE_LEFT], 0)) / 2.0;
- switch (align) {
+ switch (align_rtl_checked) {
case ALIGN_LEFT: {
- if (rtl) {
- if (_internal_margin[SIDE_RIGHT] > 0) {
- text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - get_theme_constant("hseparation");
- } else {
- text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width;
- }
+ if (icon_align_rtl_checked != ALIGN_LEFT) {
+ icon_ofs.x = 0.0;
+ }
+ if (_internal_margin[SIDE_LEFT] > 0) {
+ text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("hseparation"));
} else {
- if (_internal_margin[SIDE_LEFT] > 0) {
- text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + get_theme_constant("hseparation");
- } else {
- text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x;
- }
+ text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x;
}
text_ofs.y += style->get_offset().y;
} break;
@@ -283,49 +310,38 @@ void Button::_notification(int p_what) {
if (text_ofs.x < 0) {
text_ofs.x = 0;
}
- text_ofs += icon_ofs;
+ if (icon_align_rtl_checked == ALIGN_LEFT) {
+ text_ofs += icon_ofs;
+ }
text_ofs += style->get_offset();
} break;
case ALIGN_RIGHT: {
- if (rtl) {
- if (_internal_margin[SIDE_LEFT] > 0) {
- text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + get_theme_constant("hseparation");
- } else {
- text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x;
- }
+ if (_internal_margin[SIDE_RIGHT] > 0) {
+ text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("hseparation"));
} else {
- if (_internal_margin[SIDE_RIGHT] > 0) {
- text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - get_theme_constant("hseparation");
- } else {
- text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width;
- }
+ text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width;
}
text_ofs.y += style->get_offset().y;
+ if (icon_align_rtl_checked == ALIGN_RIGHT) {
+ text_ofs.x -= icon_ofs.x;
+ }
} break;
}
- if (rtl) {
- text_ofs.x -= icon_ofs.x;
- }
-
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
}
text_buf->draw(ci, text_ofs, color);
-
- if (!_icon.is_null() && icon_region.size.width > 0) {
- draw_texture_rect_region(_icon, icon_region, Rect2(Point2(), _icon->get_size()), color_icon);
- }
} break;
}
}
void Button::_shape() {
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
text_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
@@ -457,6 +473,16 @@ Button::TextAlign Button::get_text_align() const {
return align;
}
+void Button::set_icon_align(TextAlign p_align) {
+ icon_align = p_align;
+ minimum_size_changed();
+ update();
+}
+
+Button::TextAlign Button::get_icon_align() const {
+ return icon_align;
+}
+
bool Button::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
@@ -519,14 +545,16 @@ void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_language"), &Button::get_language);
ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon);
ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_icon);
- ClassDB::bind_method(D_METHOD("set_expand_icon"), &Button::set_expand_icon);
- ClassDB::bind_method(D_METHOD("is_expand_icon"), &Button::is_expand_icon);
ClassDB::bind_method(D_METHOD("set_flat", "enabled"), &Button::set_flat);
+ ClassDB::bind_method(D_METHOD("is_flat"), &Button::is_flat);
ClassDB::bind_method(D_METHOD("set_clip_text", "enabled"), &Button::set_clip_text);
ClassDB::bind_method(D_METHOD("get_clip_text"), &Button::get_clip_text);
ClassDB::bind_method(D_METHOD("set_text_align", "align"), &Button::set_text_align);
ClassDB::bind_method(D_METHOD("get_text_align"), &Button::get_text_align);
- ClassDB::bind_method(D_METHOD("is_flat"), &Button::is_flat);
+ ClassDB::bind_method(D_METHOD("set_icon_align", "icon_align"), &Button::set_icon_align);
+ ClassDB::bind_method(D_METHOD("get_icon_align"), &Button::get_icon_align);
+ ClassDB::bind_method(D_METHOD("set_expand_icon"), &Button::set_expand_icon);
+ ClassDB::bind_method(D_METHOD("is_expand_icon"), &Button::is_expand_icon);
BIND_ENUM_CONSTANT(ALIGN_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER);
@@ -539,6 +567,7 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_align", "get_text_align");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_icon_align", "get_icon_align");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
}
diff --git a/scene/gui/button.h b/scene/gui/button.h
index d968f63f51..253d079680 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -58,6 +58,7 @@ private:
bool expand_icon = false;
bool clip_text = false;
TextAlign align = ALIGN_CENTER;
+ TextAlign icon_align = ALIGN_LEFT;
float _internal_margin[4] = {};
void _shape();
@@ -102,6 +103,9 @@ public:
void set_text_align(TextAlign p_align);
TextAlign get_text_align() const;
+ void set_icon_align(TextAlign p_align);
+ TextAlign get_icon_align() const;
+
Button(const String &p_text = String());
~Button();
};
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index c0650a8f3f..d93107df2d 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -33,12 +33,12 @@
#include "servers/rendering_server.h"
Size2 CheckBox::get_icon_size() const {
- Ref<Texture2D> checked = Control::get_theme_icon("checked");
- Ref<Texture2D> checked_disabled = Control::get_theme_icon("checked_disabled");
- Ref<Texture2D> unchecked = Control::get_theme_icon("unchecked");
- Ref<Texture2D> unchecked_disabled = Control::get_theme_icon("unchecked_disabled");
- Ref<Texture2D> radio_checked = Control::get_theme_icon("radio_checked");
- Ref<Texture2D> radio_unchecked = Control::get_theme_icon("radio_unchecked");
+ Ref<Texture2D> checked = Control::get_theme_icon(SNAME("checked"));
+ Ref<Texture2D> checked_disabled = Control::get_theme_icon(SNAME("checked_disabled"));
+ Ref<Texture2D> unchecked = Control::get_theme_icon(SNAME("unchecked"));
+ Ref<Texture2D> unchecked_disabled = Control::get_theme_icon(SNAME("unchecked_disabled"));
+ Ref<Texture2D> radio_checked = Control::get_theme_icon(SNAME("radio_checked"));
+ Ref<Texture2D> radio_unchecked = Control::get_theme_icon(SNAME("radio_unchecked"));
Size2 tex_size = Size2(0, 0);
if (!checked.is_null()) {
@@ -61,9 +61,9 @@ Size2 CheckBox::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0) {
- minsize.width += get_theme_constant("hseparation");
+ minsize.width += get_theme_constant(SNAME("hseparation"));
}
- Ref<StyleBox> sb = get_theme_stylebox("normal");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
return minsize;
@@ -83,7 +83,7 @@ void CheckBox::_notification(int p_what) {
Ref<Texture2D> on = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_checked" : "checked", is_disabled() ? "_disabled" : ""));
Ref<Texture2D> off = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_unchecked" : "unchecked", is_disabled() ? "_disabled" : ""));
- Ref<StyleBox> sb = get_theme_stylebox("normal");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
Vector2 ofs;
if (is_layout_rtl()) {
@@ -91,7 +91,7 @@ void CheckBox::_notification(int p_what) {
} else {
ofs.x = sb->get_margin(SIDE_LEFT);
}
- ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant("check_vadjust");
+ ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant(SNAME("check_vadjust"));
if (is_pressed()) {
on->draw(ci, ofs);
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index a8bf449355..162a256d23 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -52,9 +52,9 @@ Size2 CheckButton::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0) {
- minsize.width += get_theme_constant("hseparation");
+ minsize.width += get_theme_constant(SNAME("hseparation"));
}
- Ref<StyleBox> sb = get_theme_stylebox("normal");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
return minsize;
@@ -86,7 +86,7 @@ void CheckButton::_notification(int p_what) {
off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
}
- Ref<StyleBox> sb = get_theme_stylebox("normal");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
Vector2 ofs;
Size2 tex_size = get_icon_size();
@@ -95,7 +95,7 @@ void CheckButton::_notification(int p_what) {
} else {
ofs.x = get_size().width - (tex_size.width + sb->get_margin(SIDE_RIGHT));
}
- ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant("check_vadjust");
+ ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant(SNAME("check_vadjust"));
if (is_pressed()) {
on->draw(ci, ofs);
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index ba1534ed5c..f302f64224 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -50,28 +50,28 @@ void CodeEdit::_notification(int p_what) {
set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0', 0, cache.font_size).width);
set_gutter_width(fold_gutter, get_row_height() / 1.2);
- breakpoint_color = get_theme_color("breakpoint_color");
- breakpoint_icon = get_theme_icon("breakpoint");
+ breakpoint_color = get_theme_color(SNAME("breakpoint_color"));
+ breakpoint_icon = get_theme_icon(SNAME("breakpoint"));
- bookmark_color = get_theme_color("bookmark_color");
- bookmark_icon = get_theme_icon("bookmark");
+ bookmark_color = get_theme_color(SNAME("bookmark_color"));
+ bookmark_icon = get_theme_icon(SNAME("bookmark"));
- executing_line_color = get_theme_color("executing_line_color");
- executing_line_icon = get_theme_icon("executing_line");
+ executing_line_color = get_theme_color(SNAME("executing_line_color"));
+ executing_line_icon = get_theme_icon(SNAME("executing_line"));
- line_number_color = get_theme_color("line_number_color");
+ line_number_color = get_theme_color(SNAME("line_number_color"));
- folding_color = get_theme_color("code_folding_color");
- can_fold_icon = get_theme_icon("can_fold");
- folded_icon = get_theme_icon("folded");
+ folding_color = get_theme_color(SNAME("code_folding_color"));
+ can_fold_icon = get_theme_icon(SNAME("can_fold"));
+ folded_icon = get_theme_icon(SNAME("folded"));
- code_completion_max_width = get_theme_constant("completion_max_width") * cache.font->get_char_size('x').x;
- code_completion_max_lines = get_theme_constant("completion_lines");
- code_completion_scroll_width = get_theme_constant("completion_scroll_width");
- code_completion_scroll_color = get_theme_color("completion_scroll_color");
- code_completion_background_color = get_theme_color("completion_background_color");
- code_completion_selected_color = get_theme_color("completion_selected_color");
- code_completion_existing_color = get_theme_color("completion_existing_color");
+ code_completion_max_width = get_theme_constant(SNAME("completion_max_width")) * cache.font->get_char_size('x').x;
+ code_completion_max_lines = get_theme_constant(SNAME("completion_lines"));
+ code_completion_scroll_width = get_theme_constant(SNAME("completion_scroll_width"));
+ code_completion_scroll_color = get_theme_color(SNAME("completion_scroll_color"));
+ code_completion_background_color = get_theme_color(SNAME("completion_background_color"));
+ code_completion_selected_color = get_theme_color(SNAME("completion_selected_color"));
+ code_completion_existing_color = get_theme_color(SNAME("completion_existing_color"));
} break;
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
@@ -81,11 +81,11 @@ void CodeEdit::_notification(int p_what) {
bool code_completion_below = false;
if (caret_visible && code_completion_active && code_completion_options.size() > 0) {
- Ref<StyleBox> csb = get_theme_stylebox("completion");
+ Ref<StyleBox> csb = get_theme_stylebox(SNAME("completion"));
const int code_completion_options_count = code_completion_options.size();
const int lines = MIN(code_completion_options_count, code_completion_max_lines);
- const int icon_hsep = get_theme_constant("hseparation", "ItemList");
+ const int icon_hsep = get_theme_constant(SNAME("hseparation"), SNAME("ItemList"));
const Size2 icon_area_size(row_height, row_height);
code_completion_rect.size.width = code_completion_longest_line + icon_hsep + icon_area_size.width + 2;
@@ -164,8 +164,8 @@ void CodeEdit::_notification(int p_what) {
if (caret_visible && code_hint != "" && (!code_completion_active || (code_completion_below != code_hint_draw_below))) {
const Ref<Font> font = cache.font;
const int font_height = font->get_height(cache.font_size);
- Ref<StyleBox> sb = get_theme_stylebox("panel", "TooltipPanel");
- Color font_color = get_theme_color("font_color", "TooltipLabel");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"));
+ Color font_color = get_theme_color(SNAME("font_color"), SNAME("TooltipLabel"));
Vector<String> code_hint_lines = code_hint.split("\n");
int line_count = code_hint_lines.size();
@@ -969,7 +969,7 @@ void CodeEdit::set_line_as_breakpoint(int p_line, bool p_breakpointed) {
} else if (breakpointed_lines.has(p_line)) {
breakpointed_lines.erase(p_line);
}
- emit_signal("breakpoint_toggled", p_line);
+ emit_signal(SNAME("breakpoint_toggled"), p_line);
update();
}
@@ -1551,7 +1551,7 @@ void CodeEdit::request_code_completion(bool p_force) {
}
if (p_force) {
- emit_signal("request_code_completion");
+ emit_signal(SNAME("request_code_completion"));
return;
}
@@ -1559,9 +1559,9 @@ void CodeEdit::request_code_completion(bool p_force) {
int ofs = CLAMP(cursor_get_column(), 0, line.length());
if (ofs > 0 && (is_in_string(cursor_get_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(String::chr(line[ofs - 1])))) {
- emit_signal("request_code_completion");
+ emit_signal(SNAME("request_code_completion"));
} else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[ofs - 2]))) {
- emit_signal("request_code_completion");
+ emit_signal(SNAME("request_code_completion"));
}
}
@@ -2534,9 +2534,9 @@ void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
}
breakpointed_lines.erase(line);
- emit_signal("breakpoint_toggled", line);
+ emit_signal(SNAME("breakpoint_toggled"), line);
if (line_count > 0 || line >= p_from_line) {
- emit_signal("breakpoint_toggled", line + line_count);
+ emit_signal(SNAME("breakpoint_toggled"), line + line_count);
breakpointed_lines[line + line_count] = true;
continue;
}
@@ -2562,7 +2562,7 @@ CodeEdit::CodeEdit() {
set_gutter_name(gutter_idx, "main_gutter");
set_gutter_draw(gutter_idx, false);
set_gutter_overwritable(gutter_idx, true);
- set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM);
+ set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM);
set_gutter_custom_draw(gutter_idx, this, "_main_gutter_draw_callback");
gutter_idx++;
@@ -2570,7 +2570,7 @@ CodeEdit::CodeEdit() {
add_gutter();
set_gutter_name(gutter_idx, "line_numbers");
set_gutter_draw(gutter_idx, false);
- set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM);
+ set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM);
set_gutter_custom_draw(gutter_idx, this, "_line_number_draw_callback");
gutter_idx++;
@@ -2578,7 +2578,7 @@ CodeEdit::CodeEdit() {
add_gutter();
set_gutter_name(gutter_idx, "fold_gutter");
set_gutter_draw(gutter_idx, false);
- set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM);
+ set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM);
set_gutter_custom_draw(gutter_idx, this, "_fold_gutter_draw_callback");
gutter_idx++;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 049de4c8c5..261480bcdd 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -40,40 +40,48 @@
#endif
#include "scene/main/window.h"
+List<Color> ColorPicker::preset_cache;
+
void ColorPicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- btn_pick->set_icon(get_theme_icon("screen_picker", "ColorPicker"));
- bt_add_preset->set_icon(get_theme_icon("add_preset"));
+ btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker")));
+ bt_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
_update_controls();
} break;
case NOTIFICATION_ENTER_TREE: {
- btn_pick->set_icon(get_theme_icon("screen_picker", "ColorPicker"));
- bt_add_preset->set_icon(get_theme_icon("add_preset"));
+ btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker")));
+ bt_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
_update_controls();
_update_color();
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- PackedColorArray saved_presets = EditorSettings::get_singleton()->get_project_metadata("color_picker", "presets", PackedColorArray());
+ if (preset_cache.is_empty()) {
+ PackedColorArray saved_presets = EditorSettings::get_singleton()->get_project_metadata("color_picker", "presets", PackedColorArray());
+ for (int i = 0; i < saved_presets.size(); i++) {
+ preset_cache.push_back(saved_presets[i]);
+ }
+ }
- for (int i = 0; i < saved_presets.size(); i++) {
- add_preset(saved_presets[i]);
+ for (int i = 0; i < preset_cache.size(); i++) {
+ presets.push_back(preset_cache[i]);
}
+ preset->update();
}
#endif
} break;
case NOTIFICATION_PARENTED: {
for (int i = 0; i < 4; i++) {
- set_offset((Side)i, get_offset((Side)i) + get_theme_constant("margin"));
+ set_offset((Side)i, get_offset((Side)i) + get_theme_constant(SNAME("margin")));
}
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
Popup *p = Object::cast_to<Popup>(get_parent());
if (p) {
- p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant("margin") * 2, get_combined_minimum_size().height + get_theme_constant("margin") * 2));
+ p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant(SNAME("margin")) * 2, get_combined_minimum_size().height + get_theme_constant(SNAME("margin")) * 2));
}
} break;
case NOTIFICATION_WM_CLOSE_REQUEST: {
@@ -89,43 +97,49 @@ Ref<Shader> ColorPicker::circle_shader;
void ColorPicker::init_shaders() {
wheel_shader.instantiate();
- wheel_shader->set_code(
- "shader_type canvas_item;"
- "void fragment() {"
- " float x = UV.x - 0.5;"
- " float y = UV.y - 0.5;"
- " float a = atan(y, x);"
- " x += 0.001;"
- " y += 0.001;"
- " float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
- " x -= 0.002;"
- " float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
- " y -= 0.002;"
- " float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
- " x += 0.002;"
- " float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
- " COLOR = vec4(clamp((abs(fract(((a - TAU) / TAU) + vec3(3.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0), 0.0, 1.0), (b + b2 + b3 + b4) / 4.00);"
- "}");
+ wheel_shader->set_code(R"(
+shader_type canvas_item;
+
+void fragment() {
+ float x = UV.x - 0.5;
+ float y = UV.y - 0.5;
+ float a = atan(y, x);
+ x += 0.001;
+ y += 0.001;
+ float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
+ x -= 0.002;
+ float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
+ y -= 0.002;
+ float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
+ x += 0.002;
+ float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
+
+ COLOR = vec4(clamp((abs(fract(((a - TAU) / TAU) + vec3(3.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0), 0.0, 1.0), (b + b2 + b3 + b4) / 4.00);
+}
+)");
circle_shader.instantiate();
- circle_shader->set_code(
- "shader_type canvas_item;"
- "uniform float v = 1.0;"
- "void fragment() {"
- " float x = UV.x - 0.5;"
- " float y = UV.y - 0.5;"
- " float a = atan(y, x);"
- " x += 0.001;"
- " y += 0.001;"
- " float b = float(sqrt(x * x + y * y) < 0.5);"
- " x -= 0.002;"
- " float b2 = float(sqrt(x * x + y * y) < 0.5);"
- " y -= 0.002;"
- " float b3 = float(sqrt(x * x + y * y) < 0.5);"
- " x += 0.002;"
- " float b4 = float(sqrt(x * x + y * y) < 0.5);"
- " COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);"
- "}");
+ circle_shader->set_code(R"(
+shader_type canvas_item;
+
+uniform float v = 1.0;
+
+void fragment() {
+ float x = UV.x - 0.5;
+ float y = UV.y - 0.5;
+ float a = atan(y, x);
+ x += 0.001;
+ y += 0.001;
+ float b = float(sqrt(x * x + y * y) < 0.5);
+ x -= 0.002;
+ float b2 = float(sqrt(x * x + y * y) < 0.5);
+ y -= 0.002;
+ float b3 = float(sqrt(x * x + y * y) < 0.5);
+ x += 0.002;
+ float b4 = float(sqrt(x * x + y * y) < 0.5);
+
+ COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);
+})");
}
void ColorPicker::finish_shaders() {
@@ -134,7 +148,7 @@ void ColorPicker::finish_shaders() {
}
void ColorPicker::set_focus_on_line_edit() {
- c_text->call_deferred("grab_focus");
+ c_text->call_deferred(SNAME("grab_focus"));
}
void ColorPicker::_update_controls() {
@@ -172,7 +186,7 @@ void ColorPicker::_update_controls() {
}
} else {
Ref<StyleBoxEmpty> style_box_empty(memnew(StyleBoxEmpty));
- Ref<Texture2D> bar_arrow = get_theme_icon("bar_arrow");
+ Ref<Texture2D> bar_arrow = get_theme_icon(SNAME("bar_arrow"));
for (int i = 0; i < 4; i++) {
scroll[i]->add_theme_icon_override("grabber", bar_arrow);
@@ -286,7 +300,7 @@ void ColorPicker::_value_changed(double) {
}
_set_pick_color(color, false);
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
void ColorPicker::_html_submitted(const String &p_html) {
@@ -305,7 +319,7 @@ void ColorPicker::_html_submitted(const String &p_html) {
}
set_pick_color(color);
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
void ColorPicker::_update_color(bool p_update_sliders) {
@@ -380,7 +394,7 @@ void ColorPicker::_text_type_toggled() {
text_is_constructor = !text_is_constructor;
if (text_is_constructor) {
text_type->set_text("");
- text_type->set_icon(get_theme_icon("Script", "EditorIcons"));
+ text_type->set_icon(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")));
c_text->set_editable(false);
} else {
@@ -413,6 +427,7 @@ void ColorPicker::add_preset(const Color &p_color) {
presets.move_to_back(presets.find(p_color));
} else {
presets.push_back(p_color);
+ preset_cache.push_back(p_color);
}
preset->update();
@@ -427,6 +442,7 @@ void ColorPicker::add_preset(const Color &p_color) {
void ColorPicker::erase_preset(const Color &p_color) {
if (presets.find(p_color)) {
presets.erase(presets.find(p_color));
+ preset_cache.erase(preset_cache.find(p_color));
preset->update();
#ifdef TOOLS_ENABLED
@@ -527,7 +543,7 @@ void ColorPicker::_sample_input(const Ref<InputEvent> &p_event) {
// Revert to the old color when left-clicking the old color sample.
color = old_color;
_update_color();
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
}
}
@@ -544,28 +560,28 @@ void ColorPicker::_sample_draw() {
const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
if (display_old_color && old_color.a < 1.0) {
- sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), rect_old, true);
+ sample->draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPicker")), rect_old, true);
}
sample->draw_rect(rect_old, old_color);
if (old_color.r > 1 || old_color.g > 1 || old_color.b > 1) {
// Draw an indicator to denote that the old color is "overbright" and can't be displayed accurately in the preview.
- sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2());
+ sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2());
}
} else {
rect_new = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95));
}
if (color.a < 1.0) {
- sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), rect_new, true);
+ sample->draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPicker")), rect_new, true);
}
sample->draw_rect(rect_new, color);
if (color.r > 1 || color.g > 1 || color.b > 1) {
// Draw an indicator to denote that the new color is "overbright" and can't be displayed accurately in the preview.
- sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2(uv_edit->get_size().width * 0.5, 0));
+ sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2(uv_edit->get_size().width * 0.5, 0));
}
}
@@ -639,7 +655,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
default: {
}
}
- Ref<Texture2D> cursor = get_theme_icon("picker_cursor", "ColorPicker");
+ Ref<Texture2D> cursor = get_theme_icon(SNAME("picker_cursor"), SNAME("ColorPicker"));
int x;
int y;
if (picker_type == SHAPE_VHS_CIRCLE) {
@@ -669,7 +685,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
} else if (p_which == 1) {
if (picker_type == SHAPE_HSV_RECTANGLE) {
- Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker");
+ Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
c->draw_texture_rect(hue, Rect2(Point2(), c->get_size()));
int y = c->get_size().y - c->get_size().y * (1.0 - h);
Color col;
@@ -718,7 +734,7 @@ void ColorPicker::_slider_draw(int p_which) {
#endif
if (p_which == 3) {
- scroll[p_which]->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
+ scroll[p_which]->draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
left_color = color;
left_color.a = 0;
@@ -730,7 +746,7 @@ void ColorPicker::_slider_draw(int p_which) {
}
if (hsv_mode_enabled) {
if (p_which == 0) {
- Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker");
+ Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
scroll[p_which]->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
scroll[p_which]->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(scroll[p_which]->get_size().x, margin)), false, Color(1, 1, 1), true);
return;
@@ -816,10 +832,10 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
} else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
changing_color = false;
spinning = false;
} else {
@@ -863,7 +879,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
}
}
@@ -888,9 +904,9 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
} else if (!bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
}
@@ -911,7 +927,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
}
}
@@ -931,12 +947,12 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
}
set_pick_color(presets[index]);
_update_color();
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
} else if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_RIGHT && presets_enabled) {
index = bev->get_position().x / (preset->get_size().x / presets.size());
Color clicked_preset = presets[index];
erase_preset(clicked_preset);
- emit_signal("preset_removed", clicked_preset);
+ emit_signal(SNAME("preset_removed"), clicked_preset);
bt_add_preset->show();
}
}
@@ -962,7 +978,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> bev = p_event;
if (bev.is_valid() && bev->get_button_index() == MOUSE_BUTTON_LEFT && !bev->is_pressed()) {
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
screen->hide();
}
@@ -985,7 +1001,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
void ColorPicker::_add_preset_pressed() {
add_preset(color);
- emit_signal("preset_added", color);
+ emit_signal(SNAME("preset_added"), color);
}
void ColorPicker::_screen_pick_pressed() {
@@ -1002,7 +1018,7 @@ void ColorPicker::_screen_pick_pressed() {
screen->set_default_cursor_shape(CURSOR_POINTING_HAND);
screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input));
// It immediately toggles off in the first press otherwise.
- screen->call_deferred("connect", "hidden", Callable(btn_pick, "set_pressed"), varray(false));
+ screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed"), varray(false));
}
screen->raise();
#ifndef _MSC_VER
@@ -1038,7 +1054,7 @@ void ColorPicker::_focus_exit() {
}
void ColorPicker::_html_focus_exit() {
- if (c_text->get_menu()->is_visible()) {
+ if (c_text->is_menu_visible()) {
return;
}
_html_submitted(c_text->get_text());
@@ -1121,7 +1137,7 @@ ColorPicker::ColorPicker() :
uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);
uv_edit->set_h_size_flags(SIZE_EXPAND_FILL);
uv_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- uv_edit->set_custom_minimum_size(Size2(get_theme_constant("sv_width"), get_theme_constant("sv_height")));
+ uv_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));
uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit));
HBoxContainer *hb_smpl = memnew(HBoxContainer);
@@ -1151,7 +1167,7 @@ ColorPicker::ColorPicker() :
HBoxContainer *hbc = memnew(HBoxContainer);
labels[i] = memnew(Label());
- labels[i]->set_custom_minimum_size(Size2(get_theme_constant("label_width"), 0));
+ labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
hbc->add_child(labels[i]);
@@ -1210,7 +1226,7 @@ ColorPicker::ColorPicker() :
wheel_edit->set_h_size_flags(SIZE_EXPAND_FILL);
wheel_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- wheel_edit->set_custom_minimum_size(Size2(get_theme_constant("sv_width"), get_theme_constant("sv_height")));
+ wheel_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));
hb_edit->add_child(wheel_edit);
wheel_mat.instantiate();
@@ -1235,7 +1251,7 @@ ColorPicker::ColorPicker() :
wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, wheel_uv));
hb_edit->add_child(w_edit);
- w_edit->set_custom_minimum_size(Size2(get_theme_constant("h_width"), 0));
+ w_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("h_width")), 0));
w_edit->set_h_size_flags(SIZE_FILL);
w_edit->set_v_size_flags(SIZE_EXPAND_FILL);
w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input));
@@ -1275,11 +1291,11 @@ void ColorPickerButton::_about_to_popup() {
void ColorPickerButton::_color_changed(const Color &p_color) {
color = p_color;
update();
- emit_signal("color_changed", color);
+ emit_signal(SNAME("color_changed"), color);
}
void ColorPickerButton::_modal_closed() {
- emit_signal("popup_closed");
+ emit_signal(SNAME("popup_closed"));
set_pressed(false);
}
@@ -1317,14 +1333,14 @@ void ColorPickerButton::pressed() {
void ColorPickerButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- const Ref<StyleBox> normal = get_theme_stylebox("normal");
+ const Ref<StyleBox> normal = get_theme_stylebox(SNAME("normal"));
const Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size());
- draw_texture_rect(Control::get_theme_icon("bg", "ColorPickerButton"), r, true);
+ draw_texture_rect(Control::get_theme_icon(SNAME("bg"), SNAME("ColorPickerButton")), r, true);
draw_rect(r, color);
if (color.r > 1 || color.g > 1 || color.b > 1) {
// Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
- draw_texture(Control::get_theme_icon("overbright_indicator", "ColorPicker"), normal->get_offset());
+ draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), normal->get_offset());
}
} break;
case NOTIFICATION_WM_CLOSE_REQUEST: {
@@ -1389,7 +1405,7 @@ void ColorPickerButton::_update_picker() {
picker->set_pick_color(color);
picker->set_edit_alpha(edit_alpha);
picker->set_display_old_color(true);
- emit_signal("picker_created");
+ emit_signal(SNAME("picker_created"));
}
}
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 3bd2ff9375..60da3957aa 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -58,6 +58,7 @@ public:
private:
static Ref<Shader> wheel_shader;
static Ref<Shader> circle_shader;
+ static List<Color> preset_cache;
Control *screen = nullptr;
Control *uv_edit = memnew(Control);
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index dea69aae6b..c97434f69b 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -47,9 +47,9 @@ void Container::add_child_notify(Node *p_child) {
return;
}
- control->connect("size_flags_changed", callable_mp(this, &Container::queue_sort));
- control->connect("minimum_size_changed", callable_mp(this, &Container::_child_minsize_changed));
- control->connect("visibility_changed", callable_mp(this, &Container::_child_minsize_changed));
+ control->connect(SNAME("size_flags_changed"), callable_mp(this, &Container::queue_sort));
+ control->connect(SNAME("minimum_size_changed"), callable_mp(this, &Container::_child_minsize_changed));
+ control->connect(SNAME("visibility_changed"), callable_mp(this, &Container::_child_minsize_changed));
minimum_size_changed();
queue_sort();
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index a8060615d4..032533d4a9 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -339,13 +339,6 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
void Control::_get_property_list(List<PropertyInfo> *p_list) const {
Ref<Theme> theme = Theme::get_default();
- /* Using the default theme since the properties below are meant for editor only
- if (data.theme.is_valid()) {
- theme = data.theme;
- } else {
- theme = Theme::get_default();
-
- }*/
{
List<StringName> names;
@@ -421,10 +414,42 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
+void Control::_validate_property(PropertyInfo &property) const {
+ if (property.name == "theme_type_variation") {
+ List<StringName> names;
+
+ // Only the default theme and the project theme are used for the list of options.
+ // This is an imposed limitation to simplify the logic needed to leverage those options.
+ Theme::get_default()->get_type_variation_list(get_class_name(), &names);
+ if (Theme::get_project_default().is_valid()) {
+ Theme::get_project_default()->get_type_variation_list(get_class_name(), &names);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+
+ Vector<StringName> unique_names;
+ String hint_string;
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ // Skip duplicate values.
+ if (unique_names.has(E->get())) {
+ continue;
+ }
+
+ hint_string += String(E->get()) + ",";
+ unique_names.append(E->get());
+ }
+
+ property.hint_string = hint_string;
+ }
+}
+
Control *Control::get_parent_control() const {
return data.parent;
}
+Window *Control::get_parent_window() const {
+ return data.parent_window;
+}
+
void Control::set_layout_direction(Control::LayoutDirection p_direction) {
ERR_FAIL_INDEX((int)p_direction, 4);
@@ -438,21 +463,21 @@ Control::LayoutDirection Control::get_layout_direction() const {
bool Control::is_layout_rtl() const {
if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) {
- Window *parent_window = Object::cast_to<Window>(get_parent());
+ Window *parent_window = get_parent_window();
Control *parent_control = get_parent_control();
if (parent_control) {
return parent_control->is_layout_rtl();
} else if (parent_window) {
return parent_window->is_layout_rtl();
} else {
- if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
}
} else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
- if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
@@ -522,6 +547,7 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_ENTER_CANVAS: {
data.parent = Object::cast_to<Control>(get_parent());
+ data.parent_window = Object::cast_to<Window>(get_parent());
Node *parent = this; //meh
Control *parent_control = nullptr;
@@ -586,6 +612,7 @@ void Control::_notification(int p_notification) {
data.parent = nullptr;
data.parent_canvas_item = nullptr;
+ data.parent_window = nullptr;
} break;
case NOTIFICATION_MOVED_IN_PARENT: {
@@ -651,19 +678,10 @@ void Control::_notification(int p_notification) {
}
bool Control::has_point(const Point2 &p_point) const {
- if (get_script_instance()) {
- Variant v = p_point;
- const Variant *p = &v;
- Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_has_point, &p, 1, ce);
- if (ce.error == Callable::CallError::CALL_OK) {
- return ret;
- }
+ bool ret;
+ if (GDVIRTUAL_CALL(_has_point, p_point, ret)) {
+ return ret;
}
- /*if (has_stylebox("mask")) {
- Ref<StyleBox> mask = get_stylebox("mask");
- return mask->test_mask(p_point,Rect2(Point2(),get_size()));
- }*/
return Rect2(Point2(), get_size()).has_point(p_point);
}
@@ -876,18 +894,19 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
}
void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
- if (data.theme_custom_type != StringName()) {
- p_list->push_back(data.theme_custom_type);
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
+ if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) {
+ Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
+ } else {
+ Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
}
- Theme::get_type_dependencies(get_class_name(), p_list);
} else {
- Theme::get_type_dependencies(p_theme_type, p_list);
+ Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list);
}
}
Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
if (tex) {
return *tex;
@@ -900,7 +919,7 @@ Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringNam
}
Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const Ref<StyleBox> *style = data.style_override.getptr(p_name);
if (style) {
return *style;
@@ -913,7 +932,7 @@ Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const String
}
Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const Ref<Font> *font = data.font_override.getptr(p_name);
if (font) {
return *font;
@@ -926,7 +945,7 @@ Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_
}
int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const int *font_size = data.font_size_override.getptr(p_name);
if (font_size) {
return *font_size;
@@ -939,7 +958,7 @@ int Control::get_theme_font_size(const StringName &p_name, const StringName &p_t
}
Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const Color *color = data.color_override.getptr(p_name);
if (color) {
return *color;
@@ -952,7 +971,7 @@ Color Control::get_theme_color(const StringName &p_name, const StringName &p_the
}
int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const int *constant = data.constant_override.getptr(p_name);
if (constant) {
return *constant;
@@ -995,7 +1014,7 @@ bool Control::has_theme_constant_override(const StringName &p_name) const {
}
bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
if (has_theme_icon_override(p_name)) {
return true;
}
@@ -1007,7 +1026,7 @@ bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme
}
bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
if (has_theme_stylebox_override(p_name)) {
return true;
}
@@ -1019,7 +1038,7 @@ bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_t
}
bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
if (has_theme_font_override(p_name)) {
return true;
}
@@ -1031,7 +1050,7 @@ bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme
}
bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
if (has_theme_font_size_override(p_name)) {
return true;
}
@@ -1043,7 +1062,7 @@ bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_
}
bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
if (has_theme_color_override(p_name)) {
return true;
}
@@ -1055,7 +1074,7 @@ bool Control::has_theme_color(const StringName &p_name, const StringName &p_them
}
bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
if (has_theme_constant_override(p_name)) {
return true;
}
@@ -1077,7 +1096,7 @@ Rect2 Control::get_parent_anchorable_rect() const {
} else {
#ifdef TOOLS_ENABLED
Node *edited_root = get_tree()->get_edited_scene_root();
- if (edited_root && (this == edited_root || edited_root->is_a_parent_of(this))) {
+ if (edited_root && (this == edited_root || edited_root->is_ancestor_of(this))) {
parent_rect.size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
} else {
parent_rect = get_viewport()->get_visible_rect();
@@ -1497,7 +1516,7 @@ Point2 Control::get_global_position() const {
Point2 Control::get_screen_position() const {
ERR_FAIL_COND_V(!is_inside_tree(), Point2());
- Point2 global_pos = get_global_position();
+ Point2 global_pos = get_viewport()->get_canvas_transform().xform(get_global_position());
Window *w = Object::cast_to<Window>(get_viewport());
if (w && !w->is_embedding_subwindows()) {
global_pos += w->get_position();
@@ -2040,13 +2059,13 @@ Ref<Theme> Control::get_theme() const {
return data.theme;
}
-void Control::set_theme_custom_type(const StringName &p_theme_type) {
- data.theme_custom_type = p_theme_type;
+void Control::set_theme_type_variation(const StringName &p_theme_type) {
+ data.theme_type_variation = p_theme_type;
_propagate_theme_changed(this, data.theme_owner, data.theme_owner_window);
}
-StringName Control::get_theme_custom_type() const {
- return data.theme_custom_type;
+StringName Control::get_theme_type_variation() const {
+ return data.theme_type_variation;
}
void Control::set_tooltip(const String &p_tooltip) {
@@ -2466,14 +2485,6 @@ real_t Control::get_rotation() const {
return data.rotation;
}
-void Control::set_rotation_degrees(real_t p_degrees) {
- set_rotation(Math::deg2rad(p_degrees));
-}
-
-real_t Control::get_rotation_degrees() const {
- return Math::rad2deg(get_rotation());
-}
-
void Control::_override_changed() {
notification(NOTIFICATION_THEME_CHANGED);
emit_signal(SceneStringNames::get_singleton()->theme_changed);
@@ -2641,7 +2652,6 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_global_position", "position", "keep_offsets"), &Control::set_global_position, DEFVAL(false));
ClassDB::bind_method(D_METHOD("_set_global_position", "position"), &Control::_set_global_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation);
- ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Control::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale);
ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset);
ClassDB::bind_method(D_METHOD("get_offset", "offset"), &Control::get_offset);
@@ -2650,7 +2660,6 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position);
ClassDB::bind_method(D_METHOD("get_size"), &Control::get_size);
ClassDB::bind_method(D_METHOD("get_rotation"), &Control::get_rotation);
- ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Control::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
@@ -2679,8 +2688,8 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme);
ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme);
- ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Control::set_theme_custom_type);
- ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Control::get_theme_custom_type);
+ ClassDB::bind_method(D_METHOD("set_theme_type_variation", "theme_type"), &Control::set_theme_type_variation);
+ ClassDB::bind_method(D_METHOD("get_theme_type_variation"), &Control::get_theme_type_variation);
ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Control::add_theme_icon_override);
ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Control::add_theme_style_override);
@@ -2802,8 +2811,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rect_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rect_rotation_degrees", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater"), "set_rotation_degrees", "get_rotation_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rect_rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents");
@@ -2830,7 +2838,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio");
ADD_GROUP("Theme", "theme_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_type_variation", PROPERTY_HINT_ENUM_SUGGESTION), "set_theme_type_variation", "get_theme_type_variation");
ADD_GROUP("", "");
BIND_ENUM_CONSTANT(FOCUS_NONE);
@@ -2932,5 +2940,5 @@ void Control::_bind_methods() {
ADD_SIGNAL(MethodInfo("minimum_size_changed"));
ADD_SIGNAL(MethodInfo("theme_changed"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_point", PropertyInfo(Variant::VECTOR2, "point")));
+ GDVIRTUAL_BIND(_has_point);
}
diff --git a/scene/gui/control.h b/scene/gui/control.h
index ad6b4136e1..51b454b334 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -32,6 +32,7 @@
#define CONTROL_H
#include "core/math/transform_2d.h"
+#include "core/object/gdvirtual.gen.inc"
#include "core/templates/rid.h"
#include "scene/gui/shortcut.h"
#include "scene/main/canvas_item.h"
@@ -201,7 +202,8 @@ private:
Ref<Theme> theme;
Control *theme_owner = nullptr;
Window *theme_owner_window = nullptr;
- StringName theme_custom_type;
+ Window *parent_window = nullptr;
+ StringName theme_type_variation;
String tooltip;
CursorShape default_cursor = CURSOR_ARROW;
@@ -264,6 +266,7 @@ private:
static bool has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types);
_FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
+ GDVIRTUAL1RC(bool, _has_point, Vector2)
protected:
virtual void add_child_notify(Node *p_child) override;
virtual void remove_child_notify(Node *p_child) override;
@@ -277,8 +280,8 @@ protected:
void _get_property_list(List<PropertyInfo> *p_list) const;
void _notification(int p_notification);
-
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const override;
//bind helpers
@@ -340,6 +343,7 @@ public:
Size2 get_custom_minimum_size() const;
Control *get_parent_control() const;
+ Window *get_parent_window() const;
void set_layout_direction(LayoutDirection p_direction);
LayoutDirection get_layout_direction() const;
@@ -383,9 +387,7 @@ public:
void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting.
void set_rotation(real_t p_radians);
- void set_rotation_degrees(real_t p_degrees);
real_t get_rotation() const;
- real_t get_rotation_degrees() const;
void set_h_grow_direction(GrowDirection p_direction);
GrowDirection get_h_grow_direction() const;
@@ -402,8 +404,8 @@ public:
void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;
- void set_theme_custom_type(const StringName &p_theme_type);
- StringName get_theme_custom_type() const;
+ void set_theme_type_variation(const StringName &p_theme_type);
+ StringName get_theme_type_variation() const;
void set_h_size_flags(int p_flags);
int get_h_size_flags() const;
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index f63ae7569f..f5c764e9cc 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -76,7 +76,7 @@ void AcceptDialog::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- bg->add_theme_style_override("panel", bg->get_theme_stylebox("panel", "AcceptDialog"));
+ bg->add_theme_style_override("panel", bg->get_theme_stylebox(SNAME("panel"), SNAME("AcceptDialog")));
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -106,7 +106,7 @@ void AcceptDialog::_ok_pressed() {
set_visible(false);
}
ok_pressed();
- emit_signal("confirmed");
+ emit_signal(SNAME("confirmed"));
}
void AcceptDialog::_cancel_pressed() {
@@ -116,9 +116,9 @@ void AcceptDialog::_cancel_pressed() {
parent_visible = nullptr;
}
- call_deferred("hide");
+ call_deferred(SNAME("hide"));
- emit_signal("cancelled");
+ emit_signal(SNAME("cancelled"));
cancel_pressed();
@@ -148,11 +148,11 @@ bool AcceptDialog::get_hide_on_ok() const {
}
void AcceptDialog::set_autowrap(bool p_autowrap) {
- label->set_autowrap(p_autowrap);
+ label->set_autowrap_mode(p_autowrap ? Label::AUTOWRAP_WORD : Label::AUTOWRAP_OFF);
}
bool AcceptDialog::has_autowrap() {
- return label->has_autowrap();
+ return label->get_autowrap_mode() != Label::AUTOWRAP_OFF;
}
void AcceptDialog::register_text_enter(Control *p_line_edit) {
@@ -168,7 +168,7 @@ void AcceptDialog::_update_child_rects() {
if (label->get_text().is_empty()) {
label_size.height = 0;
}
- int margin = hbc->get_theme_constant("margin", "Dialogs");
+ int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
Size2 size = get_size();
Size2 hminsize = hbc->get_combined_minimum_size();
@@ -200,7 +200,7 @@ void AcceptDialog::_update_child_rects() {
}
Size2 AcceptDialog::_get_contents_minimum_size() const {
- int margin = hbc->get_theme_constant("margin", "Dialogs");
+ int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
Size2 minsize = label->get_combined_minimum_size();
for (int i = 0; i < get_child_count(); i++) {
@@ -230,7 +230,7 @@ Size2 AcceptDialog::_get_contents_minimum_size() const {
}
void AcceptDialog::_custom_action(const String &p_action) {
- emit_signal("custom_action", p_action);
+ emit_signal(SNAME("custom_action"), p_action);
custom_action(p_action);
}
@@ -263,6 +263,28 @@ Button *AcceptDialog::add_cancel_button(const String &p_cancel) {
return b;
}
+void AcceptDialog::remove_button(Control *p_button) {
+ Button *button = Object::cast_to<Button>(p_button);
+ ERR_FAIL_NULL(button);
+ ERR_FAIL_COND_MSG(button->get_parent() != hbc, vformat("Cannot remove button %s as it does not belong to this dialog.", button->get_name()));
+ ERR_FAIL_COND_MSG(button == ok, "Cannot remove dialog's OK button.");
+
+ Node *right_spacer = hbc->get_child(button->get_index() + 1);
+ // Should always be valid but let's avoid crashing
+ if (right_spacer) {
+ hbc->remove_child(right_spacer);
+ memdelete(right_spacer);
+ }
+ hbc->remove_child(button);
+
+ if (button->is_connected("pressed", callable_mp(this, &AcceptDialog::_custom_action))) {
+ button->disconnect("pressed", callable_mp(this, &AcceptDialog::_custom_action));
+ }
+ if (button->is_connected("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed))) {
+ button->disconnect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
+ }
+}
+
void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_ok_button"), &AcceptDialog::get_ok_button);
ClassDB::bind_method(D_METHOD("get_label"), &AcceptDialog::get_label);
@@ -270,6 +292,7 @@ void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_hide_on_ok"), &AcceptDialog::get_hide_on_ok);
ClassDB::bind_method(D_METHOD("add_button", "text", "right", "action"), &AcceptDialog::add_button, DEFVAL(false), DEFVAL(""));
ClassDB::bind_method(D_METHOD("add_cancel_button", "name"), &AcceptDialog::add_cancel_button);
+ ClassDB::bind_method(D_METHOD("remove_button", "button"), &AcceptDialog::remove_button);
ClassDB::bind_method(D_METHOD("register_text_enter", "line_edit"), &AcceptDialog::register_text_enter);
ClassDB::bind_method(D_METHOD("set_text", "text"), &AcceptDialog::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &AcceptDialog::get_text);
@@ -303,8 +326,8 @@ AcceptDialog::AcceptDialog() {
hbc = memnew(HBoxContainer);
- int margin = hbc->get_theme_constant("margin", "Dialogs");
- int button_margin = hbc->get_theme_constant("button_margin", "Dialogs");
+ int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
+ int button_margin = hbc->get_theme_constant(SNAME("button_margin"), SNAME("Dialogs"));
label = memnew(Label);
label->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index d389806fff..8e803a2a7c 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -82,6 +82,7 @@ public:
Button *get_ok_button() { return ok; }
Button *add_button(const String &p_text, bool p_right = false, const String &p_action = "");
Button *add_cancel_button(const String &p_cancel = "");
+ void remove_button(Control *p_button);
void set_hide_on_ok(bool p_hide);
bool get_hide_on_ok() const;
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index f8cee6daec..9ed3a2244e 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -49,9 +49,9 @@ VBoxContainer *FileDialog::get_vbox() {
}
void FileDialog::_theme_changed() {
- Color font_color = vbox->get_theme_color("font_color", "Button");
- Color font_hover_color = vbox->get_theme_color("font_hover_color", "Button");
- Color font_pressed_color = vbox->get_theme_color("font_pressed_color", "Button");
+ Color font_color = vbox->get_theme_color(SNAME("font_color"), SNAME("Button"));
+ Color font_hover_color = vbox->get_theme_color(SNAME("font_hover_color"), SNAME("Button"));
+ Color font_pressed_color = vbox->get_theme_color(SNAME("font_pressed_color"), SNAME("Button"));
dir_up->add_theme_color_override("icon_normal_color", font_color);
dir_up->add_theme_color_override("icon_hover_color", font_hover_color);
@@ -81,16 +81,16 @@ void FileDialog::_notification(int p_what) {
}
}
if (p_what == NOTIFICATION_ENTER_TREE) {
- dir_up->set_icon(vbox->get_theme_icon("parent_folder", "FileDialog"));
+ dir_up->set_icon(vbox->get_theme_icon(SNAME("parent_folder"), SNAME("FileDialog")));
if (vbox->is_layout_rtl()) {
- dir_prev->set_icon(vbox->get_theme_icon("forward_folder", "FileDialog"));
- dir_next->set_icon(vbox->get_theme_icon("back_folder", "FileDialog"));
+ dir_prev->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog")));
+ dir_next->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog")));
} else {
- dir_prev->set_icon(vbox->get_theme_icon("back_folder", "FileDialog"));
- dir_next->set_icon(vbox->get_theme_icon("forward_folder", "FileDialog"));
+ dir_prev->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog")));
+ dir_next->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog")));
}
- refresh->set_icon(vbox->get_theme_icon("reload", "FileDialog"));
- show_hidden->set_icon(vbox->get_theme_icon("toggle_hidden", "FileDialog"));
+ refresh->set_icon(vbox->get_theme_icon(SNAME("reload"), SNAME("FileDialog")));
+ show_hidden->set_icon(vbox->get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog")));
_theme_changed();
}
}
@@ -170,7 +170,7 @@ void FileDialog::_file_submitted(const String &p_file) {
void FileDialog::_save_confirm_pressed() {
String f = dir_access->get_current_dir().plus_file(file->get_text());
- emit_signal("file_selected", f);
+ emit_signal(SNAME("file_selected"), f);
hide();
}
@@ -224,7 +224,7 @@ void FileDialog::_action_pressed() {
}
if (files.size()) {
- emit_signal("files_selected", files);
+ emit_signal(SNAME("files_selected"), files);
hide();
}
@@ -234,7 +234,7 @@ void FileDialog::_action_pressed() {
String f = dir_access->get_current_dir().plus_file(file->get_text());
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
- emit_signal("file_selected", f);
+ emit_signal(SNAME("file_selected"), f);
hide();
} else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) {
String path = dir_access->get_current_dir();
@@ -248,7 +248,7 @@ void FileDialog::_action_pressed() {
}
}
- emit_signal("dir_selected", path);
+ emit_signal(SNAME("dir_selected"), path);
hide();
}
@@ -308,7 +308,7 @@ void FileDialog::_action_pressed() {
confirm_save->set_text(TTRC("File exists, overwrite?"));
confirm_save->popup_centered(Size2(200, 80));
} else {
- emit_signal("file_selected", f);
+ emit_signal(SNAME("file_selected"), f);
hide();
}
}
@@ -437,8 +437,8 @@ void FileDialog::_tree_item_activated() {
if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES || mode == FILE_MODE_OPEN_DIR || mode == FILE_MODE_OPEN_ANY) {
file->set_text("");
}
- call_deferred("_update_file_list");
- call_deferred("_update_dir");
+ call_deferred(SNAME("_update_file_list"));
+ call_deferred(SNAME("_update_dir"));
_push_history();
} else {
_action_pressed();
@@ -468,10 +468,10 @@ void FileDialog::update_file_list() {
dir_access->list_dir_begin();
TreeItem *root = tree->create_item();
- Ref<Texture2D> folder = vbox->get_theme_icon("folder", "FileDialog");
- Ref<Texture2D> file_icon = vbox->get_theme_icon("file", "FileDialog");
- const Color folder_color = vbox->get_theme_color("folder_icon_modulate", "FileDialog");
- const Color file_color = vbox->get_theme_color("file_icon_modulate", "FileDialog");
+ Ref<Texture2D> folder = vbox->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
+ Ref<Texture2D> file_icon = vbox->get_theme_icon(SNAME("file"), SNAME("FileDialog"));
+ const Color folder_color = vbox->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
+ const Color file_color = vbox->get_theme_color(SNAME("file_icon_modulate"), SNAME("FileDialog"));
List<String> files;
List<String> dirs;
@@ -573,7 +573,7 @@ void FileDialog::update_file_list() {
ti->set_icon_modulate(0, file_color);
if (mode == FILE_MODE_OPEN_DIR) {
- ti->set_custom_color(0, vbox->get_theme_color("files_disabled", "FileDialog"));
+ ti->set_custom_color(0, vbox->get_theme_color(SNAME("files_disabled"), SNAME("FileDialog")));
ti->set_selectable(0, false);
}
Dictionary d;
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index 7278ca6e94..83ecf1d534 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -101,7 +101,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
grabbed = -1;
grabbing = false;
update();
- emit_signal("ramp_changed");
+ emit_signal(SNAME("ramp_changed"));
accept_event();
}
@@ -121,7 +121,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
grabbed = -1;
grabbing = false;
update();
- emit_signal("ramp_changed");
+ emit_signal(SNAME("ramp_changed"));
accept_event();
}
}
@@ -145,7 +145,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- emit_signal("ramp_changed");
+ emit_signal(SNAME("ramp_changed"));
update();
}
}
@@ -214,13 +214,13 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- emit_signal("ramp_changed");
+ emit_signal(SNAME("ramp_changed"));
}
if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
if (grabbing) {
grabbing = false;
- emit_signal("ramp_changed");
+ emit_signal(SNAME("ramp_changed"));
}
update();
}
@@ -288,7 +288,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- emit_signal("ramp_changed");
+ emit_signal(SNAME("ramp_changed"));
update();
}
@@ -436,7 +436,7 @@ void GradientEdit::_color_changed(const Color &p_color) {
}
points.write[grabbed].color = p_color;
update();
- emit_signal("ramp_changed");
+ emit_signal(SNAME("ramp_changed"));
}
void GradientEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) {
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 39aa6749e7..2281fb19c6 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -162,7 +162,7 @@ void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) {
if (mb->is_pressed()) {
is_pressing = true;
- Ref<Texture2D> resizer = get_theme_icon("resizer");
+ Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
Rect2 resizer_hitbox = Rect2(Point2(), resizer->get_size());
if (resizer_hitbox.has_point(mb->get_position())) {
is_resizing = true;
@@ -257,7 +257,7 @@ Vector2 GraphEdit::get_scroll_ofs() const {
void GraphEdit::_scroll_moved(double) {
if (!awaiting_scroll_offset_update) {
- call_deferred("_update_scroll_offset");
+ call_deferred(SNAME("_update_scroll_offset"));
awaiting_scroll_offset_update = true;
}
top_layer->update();
@@ -265,7 +265,7 @@ void GraphEdit::_scroll_moved(double) {
update();
if (!setting_scroll_ofs) { //in godot, signals on change value are avoided as a convention
- emit_signal("scroll_offset_changed", get_scroll_ofs());
+ emit_signal(SNAME("scroll_offset_changed"), get_scroll_ofs());
}
}
@@ -345,7 +345,7 @@ void GraphEdit::_update_scroll() {
set_block_minimum_size_adjust(false);
if (!awaiting_scroll_offset_update) {
- call_deferred("_update_scroll_offset");
+ call_deferred(SNAME("_update_scroll_offset"));
awaiting_scroll_offset_update = true;
}
@@ -371,7 +371,7 @@ void GraphEdit::_graph_node_raised(Node *p_gn) {
move_child(connections_layer, first_not_comment);
top_layer->raise();
- emit_signal("node_selected", p_gn);
+ emit_signal(SNAME("node_selected"), p_gn);
}
void GraphEdit::_graph_node_moved(Node *p_gn) {
@@ -395,7 +395,7 @@ void GraphEdit::_graph_node_slot_updated(int p_index, Node *p_gn) {
void GraphEdit::add_child_notify(Node *p_child) {
Control::add_child_notify(p_child);
- top_layer->call_deferred("raise"); // Top layer always on top!
+ top_layer->call_deferred(SNAME("raise")); // Top layer always on top!
GraphNode *gn = Object::cast_to<GraphNode>(p_child);
if (gn) {
@@ -421,7 +421,7 @@ void GraphEdit::remove_child_notify(Node *p_child) {
}
if (top_layer != nullptr && is_inside_tree()) {
- top_layer->call_deferred("raise"); // Top layer always on top!
+ top_layer->call_deferred(SNAME("raise")); // Top layer always on top!
}
GraphNode *gn = Object::cast_to<GraphNode>(p_child);
@@ -442,14 +442,14 @@ void GraphEdit::remove_child_notify(Node *p_child) {
void GraphEdit::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- port_grab_distance_horizontal = get_theme_constant("port_grab_distance_horizontal");
- port_grab_distance_vertical = get_theme_constant("port_grab_distance_vertical");
-
- zoom_minus->set_icon(get_theme_icon("minus"));
- zoom_reset->set_icon(get_theme_icon("reset"));
- zoom_plus->set_icon(get_theme_icon("more"));
- snap_button->set_icon(get_theme_icon("snap"));
- minimap_button->set_icon(get_theme_icon("minimap"));
+ port_grab_distance_horizontal = get_theme_constant(SNAME("port_grab_distance_horizontal"));
+ port_grab_distance_vertical = get_theme_constant(SNAME("port_grab_distance_vertical"));
+
+ zoom_minus->set_icon(get_theme_icon(SNAME("minus")));
+ zoom_reset->set_icon(get_theme_icon(SNAME("reset")));
+ zoom_plus->set_icon(get_theme_icon(SNAME("more")));
+ snap_button->set_icon(get_theme_icon(SNAME("snap")));
+ minimap_button->set_icon(get_theme_icon(SNAME("minimap")));
}
if (p_what == NOTIFICATION_READY) {
Size2 hmin = h_scroll->get_combined_minimum_size();
@@ -466,7 +466,7 @@ void GraphEdit::_notification(int p_what) {
v_scroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0);
}
if (p_what == NOTIFICATION_DRAW) {
- draw_style_box(get_theme_stylebox("bg"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("bg")), Rect2(Point2(), get_size()));
if (is_using_snap()) {
//draw grid
@@ -479,8 +479,8 @@ void GraphEdit::_notification(int p_what) {
Point2i from = (offset / float(snap)).floor();
Point2i len = (size / float(snap)).floor() + Vector2(1, 1);
- Color grid_minor = get_theme_color("grid_minor");
- Color grid_major = get_theme_color("grid_major");
+ Color grid_minor = get_theme_color(SNAME("grid_minor"));
+ Color grid_major = get_theme_color(SNAME("grid_major"));
for (int i = from.x; i < from.x + len.x; i++) {
Color color;
@@ -518,7 +518,7 @@ void GraphEdit::_notification(int p_what) {
}
bool GraphEdit::_filter_input(const Point2 &p_point) {
- Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
+ Ref<Texture2D> port = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
@@ -548,7 +548,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseButton> mb = p_ev;
if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
connecting_valid = false;
- Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
+ Ref<Texture2D> port = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
click_pos = mb->get_position() / zoom;
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
@@ -574,7 +574,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_to = pos;
just_disconnected = true;
- emit_signal("disconnection_request", E->get().from, E->get().from_port, E->get().to, E->get().to_port);
+ emit_signal(SNAME("disconnection_request"), E->get().from, E->get().from_port, E->get().to, E->get().to_port);
to = get_node(String(connecting_from)); //maybe it was erased
if (Object::cast_to<GraphNode>(to)) {
connecting = true;
@@ -616,7 +616,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_to = pos;
just_disconnected = true;
- emit_signal("disconnection_request", E->get().from, E->get().from_port, E->get().to, E->get().to_port);
+ emit_signal(SNAME("disconnection_request"), E->get().from, E->get().from_port, E->get().to, E->get().to_port);
fr = get_node(String(connecting_from)); //maybe it was erased
if (Object::cast_to<GraphNode>(fr)) {
connecting = true;
@@ -652,7 +652,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_valid = just_disconnected || click_pos.distance_to(connecting_to / zoom) > 20.0 * zoom;
if (connecting_valid) {
- Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
+ Ref<Texture2D> port = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
Vector2 mpos = mm->get_position() / zoom;
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
@@ -701,7 +701,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
SWAP(from, to);
SWAP(from_slot, to_slot);
}
- emit_signal("connection_request", from, from_slot, to, to_slot);
+ emit_signal(SNAME("connection_request"), from, from_slot, to, to_slot);
} else if (!just_disconnected) {
String from = connecting_from;
@@ -709,9 +709,9 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
Vector2 ofs = Vector2(mb->get_position().x, mb->get_position().y);
if (!connecting_out) {
- emit_signal("connection_from_empty", from, from_slot, ofs);
+ emit_signal(SNAME("connection_from_empty"), from, from_slot, ofs);
} else {
- emit_signal("connection_to_empty", from, from_slot, ofs);
+ emit_signal(SNAME("connection_to_empty"), from, from_slot, ofs);
}
}
}
@@ -819,8 +819,8 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const
//cubic bezier code
float diff = p_to.x - p_from.x;
float cp_offset;
- int cp_len = get_theme_constant("bezier_len_pos") * p_bezier_ratio;
- int cp_neg_len = get_theme_constant("bezier_len_neg") * p_bezier_ratio;
+ int cp_len = get_theme_constant(SNAME("bezier_len_pos")) * p_bezier_ratio;
+ int cp_neg_len = get_theme_constant(SNAME("bezier_len_neg")) * p_bezier_ratio;
if (diff > 0) {
cp_offset = MIN(cp_len, diff * 0.5);
@@ -849,7 +849,7 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const
}
void GraphEdit::_connections_layer_draw() {
- Color activity_color = get_theme_color("activity");
+ Color activity_color = get_theme_color(SNAME("activity"));
//draw connections
List<List<Connection>::Element *> to_erase;
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
@@ -934,8 +934,8 @@ void GraphEdit::_top_layer_draw() {
}
if (box_selecting) {
- top_layer->draw_rect(box_selecting_rect, get_theme_color("selection_fill"));
- top_layer->draw_rect(box_selecting_rect, get_theme_color("selection_stroke"), false);
+ top_layer->draw_rect(box_selecting_rect, get_theme_color(SNAME("selection_fill")));
+ top_layer->draw_rect(box_selecting_rect, get_theme_color(SNAME("selection_stroke")), false);
}
}
@@ -948,7 +948,7 @@ void GraphEdit::_minimap_draw() {
// Draw the minimap background.
Rect2 minimap_rect = Rect2(Point2(), minimap->get_size());
- minimap->draw_style_box(minimap->get_theme_stylebox("bg"), minimap_rect);
+ minimap->draw_style_box(minimap->get_theme_stylebox(SNAME("bg")), minimap_rect);
Vector2 graph_offset = minimap->_get_graph_offset();
Vector2 minimap_offset = minimap->minimap_offset;
@@ -964,7 +964,7 @@ void GraphEdit::_minimap_draw() {
Vector2 node_size = minimap->_convert_from_graph_position(gn->get_size() * zoom);
Rect2 node_rect = Rect2(node_position, node_size);
- Ref<StyleBoxFlat> sb_minimap = minimap->get_theme_stylebox("node")->duplicate();
+ Ref<StyleBoxFlat> sb_minimap = minimap->get_theme_stylebox(SNAME("node"))->duplicate();
// Override default values with colors provided by the GraphNode's stylebox, if possible.
Ref<StyleBoxFlat> sbf = gn->get_theme_stylebox(gn->is_selected() ? "commentfocus" : "comment");
@@ -987,7 +987,7 @@ void GraphEdit::_minimap_draw() {
Vector2 node_size = minimap->_convert_from_graph_position(gn->get_size() * zoom);
Rect2 node_rect = Rect2(node_position, node_size);
- Ref<StyleBoxFlat> sb_minimap = minimap->get_theme_stylebox("node")->duplicate();
+ Ref<StyleBoxFlat> sb_minimap = minimap->get_theme_stylebox(SNAME("node"))->duplicate();
// Override default values with colors provided by the GraphNode's stylebox, if possible.
Ref<StyleBoxFlat> sbf = gn->get_theme_stylebox(gn->is_selected() ? "selectedframe" : "frame");
@@ -1000,7 +1000,7 @@ void GraphEdit::_minimap_draw() {
}
// Draw node connections.
- Color activity_color = get_theme_color("activity");
+ Color activity_color = get_theme_color(SNAME("activity"));
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
NodePath fromnp(E->get().from);
@@ -1039,11 +1039,11 @@ void GraphEdit::_minimap_draw() {
// Draw the "camera" viewport.
Rect2 camera_rect = minimap->get_camera_rect();
- minimap->draw_style_box(minimap->get_theme_stylebox("camera"), camera_rect);
+ minimap->draw_style_box(minimap->get_theme_stylebox(SNAME("camera")), camera_rect);
// Draw the resizer control.
- Ref<Texture2D> resizer = minimap->get_theme_icon("resizer");
- Color resizer_color = minimap->get_theme_color("resizer_color");
+ Ref<Texture2D> resizer = minimap->get_theme_icon(SNAME("resizer"));
+ Color resizer_color = minimap->get_theme_color(SNAME("resizer_color"));
minimap->draw_texture(resizer, Point2(), resizer_color);
}
@@ -1070,7 +1070,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (mm.is_valid() && dragging) {
if (!moving_selection) {
- emit_signal("begin_node_move");
+ emit_signal(SNAME("begin_node_move"));
moving_selection = true;
}
@@ -1113,17 +1113,17 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (in_box) {
if (!gn->is_selected() && box_selection_mode_additive) {
- emit_signal("node_selected", gn);
+ emit_signal(SNAME("node_selected"), gn);
} else if (gn->is_selected() && !box_selection_mode_additive) {
- emit_signal("node_deselected", gn);
+ emit_signal(SNAME("node_deselected"), gn);
}
gn->set_selected(box_selection_mode_additive);
} else {
bool select = (previous_selected.find(gn) != nullptr);
if (gn->is_selected() && !select) {
- emit_signal("node_deselected", gn);
+ emit_signal(SNAME("node_deselected"), gn);
} else if (!gn->is_selected() && select) {
- emit_signal("node_selected", gn);
+ emit_signal(SNAME("node_selected"), gn);
}
gn->set_selected(select);
}
@@ -1146,9 +1146,9 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
bool select = (previous_selected.find(gn) != nullptr);
if (gn->is_selected() && !select) {
- emit_signal("node_deselected", gn);
+ emit_signal(SNAME("node_deselected"), gn);
} else if (!gn->is_selected() && select) {
- emit_signal("node_selected", gn);
+ emit_signal(SNAME("node_selected"), gn);
}
gn->set_selected(select);
}
@@ -1160,7 +1160,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
top_layer->update();
minimap->update();
} else {
- emit_signal("popup_request", b->get_global_position());
+ emit_signal(SNAME("popup_request"), b->get_global_position());
}
}
}
@@ -1175,7 +1175,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
Rect2 r = gn->get_rect();
r.size *= zoom;
if (r.has_point(b->get_position())) {
- emit_signal("node_deselected", gn);
+ emit_signal(SNAME("node_deselected"), gn);
gn->set_selected(false);
}
}
@@ -1192,7 +1192,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
if (moving_selection) {
- emit_signal("end_node_move");
+ emit_signal(SNAME("end_node_move"));
moving_selection = false;
}
@@ -1238,7 +1238,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
o_gn->set_selected(true);
} else {
if (o_gn->is_selected()) {
- emit_signal("node_deselected", o_gn);
+ emit_signal(SNAME("node_deselected"), o_gn);
}
o_gn->set_selected(false);
}
@@ -1298,7 +1298,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
continue;
}
if (gn2->is_selected()) {
- emit_signal("node_deselected", gn2);
+ emit_signal(SNAME("node_deselected"), gn2);
}
gn2->set_selected(false);
}
@@ -1333,16 +1333,16 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (p_ev->is_pressed()) {
if (p_ev->is_action("ui_graph_duplicate")) {
- emit_signal("duplicate_nodes_request");
+ emit_signal(SNAME("duplicate_nodes_request"));
accept_event();
} else if (p_ev->is_action("ui_copy")) {
- emit_signal("copy_nodes_request");
+ emit_signal(SNAME("copy_nodes_request"));
accept_event();
} else if (p_ev->is_action("ui_paste")) {
- emit_signal("paste_nodes_request");
+ emit_signal(SNAME("paste_nodes_request"));
accept_event();
} else if (p_ev->is_action("ui_graph_delete")) {
- emit_signal("delete_nodes_request");
+ emit_signal(SNAME("delete_nodes_request"));
accept_event();
}
}
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 93f1fe9e8e..e85cefcb7b 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -180,9 +180,9 @@ void GraphNode::_resort() {
/** First pass, determine minimum size AND amount of stretchable elements */
Size2i new_size = get_size();
- Ref<StyleBox> sb = get_theme_stylebox("frame");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("frame"));
- int sep = get_theme_constant("separation");
+ int sep = get_theme_constant(SNAME("separation"));
bool first = true;
int children_count = 0;
@@ -323,8 +323,8 @@ void GraphNode::_resort() {
bool GraphNode::has_point(const Point2 &p_point) const {
if (comment) {
- Ref<StyleBox> comment = get_theme_stylebox("comment");
- Ref<Texture2D> resizer = get_theme_icon("resizer");
+ Ref<StyleBox> comment = get_theme_stylebox(SNAME("comment"));
+ Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
if (Rect2(get_size() - resizer->get_size(), resizer->get_size()).has_point(p_point)) {
return true;
@@ -355,18 +355,18 @@ void GraphNode::_notification(int p_what) {
//sb=sb->duplicate();
//sb->call("set_modulate",modulate);
- Ref<Texture2D> port = get_theme_icon("port");
- Ref<Texture2D> close = get_theme_icon("close");
- Ref<Texture2D> resizer = get_theme_icon("resizer");
- int close_offset = get_theme_constant("close_offset");
- int close_h_offset = get_theme_constant("close_h_offset");
- Color close_color = get_theme_color("close_color");
- Color resizer_color = get_theme_color("resizer_color");
- int title_offset = get_theme_constant("title_offset");
- int title_h_offset = get_theme_constant("title_h_offset");
- Color title_color = get_theme_color("title_color");
+ Ref<Texture2D> port = get_theme_icon(SNAME("port"));
+ Ref<Texture2D> close = get_theme_icon(SNAME("close"));
+ Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
+ int close_offset = get_theme_constant(SNAME("close_offset"));
+ int close_h_offset = get_theme_constant(SNAME("close_h_offset"));
+ Color close_color = get_theme_color(SNAME("close_color"));
+ Color resizer_color = get_theme_color(SNAME("resizer_color"));
+ int title_offset = get_theme_constant(SNAME("title_offset"));
+ int title_h_offset = get_theme_constant(SNAME("title_h_offset"));
+ Color title_color = get_theme_color(SNAME("title_color"));
Point2i icofs = -port->get_size() * 0.5;
- int edgeofs = get_theme_constant("port_offset");
+ int edgeofs = get_theme_constant(SNAME("port_offset"));
icofs.y += sb->get_margin(SIDE_TOP);
draw_style_box(sb, Rect2(Point2(), get_size()));
@@ -375,10 +375,10 @@ void GraphNode::_notification(int p_what) {
case OVERLAY_DISABLED: {
} break;
case OVERLAY_BREAKPOINT: {
- draw_style_box(get_theme_stylebox("breakpoint"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("breakpoint")), Rect2(Point2(), get_size()));
} break;
case OVERLAY_POSITION: {
- draw_style_box(get_theme_stylebox("position"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox(SNAME("position")), Rect2(Point2(), get_size()));
} break;
}
@@ -446,8 +446,8 @@ void GraphNode::_notification(int p_what) {
}
void GraphNode::_shape() {
- Ref<Font> font = get_theme_font("title_font");
- int font_size = get_theme_font_size("title_font_size");
+ Ref<Font> font = get_theme_font(SNAME("title_font"));
+ int font_size = get_theme_font_size(SNAME("title_font_size"));
title_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
@@ -481,7 +481,7 @@ void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const C
update();
connpos_dirty = true;
- emit_signal("slot_updated", p_idx);
+ emit_signal(SNAME("slot_updated"), p_idx);
}
void GraphNode::clear_slot(int p_idx) {
@@ -510,7 +510,7 @@ void GraphNode::set_slot_enabled_left(int p_idx, bool p_enable_left) {
update();
connpos_dirty = true;
- emit_signal("slot_updated", p_idx);
+ emit_signal(SNAME("slot_updated"), p_idx);
}
void GraphNode::set_slot_type_left(int p_idx, int p_type_left) {
@@ -520,7 +520,7 @@ void GraphNode::set_slot_type_left(int p_idx, int p_type_left) {
update();
connpos_dirty = true;
- emit_signal("slot_updated", p_idx);
+ emit_signal(SNAME("slot_updated"), p_idx);
}
int GraphNode::get_slot_type_left(int p_idx) const {
@@ -537,7 +537,7 @@ void GraphNode::set_slot_color_left(int p_idx, const Color &p_color_left) {
update();
connpos_dirty = true;
- emit_signal("slot_updated", p_idx);
+ emit_signal(SNAME("slot_updated"), p_idx);
}
Color GraphNode::get_slot_color_left(int p_idx) const {
@@ -561,7 +561,7 @@ void GraphNode::set_slot_enabled_right(int p_idx, bool p_enable_right) {
update();
connpos_dirty = true;
- emit_signal("slot_updated", p_idx);
+ emit_signal(SNAME("slot_updated"), p_idx);
}
void GraphNode::set_slot_type_right(int p_idx, int p_type_right) {
@@ -571,7 +571,7 @@ void GraphNode::set_slot_type_right(int p_idx, int p_type_right) {
update();
connpos_dirty = true;
- emit_signal("slot_updated", p_idx);
+ emit_signal(SNAME("slot_updated"), p_idx);
}
int GraphNode::get_slot_type_right(int p_idx) const {
@@ -588,7 +588,7 @@ void GraphNode::set_slot_color_right(int p_idx, const Color &p_color_right) {
update();
connpos_dirty = true;
- emit_signal("slot_updated", p_idx);
+ emit_signal(SNAME("slot_updated"), p_idx);
}
Color GraphNode::get_slot_color_right(int p_idx) const {
@@ -599,14 +599,14 @@ Color GraphNode::get_slot_color_right(int p_idx) const {
}
Size2 GraphNode::get_minimum_size() const {
- int sep = get_theme_constant("separation");
- Ref<StyleBox> sb = get_theme_stylebox("frame");
+ int sep = get_theme_constant(SNAME("separation"));
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("frame"));
bool first = true;
Size2 minsize;
minsize.x = title_buf->get_size().x;
if (show_close) {
- Ref<Texture2D> close = get_theme_icon("close");
+ Ref<Texture2D> close = get_theme_icon(SNAME("close"));
minsize.x += sep + close->get_width();
}
@@ -699,7 +699,7 @@ String GraphNode::get_language() const {
void GraphNode::set_position_offset(const Vector2 &p_offset) {
position_offset = p_offset;
- emit_signal("position_offset_changed");
+ emit_signal(SNAME("position_offset_changed"));
update();
}
@@ -720,7 +720,7 @@ void GraphNode::set_drag(bool p_drag) {
if (p_drag) {
drag_from = get_position_offset();
} else {
- emit_signal("dragged", drag_from, get_position_offset()); //useful for undo/redo
+ emit_signal(SNAME("dragged"), drag_from, get_position_offset()); //useful for undo/redo
}
}
@@ -738,10 +738,10 @@ bool GraphNode::is_close_button_visible() const {
}
void GraphNode::_connpos_update() {
- int edgeofs = get_theme_constant("port_offset");
- int sep = get_theme_constant("separation");
+ int edgeofs = get_theme_constant(SNAME("port_offset"));
+ int sep = get_theme_constant(SNAME("separation"));
- Ref<StyleBox> sb = get_theme_stylebox("frame");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("frame"));
conn_input_cache.clear();
conn_output_cache.clear();
int vofs = 0;
@@ -757,7 +757,7 @@ void GraphNode::_connpos_update() {
continue;
}
- Size2i size = c->get_combined_minimum_size();
+ Size2i size = c->get_rect().size;
int y = sb->get_margin(SIDE_TOP) + vofs;
int h = size.y;
@@ -875,12 +875,12 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
if (close_rect.size != Size2() && close_rect.has_point(mpos)) {
//send focus to parent
get_parent_control()->grab_focus();
- emit_signal("close_request");
+ emit_signal(SNAME("close_request"));
accept_event();
return;
}
- Ref<Texture2D> resizer = get_theme_icon("resizer");
+ Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
if (resizable && mpos.x > get_size().x - resizer->get_width() && mpos.y > get_size().y - resizer->get_height()) {
resizing = true;
@@ -890,7 +890,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
return;
}
- emit_signal("raise_request");
+ emit_signal(SNAME("raise_request"));
}
if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
@@ -904,7 +904,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
Vector2 diff = mpos - resizing_from;
- emit_signal("resize_request", resizing_from_size + diff);
+ emit_signal(SNAME("resize_request"), resizing_from_size + diff);
}
}
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index a54f5eef06..1107e3a4af 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -38,8 +38,8 @@ void GridContainer::_notification(int p_what) {
Set<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
Set<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.
- int hsep = get_theme_constant("hseparation");
- int vsep = get_theme_constant("vseparation");
+ int hsep = get_theme_constant(SNAME("hseparation"));
+ int vsep = get_theme_constant(SNAME("vseparation"));
int max_col = MIN(get_child_count(), columns);
int max_row = ceil((float)get_child_count() / (float)columns);
@@ -213,8 +213,8 @@ Size2 GridContainer::get_minimum_size() const {
Map<int, int> col_minw;
Map<int, int> row_minh;
- int hsep = get_theme_constant("hseparation");
- int vsep = get_theme_constant("vseparation");
+ int hsep = get_theme_constant(SNAME("hseparation"));
+ int vsep = get_theme_constant(SNAME("vseparation"));
int max_row = 0;
int max_col = 0;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index b0d54bf8c9..fdf6181f1d 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -42,7 +42,7 @@ void ItemList::_shape(int p_idx) {
} else {
item.text_buf->set_direction((TextServer::Direction)item.text_direction);
}
- item.text_buf->add_string(item.text, get_theme_font("font"), get_theme_font_size("font_size"), item.opentype_features, (item.language != "") ? item.language : TranslationServer::get_singleton()->get_tool_locale());
+ item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.opentype_features, (item.language != "") ? item.language : TranslationServer::get_singleton()->get_tool_locale());
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
item.text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
@@ -548,7 +548,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) {
select(defer_select_single, true);
- emit_signal("multi_selected", defer_select_single, true);
+ emit_signal(SNAME("multi_selected"), defer_select_single, true);
defer_select_single = -1;
return;
}
@@ -556,7 +556,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && (mb->get_button_index() == MOUSE_BUTTON_LEFT || (allow_rmb_select && mb->get_button_index() == MOUSE_BUTTON_RIGHT)) && mb->is_pressed()) {
search_string = ""; //any mousepress cancels
Vector2 pos = mb->get_position();
- Ref<StyleBox> bg = get_theme_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
@@ -583,7 +583,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (select_mode == SELECT_MULTI && items[i].selected && mb->is_command_pressed()) {
deselect(i);
- emit_signal("multi_selected", i, false);
+ emit_signal(SNAME("multi_selected"), i, false);
} else if (select_mode == SELECT_MULTI && mb->is_shift_pressed() && current >= 0 && current < items.size() && current != i) {
int from = current;
@@ -595,12 +595,12 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
bool selected = !items[j].selected;
select(j, false);
if (selected) {
- emit_signal("multi_selected", j, true);
+ emit_signal(SNAME("multi_selected"), j, true);
}
}
if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), i, get_local_mouse_position());
}
} else {
if (!mb->is_double_click() && !mb->is_command_pressed() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
@@ -609,7 +609,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
if (items[i].selected && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), i, get_local_mouse_position());
} else {
bool selected = items[i].selected;
@@ -617,16 +617,16 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (!selected || allow_reselect) {
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", i);
+ emit_signal(SNAME("item_selected"), i);
} else {
- emit_signal("multi_selected", i, true);
+ emit_signal(SNAME("multi_selected"), i, true);
}
}
if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), i, get_local_mouse_position());
} else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_double_click()) {
- emit_signal("item_activated", i);
+ emit_signal(SNAME("item_activated"), i);
}
}
}
@@ -634,13 +634,13 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
- emit_signal("rmb_clicked", mb->get_position());
+ emit_signal(SNAME("rmb_clicked"), mb->get_position());
return;
}
// Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting.
- emit_signal("nothing_selected");
+ emit_signal(SNAME("nothing_selected"));
}
if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) {
scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() * mb->get_factor() / 8);
@@ -661,7 +661,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(i);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
break;
@@ -676,7 +676,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(current - current_columns);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
accept_event();
}
@@ -691,7 +691,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(i);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
break;
}
@@ -705,7 +705,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(current + current_columns);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
accept_event();
}
@@ -717,7 +717,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(current - current_columns * i);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
accept_event();
break;
@@ -731,7 +731,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(current + current_columns * i);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
accept_event();
@@ -745,7 +745,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(current - 1);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
accept_event();
}
@@ -756,7 +756,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(current + 1);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
accept_event();
}
@@ -766,17 +766,17 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (current >= 0 && current < items.size()) {
if (items[current].selectable && !items[current].disabled && !items[current].selected) {
select(current, false);
- emit_signal("multi_selected", current, true);
+ emit_signal(SNAME("multi_selected"), current, true);
} else if (items[current].selected) {
deselect(current);
- emit_signal("multi_selected", current, false);
+ emit_signal(SNAME("multi_selected"), current, false);
}
}
} else if (p_event->is_action("ui_accept")) {
search_string = ""; //any mousepress cancels
if (current >= 0 && current < items.size()) {
- emit_signal("item_activated", current);
+ emit_signal(SNAME("item_activated"), current);
}
} else {
Ref<InputEventKey> k = p_event;
@@ -812,7 +812,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
set_current(i);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
break;
}
@@ -867,7 +867,7 @@ void ItemList::_notification(int p_what) {
}
if (p_what == NOTIFICATION_DRAW) {
- Ref<StyleBox> bg = get_theme_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
int mw = scroll_bar->get_minimum_size().x;
scroll_bar->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -mw);
@@ -884,24 +884,24 @@ void ItemList::_notification(int p_what) {
draw_style_box(bg, Rect2(Point2(), size));
- int hseparation = get_theme_constant("hseparation");
- int vseparation = get_theme_constant("vseparation");
- int icon_margin = get_theme_constant("icon_margin");
- int line_separation = get_theme_constant("line_separation");
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ int hseparation = get_theme_constant(SNAME("hseparation"));
+ int vseparation = get_theme_constant(SNAME("vseparation"));
+ int icon_margin = get_theme_constant(SNAME("icon_margin"));
+ int line_separation = get_theme_constant(SNAME("line_separation"));
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
- Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox("selected_focus") : get_theme_stylebox("selected");
- Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox("cursor") : get_theme_stylebox("cursor_unfocused");
+ Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox(SNAME("selected_focus")) : get_theme_stylebox(SNAME("selected"));
+ Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox(SNAME("cursor")) : get_theme_stylebox(SNAME("cursor_unfocused"));
bool rtl = is_layout_rtl();
- Color guide_color = get_theme_color("guide_color");
- Color font_color = get_theme_color("font_color");
- Color font_selected_color = get_theme_color("font_selected_color");
+ Color guide_color = get_theme_color(SNAME("guide_color"));
+ Color font_color = get_theme_color(SNAME("font_color"));
+ Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true);
- draw_style_box(get_theme_stylebox("bg_focus"), Rect2(Point2(), size));
+ draw_style_box(get_theme_stylebox(SNAME("bg_focus")), Rect2(Point2(), size));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false);
}
@@ -1299,7 +1299,7 @@ void ItemList::_scroll_changed(double) {
int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_theme_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
@@ -1337,7 +1337,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
}
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_theme_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 6580d794d1..06faf3fa3e 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -36,20 +36,20 @@
#include "servers/text_server.h"
-void Label::set_autowrap(bool p_autowrap) {
- if (autowrap != p_autowrap) {
- autowrap = p_autowrap;
+void Label::set_autowrap_mode(Label::AutowrapMode p_mode) {
+ if (autowrap_mode != p_mode) {
+ autowrap_mode = p_mode;
lines_dirty = true;
}
update();
- if (clip) {
+ if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
minimum_size_changed();
}
}
-bool Label::has_autowrap() const {
- return autowrap;
+Label::AutowrapMode Label::get_autowrap_mode() const {
+ return autowrap_mode;
}
void Label::set_uppercase(bool p_uppercase) {
@@ -64,7 +64,7 @@ bool Label::is_uppercase() const {
}
int Label::get_line_height(int p_line) const {
- Ref<Font> font = get_theme_font("font");
+ Ref<Font> font = get_theme_font(SNAME("font"));
if (p_line >= 0 && p_line < lines_rid.size()) {
return TS->shaped_text_get_size(lines_rid[p_line]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM);
} else if (lines_rid.size() > 0) {
@@ -74,12 +74,12 @@ int Label::get_line_height(int p_line) const {
}
return h;
} else {
- return font->get_height(get_theme_font_size("font_size"));
+ return font->get_height(get_theme_font_size(SNAME("font_size")));
}
}
void Label::_shape() {
- Ref<StyleBox> style = get_theme_stylebox("normal", "Label");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
int width = (get_size().width - style->get_minimum_size().width);
if (dirty) {
@@ -89,29 +89,81 @@ void Label::_shape() {
} else {
TS->shaped_text_set_direction(text_rid, (TextServer::Direction)text_direction);
}
- TS->shaped_text_add_string(text_rid, (uppercase) ? xl_text.to_upper() : xl_text, get_theme_font("font")->get_rids(), get_theme_font_size("font_size"), opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
+ TS->shaped_text_add_string(text_rid, (uppercase) ? xl_text.to_upper() : xl_text, get_theme_font(SNAME("font"))->get_rids(), get_theme_font_size(SNAME("font_size")), opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, xl_text));
dirty = false;
lines_dirty = true;
}
+
+ uint8_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
if (lines_dirty) {
for (int i = 0; i < lines_rid.size(); i++) {
TS->free(lines_rid[i]);
}
lines_rid.clear();
- Vector<Vector2i> lines = TS->shaped_text_get_line_breaks(text_rid, width, 0, (autowrap) ? (TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND) : TextServer::BREAK_MANDATORY);
+ uint8_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;
+ }
+ Vector<Vector2i> lines = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
+
for (int i = 0; i < lines.size(); i++) {
RID line = TS->shaped_text_substr(text_rid, lines[i].x, lines[i].y - lines[i].x);
+
+ switch (overrun_behavior) {
+ case OVERRUN_TRIM_WORD_ELLIPSIS:
+ overrun_flags |= TextServer::OVERRUN_TRIM;
+ overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
+ overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ break;
+ case OVERRUN_TRIM_ELLIPSIS:
+ overrun_flags |= TextServer::OVERRUN_TRIM;
+ overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ break;
+ case OVERRUN_TRIM_WORD:
+ overrun_flags |= TextServer::OVERRUN_TRIM;
+ overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
+ break;
+ case OVERRUN_TRIM_CHAR:
+ overrun_flags |= TextServer::OVERRUN_TRIM;
+ break;
+ case OVERRUN_NO_TRIMMING:
+ break;
+ }
+
+ if (autowrap_mode == AUTOWRAP_OFF && align != ALIGN_FILL && overrun_behavior != OVERRUN_NO_TRIMMING) {
+ TS->shaped_text_overrun_trim_to_width(line, width, overrun_flags);
+ }
+
lines_rid.push_back(line);
}
+
+ if (autowrap_mode != AUTOWRAP_OFF && overrun_behavior != OVERRUN_NO_TRIMMING) {
+ int visible_lines = get_visible_line_count();
+
+ if (visible_lines < lines_rid.size() && visible_lines > 0) {
+ overrun_flags |= TextServer::OVERRUN_ENFORCE_ELLIPSIS;
+ TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags);
+ }
+ }
}
if (xl_text.length() == 0) {
minsize = Size2(1, get_line_height());
return;
}
- if (!autowrap) {
+ if (autowrap_mode == AUTOWRAP_OFF) {
minsize.width = 0.0f;
for (int i = 0; i < lines_rid.size(); i++) {
if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) {
@@ -120,10 +172,21 @@ void Label::_shape() {
}
}
- if (lines_dirty) { // Fill after min_size calculation.
+ if (lines_dirty) {
+ // Fill after min_size calculation.
if (align == ALIGN_FILL) {
for (int i = 0; i < lines_rid.size(); i++) {
- TS->shaped_text_fit_to_width(lines_rid.write[i], width);
+ if (overrun_behavior != OVERRUN_NO_TRIMMING && autowrap_mode == AUTOWRAP_OFF) {
+ float line_unaltered_width = TS->shaped_text_get_width(lines_rid[i]);
+ TS->shaped_text_fit_to_width(lines_rid[i], width);
+ float new_line_width = TS->shaped_text_get_width(lines_rid[i]);
+ // Begin trimming when there is no space between words available anymore.
+ if (new_line_width < line_unaltered_width) {
+ TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
+ }
+ } else {
+ TS->shaped_text_fit_to_width(lines_rid[i], width);
+ }
}
}
lines_dirty = false;
@@ -131,15 +194,15 @@ void Label::_shape() {
_update_visible();
- if (!autowrap || !clip) {
+ if (autowrap_mode == AUTOWRAP_OFF || !clip || overrun_behavior == OVERRUN_NO_TRIMMING) {
minimum_size_changed();
}
}
void Label::_update_visible() {
- int line_spacing = get_theme_constant("line_spacing", "Label");
- Ref<StyleBox> style = get_theme_stylebox("normal", "Label");
- Ref<Font> font = get_theme_font("font");
+ int line_spacing = get_theme_constant(SNAME("line_spacing"), SNAME("Label"));
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
+ Ref<Font> font = get_theme_font(SNAME("font"));
int lines_visible = lines_rid.size();
if (max_lines_visible >= 0 && lines_visible > max_lines_visible) {
@@ -181,15 +244,15 @@ void Label::_notification(int p_what) {
Size2 string_size;
Size2 size = get_size();
- Ref<StyleBox> style = get_theme_stylebox("normal");
- Ref<Font> font = get_theme_font("font");
- Color font_color = get_theme_color("font_color");
- Color font_shadow_color = get_theme_color("font_shadow_color");
- Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
- int line_spacing = get_theme_constant("line_spacing");
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
- int shadow_outline_size = get_theme_constant("shadow_outline_size");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ Color font_color = get_theme_color(SNAME("font_color"));
+ Color font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
+ Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
+ int line_spacing = get_theme_constant(SNAME("line_spacing"));
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
+ int shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
bool rtl = is_layout_rtl();
style->draw(ci, Rect2(Point2(0, 0), get_size()));
@@ -366,17 +429,16 @@ Size2 Label::get_minimum_size() const {
Size2 min_size = minsize;
- Ref<Font> font = get_theme_font("font");
- min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size("font_size")) + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM));
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("font_size"))) + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM));
- Size2 min_style = get_theme_stylebox("normal")->get_minimum_size();
- if (autowrap) {
- return Size2(1, clip ? 1 : min_size.height) + min_style;
+ Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
+ if (autowrap_mode != AUTOWRAP_OFF) {
+ return Size2(1, (clip || overrun_behavior != OVERRUN_NO_TRIMMING) ? 1 : min_size.height) + min_style;
} else {
- if (clip) {
+ if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
min_size.width = 1;
}
-
return min_size + min_style;
}
}
@@ -393,9 +455,9 @@ int Label::get_line_count() const {
}
int Label::get_visible_line_count() const {
- Ref<Font> font = get_theme_font("font");
- Ref<StyleBox> style = get_theme_stylebox("normal");
- int line_spacing = get_theme_constant("line_spacing");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ int line_spacing = get_theme_constant(SNAME("line_spacing"));
int lines_visible = 0;
float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
@@ -536,6 +598,21 @@ bool Label::is_clipping_text() const {
return clip;
}
+void Label::set_text_overrun_behavior(Label::OverrunBehavior p_behavior) {
+ if (overrun_behavior != p_behavior) {
+ overrun_behavior = p_behavior;
+ lines_dirty = true;
+ }
+ update();
+ if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
+ minimum_size_changed();
+ }
+}
+
+Label::OverrunBehavior Label::get_text_overrun_behavior() const {
+ return overrun_behavior;
+}
+
String Label::get_text() const {
return text;
}
@@ -663,10 +740,12 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Label::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Label::get_language);
- ClassDB::bind_method(D_METHOD("set_autowrap", "enable"), &Label::set_autowrap);
- ClassDB::bind_method(D_METHOD("has_autowrap"), &Label::has_autowrap);
+ ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label::set_autowrap_mode);
+ ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &Label::get_autowrap_mode);
ClassDB::bind_method(D_METHOD("set_clip_text", "enable"), &Label::set_clip_text);
ClassDB::bind_method(D_METHOD("is_clipping_text"), &Label::is_clipping_text);
+ ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &Label::set_text_overrun_behavior);
+ ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Label::get_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &Label::set_uppercase);
ClassDB::bind_method(D_METHOD("is_uppercase"), &Label::is_uppercase);
ClassDB::bind_method(D_METHOD("get_line_height", "line"), &Label::get_line_height, DEFVAL(-1));
@@ -696,13 +775,25 @@ void Label::_bind_methods() {
BIND_ENUM_CONSTANT(VALIGN_BOTTOM);
BIND_ENUM_CONSTANT(VALIGN_FILL);
+ BIND_ENUM_CONSTANT(AUTOWRAP_OFF);
+ BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY);
+ BIND_ENUM_CONSTANT(AUTOWRAP_WORD);
+ BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART);
+
+ BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_CHAR);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_ELLIPSIS);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ELLIPSIS);
+
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
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"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
ADD_PROPERTY(PropertyInfo(Variant::INT, "valign", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_valign", "get_valign");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autowrap"), "set_autowrap", "has_autowrap");
+ 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::BOOL, "clip_text"), "set_clip_text", "is_clipping_text");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim nothing,Trim characters,Trim words,Ellipsis,Word ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1", PROPERTY_USAGE_EDITOR), "set_visible_characters", "get_visible_characters");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 032b4112e1..8b48eb9670 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -51,13 +51,29 @@ public:
VALIGN_FILL
};
+ enum AutowrapMode {
+ AUTOWRAP_OFF,
+ AUTOWRAP_ARBITRARY,
+ AUTOWRAP_WORD,
+ AUTOWRAP_WORD_SMART
+ };
+
+ enum OverrunBehavior {
+ OVERRUN_NO_TRIMMING,
+ OVERRUN_TRIM_CHAR,
+ OVERRUN_TRIM_WORD,
+ OVERRUN_TRIM_ELLIPSIS,
+ OVERRUN_TRIM_WORD_ELLIPSIS,
+ };
+
private:
Align align = ALIGN_LEFT;
VAlign valign = VALIGN_TOP;
String text;
String xl_text;
- bool autowrap = false;
+ AutowrapMode autowrap_mode = AUTOWRAP_OFF;
bool clip = false;
+ OverrunBehavior overrun_behavior = OVERRUN_NO_TRIMMING;
Size2 minsize;
bool uppercase = false;
@@ -118,8 +134,8 @@ public:
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
- void set_autowrap(bool p_autowrap);
- bool has_autowrap() const;
+ void set_autowrap_mode(AutowrapMode p_mode);
+ AutowrapMode get_autowrap_mode() const;
void set_uppercase(bool p_uppercase);
bool is_uppercase() const;
@@ -131,6 +147,9 @@ public:
void set_clip_text(bool p_clip);
bool is_clipping_text() const;
+ void set_text_overrun_behavior(OverrunBehavior p_behavior);
+ OverrunBehavior get_text_overrun_behavior() const;
+
void set_percent_visible(float p_percent);
float get_percent_visible() const;
@@ -150,5 +169,7 @@ public:
VARIANT_ENUM_CAST(Label::Align);
VARIANT_ENUM_CAST(Label::VAlign);
+VARIANT_ENUM_CAST(Label::AutowrapMode);
+VARIANT_ENUM_CAST(Label::OverrunBehavior);
#endif
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 089893e63b..19ffcfca6d 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -227,9 +227,9 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
return;
}
if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) {
+ _ensure_menu();
menu->set_position(get_screen_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
- _generate_context_menu();
menu->popup();
grab_focus();
accept_event();
@@ -348,10 +348,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (context_menu_enabled) {
if (k->is_action("ui_menu", true)) {
- Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + get_theme_font("font")->get_height(get_theme_font_size("font_size"))) / 2);
+ _ensure_menu();
+ Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")))) / 2);
menu->set_position(get_global_transform().xform(pos));
menu->set_size(Vector2(1, 1));
- _generate_context_menu();
menu->popup();
menu->grab_focus();
}
@@ -359,7 +359,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
// Default is ENTER and KP_ENTER. Cannot use ui_accept as default includes SPACE
if (k->is_action("ui_text_submit", false)) {
- emit_signal("text_submitted", text);
+ emit_signal(SNAME("text_submitted"), text);
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) {
DisplayServer::get_singleton()->virtual_keyboard_hide();
}
@@ -567,8 +567,8 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
if (!clear_button_enabled || !has_point(p_pos)) {
return false;
}
- Ref<Texture2D> icon = Control::get_theme_icon("clear");
- int x_ofs = get_theme_stylebox("normal")->get_offset().x;
+ Ref<Texture2D> icon = Control::get_theme_icon(SNAME("clear"));
+ int x_ofs = get_theme_stylebox(SNAME("normal"))->get_offset().x;
return p_pos.x > get_size().width - icon->get_width() - x_ofs;
}
@@ -612,7 +612,7 @@ void LineEdit::_notification(int p_what) {
update();
} break;
case NOTIFICATION_DRAW: {
- if ((!has_focus() && !menu->has_focus() && !caret_force_displayed) || !window_has_focus) {
+ if ((!has_focus() && !(menu && menu->has_focus()) && !caret_force_displayed) || !window_has_focus) {
draw_caret = false;
}
@@ -625,17 +625,17 @@ void LineEdit::_notification(int p_what) {
RID ci = get_canvas_item();
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
if (!is_editable()) {
- style = get_theme_stylebox("read_only");
+ style = get_theme_stylebox(SNAME("read_only"));
draw_caret = false;
}
- Ref<Font> font = get_theme_font("font");
+ Ref<Font> font = get_theme_font(SNAME("font"));
style->draw(ci, Rect2(Point2(), size));
if (has_focus()) {
- get_theme_stylebox("focus")->draw(ci, Rect2(Point2(), size));
+ get_theme_stylebox(SNAME("focus"))->draw(ci, Rect2(Point2(), size));
}
int x_ofs = 0;
@@ -673,10 +673,10 @@ void LineEdit::_notification(int p_what) {
int y_area = height - style->get_minimum_size().height;
int y_ofs = style->get_offset().y + (y_area - text_height) / 2;
- Color selection_color = get_theme_color("selection_color");
- Color font_color = is_editable() ? get_theme_color("font_color") : get_theme_color("font_uneditable_color");
- Color font_selected_color = get_theme_color("font_selected_color");
- Color caret_color = get_theme_color("caret_color");
+ Color selection_color = get_theme_color(SNAME("selection_color"));
+ Color font_color = is_editable() ? get_theme_color(SNAME("font_color")) : get_theme_color(SNAME("font_uneditable_color"));
+ Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ Color caret_color = get_theme_color(SNAME("caret_color"));
// Draw placeholder color.
if (using_placeholder) {
@@ -685,13 +685,13 @@ void LineEdit::_notification(int p_what) {
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
Color color_icon(1, 1, 1, !is_editable() ? .5 * .9 : .9);
if (display_clear_icon) {
if (clear_button_status.press_attempt && clear_button_status.pressing_inside) {
- color_icon = get_theme_color("clear_button_color_pressed");
+ color_icon = get_theme_color(SNAME("clear_button_color_pressed"));
} else {
- color_icon = get_theme_color("clear_button_color");
+ color_icon = get_theme_color(SNAME("clear_button_color"));
}
}
@@ -738,8 +738,8 @@ void LineEdit::_notification(int p_what) {
// Draw text.
ofs.y += TS->shaped_text_get_ascent(text_rid);
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
if (outline_size > 0 && font_outline_color.a > 0) {
Vector2 oofs = ofs;
for (int i = 0; i < gl_size; i++) {
@@ -784,7 +784,7 @@ void LineEdit::_notification(int p_what) {
if (l_caret == Rect2() && t_caret == Rect2()) {
// No carets, add one at the start.
- int h = get_theme_font("font")->get_height(get_theme_font_size("font_size"));
+ int h = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
int y = style->get_offset().y + (y_area - h) / 2;
if (rtl) {
l_dir = TextServer::DIRECTION_RTL;
@@ -1006,7 +1006,7 @@ void LineEdit::shift_selection_check_post(bool p_shift) {
}
void LineEdit::set_caret_at_pixel_pos(int p_x) {
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1039,7 +1039,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
if (align == ALIGN_CENTER) {
if (scroll_offset == 0) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1054,7 +1054,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
}
Vector2i LineEdit::get_caret_pixel_pos() {
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1087,7 +1087,7 @@ Vector2i LineEdit::get_caret_pixel_pos() {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
if (align == ALIGN_CENTER) {
if (scroll_offset == 0) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1252,10 +1252,12 @@ void LineEdit::set_text_direction(Control::TextDirection p_text_direction) {
}
_shape();
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+ if (menu_dir) {
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+ }
update();
}
}
@@ -1302,7 +1304,9 @@ String LineEdit::get_language() const {
void LineEdit::set_draw_control_chars(bool p_draw_control_chars) {
if (draw_control_chars != p_draw_control_chars) {
draw_control_chars = p_draw_control_chars;
- menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
+ if (menu && menu->get_item_index(MENU_DISPLAY_UCC) >= 0) {
+ menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
+ }
_shape();
update();
}
@@ -1396,7 +1400,7 @@ void LineEdit::set_caret_column(int p_column) {
return;
}
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1430,7 +1434,7 @@ void LineEdit::set_caret_column(int p_column) {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
if (align == ALIGN_CENTER) {
if (scroll_offset == 0) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1470,19 +1474,23 @@ int LineEdit::get_scroll_offset() const {
}
void LineEdit::insert_text_at_caret(String p_text) {
- if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) {
- String pre = text.substr(0, caret_column);
- String post = text.substr(caret_column, text.length() - caret_column);
- text = pre + p_text + post;
- _shape();
- TextServer::Direction dir = TS->shaped_text_get_dominant_direciton_in_range(text_rid, caret_column, caret_column + p_text.length());
- if (dir != TextServer::DIRECTION_AUTO) {
- input_direction = (TextDirection)dir;
+ if (max_length > 0) {
+ // Truncate text to append to fit in max_length, if needed.
+ int available_chars = max_length - text.length();
+ if (p_text.length() > available_chars) {
+ emit_signal(SNAME("text_change_rejected"), p_text.substr(available_chars));
+ p_text = p_text.substr(0, available_chars);
}
- set_caret_column(caret_column + p_text.length());
- } else {
- emit_signal("text_change_rejected");
}
+ String pre = text.substr(0, caret_column);
+ String post = text.substr(caret_column, text.length() - caret_column);
+ text = pre + p_text + post;
+ _shape();
+ TextServer::Direction dir = TS->shaped_text_get_dominant_direciton_in_range(text_rid, caret_column, caret_column + p_text.length());
+ if (dir != TextServer::DIRECTION_AUTO) {
+ input_direction = (TextDirection)dir;
+ }
+ set_caret_column(caret_column + p_text.length());
}
void LineEdit::clear_internal() {
@@ -1497,15 +1505,15 @@ void LineEdit::clear_internal() {
}
Size2 LineEdit::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox("normal");
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
Size2 min_size;
// Minimum size of text.
int em_space_size = font->get_char_size('M', 0, font_size).x;
- min_size.width = get_theme_constant("minimum_character_width") * em_space_size;
+ min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size;
if (expand_to_text_length) {
// Add a space because some fonts are too exact, and because caret needs a bit more when at the end.
@@ -1518,7 +1526,7 @@ Size2 LineEdit::get_minimum_size() const {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
min_size.width += r_icon->get_width();
min_size.height = MAX(min_size.height, r_icon->get_height());
}
@@ -1592,7 +1600,6 @@ void LineEdit::set_editable(bool p_editable) {
}
editable = p_editable;
- _generate_context_menu();
minimum_size_changed();
update();
@@ -1806,7 +1813,12 @@ bool LineEdit::is_context_menu_enabled() {
return context_menu_enabled;
}
+bool LineEdit::is_menu_visible() const {
+ return menu && menu->is_visible();
+}
+
PopupMenu *LineEdit::get_menu() const {
+ const_cast<LineEdit *>(this)->_ensure_menu();
return menu;
}
@@ -1843,8 +1855,6 @@ bool LineEdit::is_clear_button_enabled() const {
void LineEdit::set_shortcut_keys_enabled(bool p_enabled) {
shortcut_keys_enabled = p_enabled;
-
- _generate_context_menu();
}
bool LineEdit::is_shortcut_keys_enabled() const {
@@ -1865,8 +1875,6 @@ void LineEdit::set_selecting_enabled(bool p_enabled) {
if (!selecting_enabled) {
deselect();
}
-
- _generate_context_menu();
}
bool LineEdit::is_selecting_enabled() const {
@@ -1893,7 +1901,7 @@ void LineEdit::_text_changed() {
}
void LineEdit::_emit_text_change() {
- emit_signal("text_changed", text);
+ emit_signal(SNAME("text_changed"), text);
text_changed_dirty = false;
}
@@ -1920,8 +1928,8 @@ void LineEdit::_shape() {
}
TS->shaped_text_set_preserve_control(text_rid, draw_control_chars);
- const Ref<Font> &font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ const Ref<Font> &font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, t));
@@ -1937,12 +1945,12 @@ void LineEdit::_shape() {
void LineEdit::_fit_to_width() {
if (align == ALIGN_FILL) {
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
int t_width = get_size().width - style->get_margin(SIDE_RIGHT) - style->get_margin(SIDE_LEFT);
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
t_width -= r_icon->get_width();
}
TS->shaped_text_fit_to_width(text_rid, MAX(t_width, full_width));
@@ -2003,35 +2011,6 @@ int LineEdit::_get_menu_action_accelerator(const String &p_action) {
}
}
-void LineEdit::_generate_context_menu() {
- // Reorganize context menu.
- menu->clear();
- if (editable) {
- menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0);
- }
- menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0);
- if (editable) {
- menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0);
- }
- menu->add_separator();
- if (is_selecting_enabled()) {
- menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0);
- }
- if (editable) {
- menu->add_item(RTR("Clear"), MENU_CLEAR);
- menu->add_separator();
- menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0);
- menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
- }
- menu->add_separator();
- menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
- menu->add_separator();
- menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC);
- if (editable) {
- menu->add_submenu_item(RTR("Insert control character"), "CTLMenu");
- }
-}
-
bool LineEdit::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
@@ -2144,6 +2123,7 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_secret_character"), &LineEdit::get_secret_character);
ClassDB::bind_method(D_METHOD("menu_option", "option"), &LineEdit::menu_option);
ClassDB::bind_method(D_METHOD("get_menu"), &LineEdit::get_menu);
+ ClassDB::bind_method(D_METHOD("is_menu_visible"), &LineEdit::is_menu_visible);
ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &LineEdit::set_context_menu_enabled);
ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled);
ClassDB::bind_method(D_METHOD("set_virtual_keyboard_enabled", "enable"), &LineEdit::set_virtual_keyboard_enabled);
@@ -2158,7 +2138,7 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon);
ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
- ADD_SIGNAL(MethodInfo("text_change_rejected"));
+ ADD_SIGNAL(MethodInfo("text_change_rejected", PropertyInfo(Variant::STRING, "rejected_substring")));
ADD_SIGNAL(MethodInfo("text_submitted", PropertyInfo(Variant::STRING, "new_text")));
BIND_ENUM_CONSTANT(ALIGN_LEFT);
@@ -2198,7 +2178,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_max_length", "get_max_length");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character");
@@ -2221,11 +2201,84 @@ void LineEdit::_bind_methods() {
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "set_caret_blink_enabled", "is_caret_blink_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "set_caret_blink_speed", "get_caret_blink_speed");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_column"), "set_caret_column", "get_caret_column");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_column", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_caret_column", "get_caret_column");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_force_displayed"), "set_caret_force_displayed", "is_caret_force_displayed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
}
+void LineEdit::_ensure_menu() {
+ if (!menu) {
+ menu = memnew(PopupMenu);
+ add_child(menu);
+
+ menu_dir = memnew(PopupMenu);
+ menu_dir->set_name("DirMenu");
+ menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED);
+ menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO);
+ menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR);
+ menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL);
+ menu->add_child(menu_dir);
+
+ menu_ctl = memnew(PopupMenu);
+ menu_ctl->set_name("CTLMenu");
+ menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM);
+ menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM);
+ menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE);
+ menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE);
+ menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO);
+ menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO);
+ menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM);
+ menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI);
+ menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI);
+ menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI);
+ menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ);
+ menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
+ menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ);
+ menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
+ menu->add_child(menu_ctl);
+
+ menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
+ menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
+ menu_ctl->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
+ }
+
+ // Reorganize context menu.
+ menu->clear();
+ if (editable) {
+ menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0);
+ }
+ menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0);
+ if (editable) {
+ menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0);
+ }
+ menu->add_separator();
+ if (is_selecting_enabled()) {
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0);
+ }
+ if (editable) {
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
+ menu->add_separator();
+ menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0);
+ menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
+ }
+ menu->add_separator();
+ menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
+ menu->add_separator();
+ menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC);
+ menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
+ if (editable) {
+ menu->add_submenu_item(RTR("Insert control character"), "CTLMenu");
+ }
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+}
+
LineEdit::LineEdit() {
text_rid = TS->create_shaped_text();
_create_undo_state();
@@ -2241,44 +2294,7 @@ LineEdit::LineEdit() {
caret_blink_timer->connect("timeout", callable_mp(this, &LineEdit::_toggle_draw_caret));
set_caret_blink_enabled(false);
- menu = memnew(PopupMenu);
- add_child(menu);
-
- menu_dir = memnew(PopupMenu);
- menu_dir->set_name("DirMenu");
- menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED);
- menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO);
- menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR);
- menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), true);
- menu->add_child(menu_dir);
-
- menu_ctl = memnew(PopupMenu);
- menu_ctl->set_name("CTLMenu");
- menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM);
- menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM);
- menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE);
- menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE);
- menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO);
- menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO);
- menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM);
- menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI);
- menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI);
- menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI);
- menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ);
- menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
- menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ);
- menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
- menu->add_child(menu_ctl);
-
set_editable(true); // Initialise to opposite first, so we get past the early-out in set_editable.
- menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
- menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
- menu_ctl->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
}
LineEdit::~LineEdit() {
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 12fec2f98b..c5c92d60aa 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -165,7 +165,6 @@ private:
void _create_undo_state();
int _get_menu_action_accelerator(const String &p_action);
- void _generate_context_menu();
void _shape();
void _fit_to_width();
@@ -198,6 +197,8 @@ private:
void _backspace(bool p_word = false, bool p_all_to_left = false);
void _delete(bool p_word = false, bool p_all_to_right = false);
+ void _ensure_menu();
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -222,6 +223,7 @@ public:
void set_context_menu_enabled(bool p_enable);
bool is_context_menu_enabled();
PopupMenu *get_menu() const;
+ bool is_menu_visible() const;
void select(int p_from = 0, int p_to = -1);
void select_all();
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index ee0618a991..419d49bccf 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -32,8 +32,8 @@
#include "core/string/translation.h"
void LinkButton::_shape() {
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
text_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
@@ -158,41 +158,41 @@ void LinkButton::_notification(int p_what) {
switch (get_draw_mode()) {
case DRAW_NORMAL: {
- color = get_theme_color("font_color");
+ color = get_theme_color(SNAME("font_color"));
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
} break;
case DRAW_HOVER_PRESSED:
case DRAW_PRESSED: {
- if (has_theme_color("font_pressed_color")) {
- color = get_theme_color("font_pressed_color");
+ if (has_theme_color(SNAME("font_pressed_color"))) {
+ color = get_theme_color(SNAME("font_pressed_color"));
} else {
- color = get_theme_color("font_color");
+ color = get_theme_color(SNAME("font_color"));
}
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_HOVER: {
- color = get_theme_color("font_hover_color");
+ color = get_theme_color(SNAME("font_hover_color"));
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_DISABLED: {
- color = get_theme_color("font_disabled_color");
+ color = get_theme_color(SNAME("font_disabled_color"));
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
} break;
}
if (has_focus()) {
- Ref<StyleBox> style = get_theme_stylebox("focus");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("focus"));
style->draw(ci, Rect2(Point2(), size));
}
int width = text_buf->get_line_width();
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
if (is_layout_rtl()) {
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(get_canvas_item(), Vector2(size.width - width, 0), outline_size, font_outline_color);
@@ -206,7 +206,7 @@ void LinkButton::_notification(int p_what) {
}
if (do_underline) {
- int underline_spacing = get_theme_constant("underline_spacing") + text_buf->get_line_underline_position();
+ int underline_spacing = get_theme_constant(SNAME("underline_spacing")) + text_buf->get_line_underline_position();
int y = text_buf->get_line_ascent() + underline_spacing;
if (is_layout_rtl()) {
diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp
index 0e9610d0a3..50b4d192a9 100644
--- a/scene/gui/margin_container.cpp
+++ b/scene/gui/margin_container.cpp
@@ -31,10 +31,10 @@
#include "margin_container.h"
Size2 MarginContainer::get_minimum_size() const {
- int margin_left = get_theme_constant("margin_left");
- int margin_top = get_theme_constant("margin_top");
- int margin_right = get_theme_constant("margin_right");
- int margin_bottom = get_theme_constant("margin_bottom");
+ int margin_left = get_theme_constant(SNAME("margin_left"));
+ int margin_top = get_theme_constant(SNAME("margin_top"));
+ int margin_right = get_theme_constant(SNAME("margin_right"));
+ int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
Size2 max;
@@ -68,10 +68,10 @@ Size2 MarginContainer::get_minimum_size() const {
void MarginContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
- int margin_left = get_theme_constant("margin_left");
- int margin_top = get_theme_constant("margin_top");
- int margin_right = get_theme_constant("margin_right");
- int margin_bottom = get_theme_constant("margin_bottom");
+ int margin_left = get_theme_constant(SNAME("margin_left"));
+ int margin_top = get_theme_constant(SNAME("margin_top"));
+ int margin_right = get_theme_constant(SNAME("margin_right"));
+ int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
Size2 s = get_size();
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index e52b6917be..cd55f258b3 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -35,12 +35,12 @@
Size2 OptionButton::get_minimum_size() const {
Size2 minsize = Button::get_minimum_size();
- if (has_theme_icon("arrow")) {
- const Size2 padding = get_theme_stylebox("normal")->get_minimum_size();
- const Size2 arrow_size = Control::get_theme_icon("arrow")->get_size();
+ if (has_theme_icon(SNAME("arrow"))) {
+ const Size2 padding = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
+ const Size2 arrow_size = Control::get_theme_icon(SNAME("arrow"))->get_size();
Size2 content_size = minsize - padding;
- content_size.width += arrow_size.width + get_theme_constant("hseparation");
+ content_size.width += arrow_size.width + get_theme_constant(SNAME("hseparation"));
content_size.height = MAX(content_size.height, arrow_size.height);
minsize = content_size + padding;
@@ -52,26 +52,26 @@ Size2 OptionButton::get_minimum_size() const {
void OptionButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- if (!has_theme_icon("arrow")) {
+ if (!has_theme_icon(SNAME("arrow"))) {
return;
}
RID ci = get_canvas_item();
- Ref<Texture2D> arrow = Control::get_theme_icon("arrow");
+ Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"));
Color clr = Color(1, 1, 1);
- if (get_theme_constant("modulate_arrow")) {
+ if (get_theme_constant(SNAME("modulate_arrow"))) {
switch (get_draw_mode()) {
case DRAW_PRESSED:
- clr = get_theme_color("font_pressed_color");
+ clr = get_theme_color(SNAME("font_pressed_color"));
break;
case DRAW_HOVER:
- clr = get_theme_color("font_hover_color");
+ clr = get_theme_color(SNAME("font_hover_color"));
break;
case DRAW_DISABLED:
- clr = get_theme_color("font_disabled_color");
+ clr = get_theme_color(SNAME("font_disabled_color"));
break;
default:
- clr = get_theme_color("font_color");
+ clr = get_theme_color(SNAME("font_color"));
}
}
@@ -79,22 +79,22 @@ void OptionButton::_notification(int p_what) {
Point2 ofs;
if (is_layout_rtl()) {
- ofs = Point2(get_theme_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ ofs = Point2(get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
} else {
- ofs = Point2(size.width - arrow->get_width() - get_theme_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ ofs = Point2(size.width - arrow->get_width() - get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
}
arrow->draw(ci, ofs, clr);
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
- if (has_theme_icon("arrow")) {
+ if (has_theme_icon(SNAME("arrow"))) {
if (is_layout_rtl()) {
- _set_internal_margin(SIDE_LEFT, Control::get_theme_icon("arrow")->get_width());
+ _set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
_set_internal_margin(SIDE_RIGHT, 0.f);
} else {
_set_internal_margin(SIDE_LEFT, 0.f);
- _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon("arrow")->get_width());
+ _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
}
}
} break;
@@ -107,7 +107,7 @@ void OptionButton::_notification(int p_what) {
}
void OptionButton::_focused(int p_which) {
- emit_signal("item_focused", p_which);
+ emit_signal(SNAME("item_focused"), p_which);
}
void OptionButton::_selected(int p_which) {
@@ -220,7 +220,7 @@ void OptionButton::_select(int p_which, bool p_emit) {
set_icon(popup->get_item_icon(current));
if (is_inside_tree() && p_emit) {
- emit_signal("item_selected", current);
+ emit_signal(SNAME("item_selected"), current);
}
}
@@ -339,12 +339,12 @@ OptionButton::OptionButton() {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
if (is_layout_rtl()) {
- if (has_theme_icon("arrow")) {
- _set_internal_margin(SIDE_LEFT, Control::get_theme_icon("arrow")->get_width());
+ if (has_theme_icon(SNAME("arrow"))) {
+ _set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
}
} else {
- if (has_theme_icon("arrow")) {
- _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon("arrow")->get_width());
+ if (has_theme_icon(SNAME("arrow"))) {
+ _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
}
}
set_action_mode(ACTION_MODE_BUTTON_PRESS);
diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp
index 995e985c3a..e8e7e3d997 100644
--- a/scene/gui/panel.cpp
+++ b/scene/gui/panel.cpp
@@ -35,7 +35,7 @@
void Panel::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
- Ref<StyleBox> style = mode == MODE_BACKGROUND ? get_theme_stylebox("panel") : get_theme_stylebox("panel_fg");
+ Ref<StyleBox> style = mode == MODE_BACKGROUND ? get_theme_stylebox(SNAME("panel")) : get_theme_stylebox(SNAME("panel_fg"));
style->draw(ci, Rect2(Point2(), get_size()));
}
}
diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp
index 11d822c5e1..d910e1e882 100644
--- a/scene/gui/panel_container.cpp
+++ b/scene/gui/panel_container.cpp
@@ -33,10 +33,10 @@
Size2 PanelContainer::get_minimum_size() const {
Ref<StyleBox> style;
- if (has_theme_stylebox("panel")) {
- style = get_theme_stylebox("panel");
+ if (has_theme_stylebox(SNAME("panel"))) {
+ style = get_theme_stylebox(SNAME("panel"));
} else {
- style = get_theme_stylebox("panel", "PanelContainer");
+ style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
}
Size2 ms;
@@ -65,10 +65,10 @@ void PanelContainer::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<StyleBox> style;
- if (has_theme_stylebox("panel")) {
- style = get_theme_stylebox("panel");
+ if (has_theme_stylebox(SNAME("panel"))) {
+ style = get_theme_stylebox(SNAME("panel"));
} else {
- style = get_theme_stylebox("panel", "PanelContainer");
+ style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
}
style->draw(ci, Rect2(Point2(), get_size()));
@@ -77,10 +77,10 @@ void PanelContainer::_notification(int p_what) {
if (p_what == NOTIFICATION_SORT_CHILDREN) {
Ref<StyleBox> style;
- if (has_theme_stylebox("panel")) {
- style = get_theme_stylebox("panel");
+ if (has_theme_stylebox(SNAME("panel"))) {
+ style = get_theme_stylebox(SNAME("panel"));
} else {
- style = get_theme_stylebox("panel", "PanelContainer");
+ style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
}
Size2 size = get_size();
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 36bcca61a7..5e1c8cec37 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -71,7 +71,7 @@ void Popup::_notification(int p_what) {
_initialize_visible_parents();
} else {
_deinitialize_visible_parents();
- emit_signal("popup_hide");
+ emit_signal(SNAME("popup_hide"));
}
} break;
@@ -103,9 +103,9 @@ void Popup::_close_pressed() {
_deinitialize_visible_parents();
- call_deferred("hide");
+ call_deferred(SNAME("hide"));
- emit_signal("cancelled");
+ emit_signal(SNAME("cancelled"));
}
void Popup::set_as_minsize() {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 2100707d2d..ee9e0e8ab8 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -46,15 +46,15 @@ String PopupMenu::_get_accel_text(const Item &p_item) const {
}
Size2 PopupMenu::_get_contents_minimum_size() const {
- int vseparation = get_theme_constant("vseparation");
- int hseparation = get_theme_constant("hseparation");
+ int vseparation = get_theme_constant(SNAME("vseparation"));
+ int hseparation = get_theme_constant(SNAME("hseparation"));
- Size2 minsize = get_theme_stylebox("panel")->get_minimum_size(); // Accounts for margin in the margin container
+ Size2 minsize = get_theme_stylebox(SNAME("panel"))->get_minimum_size(); // Accounts for margin in the margin container
minsize.x += scroll_container->get_v_scrollbar()->get_size().width * 2; // Adds a buffer so that the scrollbar does not render over the top of content
float max_w = 0.0;
float icon_w = 0.0;
- int check_w = MAX(get_theme_icon("checked")->get_width(), get_theme_icon("radio_checked")->get_width()) + hseparation;
+ int check_w = MAX(get_theme_icon(SNAME("checked"))->get_width(), get_theme_icon(SNAME("radio_checked"))->get_width()) + hseparation;
int accel_max_w = 0;
bool has_check = false;
@@ -81,7 +81,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
}
if (items[i].submenu != "") {
- size.width += get_theme_icon("submenu")->get_width();
+ size.width += get_theme_icon(SNAME("submenu"))->get_width();
}
max_w = MAX(max_w, size.width);
@@ -89,7 +89,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
minsize.height += size.height;
}
- int item_side_padding = get_theme_constant("item_start_padding") + get_theme_constant("item_end_padding");
+ int item_side_padding = get_theme_constant(SNAME("item_start_padding")) + get_theme_constant(SNAME("item_end_padding"));
minsize.width += max_w + icon_w + accel_max_w + item_side_padding;
if (has_check) {
@@ -112,24 +112,24 @@ int PopupMenu::_get_item_height(int p_item) const {
int icon_height = items[p_item].get_icon_size().height;
if (items[p_item].checkable_type) {
- icon_height = MAX(icon_height, MAX(get_theme_icon("checked")->get_height(), get_theme_icon("radio_checked")->get_height()));
+ icon_height = MAX(icon_height, MAX(get_theme_icon(SNAME("checked"))->get_height(), get_theme_icon(SNAME("radio_checked"))->get_height()));
}
int text_height = items[p_item].text_buf->get_size().height;
if (text_height == 0 && !items[p_item].separator) {
- text_height = get_theme_font("font")->get_height(get_theme_font_size("font_size"));
+ text_height = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
}
int separator_height = 0;
if (items[p_item].separator) {
- separator_height = MAX(get_theme_stylebox("separator")->get_minimum_size().height, MAX(get_theme_stylebox("labeled_separator_left")->get_minimum_size().height, get_theme_stylebox("labeled_separator_right")->get_minimum_size().height));
+ separator_height = MAX(get_theme_stylebox(SNAME("separator"))->get_minimum_size().height, MAX(get_theme_stylebox(SNAME("labeled_separator_left"))->get_minimum_size().height, get_theme_stylebox(SNAME("labeled_separator_right"))->get_minimum_size().height));
}
return MAX(separator_height, MAX(text_height, icon_height));
}
int PopupMenu::_get_items_total_height() const {
- int vsep = get_theme_constant("vseparation");
+ int vsep = get_theme_constant(SNAME("vseparation"));
// Get total height of all items by taking max of icon height and font height
int items_total_height = 0;
@@ -163,9 +163,9 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
return -1;
}
- Ref<StyleBox> style = get_theme_stylebox("panel"); // Accounts for margin in the margin container
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("panel")); // Accounts for margin in the margin container
- int vseparation = get_theme_constant("vseparation");
+ int vseparation = get_theme_constant(SNAME("vseparation"));
Point2 ofs = style->get_offset() + Point2(0, vseparation / 2);
@@ -195,8 +195,8 @@ void PopupMenu::_activate_submenu(int p_over) {
return; //already visible!
}
- Ref<StyleBox> style = get_theme_stylebox("panel");
- int vsep = get_theme_constant("vseparation");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
+ int vsep = get_theme_constant(SNAME("vseparation"));
Point2 this_pos = get_position();
Rect2 this_rect(this_pos, get_size());
@@ -264,7 +264,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
for (int i = search_from; i < items.size(); i++) {
if (!items[i].separator && !items[i].disabled) {
mouse_over = i;
- emit_signal("id_focused", i);
+ emit_signal(SNAME("id_focused"), i);
_scroll_to_item(i);
control->update();
set_input_as_handled();
@@ -278,7 +278,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
for (int i = 0; i < search_from; i++) {
if (!items[i].separator && !items[i].disabled) {
mouse_over = i;
- emit_signal("id_focused", i);
+ emit_signal(SNAME("id_focused"), i);
_scroll_to_item(i);
control->update();
set_input_as_handled();
@@ -296,7 +296,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
for (int i = search_from; i >= 0; i--) {
if (!items[i].separator && !items[i].disabled) {
mouse_over = i;
- emit_signal("id_focused", i);
+ emit_signal(SNAME("id_focused"), i);
_scroll_to_item(i);
control->update();
set_input_as_handled();
@@ -310,7 +310,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
for (int i = items.size() - 1; i >= search_from; i--) {
if (!items[i].separator && !items[i].disabled) {
mouse_over = i;
- emit_signal("id_focused", i);
+ emit_signal(SNAME("id_focused"), i);
_scroll_to_item(i);
control->update();
set_input_as_handled();
@@ -459,7 +459,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
if (items[i].text.findn(search_string) == 0) {
mouse_over = i;
- emit_signal("id_focused", i);
+ emit_signal(SNAME("id_focused"), i);
_scroll_to_item(i);
control->update();
set_input_as_handled();
@@ -474,37 +474,37 @@ void PopupMenu::_draw_items() {
RID ci = control->get_canvas_item();
Size2 margin_size;
- margin_size.width = margin_container->get_theme_constant("margin_right") + margin_container->get_theme_constant("margin_left");
- margin_size.height = margin_container->get_theme_constant("margin_top") + margin_container->get_theme_constant("margin_bottom");
+ margin_size.width = margin_container->get_theme_constant(SNAME("margin_right")) + margin_container->get_theme_constant(SNAME("margin_left"));
+ margin_size.height = margin_container->get_theme_constant(SNAME("margin_top")) + margin_container->get_theme_constant(SNAME("margin_bottom"));
// Space between the item content and the sides of popup menu.
- int item_start_padding = get_theme_constant("item_start_padding");
- int item_end_padding = get_theme_constant("item_end_padding");
+ int item_start_padding = get_theme_constant(SNAME("item_start_padding"));
+ int item_end_padding = get_theme_constant(SNAME("item_end_padding"));
bool rtl = control->is_layout_rtl();
- Ref<StyleBox> style = get_theme_stylebox("panel");
- Ref<StyleBox> hover = get_theme_stylebox("hover");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
+ Ref<StyleBox> hover = get_theme_stylebox(SNAME("hover"));
// In Item::checkable_type enum order (less the non-checkable member)
- Ref<Texture2D> check[] = { get_theme_icon("checked"), get_theme_icon("radio_checked") };
- Ref<Texture2D> uncheck[] = { get_theme_icon("unchecked"), get_theme_icon("radio_unchecked") };
+ Ref<Texture2D> check[] = { get_theme_icon(SNAME("checked")), get_theme_icon(SNAME("radio_checked")) };
+ Ref<Texture2D> uncheck[] = { get_theme_icon(SNAME("unchecked")), get_theme_icon(SNAME("radio_unchecked")) };
Ref<Texture2D> submenu;
if (rtl) {
- submenu = get_theme_icon("submenu_mirrored");
+ submenu = get_theme_icon(SNAME("submenu_mirrored"));
} else {
- submenu = get_theme_icon("submenu");
+ submenu = get_theme_icon(SNAME("submenu"));
}
- Ref<StyleBox> separator = get_theme_stylebox("separator");
- Ref<StyleBox> labeled_separator_left = get_theme_stylebox("labeled_separator_left");
- Ref<StyleBox> labeled_separator_right = get_theme_stylebox("labeled_separator_right");
+ Ref<StyleBox> separator = get_theme_stylebox(SNAME("separator"));
+ Ref<StyleBox> labeled_separator_left = get_theme_stylebox(SNAME("labeled_separator_left"));
+ Ref<StyleBox> labeled_separator_right = get_theme_stylebox(SNAME("labeled_separator_right"));
- int vseparation = get_theme_constant("vseparation");
- int hseparation = get_theme_constant("hseparation");
- Color font_color = get_theme_color("font_color");
- Color font_disabled_color = get_theme_color("font_disabled_color");
- Color font_accelerator_color = get_theme_color("font_accelerator_color");
- Color font_hover_color = get_theme_color("font_hover_color");
- Color font_separator_color = get_theme_color("font_separator_color");
+ int vseparation = get_theme_constant(SNAME("vseparation"));
+ int hseparation = get_theme_constant(SNAME("hseparation"));
+ Color font_color = get_theme_color(SNAME("font_color"));
+ Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ Color font_accelerator_color = get_theme_color(SNAME("font_accelerator_color"));
+ Color font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ Color font_separator_color = get_theme_color(SNAME("font_separator_color"));
float scroll_width = scroll_container->get_v_scrollbar()->is_visible_in_tree() ? scroll_container->get_v_scrollbar()->get_size().width : 0;
float display_width = control->get_size().width - scroll_width;
@@ -525,7 +525,7 @@ void PopupMenu::_draw_items() {
float check_ofs = 0.0;
if (has_check) {
- check_ofs = MAX(get_theme_icon("checked")->get_width(), get_theme_icon("radio_checked")->get_width()) + hseparation;
+ check_ofs = MAX(get_theme_icon(SNAME("checked"))->get_width(), get_theme_icon(SNAME("radio_checked"))->get_width()) + hseparation;
}
Point2 ofs = Point2();
@@ -606,8 +606,8 @@ void PopupMenu::_draw_items() {
}
// Text
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
if (items[i].separator) {
if (text != String()) {
int center = (display_width - items[i].text_buf->get_size().width) / 2;
@@ -657,7 +657,7 @@ void PopupMenu::_draw_items() {
}
void PopupMenu::_draw_background() {
- Ref<StyleBox> style = get_theme_stylebox("panel");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
RID ci2 = margin_container->get_canvas_item();
style->draw(ci2, Rect2(Point2(), margin_container->get_size()));
}
@@ -691,8 +691,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("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_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);
@@ -791,7 +791,7 @@ void PopupMenu::_notification(int p_what) {
}
// Set margin on the margin container
- Ref<StyleBox> panel_style = get_theme_stylebox("panel");
+ Ref<StyleBox> panel_style = get_theme_stylebox(SNAME("panel"));
margin_container->add_theme_constant_override("margin_top", panel_style->get_margin(Side::SIDE_TOP));
margin_container->add_theme_constant_override("margin_bottom", panel_style->get_margin(Side::SIDE_BOTTOM));
margin_container->add_theme_constant_override("margin_left", panel_style->get_margin(Side::SIDE_LEFT));
@@ -1376,8 +1376,8 @@ void PopupMenu::activate_item(int p_item) {
need_hide = false;
}
- emit_signal("id_pressed", id);
- emit_signal("index_pressed", p_item);
+ emit_signal(SNAME("id_pressed"), id);
+ emit_signal(SNAME("index_pressed"), p_item);
if (need_hide) {
hide();
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index 6e8dfd5994..2cfaaa2fde 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -32,10 +32,10 @@
#include "scene/resources/text_line.h"
Size2 ProgressBar::get_minimum_size() const {
- Ref<StyleBox> bg = get_theme_stylebox("bg");
- Ref<StyleBox> fg = get_theme_stylebox("fg");
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
+ Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
Size2 minimum_size = bg->get_minimum_size();
minimum_size.height = MAX(minimum_size.height, fg->get_minimum_size().height);
@@ -53,11 +53,11 @@ Size2 ProgressBar::get_minimum_size() const {
void ProgressBar::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<StyleBox> bg = get_theme_stylebox("bg");
- Ref<StyleBox> fg = get_theme_stylebox("fg");
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
- Color font_color = get_theme_color("font_color");
+ Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
+ Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
+ Color font_color = get_theme_color(SNAME("font_color"));
draw_style_box(bg, Rect2(Point2(), get_size()));
float r = get_as_ratio();
@@ -75,8 +75,8 @@ void ProgressBar::_notification(int p_what) {
String txt = TS->format_number(itos(int(get_as_ratio() * 100))) + TS->percent_sign();
TextLine tl = TextLine(txt, font, font_size);
Vector2 text_pos = (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round();
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
if (outline_size > 0 && font_outline_color.a > 0) {
tl.draw_outline(get_canvas_item(), text_pos, outline_size, font_outline_color);
}
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 4ea1e1eb9f..92d4261d8d 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -42,7 +42,7 @@ TypedArray<String> Range::get_configuration_warnings() const {
void Range::_value_changed_notify() {
_value_changed(shared->val);
- emit_signal("value_changed", shared->val);
+ emit_signal(SNAME("value_changed"), shared->val);
update();
}
@@ -57,7 +57,7 @@ void Range::Shared::emit_value_changed() {
}
void Range::_changed_notify(const char *p_what) {
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
update();
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index f32ad2144a..99395aae30 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -136,7 +136,7 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) co
}
Rect2 RichTextLabel::_get_text_rect() {
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
}
@@ -229,8 +229,8 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font>
switch (it->type) {
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
- int hseparation = get_theme_constant("table_hseparation");
- int vseparation = get_theme_constant("table_vseparation");
+ int hseparation = get_theme_constant(SNAME("table_hseparation"));
+ int vseparation = get_theme_constant(SNAME("table_vseparation"));
int col_count = table->columns.size();
for (int i = 0; i < col_count; i++) {
@@ -458,8 +458,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
} break;
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
- int hseparation = get_theme_constant("table_hseparation");
- int vseparation = get_theme_constant("table_vseparation");
+ int hseparation = get_theme_constant(SNAME("table_hseparation"));
+ int vseparation = get_theme_constant(SNAME("table_vseparation"));
int col_count = table->columns.size();
int t_char_count = 0;
// Set minimums to zero.
@@ -672,11 +672,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
if (prefix != "") {
Ref<Font> font = _find_font(l.from);
if (font.is_null()) {
- font = get_theme_font("normal_font");
+ font = get_theme_font(SNAME("normal_font"));
}
int font_size = _find_font_size(l.from);
if (font_size == -1) {
- font_size = get_theme_font_size("normal_font_size");
+ font_size = get_theme_font_size(SNAME("normal_font_size"));
}
if (rtl) {
float offx = 0.0f;
@@ -775,10 +775,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} break;
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
- Color odd_row_bg = get_theme_color("table_odd_row_bg");
- Color even_row_bg = get_theme_color("table_even_row_bg");
- Color border = get_theme_color("table_border");
- int hseparation = get_theme_constant("table_hseparation");
+ Color odd_row_bg = get_theme_color(SNAME("table_odd_row_bg"));
+ Color even_row_bg = get_theme_color(SNAME("table_even_row_bg"));
+ Color border = get_theme_color(SNAME("table_border"));
+ int hseparation = get_theme_constant(SNAME("table_hseparation"));
int col_count = table->columns.size();
int row_count = table->rows.size();
@@ -916,7 +916,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
}
- Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
+ Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
// Draw glyph outlines.
for (int j = 0; j < glyphs[i].repeat; j++) {
@@ -940,8 +940,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
_draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 0);
// Draw main text.
- Color selection_fg = get_theme_color("font_selected_color");
- Color selection_bg = get_theme_color("selection_color");
+ Color selection_fg = get_theme_color(SNAME("font_selected_color"));
+ Color selection_bg = get_theme_color(SNAME("selection_color"));
int sel_start = -1;
int sel_end = -1;
@@ -1192,8 +1192,8 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
if (rect.has_point(p_click - p_ofs - off)) {
switch (it->type) {
case ITEM_TABLE: {
- int hseparation = get_theme_constant("table_hseparation");
- int vseparation = get_theme_constant("table_vseparation");
+ int hseparation = get_theme_constant(SNAME("table_hseparation"));
+ int vseparation = get_theme_constant(SNAME("table_vseparation"));
ItemTable *table = static_cast<ItemTable *>(it);
@@ -1362,7 +1362,7 @@ void RichTextLabel::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
if (meta_hovering) {
meta_hovering = nullptr;
- emit_signal("meta_hover_ended", current_meta);
+ emit_signal(SNAME("meta_hover_ended"), current_meta);
current_meta = false;
update();
}
@@ -1395,11 +1395,11 @@ void RichTextLabel::_notification(int p_what) {
Size2 size = get_size();
Rect2 text_rect = _get_text_rect();
- draw_style_box(get_theme_stylebox("normal"), Rect2(Point2(), size));
+ draw_style_box(get_theme_stylebox(SNAME("normal")), Rect2(Point2(), size));
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- draw_style_box(get_theme_stylebox("focus"), Rect2(Point2(), size));
+ draw_style_box(get_theme_stylebox(SNAME("focus")), Rect2(Point2(), size));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
@@ -1419,13 +1419,13 @@ void RichTextLabel::_notification(int p_what) {
if (from_line >= main->lines.size()) {
break; //nothing to draw
}
- Ref<Font> base_font = get_theme_font("normal_font");
- Color base_color = get_theme_color("default_color");
- Color outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
- Color font_shadow_color = get_theme_color("font_shadow_color");
- bool use_outline = get_theme_constant("shadow_as_outline");
- Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
+ Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
+ Color base_color = get_theme_color(SNAME("default_color"));
+ Color outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
+ bool use_outline = get_theme_constant(SNAME("shadow_as_outline"));
+ Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
visible_paragraph_count = 0;
visible_line_count = 0;
@@ -1568,7 +1568,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
Variant meta;
if (!outside && _find_meta(c_item, &meta)) {
//meta clicked
- emit_signal("meta_clicked", meta);
+ emit_signal(SNAME("meta_clicked"), meta);
}
}
}
@@ -1611,11 +1611,11 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
handled = true;
}
if (k->is_action("ui_up") && vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() - get_theme_font("normal_font")->get_height(get_theme_font_size("normal_font_size")));
+ vscroll->set_value(vscroll->get_value() - get_theme_font(SNAME("normal_font"))->get_height(get_theme_font_size(SNAME("normal_font_size"))));
handled = true;
}
if (k->is_action("ui_down") && vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() + get_theme_font("normal_font")->get_height(get_theme_font_size("normal_font_size")));
+ vscroll->set_value(vscroll->get_value() + get_theme_font(SNAME("normal_font"))->get_height(get_theme_font_size(SNAME("normal_font_size"))));
handled = true;
}
if (k->is_action("ui_home") && vscroll->is_visible_in_tree()) {
@@ -1693,15 +1693,15 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
if (c_item && !outside && _find_meta(c_item, &meta, &item_meta)) {
if (meta_hovering != item_meta) {
if (meta_hovering) {
- emit_signal("meta_hover_ended", current_meta);
+ emit_signal(SNAME("meta_hover_ended"), current_meta);
}
meta_hovering = item_meta;
current_meta = meta;
- emit_signal("meta_hover_started", meta);
+ emit_signal(SNAME("meta_hover_started"), meta);
}
} else if (meta_hovering) {
meta_hovering = nullptr;
- emit_signal("meta_hover_ended", current_meta);
+ emit_signal(SNAME("meta_hover_ended"), current_meta);
current_meta = false;
}
}
@@ -2105,8 +2105,8 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
}
Rect2 text_rect = _get_text_rect();
- Ref<Font> base_font = get_theme_font("normal_font");
- int base_font_size = get_theme_font_size("normal_font_size");
+ Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
+ int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
for (int i = p_frame->first_resized_line; i < p_frame->lines.size(); i++) {
_resize_line(p_frame, i, base_font, base_font_size, text_rect.get_size().width - scroll_w);
@@ -2140,8 +2140,8 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
}
Rect2 text_rect = _get_text_rect();
- Ref<Font> base_font = get_theme_font("normal_font");
- int base_font_size = get_theme_font_size("normal_font_size");
+ Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
+ int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
int total_chars = (p_frame->first_invalid_line == 0) ? 0 : (p_frame->lines[p_frame->first_invalid_line].char_offset + p_frame->lines[p_frame->first_invalid_line].char_count);
for (int i = p_frame->first_invalid_line; i < p_frame->lines.size(); i++) {
@@ -2406,35 +2406,35 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) {
}
void RichTextLabel::push_normal() {
- Ref<Font> normal_font = get_theme_font("normal_font");
+ Ref<Font> normal_font = get_theme_font(SNAME("normal_font"));
ERR_FAIL_COND(normal_font.is_null());
push_font(normal_font);
}
void RichTextLabel::push_bold() {
- Ref<Font> bold_font = get_theme_font("bold_font");
+ Ref<Font> bold_font = get_theme_font(SNAME("bold_font"));
ERR_FAIL_COND(bold_font.is_null());
push_font(bold_font);
}
void RichTextLabel::push_bold_italics() {
- Ref<Font> bold_italics_font = get_theme_font("bold_italics_font");
+ Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
ERR_FAIL_COND(bold_italics_font.is_null());
push_font(bold_italics_font);
}
void RichTextLabel::push_italics() {
- Ref<Font> italics_font = get_theme_font("italics_font");
+ Ref<Font> italics_font = get_theme_font(SNAME("italics_font"));
ERR_FAIL_COND(italics_font.is_null());
push_font(italics_font);
}
void RichTextLabel::push_mono() {
- Ref<Font> mono_font = get_theme_font("mono_font");
+ Ref<Font> mono_font = get_theme_font(SNAME("mono_font"));
ERR_FAIL_COND(mono_font.is_null());
push_font(mono_font);
@@ -2774,13 +2774,13 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
int pos = 0;
List<String> tag_stack;
- Ref<Font> normal_font = get_theme_font("normal_font");
- Ref<Font> bold_font = get_theme_font("bold_font");
- Ref<Font> italics_font = get_theme_font("italics_font");
- Ref<Font> bold_italics_font = get_theme_font("bold_italics_font");
- Ref<Font> mono_font = get_theme_font("mono_font");
+ Ref<Font> normal_font = get_theme_font(SNAME("normal_font"));
+ Ref<Font> bold_font = get_theme_font(SNAME("bold_font"));
+ Ref<Font> italics_font = get_theme_font(SNAME("italics_font"));
+ Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
+ Ref<Font> mono_font = get_theme_font(SNAME("mono_font"));
- Color base_color = get_theme_color("default_color");
+ Color base_color = get_theme_color(SNAME("default_color"));
int indent_level = 0;
@@ -3140,11 +3140,11 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
tag_stack.push_front("url");
} else if (tag.begins_with("dropcap")) {
Vector<String> subtag = tag.substr(5, tag.length()).split(" ");
- Ref<Font> f = get_theme_font("normal_font");
- int fs = get_theme_font_size("normal_font_size") * 3;
- Color color = get_theme_color("default_color");
- Color outline_color = get_theme_color("outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Ref<Font> f = get_theme_font(SNAME("normal_font"));
+ int fs = get_theme_font_size(SNAME("normal_font_size")) * 3;
+ Color color = get_theme_color(SNAME("default_color"));
+ Color outline_color = get_theme_color(SNAME("outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
Rect2 dropcap_margins = Rect2();
for (int i = 0; i < subtag.size(); i++) {
@@ -4168,7 +4168,7 @@ void RichTextLabel::set_fixed_size_to_width(int p_width) {
}
Size2 RichTextLabel::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
Size2 size = style->get_minimum_size();
if (fixed_width != -1) {
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 62276e3af0..ce04a0204b 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -46,7 +46,7 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseMotion> m = p_event;
if (!m.is_valid() || drag.active) {
- emit_signal("scrolling");
+ emit_signal(SNAME("scrolling"));
}
Ref<InputEventMouseButton> b = p_event;
@@ -70,8 +70,8 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (b->is_pressed()) {
double ofs = orientation == VERTICAL ? b->get_position().y : b->get_position().x;
- Ref<Texture2D> decr = get_theme_icon("decrement");
- Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -140,7 +140,7 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (drag.active) {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
ofs -= decr_size;
@@ -150,8 +150,8 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
set_as_ratio(drag.value_at_click + diff);
} else {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_theme_icon("decrement");
- Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -215,17 +215,17 @@ void ScrollBar::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
- Ref<Texture2D> decr = highlight == HIGHLIGHT_DECR ? get_theme_icon("decrement_highlight") : get_theme_icon("decrement");
- Ref<Texture2D> incr = highlight == HIGHLIGHT_INCR ? get_theme_icon("increment_highlight") : get_theme_icon("increment");
- Ref<StyleBox> bg = has_focus() ? get_theme_stylebox("scroll_focus") : get_theme_stylebox("scroll");
+ Ref<Texture2D> decr = highlight == HIGHLIGHT_DECR ? get_theme_icon(SNAME("decrement_highlight")) : get_theme_icon(SNAME("decrement"));
+ Ref<Texture2D> incr = highlight == HIGHLIGHT_INCR ? get_theme_icon(SNAME("increment_highlight")) : get_theme_icon(SNAME("increment"));
+ Ref<StyleBox> bg = has_focus() ? get_theme_stylebox(SNAME("scroll_focus")) : get_theme_stylebox(SNAME("scroll"));
Ref<StyleBox> grabber;
if (drag.active) {
- grabber = get_theme_stylebox("grabber_pressed");
+ grabber = get_theme_stylebox(SNAME("grabber_pressed"));
} else if (highlight == HIGHLIGHT_RANGE) {
- grabber = get_theme_stylebox("grabber_highlight");
+ grabber = get_theme_stylebox(SNAME("grabber_highlight"));
} else {
- grabber = get_theme_stylebox("grabber");
+ grabber = get_theme_stylebox(SNAME("grabber"));
}
Point2 ofs;
@@ -389,7 +389,7 @@ void ScrollBar::_notification(int p_what) {
}
double ScrollBar::get_grabber_min_size() const {
- Ref<StyleBox> grabber = get_theme_stylebox("grabber");
+ Ref<StyleBox> grabber = get_theme_stylebox(SNAME("grabber"));
Size2 gminsize = grabber->get_minimum_size() + grabber->get_center_size();
return (orientation == VERTICAL) ? gminsize.height : gminsize.width;
}
@@ -415,17 +415,17 @@ double ScrollBar::get_area_size() const {
switch (orientation) {
case VERTICAL: {
double area = get_size().height;
- area -= get_theme_stylebox("scroll")->get_minimum_size().height;
- area -= get_theme_icon("increment")->get_height();
- area -= get_theme_icon("decrement")->get_height();
+ area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().height;
+ area -= get_theme_icon(SNAME("increment"))->get_height();
+ area -= get_theme_icon(SNAME("decrement"))->get_height();
area -= get_grabber_min_size();
return area;
} break;
case HORIZONTAL: {
double area = get_size().width;
- area -= get_theme_stylebox("scroll")->get_minimum_size().width;
- area -= get_theme_icon("increment")->get_width();
- area -= get_theme_icon("decrement")->get_width();
+ area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().width;
+ area -= get_theme_icon(SNAME("increment"))->get_width();
+ area -= get_theme_icon(SNAME("decrement"))->get_width();
area -= get_grabber_min_size();
return area;
} break;
@@ -439,13 +439,13 @@ double ScrollBar::get_area_offset() const {
double ofs = 0.0;
if (orientation == VERTICAL) {
- ofs += get_theme_stylebox("hscroll")->get_margin(SIDE_TOP);
- ofs += get_theme_icon("decrement")->get_height();
+ ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_TOP);
+ ofs += get_theme_icon(SNAME("decrement"))->get_height();
}
if (orientation == HORIZONTAL) {
- ofs += get_theme_stylebox("hscroll")->get_margin(SIDE_LEFT);
- ofs += get_theme_icon("decrement")->get_width();
+ ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_LEFT);
+ ofs += get_theme_icon(SNAME("decrement"))->get_width();
}
return ofs;
@@ -456,9 +456,9 @@ double ScrollBar::get_grabber_offset() const {
}
Size2 ScrollBar::get_minimum_size() const {
- Ref<Texture2D> incr = get_theme_icon("increment");
- Ref<Texture2D> decr = get_theme_icon("decrement");
- Ref<StyleBox> bg = get_theme_stylebox("scroll");
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
+ Ref<StyleBox> bg = get_theme_stylebox(SNAME("scroll"));
Size2 minsize;
if (orientation == VERTICAL) {
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 95445bdb7e..eb5fc924da 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -33,7 +33,7 @@
#include "scene/main/window.h"
Size2 ScrollContainer::get_minimum_size() const {
- Ref<StyleBox> sb = get_theme_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
Size2 min_size;
for (int i = 0; i < get_child_count(); i++) {
@@ -77,7 +77,7 @@ void ScrollContainer::_cancel_drag() {
drag_from = Vector2();
if (beyond_deadzone) {
- emit_signal("scroll_ended");
+ emit_signal(SNAME("scroll_ended"));
propagate_notification(NOTIFICATION_SCROLL_END);
beyond_deadzone = false;
}
@@ -173,7 +173,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (beyond_deadzone || (scroll_h && Math::abs(drag_accum.x) > deadzone) || (scroll_v && Math::abs(drag_accum.y) > deadzone)) {
if (!beyond_deadzone) {
propagate_notification(NOTIFICATION_SCROLL_BEGIN);
- emit_signal("scroll_started");
+ emit_signal(SNAME("scroll_started"));
beyond_deadzone = true;
// resetting drag_accum here ensures smooth scrolling after reaching deadzone
@@ -235,13 +235,13 @@ void ScrollContainer::_update_scrollbar_position() {
}
void ScrollContainer::_gui_focus_changed(Control *p_control) {
- if (follow_focus && is_a_parent_of(p_control)) {
+ if (follow_focus && is_ancestor_of(p_control)) {
ensure_control_visible(p_control);
}
}
void ScrollContainer::ensure_control_visible(Control *p_control) {
- ERR_FAIL_COND_MSG(!is_a_parent_of(p_control), "Must be a parent of the control.");
+ ERR_FAIL_COND_MSG(!is_ancestor_of(p_control), "Must be an ancestor of the control.");
Rect2 global_rect = get_global_rect();
Rect2 other_rect = p_control->get_global_rect();
@@ -260,7 +260,7 @@ void ScrollContainer::_update_dimensions() {
Size2 size = get_size();
Point2 ofs;
- Ref<StyleBox> sb = get_theme_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
size -= sb->get_minimum_size();
ofs += sb->get_offset();
bool rtl = is_layout_rtl();
@@ -319,7 +319,7 @@ void ScrollContainer::_update_dimensions() {
void ScrollContainer::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
_updating_scrollbars = true;
- call_deferred("_update_scrollbar_position");
+ call_deferred(SNAME("_update_scrollbar_position"));
};
if (p_what == NOTIFICATION_READY) {
@@ -332,7 +332,7 @@ void ScrollContainer::_notification(int p_what) {
};
if (p_what == NOTIFICATION_DRAW) {
- Ref<StyleBox> sb = get_theme_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
draw_style_box(sb, Rect2(Vector2(), get_size()));
update_scrollbars();
@@ -409,7 +409,7 @@ void ScrollContainer::_notification(int p_what) {
void ScrollContainer::update_scrollbars() {
Size2 size = get_size();
- Ref<StyleBox> sb = get_theme_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
size -= sb->get_minimum_size();
Size2 hmin;
diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp
index 3cb8ccf135..1f3cb7aa24 100644
--- a/scene/gui/separator.cpp
+++ b/scene/gui/separator.cpp
@@ -33,9 +33,9 @@
Size2 Separator::get_minimum_size() const {
Size2 ms(3, 3);
if (orientation == VERTICAL) {
- ms.x = get_theme_constant("separation");
+ ms.x = get_theme_constant(SNAME("separation"));
} else { // HORIZONTAL
- ms.y = get_theme_constant("separation");
+ ms.y = get_theme_constant(SNAME("separation"));
}
return ms;
}
@@ -44,7 +44,7 @@ void Separator::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
Size2i size = get_size();
- Ref<StyleBox> style = get_theme_stylebox("separator");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("separator"));
Size2i ssize = style->get_minimum_size() + style->get_center_size();
if (orientation == VERTICAL) {
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 5947f3b99e..61b5325175 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -32,10 +32,10 @@
#include "core/os/keyboard.h"
Size2 Slider::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox("slider");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
Size2i ss = style->get_minimum_size() + style->get_center_size();
- Ref<Texture2D> grabber = get_theme_icon("grabber");
+ Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
Size2i rs = grabber->get_size();
if (orientation == HORIZONTAL) {
@@ -89,7 +89,7 @@ void Slider::_gui_input(Ref<InputEvent> p_event) {
if (mm.is_valid()) {
if (grab.active) {
Size2i size = get_size();
- Ref<Texture2D> grabber = get_theme_icon("grabber");
+ Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
float motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos;
if (orientation == VERTICAL) {
motion = -motion;
@@ -161,11 +161,11 @@ void Slider::_notification(int p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
Size2i size = get_size();
- Ref<StyleBox> style = get_theme_stylebox("slider");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
bool highlighted = mouse_inside || has_focus();
Ref<StyleBox> grabber_area = get_theme_stylebox(highlighted ? "grabber_area_highlight" : "grabber_area");
Ref<Texture2D> grabber = get_theme_icon(editable ? (highlighted ? "grabber_highlight" : "grabber") : "grabber_disabled");
- Ref<Texture2D> tick = get_theme_icon("tick");
+ Ref<Texture2D> tick = get_theme_icon(SNAME("tick"));
double ratio = Math::is_nan(get_as_ratio()) ? 0 : get_as_ratio();
if (orientation == VERTICAL) {
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 941dd30057..3f0368a4e2 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -170,7 +170,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
void SpinBox::_line_edit_focus_exit() {
// discontinue because the focus_exit was caused by right-click context menu
- if (line_edit->get_menu()->is_visible()) {
+ if (line_edit->is_menu_visible()) {
return;
}
@@ -188,7 +188,7 @@ inline void SpinBox::_adjust_width_for_icon(const Ref<Texture2D> &icon) {
void SpinBox::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<Texture2D> updown = get_theme_icon("updown");
+ Ref<Texture2D> updown = get_theme_icon(SNAME("updown"));
_adjust_width_for_icon(updown);
@@ -204,15 +204,15 @@ void SpinBox::_notification(int p_what) {
} else if (p_what == NOTIFICATION_FOCUS_EXIT) {
//_value_changed(0);
} else if (p_what == NOTIFICATION_ENTER_TREE) {
- _adjust_width_for_icon(get_theme_icon("updown"));
+ _adjust_width_for_icon(get_theme_icon(SNAME("updown")));
_value_changed(0);
} else if (p_what == NOTIFICATION_EXIT_TREE) {
_release_mouse();
} else if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
_value_changed(0);
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
- call_deferred("minimum_size_changed");
- get_line_edit()->call_deferred("minimum_size_changed");
+ call_deferred(SNAME("minimum_size_changed"));
+ get_line_edit()->call_deferred(SNAME("minimum_size_changed"));
} else if (p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
update();
}
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index df4cf9a740..3114e5b7c0 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -38,7 +38,7 @@ Control *SplitContainer::_getch(int p_idx) const {
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
- if (!c || !c->is_visible_in_tree()) {
+ if (!c || !c->is_visible()) {
continue;
}
if (c->is_set_as_top_level()) {
@@ -76,8 +76,8 @@ void SplitContainer::_resort() {
bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND;
// Determine the separation between items
- Ref<Texture2D> g = get_theme_icon("grabber");
- int sep = get_theme_constant("separation");
+ Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
+ int sep = get_theme_constant(SNAME("separation"));
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
// Compute the minimum size
@@ -131,8 +131,8 @@ Size2 SplitContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- Ref<Texture2D> g = get_theme_icon("grabber");
- int sep = get_theme_constant("separation");
+ Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
+ int sep = get_theme_constant(SNAME("separation"));
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
for (int i = 0; i < 2; i++) {
@@ -173,7 +173,7 @@ void SplitContainer::_notification(int p_what) {
} break;
case NOTIFICATION_MOUSE_EXIT: {
mouse_inside = false;
- if (get_theme_constant("autohide")) {
+ if (get_theme_constant(SNAME("autohide"))) {
update();
}
} break;
@@ -182,7 +182,7 @@ void SplitContainer::_notification(int p_what) {
return;
}
- if (collapsed || (!dragging && !mouse_inside && get_theme_constant("autohide"))) {
+ if (collapsed || (!dragging && !mouse_inside && get_theme_constant(SNAME("autohide")))) {
return;
}
@@ -190,8 +190,8 @@ void SplitContainer::_notification(int p_what) {
return;
}
- int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant("separation") : 0;
- Ref<Texture2D> tex = get_theme_icon("grabber");
+ int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant(SNAME("separation")) : 0;
+ Ref<Texture2D> tex = get_theme_icon(SNAME("grabber"));
Size2 size = get_size();
if (vertical) {
@@ -218,7 +218,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid()) {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
- int sep = get_theme_constant("separation");
+ int sep = get_theme_constant(SNAME("separation"));
if (vertical) {
if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + sep) {
@@ -244,14 +244,14 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
bool mouse_inside_state = false;
if (vertical) {
- mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_theme_constant("separation");
+ mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_theme_constant(SNAME("separation"));
} else {
- mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_theme_constant("separation");
+ mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_theme_constant(SNAME("separation"));
}
if (mouse_inside != mouse_inside_state) {
mouse_inside = mouse_inside_state;
- if (get_theme_constant("autohide")) {
+ if (get_theme_constant(SNAME("autohide"))) {
update();
}
}
@@ -267,7 +267,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
}
should_clamp_split_offset = true;
queue_sort();
- emit_signal("dragged", get_split_offset());
+ emit_signal(SNAME("dragged"), get_split_offset());
}
}
@@ -277,7 +277,7 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const
}
if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) {
- int sep = get_theme_constant("separation");
+ int sep = get_theme_constant(SNAME("separation"));
if (vertical) {
if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep) {
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 133966013b..8f84585f9b 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -43,9 +43,9 @@ int TabContainer::_get_top_margin() const {
}
// Respect the minimum tab height.
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
int tab_height = MAX(MAX(tab_unselected->get_minimum_size().height, tab_selected->get_minimum_size().height), tab_disabled->get_minimum_size().height);
@@ -88,11 +88,11 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
}
// Handle menu button.
- Ref<Texture2D> menu = get_theme_icon("menu");
+ Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
if (is_layout_rtl()) {
if (popup && pos.x < menu->get_width()) {
- emit_signal("pre_popup_pressed");
+ emit_signal(SNAME("pre_popup_pressed"));
Vector2 popup_pos = get_screen_position();
popup_pos.y += menu->get_height();
@@ -103,7 +103,7 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
}
} else {
if (popup && pos.x > size.width - menu->get_width()) {
- emit_signal("pre_popup_pressed");
+ emit_signal(SNAME("pre_popup_pressed"));
Vector2 popup_pos = get_screen_position();
popup_pos.x += size.width - popup->get_size().width;
@@ -129,8 +129,8 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
popup_ofs = menu->get_width();
}
- Ref<Texture2D> increment = get_theme_icon("increment");
- Ref<Texture2D> decrement = get_theme_icon("decrement");
+ Ref<Texture2D> increment = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decrement = get_theme_icon(SNAME("decrement"));
if (is_layout_rtl()) {
if (pos.x < popup_ofs + decrement->get_width()) {
if (last_tab_cache < tabs.size() - 1) {
@@ -203,7 +203,7 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
- Ref<Texture2D> menu = get_theme_icon("menu");
+ Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
if (popup) {
if (is_layout_rtl()) {
if (pos.x <= menu->get_width()) {
@@ -248,8 +248,8 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
popup_ofs = menu->get_width();
}
- Ref<Texture2D> increment = get_theme_icon("increment");
- Ref<Texture2D> decrement = get_theme_icon("decrement");
+ Ref<Texture2D> increment = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decrement = get_theme_icon(SNAME("decrement"));
if (is_layout_rtl()) {
if (pos.x <= popup_ofs + decrement->get_width()) {
@@ -289,10 +289,10 @@ void TabContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_RESIZED: {
Vector<Control *> tabs = _get_tabs();
- int side_margin = get_theme_constant("side_margin");
- Ref<Texture2D> menu = get_theme_icon("menu");
- Ref<Texture2D> increment = get_theme_icon("increment");
- Ref<Texture2D> decrement = get_theme_icon("decrement");
+ int side_margin = get_theme_constant(SNAME("side_margin"));
+ Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
+ Ref<Texture2D> increment = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decrement = get_theme_icon(SNAME("decrement"));
int header_width = get_size().width - side_margin * 2;
// Find the width of the header area.
@@ -332,26 +332,26 @@ void TabContainer::_notification(int p_what) {
bool rtl = is_layout_rtl();
// Draw only the tab area if the header is hidden.
- Ref<StyleBox> panel = get_theme_stylebox("panel");
+ Ref<StyleBox> panel = get_theme_stylebox(SNAME("panel"));
if (!tabs_visible) {
panel->draw(canvas, Rect2(0, 0, size.width, size.height));
return;
}
Vector<Control *> tabs = _get_tabs();
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
- Ref<Texture2D> increment = get_theme_icon("increment");
- Ref<Texture2D> increment_hl = get_theme_icon("increment_highlight");
- Ref<Texture2D> decrement = get_theme_icon("decrement");
- Ref<Texture2D> decrement_hl = get_theme_icon("decrement_highlight");
- Ref<Texture2D> menu = get_theme_icon("menu");
- Ref<Texture2D> menu_hl = get_theme_icon("menu_highlight");
- Color font_selected_color = get_theme_color("font_selected_color");
- Color font_unselected_color = get_theme_color("font_unselected_color");
- Color font_disabled_color = get_theme_color("font_disabled_color");
- int side_margin = get_theme_constant("side_margin");
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
+ Ref<Texture2D> increment = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> increment_hl = get_theme_icon(SNAME("increment_highlight"));
+ Ref<Texture2D> decrement = get_theme_icon(SNAME("decrement"));
+ Ref<Texture2D> decrement_hl = get_theme_icon(SNAME("decrement_highlight"));
+ Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
+ Ref<Texture2D> menu_hl = get_theme_icon(SNAME("menu_highlight"));
+ Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ Color font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
+ Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ int side_margin = get_theme_constant(SNAME("side_margin"));
// Find out start and width of the header area.
int header_x = side_margin;
@@ -529,7 +529,7 @@ void TabContainer::_notification(int p_what) {
text_buf.write[i]->clear();
}
_theme_changing = true;
- call_deferred("_on_theme_changed"); // Wait until all changed theme.
+ call_deferred(SNAME("_on_theme_changed")); // Wait until all changed theme.
} break;
}
}
@@ -537,10 +537,10 @@ void TabContainer::_notification(int p_what) {
void TabContainer::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x) {
Vector<Control *> tabs = _get_tabs();
RID canvas = get_canvas_item();
- Ref<Font> font = get_theme_font("font");
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
- int icon_text_distance = get_theme_constant("icon_separation");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
+ int icon_text_distance = get_theme_constant(SNAME("icon_separation"));
int tab_width = _get_tab_width(p_index);
int header_height = _get_top_margin();
@@ -580,8 +580,8 @@ void TabContainer::_refresh_texts() {
text_buf.clear();
Vector<Control *> tabs = _get_tabs();
bool rtl = is_layout_rtl();
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
for (int i = 0; i < tabs.size(); i++) {
Control *control = Object::cast_to<Control>(tabs[i]);
String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(tr(control->get_name()));
@@ -609,7 +609,7 @@ void TabContainer::_on_theme_changed() {
}
void TabContainer::_repaint() {
- Ref<StyleBox> sb = get_theme_stylebox("panel");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"));
Vector<Control *> tabs = _get_tabs();
for (int i = 0; i < tabs.size(); i++) {
Control *c = tabs[i];
@@ -646,8 +646,8 @@ int TabContainer::_get_tab_width(int p_index) const {
}
// Get the width of the text displayed on the tab.
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(tr(control->get_name()));
int width = font->get_string_size(text, font_size).width;
@@ -657,15 +657,15 @@ int TabContainer::_get_tab_width(int p_index) const {
if (icon.is_valid()) {
width += icon->get_width();
if (text != "") {
- width += get_theme_constant("icon_separation");
+ width += get_theme_constant(SNAME("icon_separation"));
}
}
}
// Respect a minimum size.
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
if (get_tab_disabled(p_index)) {
width += tab_disabled->get_minimum_size().width;
} else if (p_index == current) {
@@ -715,7 +715,7 @@ void TabContainer::add_child_notify(Node *p_child) {
c->hide();
} else {
c->show();
- //call_deferred("set_current_tab",0);
+ //call_deferred(SNAME("set_current_tab"),0);
first = true;
current = 0;
previous = 0;
@@ -724,7 +724,7 @@ void TabContainer::add_child_notify(Node *p_child) {
if (tabs_visible) {
c->set_offset(SIDE_TOP, _get_top_margin());
}
- Ref<StyleBox> sb = get_theme_stylebox("panel");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"));
c->set_offset(Side(SIDE_TOP), c->get_offset(Side(SIDE_TOP)) + sb->get_margin(Side(SIDE_TOP)));
c->set_offset(Side(SIDE_LEFT), c->get_offset(Side(SIDE_LEFT)) + sb->get_margin(Side(SIDE_LEFT)));
c->set_offset(Side(SIDE_RIGHT), c->get_offset(Side(SIDE_RIGHT)) - sb->get_margin(Side(SIDE_RIGHT)));
@@ -732,13 +732,13 @@ void TabContainer::add_child_notify(Node *p_child) {
update();
p_child->connect("renamed", callable_mp(this, &TabContainer::_child_renamed_callback));
if (first && is_inside_tree()) {
- emit_signal("tab_changed", current);
+ emit_signal(SNAME("tab_changed"), current);
}
}
void TabContainer::move_child_notify(Node *p_child) {
Container::move_child_notify(p_child);
- call_deferred("_update_current_tab");
+ call_deferred(SNAME("_update_current_tab"));
_refresh_texts();
update();
}
@@ -756,11 +756,11 @@ void TabContainer::set_current_tab(int p_current) {
_repaint();
if (pending_previous == current) {
- emit_signal("tab_selected", current);
+ emit_signal(SNAME("tab_selected"), current);
} else {
previous = pending_previous;
- emit_signal("tab_selected", current);
- emit_signal("tab_changed", current);
+ emit_signal(SNAME("tab_selected"), current);
+ emit_signal(SNAME("tab_changed"), current);
}
update();
@@ -799,7 +799,7 @@ void TabContainer::remove_child_notify(Node *p_child) {
return;
}
- call_deferred("_update_current_tab");
+ call_deferred(SNAME("_update_current_tab"));
p_child->disconnect("renamed", callable_mp(this, &TabContainer::_child_renamed_callback));
@@ -913,7 +913,7 @@ void TabContainer::drop_data(const Point2 &p_point, const Variant &p_data) {
}
move_child(moving_tabc, hover_now);
set_current_tab(hover_now);
- emit_signal("tab_changed", hover_now);
+ emit_signal(SNAME("tab_changed"), hover_now);
}
}
}
@@ -944,12 +944,12 @@ int TabContainer::get_tab_idx_at_point(const Point2 &p_point) const {
Popup *popup = get_popup();
if (popup) {
- Ref<Texture2D> menu = get_theme_icon("menu");
+ Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
button_ofs += menu->get_width();
}
if (buttons_visible_cache) {
- Ref<Texture2D> increment = get_theme_icon("increment");
- Ref<Texture2D> decrement = get_theme_icon("decrement");
+ Ref<Texture2D> increment = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decrement = get_theme_icon(SNAME("decrement"));
button_ofs += increment->get_width() + decrement->get_width();
}
if (px > size.width - button_ofs) {
@@ -1136,17 +1136,17 @@ Size2 TabContainer::get_minimum_size() const {
ms.y = MAX(ms.y, cms.y);
}
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
- Ref<Font> font = get_theme_font("font");
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
+ Ref<Font> font = get_theme_font(SNAME("font"));
if (tabs_visible) {
ms.y += MAX(MAX(tab_unselected->get_minimum_size().y, tab_selected->get_minimum_size().y), tab_disabled->get_minimum_size().y);
ms.y += _get_top_margin();
}
- Ref<StyleBox> sb = get_theme_stylebox("panel");
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"));
ms += sb->get_minimum_size();
return ms;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 6f1cff9ec8..9e8fe27ffb 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -38,9 +38,9 @@
#include "scene/gui/texture_rect.h"
Size2 Tabs::get_minimum_size() const {
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
int y_margin = MAX(MAX(tab_unselected->get_minimum_size().height, tab_selected->get_minimum_size().height), tab_disabled->get_minimum_size().height);
@@ -51,7 +51,7 @@ Size2 Tabs::get_minimum_size() const {
if (tex.is_valid()) {
ms.height = MAX(ms.height, tex->get_size().height);
if (tabs[i].text != "") {
- ms.width += get_theme_constant("hseparation");
+ ms.width += get_theme_constant(SNAME("hseparation"));
}
}
@@ -69,15 +69,15 @@ Size2 Tabs::get_minimum_size() const {
if (tabs[i].right_button.is_valid()) {
Ref<Texture2D> rb = tabs[i].right_button;
Size2 bms = rb->get_size();
- bms.width += get_theme_constant("hseparation");
+ bms.width += get_theme_constant(SNAME("hseparation"));
ms.width += bms.width;
ms.height = MAX(bms.height + tab_unselected->get_minimum_size().height, ms.height);
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<Texture2D> cb = get_theme_icon("close");
+ Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
Size2 bms = cb->get_size();
- bms.width += get_theme_constant("hseparation");
+ bms.width += get_theme_constant(SNAME("hseparation"));
ms.width += bms.width;
ms.height = MAX(bms.height + tab_unselected->get_minimum_size().height, ms.height);
}
@@ -100,8 +100,8 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
highlight_arrow = -1;
if (buttons_visible) {
- Ref<Texture2D> incr = get_theme_icon("increment");
- Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
if (is_layout_rtl()) {
if (pos.x < decr->get_width()) {
@@ -148,7 +148,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (rb_hover != -1) {
//pressed
- emit_signal("right_button_pressed", rb_hover);
+ emit_signal(SNAME("right_button_pressed"), rb_hover);
}
rb_pressing = false;
@@ -158,7 +158,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (cb_hover != -1) {
//pressed
- emit_signal("tab_closed", cb_hover);
+ emit_signal(SNAME("tab_closed"), cb_hover);
}
cb_pressing = false;
@@ -170,8 +170,8 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
Point2 pos(mb->get_position().x, mb->get_position().y);
if (buttons_visible) {
- Ref<Texture2D> incr = get_theme_icon("increment");
- Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
if (is_layout_rtl()) {
if (pos.x < decr->get_width()) {
@@ -229,15 +229,15 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
if (found != -1) {
set_current_tab(found);
- emit_signal("tab_clicked", found);
+ emit_signal(SNAME("tab_clicked"), found);
}
}
}
}
void Tabs::_shape(int p_tab) {
- Ref<Font> font = get_theme_font("font");
- int font_size = get_theme_font_size("font_size");
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
tabs.write[p_tab].xl_text = tr(tabs[p_tab].text);
tabs.write[p_tab].text_buf->clear();
@@ -274,15 +274,15 @@ void Tabs::_notification(int p_what) {
_update_cache();
RID ci = get_canvas_item();
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
- Color font_selected_color = get_theme_color("font_selected_color");
- Color font_unselected_color = get_theme_color("font_unselected_color");
- Color font_disabled_color = get_theme_color("font_disabled_color");
- Ref<Texture2D> close = get_theme_icon("close");
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
+ Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ Color font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
+ Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ Ref<Texture2D> close = get_theme_icon(SNAME("close"));
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
Vector2 size = get_size();
bool rtl = is_layout_rtl();
@@ -306,10 +306,10 @@ void Tabs::_notification(int p_what) {
w = 0;
}
- Ref<Texture2D> incr = get_theme_icon("increment");
- Ref<Texture2D> decr = get_theme_icon("decrement");
- Ref<Texture2D> incr_hl = get_theme_icon("increment_highlight");
- Ref<Texture2D> decr_hl = get_theme_icon("decrement_highlight");
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
+ Ref<Texture2D> incr_hl = get_theme_icon(SNAME("increment_highlight"));
+ Ref<Texture2D> decr_hl = get_theme_icon(SNAME("decrement_highlight"));
int limit = get_size().width;
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
@@ -363,7 +363,7 @@ void Tabs::_notification(int p_what) {
icon->draw(ci, Point2i(w, sb->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
}
if (tabs[i].text != "") {
- w += icon->get_width() + get_theme_constant("hseparation");
+ w += icon->get_width() + get_theme_constant(SNAME("hseparation"));
}
}
@@ -384,10 +384,10 @@ void Tabs::_notification(int p_what) {
w += tabs[i].size_text;
if (tabs[i].right_button.is_valid()) {
- Ref<StyleBox> style = get_theme_stylebox("button");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("button"));
Ref<Texture2D> rb = tabs[i].right_button;
- w += get_theme_constant("hseparation");
+ w += get_theme_constant(SNAME("hseparation"));
Rect2 rb_rect;
rb_rect.size = style->get_minimum_size() + rb->get_size();
@@ -400,7 +400,7 @@ void Tabs::_notification(int p_what) {
if (rb_hover == i) {
if (rb_pressing) {
- get_theme_stylebox("button_pressed")->draw(ci, rb_rect);
+ get_theme_stylebox(SNAME("button_pressed"))->draw(ci, rb_rect);
} else {
style->draw(ci, rb_rect);
}
@@ -416,10 +416,10 @@ void Tabs::_notification(int p_what) {
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<StyleBox> style = get_theme_stylebox("button");
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("button"));
Ref<Texture2D> cb = close;
- w += get_theme_constant("hseparation");
+ w += get_theme_constant(SNAME("hseparation"));
Rect2 cb_rect;
cb_rect.size = style->get_minimum_size() + cb->get_size();
@@ -432,7 +432,7 @@ void Tabs::_notification(int p_what) {
if (!tabs[i].disabled && cb_hover == i) {
if (cb_pressing) {
- get_theme_stylebox("button_pressed")->draw(ci, cb_rect);
+ get_theme_stylebox(SNAME("button_pressed"))->draw(ci, cb_rect);
} else {
style->draw(ci, cb_rect);
}
@@ -503,7 +503,7 @@ void Tabs::set_current_tab(int p_current) {
_update_cache();
update();
- emit_signal("tab_changed", p_current);
+ emit_signal(SNAME("tab_changed"), p_current);
}
int Tabs::get_current_tab() const {
@@ -659,7 +659,7 @@ void Tabs::_update_hover() {
}
if (hover != hover_now) {
hover = hover_now;
- emit_signal("tab_hovered", hover);
+ emit_signal(SNAME("tab_hovered"), hover);
}
if (hover_buttons == -1) { // no hover
@@ -669,11 +669,11 @@ void Tabs::_update_hover() {
}
void Tabs::_update_cache() {
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<Texture2D> incr = get_theme_icon("increment");
- Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
int w = 0;
@@ -712,12 +712,12 @@ void Tabs::_update_cache() {
slen = m_width - (sb->get_margin(SIDE_LEFT) + sb->get_margin(SIDE_RIGHT));
if (tabs[i].icon.is_valid()) {
slen -= tabs[i].icon->get_width();
- slen -= get_theme_constant("hseparation");
+ slen -= get_theme_constant(SNAME("hseparation"));
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<Texture2D> cb = get_theme_icon("close");
+ Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
slen -= cb->get_width();
- slen -= get_theme_constant("hseparation");
+ slen -= get_theme_constant(SNAME("hseparation"));
}
slen = MAX(slen, 1);
lsize = m_width;
@@ -745,7 +745,7 @@ void Tabs::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
t.xl_text = tr(p_str);
t.text_buf.instantiate();
t.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
- t.text_buf->add_string(t.xl_text, get_theme_font("font"), get_theme_font_size("font_size"), Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ t.text_buf->add_string(t.xl_text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
t.icon = p_icon;
t.disabled = false;
t.ofs_cache = 0;
@@ -753,7 +753,7 @@ void Tabs::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
tabs.push_back(t);
_update_cache();
- call_deferred("_update_hover");
+ call_deferred(SNAME("_update_hover"));
update();
minimum_size_changed();
}
@@ -762,7 +762,7 @@ void Tabs::clear_tabs() {
tabs.clear();
current = 0;
previous = 0;
- call_deferred("_update_hover");
+ call_deferred(SNAME("_update_hover"));
update();
}
@@ -773,7 +773,7 @@ void Tabs::remove_tab(int p_idx) {
current--;
}
_update_cache();
- call_deferred("_update_hover");
+ call_deferred(SNAME("_update_hover"));
update();
minimum_size_changed();
@@ -870,7 +870,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
hover_now = get_tab_count() - 1;
}
move_tab(tab_from_id, hover_now);
- emit_signal("reposition_active_tab_request", hover_now);
+ emit_signal(SNAME("reposition_active_tab_request"), hover_now);
set_current_tab(hover_now);
} else if (get_tabs_rearrange_group() != -1) {
// drag and drop between Tabs
@@ -887,7 +887,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
tabs.insert(hover_now, moving_tab);
from_tabs->remove_tab(tab_from_id);
set_current_tab(hover_now);
- emit_signal("tab_changed", hover_now);
+ emit_signal(SNAME("tab_changed"), hover_now);
_update_cache();
}
}
@@ -949,9 +949,9 @@ void Tabs::move_tab(int from, int to) {
int Tabs::get_tab_width(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0);
- Ref<StyleBox> tab_unselected = get_theme_stylebox("tab_unselected");
- Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
- Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
+ Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
+ Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
int x = 0;
@@ -959,7 +959,7 @@ int Tabs::get_tab_width(int p_idx) const {
if (tex.is_valid()) {
x += tex->get_width();
if (tabs[p_idx].text != "") {
- x += get_theme_constant("hseparation");
+ x += get_theme_constant(SNAME("hseparation"));
}
}
@@ -976,13 +976,13 @@ int Tabs::get_tab_width(int p_idx) const {
if (tabs[p_idx].right_button.is_valid()) {
Ref<Texture2D> rb = tabs[p_idx].right_button;
x += rb->get_width();
- x += get_theme_constant("hseparation");
+ x += get_theme_constant(SNAME("hseparation"));
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current)) {
- Ref<Texture2D> cb = get_theme_icon("close");
+ Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
x += cb->get_width();
- x += get_theme_constant("hseparation");
+ x += get_theme_constant(SNAME("hseparation"));
}
return x;
@@ -993,8 +993,8 @@ void Tabs::_ensure_no_over_offset() {
return;
}
- Ref<Texture2D> incr = get_theme_icon("increment");
- Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
int limit = get_size().width;
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
@@ -1034,8 +1034,8 @@ void Tabs::ensure_tab_visible(int p_idx) {
}
int prev_offset = offset;
- Ref<Texture2D> incr = get_theme_icon("increment");
- Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
int limit = get_size().width;
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 370fdd8b88..be3edccc99 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -542,8 +542,8 @@ void TextEdit::_notification(int p_what) {
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
if (is_visible()) {
- call_deferred("_update_scrollbars");
- call_deferred("_update_wrap_at");
+ call_deferred(SNAME("_update_scrollbars"));
+ call_deferred(SNAME("_update_wrap_at"));
}
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
@@ -599,7 +599,7 @@ void TextEdit::_notification(int p_what) {
Size2 size = get_size();
bool rtl = is_layout_rtl();
- if ((!has_focus() && !menu->has_focus()) || !window_has_focus) {
+ if ((!has_focus() && !(menu && menu->has_focus())) || !window_has_focus) {
draw_caret = false;
}
@@ -1119,7 +1119,7 @@ void TextEdit::_notification(int p_what) {
}
tl->draw(ci, Point2(gutter_offset + ofs_x, yofs), get_line_gutter_item_color(line, g));
} break;
- case GUTTER_TPYE_ICON: {
+ case GUTTER_TYPE_ICON: {
const Ref<Texture2D> icon = get_line_gutter_icon(line, g);
if (icon.is_null()) {
break;
@@ -1147,7 +1147,7 @@ void TextEdit::_notification(int p_what) {
icon->draw_rect(ci, gutter_rect, false, get_line_gutter_item_color(line, g));
} break;
- case GUTTER_TPYE_CUSTOM: {
+ case GUTTER_TYPE_CUSTOM: {
if (gutter.custom_draw_obj.is_valid()) {
Object *cdo = ObjectDB::get_instance(gutter.custom_draw_obj);
if (cdo) {
@@ -2361,7 +2361,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (mpos.x > left_margin && mpos.x <= (left_margin + gutters[i].width) - 3) {
- emit_signal("gutter_clicked", row, i);
+ emit_signal(SNAME("gutter_clicked"), row, i);
return;
}
@@ -2470,9 +2470,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+ _ensure_menu();
menu->set_position(get_screen_transform().xform(mpos));
menu->set_size(Vector2(1, 1));
- _generate_context_menu();
menu->popup();
grab_focus();
}
@@ -2482,7 +2482,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
int row, col;
_get_mouse_pos(Point2i(mpos.x, mpos.y), row, col);
- emit_signal("symbol_lookup", highlighted_word, row, col);
+ emit_signal(SNAME("symbol_lookup"), highlighted_word, row, col);
return;
}
@@ -2524,7 +2524,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (!dragging_minimap && !dragging_selection && mm->is_command_pressed() && mm->get_button_mask() == 0) {
String new_word = get_word_at_pos(mpos);
if (new_word != highlighted_word) {
- emit_signal("symbol_validate", new_word);
+ emit_signal(SNAME("symbol_validate"), new_word);
}
} else {
if (highlighted_word != String()) {
@@ -2575,7 +2575,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (select_identifiers_enabled) {
if (k->is_pressed() && !dragging_minimap && !dragging_selection) {
Point2 mp = _get_local_mouse_pos();
- emit_signal("symbol_validate", get_word_at_pos(mp));
+ emit_signal(SNAME("symbol_validate"), get_word_at_pos(mp));
} else {
set_highlighted_word(String());
}
@@ -2709,9 +2709,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// MISC.
if (k->is_action("ui_menu", true)) {
if (context_menu_enabled) {
+ _ensure_menu();
menu->set_position(get_screen_transform().xform(_get_cursor_pixel_pos()));
menu->set_size(Vector2(1, 1));
- _generate_context_menu();
menu->popup();
menu->grab_focus();
}
@@ -2990,7 +2990,7 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
}
text_changed_dirty = true;
}
- emit_signal("lines_edited_from", p_line, r_end_line);
+ emit_signal(SNAME("lines_edited_from"), p_line, r_end_line);
}
String TextEdit::_base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const {
@@ -3041,7 +3041,7 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li
}
text_changed_dirty = true;
}
- emit_signal("lines_edited_from", p_to_line, p_from_line);
+ emit_signal(SNAME("lines_edited_from"), p_to_line, p_from_line);
}
void TextEdit::_insert_text(int p_line, int p_char, const String &p_text, int *r_end_line, int *r_end_char) {
@@ -3212,35 +3212,6 @@ int TextEdit::_get_menu_action_accelerator(const String &p_action) {
}
}
-void TextEdit::_generate_context_menu() {
- // Reorganize context menu.
- menu->clear();
- if (!readonly) {
- menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0);
- }
- menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0);
- if (!readonly) {
- menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0);
- }
- menu->add_separator();
- if (is_selecting_enabled()) {
- menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0);
- }
- if (!readonly) {
- menu->add_item(RTR("Clear"), MENU_CLEAR);
- menu->add_separator();
- menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0);
- menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
- }
- menu->add_separator();
- menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
- menu->add_separator();
- menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC);
- if (!readonly) {
- menu->add_submenu_item(RTR("Insert control character"), "CTLMenu");
- }
-}
-
int TextEdit::get_visible_rows() const {
return _get_control_height() / get_row_height();
}
@@ -3858,10 +3829,12 @@ void TextEdit::set_text_direction(Control::TextDirection p_text_direction) {
text.set_direction_and_language(dir, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
text.invalidate_all();
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+ if (menu_dir) {
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+ }
update();
}
}
@@ -3917,7 +3890,9 @@ String TextEdit::get_language() const {
void TextEdit::set_draw_control_chars(bool p_draw_control_chars) {
if (draw_control_chars != p_draw_control_chars) {
draw_control_chars = p_draw_control_chars;
- menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
+ if (menu && menu->get_item_index(MENU_DISPLAY_UCC) >= 0) {
+ menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
+ }
text.set_draw_control_chars(draw_control_chars);
text.invalidate_all();
update();
@@ -3988,7 +3963,6 @@ void TextEdit::set_readonly(bool p_readonly) {
}
readonly = p_readonly;
- _generate_context_menu();
update();
}
@@ -4008,14 +3982,6 @@ bool TextEdit::is_wrap_enabled() const {
return wrap_enabled;
}
-void TextEdit::set_max_chars(int p_max_chars) {
- max_chars = p_max_chars;
-}
-
-int TextEdit::get_max_chars() const {
- return max_chars;
-}
-
void TextEdit::_reset_caret_blink_timer() {
if (caret_blink_enabled) {
draw_caret = true;
@@ -4035,35 +4001,35 @@ void TextEdit::_toggle_draw_caret() {
}
void TextEdit::_update_caches() {
- cache.style_normal = get_theme_stylebox("normal");
- cache.style_focus = get_theme_stylebox("focus");
- cache.style_readonly = get_theme_stylebox("read_only");
- cache.font = get_theme_font("font");
- cache.font_size = get_theme_font_size("font_size");
- cache.outline_color = get_theme_color("font_outline_color");
- cache.outline_size = get_theme_constant("outline_size");
- cache.caret_color = get_theme_color("caret_color");
- cache.caret_background_color = get_theme_color("caret_background_color");
- cache.font_color = get_theme_color("font_color");
- cache.font_selected_color = get_theme_color("font_selected_color");
- cache.font_readonly_color = get_theme_color("font_readonly_color");
- cache.selection_color = get_theme_color("selection_color");
- cache.current_line_color = get_theme_color("current_line_color");
- cache.line_length_guideline_color = get_theme_color("line_length_guideline_color");
- cache.code_folding_color = get_theme_color("code_folding_color", "CodeEdit");
- cache.brace_mismatch_color = get_theme_color("brace_mismatch_color");
- cache.word_highlighted_color = get_theme_color("word_highlighted_color");
- cache.search_result_color = get_theme_color("search_result_color");
- cache.search_result_border_color = get_theme_color("search_result_border_color");
- cache.background_color = get_theme_color("background_color");
+ cache.style_normal = get_theme_stylebox(SNAME("normal"));
+ cache.style_focus = get_theme_stylebox(SNAME("focus"));
+ cache.style_readonly = get_theme_stylebox(SNAME("read_only"));
+ cache.font = get_theme_font(SNAME("font"));
+ cache.font_size = get_theme_font_size(SNAME("font_size"));
+ cache.outline_color = get_theme_color(SNAME("font_outline_color"));
+ cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ cache.caret_color = get_theme_color(SNAME("caret_color"));
+ cache.caret_background_color = get_theme_color(SNAME("caret_background_color"));
+ cache.font_color = get_theme_color(SNAME("font_color"));
+ cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ cache.font_readonly_color = get_theme_color(SNAME("font_readonly_color"));
+ cache.selection_color = get_theme_color(SNAME("selection_color"));
+ cache.current_line_color = get_theme_color(SNAME("current_line_color"));
+ cache.line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color"));
+ cache.code_folding_color = get_theme_color(SNAME("code_folding_color"), SNAME("CodeEdit"));
+ cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"));
+ cache.word_highlighted_color = get_theme_color(SNAME("word_highlighted_color"));
+ cache.search_result_color = get_theme_color(SNAME("search_result_color"));
+ cache.search_result_border_color = get_theme_color(SNAME("search_result_border_color"));
+ cache.background_color = get_theme_color(SNAME("background_color"));
#ifdef TOOLS_ENABLED
- cache.line_spacing = get_theme_constant("line_spacing") * EDSCALE;
+ cache.line_spacing = get_theme_constant(SNAME("line_spacing")) * EDSCALE;
#else
- cache.line_spacing = get_theme_constant("line_spacing");
+ cache.line_spacing = get_theme_constant(SNAME("line_spacing"));
#endif
- cache.tab_icon = get_theme_icon("tab");
- cache.space_icon = get_theme_icon("space");
- cache.folded_eol_icon = get_theme_icon("folded_eol_icon", "CodeEdit");
+ cache.tab_icon = get_theme_icon(SNAME("tab"));
+ cache.space_icon = get_theme_icon(SNAME("space"));
+ cache.folded_eol_icon = get_theme_icon(SNAME("folded_eol_icon"), SNAME("CodeEdit"));
TextServer::Direction dir;
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
@@ -4120,7 +4086,7 @@ void TextEdit::add_gutter(int p_at) {
for (int i = 0; i < text.size() + 1; i++) {
text.add_gutter(p_at);
}
- emit_signal("gutter_added");
+ emit_signal(SNAME("gutter_added"));
update();
}
@@ -4132,7 +4098,7 @@ void TextEdit::remove_gutter(int p_gutter) {
for (int i = 0; i < text.size() + 1; i++) {
text.remove_gutter(p_gutter);
}
- emit_signal("gutter_removed");
+ emit_signal(SNAME("gutter_removed"));
update();
}
@@ -4756,12 +4722,12 @@ bool TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_from_l
}
void TextEdit::_cursor_changed_emit() {
- emit_signal("cursor_changed");
+ emit_signal(SNAME("cursor_changed"));
cursor_changed_dirty = false;
}
void TextEdit::_text_changed_emit() {
- emit_signal("text_changed");
+ emit_signal(SNAME("text_changed"));
text_changed_dirty = false;
}
@@ -5572,8 +5538,6 @@ bool TextEdit::is_context_menu_enabled() {
void TextEdit::set_shortcut_keys_enabled(bool p_enabled) {
shortcut_keys_enabled = p_enabled;
-
- _generate_context_menu();
}
void TextEdit::set_virtual_keyboard_enabled(bool p_enable) {
@@ -5586,8 +5550,6 @@ void TextEdit::set_selecting_enabled(bool p_enabled) {
if (!selecting_enabled) {
deselect();
}
-
- _generate_context_menu();
}
bool TextEdit::is_selecting_enabled() const {
@@ -5602,7 +5564,12 @@ bool TextEdit::is_virtual_keyboard_enabled() const {
return virtual_keyboard_enabled;
}
+bool TextEdit::is_menu_visible() const {
+ return menu && menu->is_visible();
+}
+
PopupMenu *TextEdit::get_menu() const {
+ const_cast<TextEdit *>(this)->_ensure_menu();
return menu;
}
@@ -5790,8 +5757,8 @@ void TextEdit::_bind_methods() {
/* Gutters. */
BIND_ENUM_CONSTANT(GUTTER_TYPE_STRING);
- BIND_ENUM_CONSTANT(GUTTER_TPYE_ICON);
- BIND_ENUM_CONSTANT(GUTTER_TPYE_CUSTOM);
+ BIND_ENUM_CONSTANT(GUTTER_TYPE_ICON);
+ BIND_ENUM_CONSTANT(GUTTER_TYPE_CUSTOM);
ClassDB::bind_method(D_METHOD("add_gutter", "at"), &TextEdit::add_gutter, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("remove_gutter", "gutter"), &TextEdit::remove_gutter);
@@ -5841,6 +5808,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu);
+ ClassDB::bind_method(D_METHOD("is_menu_visible"), &TextEdit::is_menu_visible);
ClassDB::bind_method(D_METHOD("draw_minimap", "draw"), &TextEdit::set_draw_minimap);
ClassDB::bind_method(D_METHOD("is_drawing_minimap"), &TextEdit::is_drawing_minimap);
@@ -5929,6 +5897,79 @@ void TextEdit::_bind_methods() {
ProjectSettings::get_singleton()->set_custom_property_info("gui/common/text_edit_undo_stack_max_size", PropertyInfo(Variant::INT, "gui/common/text_edit_undo_stack_max_size", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); // No negative numbers.
}
+void TextEdit::_ensure_menu() {
+ if (!menu) {
+ menu = memnew(PopupMenu);
+ add_child(menu);
+
+ menu_dir = memnew(PopupMenu);
+ menu_dir->set_name("DirMenu");
+ menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED);
+ menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO);
+ menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR);
+ menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL);
+ menu->add_child(menu_dir);
+
+ menu_ctl = memnew(PopupMenu);
+ menu_ctl->set_name("CTLMenu");
+ menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM);
+ menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM);
+ menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE);
+ menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE);
+ menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO);
+ menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO);
+ menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM);
+ menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI);
+ menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI);
+ menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI);
+ menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ);
+ menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
+ menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ);
+ menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
+ menu->add_child(menu_ctl);
+
+ menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
+ menu_dir->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
+ menu_ctl->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
+ }
+
+ // Reorganize context menu.
+ menu->clear();
+ if (!readonly) {
+ menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0);
+ }
+ menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0);
+ if (!readonly) {
+ menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0);
+ }
+ menu->add_separator();
+ if (is_selecting_enabled()) {
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0);
+ }
+ if (!readonly) {
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
+ menu->add_separator();
+ menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0);
+ menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
+ }
+ menu->add_separator();
+ menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
+ menu->add_separator();
+ menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC);
+ menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
+ if (!readonly) {
+ menu->add_submenu_item(RTR("Insert control character"), "CTLMenu");
+ }
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
+ menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+}
+
TextEdit::TextEdit() {
clear();
set_focus_mode(FOCUS_ALL);
@@ -5968,44 +6009,7 @@ TextEdit::TextEdit() {
undo_stack_max_size = GLOBAL_GET("gui/common/text_edit_undo_stack_max_size");
- menu = memnew(PopupMenu);
- add_child(menu);
-
- menu_dir = memnew(PopupMenu);
- menu_dir->set_name("DirMenu");
- menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED);
- menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO);
- menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR);
- menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL);
- menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), true);
- menu->add_child(menu_dir);
-
- menu_ctl = memnew(PopupMenu);
- menu_ctl->set_name("CTLMenu");
- menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM);
- menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM);
- menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE);
- menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE);
- menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO);
- menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO);
- menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM);
- menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI);
- menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI);
- menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI);
- menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ);
- menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
- menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ);
- menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
- menu->add_child(menu_ctl);
-
set_readonly(false);
- menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
- menu_dir->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
- menu_ctl->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
}
TextEdit::~TextEdit() {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 146de50275..62d576b48a 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -44,8 +44,8 @@ class TextEdit : public Control {
public:
enum GutterType {
GUTTER_TYPE_STRING,
- GUTTER_TPYE_ICON,
- GUTTER_TPYE_CUSTOM
+ GUTTER_TYPE_ICON,
+ GUTTER_TYPE_CUSTOM
};
enum SelectionMode {
@@ -258,7 +258,6 @@ private:
uint32_t version = 0;
uint32_t saved_version = 0;
- int max_chars = 0;
bool readonly = true; // Initialise to opposite first, so we get past the early-out in set_readonly.
Timer *caret_blink_timer;
@@ -337,8 +336,6 @@ private:
bool shortcut_keys_enabled = true;
bool virtual_keyboard_enabled = true;
- void _generate_context_menu();
-
int get_visible_rows() const;
int get_total_visible_rows() const;
@@ -411,9 +408,11 @@ private:
Dictionary _search_bind(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const;
- PopupMenu *menu;
- PopupMenu *menu_dir;
- PopupMenu *menu_ctl;
+ PopupMenu *menu = nullptr;
+ PopupMenu *menu_dir = nullptr;
+ PopupMenu *menu_ctl = nullptr;
+
+ void _ensure_menu();
void _clear();
@@ -678,9 +677,6 @@ public:
void set_readonly(bool p_readonly);
bool is_readonly() const;
- void set_max_chars(int p_max_chars);
- int get_max_chars() const;
-
void set_wrap_enabled(bool p_wrap_enabled);
bool is_wrap_enabled() const;
bool line_wraps(int line) const;
@@ -785,6 +781,7 @@ public:
void set_virtual_keyboard_enabled(bool p_enable);
bool is_virtual_keyboard_enabled() const;
+ bool is_menu_visible() const;
PopupMenu *get_menu() const;
String get_text_for_lookup_completion();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index f677b3592a..09db3205d9 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -99,39 +99,44 @@ void TreeItem::_change_tree(Tree *p_tree) {
c = c->next;
}
- if (tree && tree->root == this) {
- tree->root = nullptr;
- }
+ if (tree) {
+ if (tree->root == this) {
+ tree->root = nullptr;
+ }
- if (tree && tree->popup_edited_item == this) {
- tree->popup_edited_item = nullptr;
- tree->pressing_for_editor = false;
- }
+ if (tree->popup_edited_item == this) {
+ tree->popup_edited_item = nullptr;
+ tree->pressing_for_editor = false;
+ }
- if (tree && tree->cache.hover_item == this) {
- tree->cache.hover_item = nullptr;
- }
+ if (tree->cache.hover_item == this) {
+ tree->cache.hover_item = nullptr;
+ }
- if (tree && tree->selected_item == this) {
- tree->selected_item = nullptr;
- }
+ if (tree->selected_item == this) {
+ tree->selected_item = nullptr;
+ }
- if (tree && tree->drop_mode_over == this) {
- tree->drop_mode_over = nullptr;
- }
+ if (tree->drop_mode_over == this) {
+ tree->drop_mode_over = nullptr;
+ }
- if (tree && tree->single_select_defer == this) {
- tree->single_select_defer = nullptr;
- }
+ if (tree->single_select_defer == this) {
+ tree->single_select_defer = nullptr;
+ }
+
+ if (tree->edited_item == this) {
+ tree->edited_item = nullptr;
+ tree->pressing_for_editor = false;
+ }
- if (tree && tree->edited_item == this) {
- tree->edited_item = nullptr;
- tree->pressing_for_editor = false;
+ tree->update();
}
tree = p_tree;
if (tree) {
+ tree->update();
cells.resize(tree->columns.size());
}
}
@@ -411,7 +416,7 @@ void TreeItem::set_collapsed(bool p_collapsed) {
if (tree->select_mode == Tree::SELECT_MULTI) {
tree->selected_item = this;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
} else {
select(tree->selected_col);
}
@@ -421,7 +426,7 @@ void TreeItem::set_collapsed(bool p_collapsed) {
}
_changed_notify();
- tree->emit_signal("item_collapsed", this);
+ tree->emit_signal(SNAME("item_collapsed"), this);
}
bool TreeItem::is_collapsed() {
@@ -451,6 +456,7 @@ TreeItem *TreeItem::create_child(int p_idx) {
TreeItem *ti = memnew(TreeItem(tree));
if (tree) {
ti->cells.resize(tree->columns.size());
+ tree->update();
}
TreeItem *l_prev = nullptr;
@@ -489,11 +495,11 @@ TreeItem *TreeItem::create_child(int p_idx) {
return ti;
}
-Tree *TreeItem::get_tree() {
+Tree *TreeItem::get_tree() const {
return tree;
}
-TreeItem *TreeItem::get_next() {
+TreeItem *TreeItem::get_next() const {
return next;
}
@@ -516,11 +522,11 @@ TreeItem *TreeItem::get_prev() {
return prev;
}
-TreeItem *TreeItem::get_parent() {
+TreeItem *TreeItem::get_parent() const {
return parent;
}
-TreeItem *TreeItem::get_first_child() {
+TreeItem *TreeItem::get_first_child() const {
return first_child;
}
@@ -654,11 +660,7 @@ void TreeItem::move_before(TreeItem *p_item) {
next = p_item;
p_item->prev = this;
- if (old_tree && old_tree != tree) {
- old_tree->update();
- }
-
- if (tree) {
+ if (tree && old_tree == tree) {
tree->update();
}
}
@@ -696,11 +698,7 @@ void TreeItem::move_after(TreeItem *p_item) {
parent->children_cache.append(this);
}
- if (old_tree && old_tree != tree) {
- old_tree->update();
- }
-
- if (tree) {
+ if (tree && old_tree == tree) {
tree->update();
}
}
@@ -953,6 +951,56 @@ bool TreeItem::is_folding_disabled() const {
return disable_folding;
}
+Size2 TreeItem::get_minimum_size(int p_column) {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), Size2());
+ Tree *tree = get_tree();
+ ERR_FAIL_COND_V(!tree, Size2());
+
+ Size2 size;
+
+ // Default offset?
+ //size.width += (disable_folding || tree->hide_folding) ? tree->cache.hseparation : tree->cache.item_margin;
+
+ // Text.
+ const TreeItem::Cell &cell = cells[p_column];
+ if (!cell.text.is_empty()) {
+ if (cell.dirty) {
+ tree->update_item_cell(this, p_column);
+ }
+ Size2 text_size = cell.text_buf->get_size();
+ size.width += text_size.width;
+ size.height = MAX(size.height, text_size.height);
+ }
+
+ // Icon.
+ if (cell.mode == CELL_MODE_CHECK) {
+ size.width += tree->cache.checked->get_width() + tree->cache.hseparation;
+ }
+ if (cell.icon.is_valid()) {
+ Size2i icon_size = cell.get_icon_size();
+ if (cell.icon_max_w > 0 && icon_size.width > cell.icon_max_w) {
+ icon_size.width = cell.icon_max_w;
+ }
+ size.width += icon_size.width + tree->cache.hseparation;
+ size.height = MAX(size.height, icon_size.height);
+ }
+
+ // Buttons.
+ for (int i = 0; i < cell.buttons.size(); i++) {
+ Ref<Texture2D> texture = cell.buttons[i].texture;
+ if (texture.is_valid()) {
+ Size2 button_size = texture->get_size() + tree->cache.button_pressed->get_minimum_size();
+ size.width += button_size.width;
+ size.height = MAX(size.height, button_size.height);
+ }
+ }
+ if (cell.buttons.size() >= 2) {
+ size.width += (cell.buttons.size() - 1) * tree->cache.button_margin;
+ }
+
+ return size;
+}
+
Variant TreeItem::_call_recursive_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
@@ -1167,59 +1215,62 @@ TreeItem::~TreeItem() {
/**********************************************/
void Tree::update_cache() {
- cache.font = get_theme_font("font");
- cache.font_size = get_theme_font_size("font_size");
- cache.tb_font = get_theme_font("title_button_font");
- cache.tb_font_size = get_theme_font_size("title_button_font_size");
- cache.bg = get_theme_stylebox("bg");
- cache.selected = get_theme_stylebox("selected");
- cache.selected_focus = get_theme_stylebox("selected_focus");
- cache.cursor = get_theme_stylebox("cursor");
- cache.cursor_unfocus = get_theme_stylebox("cursor_unfocused");
- cache.button_pressed = get_theme_stylebox("button_pressed");
-
- cache.checked = get_theme_icon("checked");
- cache.unchecked = get_theme_icon("unchecked");
+ cache.font = get_theme_font(SNAME("font"));
+ cache.font_size = get_theme_font_size(SNAME("font_size"));
+ cache.tb_font = get_theme_font(SNAME("title_button_font"));
+ cache.tb_font_size = get_theme_font_size(SNAME("title_button_font_size"));
+ cache.bg = get_theme_stylebox(SNAME("bg"));
+ cache.selected = get_theme_stylebox(SNAME("selected"));
+ cache.selected_focus = get_theme_stylebox(SNAME("selected_focus"));
+ cache.cursor = get_theme_stylebox(SNAME("cursor"));
+ cache.cursor_unfocus = get_theme_stylebox(SNAME("cursor_unfocused"));
+ cache.button_pressed = get_theme_stylebox(SNAME("button_pressed"));
+
+ cache.checked = get_theme_icon(SNAME("checked"));
+ cache.unchecked = get_theme_icon(SNAME("unchecked"));
if (is_layout_rtl()) {
- cache.arrow_collapsed = get_theme_icon("arrow_collapsed_mirrored");
+ cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
} else {
- cache.arrow_collapsed = get_theme_icon("arrow_collapsed");
- }
- cache.arrow = get_theme_icon("arrow");
- cache.select_arrow = get_theme_icon("select_arrow");
- cache.updown = get_theme_icon("updown");
-
- cache.custom_button = get_theme_stylebox("custom_button");
- cache.custom_button_hover = get_theme_stylebox("custom_button_hover");
- cache.custom_button_pressed = get_theme_stylebox("custom_button_pressed");
- cache.custom_button_font_highlight = get_theme_color("custom_button_font_highlight");
-
- cache.font_color = get_theme_color("font_color");
- cache.font_selected_color = get_theme_color("font_selected_color");
- cache.drop_position_color = get_theme_color("drop_position_color");
- cache.hseparation = get_theme_constant("hseparation");
- cache.vseparation = get_theme_constant("vseparation");
- cache.item_margin = get_theme_constant("item_margin");
- cache.button_margin = get_theme_constant("button_margin");
-
- cache.draw_guides = get_theme_constant("draw_guides");
- cache.guide_color = get_theme_color("guide_color");
- cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines");
- cache.relationship_line_width = get_theme_constant("relationship_line_width");
- cache.parent_hl_line_width = get_theme_constant("parent_hl_line_width");
- cache.children_hl_line_width = get_theme_constant("children_hl_line_width");
- cache.parent_hl_line_margin = get_theme_constant("parent_hl_line_margin");
- cache.relationship_line_color = get_theme_color("relationship_line_color");
- cache.parent_hl_line_color = get_theme_color("parent_hl_line_color");
- cache.children_hl_line_color = get_theme_color("children_hl_line_color");
-
- cache.scroll_border = get_theme_constant("scroll_border");
- cache.scroll_speed = get_theme_constant("scroll_speed");
-
- cache.title_button = get_theme_stylebox("title_button_normal");
- cache.title_button_pressed = get_theme_stylebox("title_button_pressed");
- cache.title_button_hover = get_theme_stylebox("title_button_hover");
- cache.title_button_color = get_theme_color("title_button_color");
+ cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed"));
+ }
+ cache.arrow = get_theme_icon(SNAME("arrow"));
+ cache.select_arrow = get_theme_icon(SNAME("select_arrow"));
+ cache.updown = get_theme_icon(SNAME("updown"));
+
+ cache.custom_button = get_theme_stylebox(SNAME("custom_button"));
+ cache.custom_button_hover = get_theme_stylebox(SNAME("custom_button_hover"));
+ cache.custom_button_pressed = get_theme_stylebox(SNAME("custom_button_pressed"));
+ cache.custom_button_font_highlight = get_theme_color(SNAME("custom_button_font_highlight"));
+
+ cache.font_color = get_theme_color(SNAME("font_color"));
+ cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
+ cache.hseparation = get_theme_constant(SNAME("hseparation"));
+ cache.vseparation = get_theme_constant(SNAME("vseparation"));
+ cache.item_margin = get_theme_constant(SNAME("item_margin"));
+ cache.button_margin = get_theme_constant(SNAME("button_margin"));
+
+ cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+
+ cache.draw_guides = get_theme_constant(SNAME("draw_guides"));
+ cache.guide_color = get_theme_color(SNAME("guide_color"));
+ cache.draw_relationship_lines = get_theme_constant(SNAME("draw_relationship_lines"));
+ cache.relationship_line_width = get_theme_constant(SNAME("relationship_line_width"));
+ cache.parent_hl_line_width = get_theme_constant(SNAME("parent_hl_line_width"));
+ cache.children_hl_line_width = get_theme_constant(SNAME("children_hl_line_width"));
+ cache.parent_hl_line_margin = get_theme_constant(SNAME("parent_hl_line_margin"));
+ cache.relationship_line_color = get_theme_color(SNAME("relationship_line_color"));
+ cache.parent_hl_line_color = get_theme_color(SNAME("parent_hl_line_color"));
+ cache.children_hl_line_color = get_theme_color(SNAME("children_hl_line_color"));
+
+ cache.scroll_border = get_theme_constant(SNAME("scroll_border"));
+ cache.scroll_speed = get_theme_constant(SNAME("scroll_speed"));
+
+ cache.title_button = get_theme_stylebox(SNAME("title_button_normal"));
+ cache.title_button_pressed = get_theme_stylebox(SNAME("title_button_pressed"));
+ cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));
+ cache.title_button_color = get_theme_color(SNAME("title_button_color"));
v_scroll->set_custom_step(cache.font->get_height(cache.font_size));
}
@@ -1463,7 +1514,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int htotal = 0;
int label_h = compute_item_height(p_item);
- bool rtl = is_layout_rtl();
+ bool rtl = cache.rtl;
/* Calculate height of the label part */
label_h += cache.vseparation;
@@ -1509,6 +1560,20 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
}
+ if (!rtl && p_item->cells[i].buttons.size()) {
+ int button_w = 0;
+ for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
+ Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
+ button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ }
+
+ int total_ofs = ofs - cache.offset.x;
+
+ if (total_ofs + w > p_draw_size.width) {
+ w = MAX(button_w, p_draw_size.width - total_ofs);
+ }
+ }
+
int bw = 0;
for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
@@ -1633,8 +1698,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_selected_color" : "font_color");
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = cache.font_outline_color;
+ int outline_size = cache.font_outline_size;
Color icon_col = p_item->cells[i].icon_color;
if (p_item->cells[i].dirty) {
@@ -2010,7 +2075,7 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c
selected_item = p_selected;
selected_col = 0;
if (!emitted_row) {
- emit_signal("item_selected");
+ emit_signal(SNAME("item_selected"));
emitted_row = true;
}
/*
@@ -2030,28 +2095,28 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c
selected_item = p_selected;
selected_col = i;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
if (select_mode == SELECT_MULTI) {
- emit_signal("multi_selected", p_current, i, true);
+ emit_signal(SNAME("multi_selected"), p_current, i, true);
} else if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected");
+ emit_signal(SNAME("item_selected"));
}
} else if (select_mode == SELECT_MULTI && (selected_item != p_selected || selected_col != i)) {
selected_item = p_selected;
selected_col = i;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
}
} else {
if (r_in_range && *r_in_range && !p_force_deselect) {
if (!c.selected && c.selectable) {
c.selected = true;
- emit_signal("multi_selected", p_current, i, true);
+ emit_signal(SNAME("multi_selected"), p_current, i, true);
}
} else if (!r_in_range || p_force_deselect) {
if (select_mode == SELECT_MULTI && c.selected) {
- emit_signal("multi_selected", p_current, i, false);
+ emit_signal(SNAME("multi_selected"), p_current, i, false);
}
c.selected = false;
}
@@ -2088,13 +2153,24 @@ void Tree::_range_click_timeout() {
}
}
+ if (!root) {
+ return;
+ }
+
click_handled = false;
Ref<InputEventMouseButton> mb;
mb.instantiate();
+ int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ if (h_scroll->is_visible()) {
+ x_limit -= h_scroll->get_minimum_size().width;
+ }
+
+ cache.rtl = is_layout_rtl();
+
propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, false, root, MOUSE_BUTTON_LEFT, mb);
+ propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MOUSE_BUTTON_LEFT, mb);
blocked--;
if (range_click_timer->is_one_shot()) {
@@ -2108,7 +2184,7 @@ void Tree::_range_click_timeout() {
}
if (propagate_mouse_activated) {
- emit_signal("item_activated");
+ emit_signal(SNAME("item_activated"));
propagate_mouse_activated = false;
}
@@ -2117,7 +2193,7 @@ void Tree::_range_click_timeout() {
}
}
-int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
+int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
int item_h = compute_item_height(p_item) + cache.vseparation;
bool skip = (p_item == root && hide_root);
@@ -2142,6 +2218,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
int col = -1;
int col_ofs = 0;
int col_width = 0;
+
+ int limit_w = x_limit;
+
for (int i = 0; i < columns.size(); i++) {
col_width = get_column_width(i);
@@ -2157,6 +2236,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
if (x > col_width) {
col_ofs += col_width;
x -= col_width;
+ limit_w -= col_width;
continue;
}
@@ -2170,10 +2250,12 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
int margin = x_ofs + cache.item_margin; //-cache.hseparation;
//int lm = cache.bg->get_margin(SIDE_LEFT);
col_width -= margin;
+ limit_w -= margin;
col_ofs += margin;
x -= margin;
} else {
col_width -= cache.hseparation;
+ limit_w -= cache.hseparation;
x -= cache.hseparation;
}
@@ -2187,6 +2269,16 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
bool already_selected = c.selected;
bool already_cursor = (p_item == selected_item) && col == selected_col;
+ if (!cache.rtl && p_item->cells[col].buttons.size()) {
+ int button_w = 0;
+ for (int j = p_item->cells[col].buttons.size() - 1; j >= 0; j--) {
+ Ref<Texture2D> b = p_item->cells[col].buttons[j].texture;
+ button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ }
+
+ col_width = MAX(button_w, MIN(limit_w, col_width));
+ }
+
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
int w = b->get_size().width + cache.button_pressed->get_minimum_size().width;
@@ -2205,9 +2297,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
cache.click_column = col;
cache.click_pos = get_global_mouse_position() - get_global_position();
update();
- //emit_signal("button_pressed");
+ //emit_signal(SNAME("button_pressed"));
return -1;
}
+
col_width -= w + cache.button_margin;
}
@@ -2225,15 +2318,15 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
if (select_mode == SELECT_MULTI && p_mod->is_command_pressed() && c.selectable) {
if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) {
p_item->select(col);
- emit_signal("multi_selected", p_item, col, true);
+ emit_signal(SNAME("multi_selected"), p_item, col, true);
if (p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
//p_item->selected_signal.call(col);
} else {
p_item->deselect(col);
- emit_signal("multi_selected", p_item, col, false);
+ emit_signal(SNAME("multi_selected"), p_item, col, false);
//p_item->deselected_signal.call(col);
}
@@ -2244,7 +2337,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
select_single_item(p_item, root, col, selected_item, &inrange);
if (p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
} else {
int icount = _count_selected_items(root);
@@ -2258,14 +2351,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
if (p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
}
}
/*
if (!c.selected && select_mode==SELECT_MULTI) {
- emit_signal("multi_selected",p_item,col,true);
+ emit_signal(SNAME("multi_selected"),p_item,col,true);
}
*/
update();
@@ -2379,7 +2472,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
custom_popup_rect = Rect2i(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - cache.offset.y), Size2(get_column_width(col), item_h));
if (on_arrow || !p_item->cells[col].custom_button) {
- emit_signal("custom_popup_edited", ((bool)(x >= (col_width - item_h / 2))));
+ emit_signal(SNAME("custom_popup_edited"), ((bool)(x >= (col_width - item_h / 2))));
}
if (!p_item->cells[col].custom_button || !on_arrow) {
@@ -2418,7 +2511,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
TreeItem *c = p_item->first_child;
while (c) {
- int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, p_double_click, c, p_button, p_mod);
+ int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, x_limit, p_double_click, c, p_button, p_mod);
if (child_h < 0) {
return -1; // break, stop propagating, no need to anymore
@@ -2431,7 +2524,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
}
if (p_item == root && p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("empty_rmb", get_local_mouse_position());
+ emit_signal(SNAME("empty_rmb"), get_local_mouse_position());
}
}
@@ -2537,7 +2630,7 @@ void Tree::_go_left() {
} else {
if (select_mode == SELECT_MULTI) {
selected_col--;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
} else {
selected_item->select(selected_col - 1);
}
@@ -2558,7 +2651,7 @@ void Tree::_go_right() {
} else {
if (select_mode == SELECT_MULTI) {
selected_col++;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
} else {
selected_item->select(selected_col + 1);
}
@@ -2591,7 +2684,7 @@ void Tree::_go_up() {
return;
}
selected_item = prev;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
int col = selected_col < 0 ? 0 : selected_col;
@@ -2634,7 +2727,7 @@ void Tree::_go_down() {
}
selected_item = next;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
int col = selected_col < 0 ? 0 : selected_col;
@@ -2735,7 +2828,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (select_mode == SELECT_MULTI) {
selected_item = next;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
while (next && !next->cells[selected_col].selectable) {
@@ -2773,7 +2866,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (select_mode == SELECT_MULTI) {
selected_item = prev;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
while (prev && !prev->cells[selected_col].selectable) {
@@ -2789,7 +2882,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (selected_item) {
//bring up editor if possible
if (!edit_selected()) {
- emit_signal("item_activated");
+ emit_signal(SNAME("item_activated"));
incr_search.clear();
}
}
@@ -2801,10 +2894,10 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (selected_item->is_selected(selected_col)) {
selected_item->deselect(selected_col);
- emit_signal("multi_selected", selected_item, selected_col, false);
+ emit_signal(SNAME("multi_selected"), selected_item, selected_col, false);
} else if (selected_item->is_selectable(selected_col)) {
selected_item->select(selected_col);
- emit_signal("multi_selected", selected_item, selected_col, true);
+ emit_signal(SNAME("multi_selected"), selected_item, selected_col, true);
}
}
accept_event();
@@ -2988,7 +3081,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
if (pos.x < len) {
- emit_signal("column_title_pressed", i);
+ emit_signal(SNAME("column_title_pressed"), i);
break;
}
}
@@ -3015,10 +3108,10 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (rect.has_point(mpos)) {
if (!edit_selected()) {
- emit_signal("item_double_clicked");
+ emit_signal(SNAME("item_double_clicked"));
}
} else {
- emit_signal("item_double_clicked");
+ emit_signal(SNAME("item_double_clicked"));
}
}
pressing_for_editor = false;
@@ -3027,7 +3120,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (cache.click_type == Cache::CLICK_BUTTON && cache.click_item != nullptr) {
// make sure in case of wrong reference after reconstructing whole TreeItems
cache.click_item = get_item_at_position(cache.click_pos);
- emit_signal("button_pressed", cache.click_item, cache.click_column, cache.click_id);
+ emit_signal(SNAME("button_pressed"), cache.click_item, cache.click_column, cache.click_id);
}
cache.click_type = Cache::CLICK_NONE;
cache.click_index = -1;
@@ -3087,7 +3180,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (!root || (!root->get_first_child() && hide_root)) {
if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) {
- emit_signal("empty_tree_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("empty_tree_rmb_selected"), get_local_mouse_position());
}
break;
}
@@ -3096,8 +3189,14 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
pressing_for_editor = false;
propagate_mouse_activated = false;
+ int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ if (h_scroll->is_visible()) {
+ x_limit -= h_scroll->get_minimum_size().width;
+ }
+
+ cache.rtl = is_layout_rtl();
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, b->is_double_click(), root, b->get_button_index(), b);
+ propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, b->is_double_click(), root, b->get_button_index(), b);
blocked--;
if (pressing_for_editor) {
@@ -3132,13 +3231,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
if (get_item_at_position(b->get_position()) == nullptr && !b->is_shift_pressed() && !b->is_ctrl_pressed() && !b->is_command_pressed()) {
- emit_signal("nothing_selected");
+ emit_signal(SNAME("nothing_selected"));
}
}
}
if (propagate_mouse_activated) {
- emit_signal("item_activated");
+ emit_signal(SNAME("item_activated"));
propagate_mouse_activated = false;
}
@@ -3207,7 +3306,7 @@ bool Tree::edit_selected() {
edited_item = s;
edited_col = col;
custom_popup_rect = Rect2i(get_global_position() + rect.position, rect.size);
- emit_signal("custom_popup_edited", false);
+ emit_signal(SNAME("custom_popup_edited"), false);
item_edited(col, s);
return true;
@@ -3276,7 +3375,7 @@ Size2 Tree::get_internal_min_size() const {
size.height += get_item_height(root);
}
for (int i = 0; i < columns.size(); i++) {
- size.width += columns[i].min_width;
+ size.width += get_column_minimum_width(i);
}
return size;
@@ -3300,26 +3399,38 @@ void Tree::update_scrollbars() {
h_scroll->set_begin(Point2(0, size.height - hmin.height));
h_scroll->set_end(Point2(size.width - vmin.width, size.height));
- Size2 min = get_internal_min_size();
+ Size2 internal_min_size = get_internal_min_size();
- if (min.height < size.height - hmin.height) {
- v_scroll->hide();
- cache.offset.y = 0;
- } else {
+ bool display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) > size.height;
+ bool display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) > size.width;
+ for (int i = 0; i < 2; i++) {
+ // Check twice, as both values are dependent on each other.
+ if (display_hscroll) {
+ display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) + hmin.height > size.height;
+ }
+ if (display_vscroll) {
+ display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) + vmin.width > size.width;
+ }
+ }
+
+ if (display_vscroll) {
v_scroll->show();
- v_scroll->set_max(min.height);
+ v_scroll->set_max(internal_min_size.height);
v_scroll->set_page(size.height - hmin.height - tbh);
cache.offset.y = v_scroll->get_value();
+ } else {
+ v_scroll->hide();
+ cache.offset.y = 0;
}
- if (min.width < size.width - vmin.width) {
- h_scroll->hide();
- cache.offset.x = 0;
- } else {
+ if (display_hscroll) {
h_scroll->show();
- h_scroll->set_max(min.width);
+ h_scroll->set_max(internal_min_size.width);
h_scroll->set_page(size.width - vmin.width);
cache.offset.x = h_scroll->get_value();
+ } else {
+ h_scroll->hide();
+ cache.offset.x = 0;
}
}
@@ -3431,12 +3542,15 @@ void Tree::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<StyleBox> bg = cache.bg;
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
Point2 draw_ofs;
draw_ofs += bg->get_offset();
Size2 draw_size = get_size() - bg->get_minimum_size();
+ if (h_scroll->is_visible()) {
+ draw_size.width -= h_scroll->get_minimum_size().width;
+ }
bg->draw(ci, Rect2(Point2(), get_size()));
@@ -3445,7 +3559,9 @@ void Tree::_notification(int p_what) {
draw_ofs.y += tbh;
draw_size.y -= tbh;
- if (root) {
+ cache.rtl = is_layout_rtl();
+
+ if (root && get_size().x > 0 && get_size().y > 0) {
draw_item(Point2(), draw_ofs, draw_size, root);
}
@@ -3456,7 +3572,7 @@ void Tree::_notification(int p_what) {
Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? cache.title_button_hover : cache.title_button);
Ref<Font> f = cache.tb_font;
Rect2 tbrect = Rect2(ofs2 - cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
- if (is_layout_rtl()) {
+ if (cache.rtl) {
tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
}
sb->draw(ci, tbrect);
@@ -3477,7 +3593,7 @@ void Tree::_notification(int p_what) {
// Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling.
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- const Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus");
+ const Ref<StyleBox> bg_focus = get_theme_stylebox(SNAME("bg_focus"));
bg_focus->draw(ci, Rect2(Point2(), get_size()));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
@@ -3513,7 +3629,17 @@ void Tree::_update_all() {
}
Size2 Tree::get_minimum_size() const {
- return Size2(1, 1);
+ if (h_scroll_enabled && v_scroll_enabled) {
+ return Size2();
+ } else {
+ Vector2 min_size = get_internal_min_size();
+ Ref<StyleBox> bg = cache.bg;
+ if (bg.is_valid()) {
+ min_size.x += bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
+ min_size.y += bg->get_margin(SIDE_TOP) + bg->get_margin(SIDE_BOTTOM);
+ }
+ return Vector2(h_scroll_enabled ? 0 : min_size.x, v_scroll_enabled ? 0 : min_size.y);
+ }
}
TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
@@ -3541,11 +3667,11 @@ TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
return ti;
}
-TreeItem *Tree::get_root() {
+TreeItem *Tree::get_root() const {
return root;
}
-TreeItem *Tree::get_last_item() {
+TreeItem *Tree::get_last_item() const {
TreeItem *last = root;
while (last) {
@@ -3568,9 +3694,9 @@ void Tree::item_edited(int p_column, TreeItem *p_item, bool p_lmb) {
edited_item->cells.write[p_column].dirty = true;
}
if (p_lmb) {
- emit_signal("item_edited");
+ emit_signal(SNAME("item_edited"));
} else {
- emit_signal("item_rmb_edited");
+ emit_signal(SNAME("item_rmb_edited"));
}
}
@@ -3588,7 +3714,7 @@ void Tree::item_selected(int p_column, TreeItem *p_item) {
}
p_item->cells.write[p_column].selected = true;
- //emit_signal("multi_selected",p_item,p_column,true); - NO this is for TreeItem::select
+ //emit_signal(SNAME("multi_selected"),p_item,p_column,true); - NO this is for TreeItem::select
selected_col = p_column;
if (!selected_item) {
@@ -3675,13 +3801,13 @@ bool Tree::is_root_hidden() const {
return hide_root;
}
-void Tree::set_column_min_width(int p_column, int p_min_width) {
+void Tree::set_column_custom_minimum_width(int p_column, int p_min_width) {
ERR_FAIL_INDEX(p_column, columns.size());
- if (p_min_width < 1) {
+ if (p_min_width < 0) {
return;
}
- columns.write[p_column].min_width = p_min_width;
+ columns.write[p_column].custom_min_width = p_min_width;
update();
}
@@ -3692,6 +3818,36 @@ void Tree::set_column_expand(int p_column, bool p_expand) {
update();
}
+void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+ columns.write[p_column].expand_ratio = p_ratio;
+ update();
+}
+
+void Tree::set_column_clip_content(int p_column, bool p_fit) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+
+ columns.write[p_column].clip_content = p_fit;
+ update();
+}
+
+bool Tree::is_column_expanding(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), false);
+
+ return columns[p_column].expand;
+}
+int Tree::get_column_expand_ratio(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), 1);
+
+ return columns[p_column].expand_ratio;
+}
+
+bool Tree::is_column_clipping_content(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), false);
+
+ return columns[p_column].clip_content;
+}
+
TreeItem *Tree::get_selected() const {
return selected_item;
}
@@ -3748,44 +3904,81 @@ TreeItem *Tree::get_next_selected(TreeItem *p_item) {
return nullptr;
}
-int Tree::get_column_width(int p_column) const {
+int Tree::get_column_minimum_width(int p_column) const {
ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
- if (!columns[p_column].expand) {
- return columns[p_column].min_width;
+ int min_width = columns[p_column].custom_min_width;
+
+ if (show_column_titles) {
+ min_width = MAX(cache.font->get_string_size(columns[p_column].title).width, min_width);
+ }
+
+ if (!columns[p_column].clip_content) {
+ int depth = 0;
+ TreeItem *next;
+ for (TreeItem *item = get_root(); item; item = next) {
+ next = item->get_next_visible();
+ // Compute the depth in tree.
+ if (next && p_column == 0) {
+ if (next->get_parent() == item) {
+ depth += 1;
+ } else {
+ TreeItem *common_parent = item->get_parent();
+ while (common_parent != next->get_parent()) {
+ common_parent = common_parent->get_parent();
+ depth -= 1;
+ }
+ }
+ }
+
+ // Get the item minimum size.
+ Size2 item_size = item->get_minimum_size(p_column);
+ if (p_column == 0) {
+ item_size.width += cache.item_margin * depth;
+ }
+ min_width = MAX(min_width, item_size.width);
+ }
}
- int expand_area = get_size().width;
+ return min_width;
+}
- Ref<StyleBox> bg = cache.bg;
+int Tree::get_column_width(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
- if (bg.is_valid()) {
- expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
- }
+ int column_width = get_column_minimum_width(p_column);
- if (v_scroll->is_visible_in_tree()) {
- expand_area -= v_scroll->get_combined_minimum_size().width;
- }
+ if (columns[p_column].expand) {
+ int expand_area = get_size().width;
- int expanding_columns = 0;
- int expanding_total = 0;
+ Ref<StyleBox> bg = cache.bg;
- for (int i = 0; i < columns.size(); i++) {
- if (!columns[i].expand) {
- expand_area -= columns[i].min_width;
- } else {
- expanding_total += columns[i].min_width;
- expanding_columns++;
+ if (bg.is_valid()) {
+ expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
}
- }
- if (expand_area < expanding_total) {
- return columns[p_column].min_width;
- }
+ if (v_scroll->is_visible_in_tree()) {
+ expand_area -= v_scroll->get_combined_minimum_size().width;
+ }
- ERR_FAIL_COND_V(expanding_columns == 0, -1); // shouldn't happen
+ int expanding_total = 0;
- return expand_area * columns[p_column].min_width / expanding_total;
+ for (int i = 0; i < columns.size(); i++) {
+ expand_area -= get_column_minimum_width(i);
+ if (columns[i].expand) {
+ expanding_total += columns[i].expand_ratio;
+ }
+ }
+
+ if (expand_area >= expanding_total && expanding_total > 0) {
+ column_width += expand_area * columns[p_column].expand_ratio / expanding_total;
+ }
+ }
+
+ if (p_column < columns.size() - 1) {
+ column_width += cache.hseparation;
+ }
+ return column_width;
}
void Tree::propagate_set_columns(TreeItem *p_item) {
@@ -3882,7 +4075,7 @@ void Tree::ensure_cursor_is_visible() {
if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
v_scroll->set_value(y_offset);
} else if (y_offset + cell_h > v_scroll->get_value() + screen_h) {
- v_scroll->call_deferred("set_value", y_offset - screen_h + cell_h);
+ v_scroll->call_deferred(SNAME("set_value"), y_offset - screen_h + cell_h);
} else if (y_offset < v_scroll->get_value()) {
v_scroll->set_value(y_offset);
}
@@ -3900,7 +4093,7 @@ void Tree::ensure_cursor_is_visible() {
if (cell_w > screen_w) {
h_scroll->set_value(x_offset);
} else if (x_offset + cell_w > h_scroll->get_value() + screen_w) {
- h_scroll->call_deferred("set_value", x_offset - screen_w + cell_w);
+ h_scroll->call_deferred(SNAME("set_value"), x_offset - screen_w + cell_w);
} else if (x_offset < h_scroll->get_value()) {
h_scroll->set_value(x_offset);
}
@@ -4047,6 +4240,24 @@ void Tree::scroll_to_item(TreeItem *p_item) {
}
}
+void Tree::set_h_scroll_enabled(bool p_enable) {
+ h_scroll_enabled = p_enable;
+ minimum_size_changed();
+}
+
+bool Tree::is_h_scroll_enabled() const {
+ return h_scroll_enabled;
+}
+
+void Tree::set_v_scroll_enabled(bool p_enable) {
+ v_scroll_enabled = p_enable;
+ minimum_size_changed();
+}
+
+bool Tree::is_v_scroll_enabled() const {
+ return v_scroll_enabled;
+}
+
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
TreeItem *from = p_at;
TreeItem *loop = nullptr; // Safe-guard against infinite loop.
@@ -4422,8 +4633,14 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_item", "parent", "idx"), &Tree::_create_item, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_root"), &Tree::get_root);
- ClassDB::bind_method(D_METHOD("set_column_min_width", "column", "min_width"), &Tree::set_column_min_width);
+ ClassDB::bind_method(D_METHOD("set_column_custom_minimum_width", "column", "min_width"), &Tree::set_column_custom_minimum_width);
ClassDB::bind_method(D_METHOD("set_column_expand", "column", "expand"), &Tree::set_column_expand);
+ ClassDB::bind_method(D_METHOD("set_column_expand_ratio", "column", "ratio"), &Tree::set_column_expand_ratio);
+ ClassDB::bind_method(D_METHOD("set_column_clip_content", "column", "enable"), &Tree::set_column_clip_content);
+ ClassDB::bind_method(D_METHOD("is_column_expanding", "column"), &Tree::is_column_expanding);
+ ClassDB::bind_method(D_METHOD("is_column_clipping_content", "column"), &Tree::is_column_clipping_content);
+ ClassDB::bind_method(D_METHOD("get_column_expand_ratio", "column"), &Tree::get_column_expand_ratio);
+
ClassDB::bind_method(D_METHOD("get_column_width", "column"), &Tree::get_column_width);
ClassDB::bind_method(D_METHOD("set_hide_root", "enable"), &Tree::set_hide_root);
@@ -4468,6 +4685,12 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scroll"), &Tree::get_scroll);
ClassDB::bind_method(D_METHOD("scroll_to_item", "item"), &Tree::_scroll_to_item);
+ ClassDB::bind_method(D_METHOD("set_h_scroll_enabled", "h_scroll"), &Tree::set_h_scroll_enabled);
+ ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"), &Tree::is_h_scroll_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_v_scroll_enabled", "h_scroll"), &Tree::set_v_scroll_enabled);
+ ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &Tree::is_v_scroll_enabled);
+
ClassDB::bind_method(D_METHOD("set_hide_folding", "hide"), &Tree::set_hide_folding);
ClassDB::bind_method(D_METHOD("is_folding_hidden"), &Tree::is_folding_hidden);
@@ -4487,6 +4710,8 @@ void Tree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_root"), "set_hide_root", "is_root_hidden");
ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In Between"), "set_drop_mode_flags", "get_drop_mode_flags");
ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Row,Multi"), "set_select_mode", "get_select_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_horizontal_enabled"), "set_h_scroll_enabled", "is_h_scroll_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_vertical_enabled"), "set_v_scroll_enabled", "is_v_scroll_enabled");
ADD_SIGNAL(MethodInfo("item_selected"));
ADD_SIGNAL(MethodInfo("cell_selected"));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 42dd27cb55..10e6642303 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -315,16 +315,18 @@ public:
void set_disable_folding(bool p_disable);
bool is_folding_disabled() const;
+ Size2 get_minimum_size(int p_column);
+
/* Item manipulation */
TreeItem *create_child(int p_idx = -1);
- Tree *get_tree();
+ Tree *get_tree() const;
TreeItem *get_prev();
- TreeItem *get_next();
- TreeItem *get_parent();
- TreeItem *get_first_child();
+ TreeItem *get_next() const;
+ TreeItem *get_parent() const;
+ TreeItem *get_first_child() const;
TreeItem *get_prev_visible(bool p_wrap = false);
TreeItem *get_next_visible(bool p_wrap = false);
@@ -408,8 +410,10 @@ private:
int drop_mode_flags = 0;
struct ColumnInfo {
- int min_width = 1;
+ int custom_min_width = 0;
+ int expand_ratio = 1;
bool expand = true;
+ bool clip_content = false;
String title;
Ref<TextLine> text_buf;
Dictionary opentype_features;
@@ -448,7 +452,7 @@ private:
void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color);
int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false);
- int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
+ int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
void _text_editor_submit(String p_text);
void _text_editor_modal_close();
void value_editor_changed(double p_value);
@@ -502,6 +506,7 @@ private:
Color parent_hl_line_color;
Color children_hl_line_color;
Color custom_button_font_highlight;
+ Color font_outline_color;
int hseparation = 0;
int vseparation = 0;
@@ -516,6 +521,7 @@ private:
int draw_guides = 0;
int scroll_border = 0;
int scroll_speed = 0;
+ int font_outline_size = 0;
enum ClickType {
CLICK_NONE,
@@ -538,6 +544,8 @@ private:
Point2i text_editor_position;
+ bool rtl = false;
+
} cache;
int _get_title_button_height() const;
@@ -546,6 +554,9 @@ private:
HScrollBar *h_scroll;
VScrollBar *v_scroll;
+ bool h_scroll_enabled = true;
+ bool v_scroll_enabled = true;
+
Size2 get_internal_min_size() const;
void update_cache();
void update_scrollbars();
@@ -623,12 +634,19 @@ public:
void clear();
TreeItem *create_item(TreeItem *p_parent = nullptr, int p_idx = -1);
- TreeItem *get_root();
- TreeItem *get_last_item();
+ TreeItem *get_root() const;
+ TreeItem *get_last_item() const;
- void set_column_min_width(int p_column, int p_min_width);
+ void set_column_custom_minimum_width(int p_column, int p_min_width);
void set_column_expand(int p_column, bool p_expand);
+ void set_column_expand_ratio(int p_column, int p_ratio);
+ void set_column_clip_content(int p_column, bool p_fit);
+ int get_column_minimum_width(int p_column) const;
int get_column_width(int p_column) const;
+ int get_column_expand_ratio(int p_column) const;
+
+ bool is_column_expanding(int p_column) const;
+ bool is_column_clipping_content(int p_column) const;
void set_hide_root(bool p_enabled);
bool is_root_hidden() const;
@@ -679,6 +697,10 @@ public:
Point2 get_scroll() const;
void scroll_to_item(TreeItem *p_item);
+ void set_h_scroll_enabled(bool p_enable);
+ bool is_h_scroll_enabled() const;
+ void set_v_scroll_enabled(bool p_enable);
+ bool is_v_scroll_enabled() const;
void set_cursor_can_exit_tree(bool p_enable);
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index ed3c0b7a56..229b5384ea 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -452,7 +452,7 @@ void VideoPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "VideoStream"), "set_stream", "get_stream");
//ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), "set_loop", "has_loop") ;
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_volume_db", "get_volume_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume", PROPERTY_HINT_EXP_RANGE, "0,15,0.01", PROPERTY_USAGE_NONE), "set_volume", "get_volume");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume", PROPERTY_HINT_RANGE, "0,15,0.01,exp", PROPERTY_USAGE_NONE), "set_volume", "get_volume");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "has_autoplay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_paused", "is_paused");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand");
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 361f584a5d..5a12480577 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -128,24 +128,21 @@ void CanvasItemMaterial::_update_shader() {
if (particles_animation) {
code += "uniform int particles_anim_h_frames;\n";
code += "uniform int particles_anim_v_frames;\n";
- code += "uniform bool particles_anim_loop;\n";
+ code += "uniform bool particles_anim_loop;\n\n";
code += "void vertex() {\n";
-
- code += "\tfloat h_frames = float(particles_anim_h_frames);\n";
- code += "\tfloat v_frames = float(particles_anim_v_frames);\n";
-
- code += "\tVERTEX.xy /= vec2(h_frames, v_frames);\n";
-
- code += "\tfloat particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n";
- code += "\tfloat particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n";
- code += "\tif (!particles_anim_loop) {\n";
- code += "\t\tparticle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n";
- code += "\t} else {\n";
- code += "\t\tparticle_frame = mod(particle_frame, particle_total_frames);\n";
- code += "\t}";
- code += "\tUV /= vec2(h_frames, v_frames);\n";
- code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n";
+ code += " float h_frames = float(particles_anim_h_frames);\n";
+ code += " float v_frames = float(particles_anim_v_frames);\n";
+ code += " VERTEX.xy /= vec2(h_frames, v_frames);\n";
+ code += " float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n";
+ code += " float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n";
+ code += " if (!particles_anim_loop) {\n";
+ code += " particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n";
+ code += " } else {\n";
+ code += " particle_frame = mod(particle_frame, particle_total_frames);\n";
+ code += " }";
+ code += " UV /= vec2(h_frames, v_frames);\n";
+ code += " UV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n";
code += "}\n";
}
@@ -239,7 +236,7 @@ bool CanvasItemMaterial::get_particles_anim_loop() const {
void CanvasItemMaterial::_validate_property(PropertyInfo &property) const {
if (property.name.begins_with("particles_anim_") && !particles_animation) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -526,7 +523,7 @@ void CanvasItem::_enter_canvas() {
get_viewport()->gui_reset_canvas_sort_index();
}
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE, group, "_top_level_raise_self");
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE, group, SNAME("_top_level_raise_self"));
} else {
CanvasItem *parent = get_parent_item();
@@ -545,7 +542,7 @@ void CanvasItem::_exit_canvas() {
notification(NOTIFICATION_EXIT_CANVAS, true); //reverse the notification
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, RID());
canvas_layer = nullptr;
- group = "";
+ group = StringName();
}
void CanvasItem::_notification(int p_what) {
@@ -591,7 +588,7 @@ void CanvasItem::_notification(int p_what) {
break;
}
- if (group != "") {
+ if (group != StringName()) {
get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE, group, "_top_level_raise_self");
} else {
CanvasItem *p = get_parent_item();
@@ -651,7 +648,7 @@ void CanvasItem::update() {
pending_update = true;
- MessageQueue::get_singleton()->push_call(this, "_update_callback");
+ MessageQueue::get_singleton()->push_call(this, SNAME("_update_callback"));
}
void CanvasItem::set_modulate(const Color &p_modulate) {
@@ -1227,7 +1224,7 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
ADD_GROUP("Material", "");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_parent_material"), "set_use_parent_material", "get_use_parent_material");
// ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),"set_transform_notify","is_transform_notify_enabled");
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index afdd18d76b..f264764870 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -187,7 +187,7 @@ private:
mutable SelfList<Node> xform_change;
RID canvas_item;
- String group;
+ StringName group;
CanvasLayer *canvas_layer = nullptr;
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index f699e68715..4540e42b4c 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -103,14 +103,6 @@ real_t CanvasLayer::get_rotation() const {
return rot;
}
-void CanvasLayer::set_rotation_degrees(real_t p_degrees) {
- set_rotation(Math::deg2rad(p_degrees));
-}
-
-real_t CanvasLayer::get_rotation_degrees() const {
- return Math::rad2deg(get_rotation());
-}
-
void CanvasLayer::set_scale(const Vector2 &p_scale) {
if (locrotscale_dirty) {
_update_locrotscale();
@@ -277,9 +269,6 @@ void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &CanvasLayer::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &CanvasLayer::get_rotation);
- ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &CanvasLayer::set_rotation_degrees);
- ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &CanvasLayer::get_rotation_degrees);
-
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &CanvasLayer::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &CanvasLayer::get_scale);
@@ -298,8 +287,7 @@ void CanvasLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer");
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_degrees", PROPERTY_HINT_RANGE, "-1080,1080,0.1,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform");
ADD_GROUP("", "");
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index 899039340a..5de1ebf18d 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -79,9 +79,6 @@ public:
void set_rotation(real_t p_radians);
real_t get_rotation() const;
- void set_rotation_degrees(real_t p_degrees);
- real_t get_rotation_degrees() const;
-
void set_scale(const Size2 &p_scale);
Size2 get_scale() const;
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 775dfa4c46..f649380afa 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -151,7 +151,7 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust
client->set_blocking_mode(false);
err = _request();
if (err != OK) {
- call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
return ERR_CANT_CONNECT;
}
@@ -167,7 +167,7 @@ void HTTPRequest::_thread_func(void *p_userdata) {
Error err = hr->_request();
if (err != OK) {
- hr->call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
+ hr->call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
} else {
while (!hr->thread_request_quit.is_set()) {
bool exit = hr->_update_connection();
@@ -209,7 +209,7 @@ void HTTPRequest::cancel_request() {
bool HTTPRequest::_handle_response(bool *ret_value) {
if (!client->has_response()) {
- call_deferred("_request_done", RESULT_NO_RESPONSE, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_NO_RESPONSE, 0, PackedStringArray(), PackedByteArray());
*ret_value = true;
return true;
}
@@ -228,7 +228,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
// Handle redirect
if (max_redirects >= 0 && redirections >= max_redirects) {
- call_deferred("_request_done", RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PackedByteArray());
*ret_value = true;
return true;
}
@@ -273,7 +273,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
bool HTTPRequest::_update_connection() {
switch (client->get_status()) {
case HTTPClient::STATUS_DISCONNECTED: {
- call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
return true; // End it, since it's doing something
} break;
case HTTPClient::STATUS_RESOLVING: {
@@ -282,7 +282,7 @@ bool HTTPRequest::_update_connection() {
return false;
} break;
case HTTPClient::STATUS_CANT_RESOLVE: {
- call_deferred("_request_done", RESULT_CANT_RESOLVE, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_CANT_RESOLVE, 0, PackedStringArray(), PackedByteArray());
return true;
} break;
@@ -292,7 +292,7 @@ bool HTTPRequest::_update_connection() {
return false;
} break; // Connecting to IP
case HTTPClient::STATUS_CANT_CONNECT: {
- call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
return true;
} break;
@@ -307,16 +307,16 @@ bool HTTPRequest::_update_connection() {
return ret_value;
}
- call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, PackedByteArray());
return true;
}
if (body_len < 0) {
// Chunked transfer is done
- call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
+ call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
- call_deferred("_request_done", RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray());
return true;
// Request might have been done
} else {
@@ -325,7 +325,7 @@ bool HTTPRequest::_update_connection() {
int size = request_data.size();
Error err = client->request(method, request_string, headers, size > 0 ? request_data.ptr() : nullptr, size);
if (err != OK) {
- call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray());
return true;
}
@@ -348,7 +348,7 @@ bool HTTPRequest::_update_connection() {
}
if (!client->is_response_chunked() && client->get_response_body_length() == 0) {
- call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, PackedByteArray());
return true;
}
@@ -357,14 +357,14 @@ bool HTTPRequest::_update_connection() {
body_len = client->get_response_body_length();
if (body_size_limit >= 0 && body_len > body_size_limit) {
- call_deferred("_request_done", RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray());
return true;
}
if (download_to_file != String()) {
file = FileAccess::open(download_to_file, FileAccess::WRITE);
if (!file) {
- call_deferred("_request_done", RESULT_DOWNLOAD_FILE_CANT_OPEN, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_DOWNLOAD_FILE_CANT_OPEN, response_code, response_headers, PackedByteArray());
return true;
}
}
@@ -383,7 +383,7 @@ bool HTTPRequest::_update_connection() {
const uint8_t *r = chunk.ptr();
file->store_buffer(r, chunk.size());
if (file->get_error() != OK) {
- call_deferred("_request_done", RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PackedByteArray());
return true;
}
} else {
@@ -392,18 +392,18 @@ bool HTTPRequest::_update_connection() {
}
if (body_size_limit >= 0 && downloaded.get() > body_size_limit) {
- call_deferred("_request_done", RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray());
return true;
}
if (body_len >= 0) {
if (downloaded.get() == body_len) {
- call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
+ call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
} else if (client->get_status() == HTTPClient::STATUS_DISCONNECTED) {
// We read till EOF, with no errors. Request is done.
- call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
+ call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
@@ -411,11 +411,11 @@ bool HTTPRequest::_update_connection() {
} break; // Request resulted in body: break which must be read
case HTTPClient::STATUS_CONNECTION_ERROR: {
- call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray());
return true;
} break;
case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR: {
- call_deferred("_request_done", RESULT_SSL_HANDSHAKE_ERROR, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_SSL_HANDSHAKE_ERROR, 0, PackedStringArray(), PackedByteArray());
return true;
} break;
}
@@ -463,7 +463,7 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra
data = &p_data;
}
- emit_signal("request_completed", p_status, p_code, p_headers, *data);
+ emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, *data);
}
void HTTPRequest::_notification(int p_what) {
@@ -563,7 +563,7 @@ int HTTPRequest::get_timeout() {
void HTTPRequest::_timeout() {
cancel_request();
- call_deferred("_request_done", RESULT_TIMEOUT, 0, PackedStringArray(), PackedByteArray());
+ call_deferred(SNAME("_request_done"), RESULT_TIMEOUT, 0, PackedStringArray(), PackedByteArray());
}
void HTTPRequest::_bind_methods() {
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index baf185c847..0d060240de 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -403,6 +403,7 @@ void Node::set_process_mode(ProcessMode p_mode) {
}
bool prev_can_process = can_process();
+ bool prev_enabled = _is_enabled();
data.process_mode = p_mode;
@@ -417,6 +418,7 @@ void Node::set_process_mode(ProcessMode p_mode) {
}
bool next_can_process = can_process();
+ bool next_enabled = _is_enabled();
int pause_notification = 0;
@@ -426,12 +428,21 @@ void Node::set_process_mode(ProcessMode p_mode) {
pause_notification = NOTIFICATION_UNPAUSED;
}
- _propagate_process_owner(data.process_owner, pause_notification);
+ int enabled_notification = 0;
+
+ if (prev_enabled && !next_enabled) {
+ enabled_notification = NOTIFICATION_DISABLED;
+ } else if (!prev_enabled && next_enabled) {
+ enabled_notification = NOTIFICATION_ENABLED;
+ }
+
+ _propagate_process_owner(data.process_owner, pause_notification, enabled_notification);
+
#ifdef TOOLS_ENABLED
// This is required for the editor to update the visibility of disabled nodes
// It's very expensive during runtime to change, so editor-only
if (Engine::get_singleton()->is_editor_hint()) {
- get_tree()->emit_signal("tree_process_mode_changed");
+ get_tree()->emit_signal(SNAME("tree_process_mode_changed"));
}
#endif
}
@@ -455,17 +466,21 @@ Node::ProcessMode Node::get_process_mode() const {
return data.process_mode;
}
-void Node::_propagate_process_owner(Node *p_owner, int p_notification) {
+void Node::_propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification) {
data.process_owner = p_owner;
- if (p_notification != 0) {
- notification(p_notification);
+ if (p_pause_notification != 0) {
+ notification(p_pause_notification);
+ }
+
+ if (p_enabled_notification != 0) {
+ notification(p_enabled_notification);
}
for (int i = 0; i < data.children.size(); i++) {
Node *c = data.children[i];
if (c->data.process_mode == PROCESS_MODE_INHERIT) {
- c->_propagate_process_owner(p_owner, p_notification);
+ c->_propagate_process_owner(p_owner, p_pause_notification, p_enabled_notification);
}
}
}
@@ -492,7 +507,7 @@ bool Node::is_network_master() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
+uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
for (int i = 0; i < data.rpc_methods.size(); i++) {
if (data.rpc_methods[i].name == p_method) {
MultiplayerAPI::RPCConfig &nd = data.rpc_methods.write[i];
@@ -669,6 +684,27 @@ bool Node::_can_process(bool p_paused) const {
}
}
+bool Node::_is_enabled() const {
+ ProcessMode process_mode;
+
+ if (data.process_mode == PROCESS_MODE_INHERIT) {
+ if (!data.process_owner) {
+ process_mode = PROCESS_MODE_PAUSABLE;
+ } else {
+ process_mode = data.process_owner->data.process_mode;
+ }
+ } else {
+ process_mode = data.process_mode;
+ }
+
+ return (process_mode != PROCESS_MODE_DISABLED);
+}
+
+bool Node::is_enabled() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
+ return _is_enabled();
+}
+
float Node::get_physics_process_delta_time() const {
if (data.tree) {
return data.tree->get_physics_process_time();
@@ -832,7 +868,7 @@ void Node::set_name(const String &p_name) {
propagate_notification(NOTIFICATION_PATH_CHANGED);
if (is_inside_tree()) {
- emit_signal("renamed");
+ emit_signal(SNAME("renamed"));
get_tree()->node_renamed(this);
get_tree()->tree_changed();
}
@@ -1041,7 +1077,7 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) {
ERR_FAIL_COND_MSG(p_child == this, vformat("Can't add child '%s' to itself.", p_child->get_name())); // adding to itself!
ERR_FAIL_COND_MSG(p_child->data.parent, vformat("Can't add child '%s' to '%s', already has a parent '%s'.", p_child->get_name(), get_name(), p_child->data.parent->get_name())); //Fail if node has a parent
#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_MSG(p_child->is_a_parent_of(this), vformat("Can't add child '%s' to '%s' as it would result in a cyclic dependency since '%s' is already a parent of '%s'.", p_child->get_name(), get_name(), p_child->get_name(), get_name()));
+ ERR_FAIL_COND_MSG(p_child->is_ancestor_of(this), vformat("Can't add child '%s' to '%s' as it would result in a cyclic dependency since '%s' is already a parent of '%s'.", p_child->get_name(), get_name(), p_child->get_name(), get_name()));
#endif
ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_node() failed. Consider using call_deferred(\"add_child\", child) instead.");
@@ -1284,7 +1320,7 @@ Node *Node::find_parent(const String &p_mask) const {
return nullptr;
}
-bool Node::is_a_parent_of(const Node *p_node) const {
+bool Node::is_ancestor_of(const Node *p_node) const {
ERR_FAIL_NULL_V(p_node, false);
Node *p = p_node->data.parent;
while (p) {
@@ -1749,7 +1785,7 @@ String Node::get_editor_description() const {
void Node::set_editable_instance(Node *p_node, bool p_editable) {
ERR_FAIL_NULL(p_node);
- ERR_FAIL_COND(!is_a_parent_of(p_node));
+ ERR_FAIL_COND(!is_ancestor_of(p_node));
if (!p_editable) {
p_node->data.editable_instance = false;
// Avoid this flag being needlessly saved;
@@ -1764,13 +1800,13 @@ bool Node::is_editable_instance(const Node *p_node) const {
if (!p_node) {
return false; // Easier, null is never editable. :)
}
- ERR_FAIL_COND_V(!is_a_parent_of(p_node), false);
+ ERR_FAIL_COND_V(!is_ancestor_of(p_node), false);
return p_node->data.editable_instance;
}
Node *Node::get_deepest_editable_node(Node *p_start_node) const {
ERR_FAIL_NULL_V(p_start_node, nullptr);
- ERR_FAIL_COND_V(!is_a_parent_of(p_start_node), p_start_node);
+ ERR_FAIL_COND_V(!is_ancestor_of(p_start_node), p_start_node);
Node const *iterated_item = p_start_node;
Node *node = p_start_node;
@@ -1786,6 +1822,18 @@ Node *Node::get_deepest_editable_node(Node *p_start_node) const {
return node;
}
+String Node::to_string() {
+ if (get_script_instance()) {
+ bool valid;
+ String ret = get_script_instance()->to_string(&valid);
+ if (valid) {
+ return ret;
+ }
+ }
+
+ return (get_name() ? String(get_name()) + ":" : "") + Object::to_string();
+}
+
void Node::set_scene_instance_state(const Ref<SceneState> &p_state) {
data.instance_state = p_state;
}
@@ -2074,7 +2122,7 @@ void Node::remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resourc
// because re-targeting of connections from some descendant to another is not possible
// if the emitter node comes later in tree order than the receiver
void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
- if ((this != p_original) && !(p_original->is_a_parent_of(this))) {
+ if ((this != p_original) && !(p_original->is_ancestor_of(this))) {
return;
}
@@ -2457,7 +2505,9 @@ String Node::get_configuration_warnings_as_string() const {
if (i > 0) {
all_warnings += "\n\n";
}
- all_warnings += String(warnings[i]);
+ // Format as a bullet point list to make multiple warnings easier to distinguish
+ // from each other.
+ all_warnings += String::utf8("• ") + String(warnings[i]);
}
return all_warnings;
}
@@ -2467,7 +2517,7 @@ void Node::update_configuration_warnings() {
if (!is_inside_tree()) {
return;
}
- if (get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) {
+ if (get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
get_tree()->emit_signal(SceneStringNames::get_singleton()->node_configuration_warning_changed, this);
}
#endif
@@ -2514,7 +2564,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_node_and_resource", "path"), &Node::_get_node_and_resource);
ClassDB::bind_method(D_METHOD("is_inside_tree"), &Node::is_inside_tree);
- ClassDB::bind_method(D_METHOD("is_a_parent_of", "node"), &Node::is_a_parent_of);
+ ClassDB::bind_method(D_METHOD("is_ancestor_of", "node"), &Node::is_ancestor_of);
ClassDB::bind_method(D_METHOD("is_greater_than", "node"), &Node::is_greater_than);
ClassDB::bind_method(D_METHOD("get_path"), &Node::get_path);
ClassDB::bind_method(D_METHOD("get_path_to", "node"), &Node::get_path_to);
@@ -2585,7 +2635,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer);
ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer);
- ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
@@ -2628,6 +2678,8 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS);
BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE);
+ BIND_CONSTANT(NOTIFICATION_DISABLED);
+ BIND_CONSTANT(NOTIFICATION_ENABLED);
BIND_CONSTANT(NOTIFICATION_EDITOR_PRE_SAVE);
BIND_CONSTANT(NOTIFICATION_EDITOR_POST_SAVE);
diff --git a/scene/main/node.h b/scene/main/node.h
index 0d1685a2be..20315d7a86 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -166,7 +166,7 @@ private:
void _propagate_after_exit_tree();
void _propagate_validate_owner();
void _print_stray_nodes();
- void _propagate_process_owner(Node *p_owner, int p_notification);
+ void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification);
Array _get_node_and_resource(const NodePath &p_path);
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
@@ -184,6 +184,7 @@ private:
void _propagate_pause_notification(bool p_enable);
_FORCE_INLINE_ bool _can_process(bool p_paused) const;
+ _FORCE_INLINE_ bool _is_enabled() const;
protected:
void _block() { data.blocked++; }
@@ -227,6 +228,8 @@ public:
NOTIFICATION_INTERNAL_PROCESS = 25,
NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26,
NOTIFICATION_POST_ENTER_TREE = 27,
+ NOTIFICATION_DISABLED = 28,
+ NOTIFICATION_ENABLED = 29,
//keep these linked to node
NOTIFICATION_WM_MOUSE_ENTER = 1002,
@@ -282,7 +285,7 @@ public:
_FORCE_INLINE_ bool is_inside_tree() const { return data.inside_tree; }
- bool is_a_parent_of(const Node *p_node) const;
+ bool is_ancestor_of(const Node *p_node) const;
bool is_greater_than(const Node *p_node) const;
NodePath get_path() const;
@@ -326,6 +329,8 @@ public:
bool is_editable_instance(const Node *p_node) const;
Node *get_deepest_editable_node(Node *p_start_node) const;
+ virtual String to_string() override;
+
/* NOTIFICATIONS */
void propagate_notification(int p_notification);
@@ -385,6 +390,7 @@ public:
ProcessMode get_process_mode() const;
bool can_process() const;
bool can_process_notification(int p_what) const;
+ bool is_enabled() const;
void request_ready();
@@ -426,7 +432,7 @@ public:
int get_network_master() const;
bool is_network_master() const;
- uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
+ uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const;
void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 6c46db7801..2fe5d7aa78 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -169,8 +169,8 @@ void SceneTree::_flush_ugc() {
v[i] = E->get()[i];
}
- static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5");
- call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4]);
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
+ call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
unique_group_calls.erase(E);
}
@@ -406,11 +406,11 @@ bool SceneTree::physics_process(float p_time) {
MainLoop::physics_process(p_time);
physics_process_time = p_time;
- emit_signal("physics_frame");
+ emit_signal(SNAME("physics_frame"));
- _notify_group_pause("physics_process_internal", Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
- call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_process_picking");
- _notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
+ _notify_group_pause(SNAME("physics_process_internal"), Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
+ call_group_flags(GROUP_CALL_REALTIME, SNAME("_picking_viewports"), SNAME("_process_picking"));
+ _notify_group_pause(SNAME("physics_process"), Node::NOTIFICATION_PHYSICS_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
@@ -436,14 +436,14 @@ bool SceneTree::process(float p_time) {
multiplayer->poll();
}
- emit_signal("process_frame");
+ emit_signal(SNAME("process_frame"));
MessageQueue::get_singleton()->flush(); //small little hack
flush_transform_notifications();
- _notify_group_pause("process_internal", Node::NOTIFICATION_INTERNAL_PROCESS);
- _notify_group_pause("process", Node::NOTIFICATION_PROCESS);
+ _notify_group_pause(SNAME("process_internal"), Node::NOTIFICATION_INTERNAL_PROCESS);
+ _notify_group_pause(SNAME("process"), Node::NOTIFICATION_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
@@ -471,7 +471,7 @@ bool SceneTree::process(float p_time) {
E->get()->set_time_left(time_left);
if (time_left < 0) {
- E->get()->emit_signal("timeout");
+ E->get()->emit_signal(SNAME("timeout"));
timers.erase(E);
}
if (E == L) {
@@ -490,7 +490,7 @@ bool SceneTree::process(float p_time) {
if (Engine::get_singleton()->is_editor_hint()) {
//simple hack to reload fallback environment if it changed from editor
- String env_path = ProjectSettings::get_singleton()->get("rendering/environment/defaults/default_environment");
+ String env_path = ProjectSettings::get_singleton()->get(SNAME("rendering/environment/defaults/default_environment"));
env_path = env_path.strip_edges(); //user may have added a space or two
String cpath;
Ref<Environment> fallback = get_root()->get_world_3d()->get_fallback_environment();
@@ -623,7 +623,7 @@ void SceneTree::set_quit_on_go_back(bool p_enable) {
#ifdef TOOLS_ENABLED
bool SceneTree::is_node_being_edited(const Node *p_node) const {
- return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_a_parent_of(p_node) || edited_scene_root == p_node);
+ return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_ancestor_of(p_node) || edited_scene_root == p_node);
}
#endif
@@ -927,8 +927,8 @@ Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Cal
v[i] = *p_args[i + 3];
}
- static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5");
- call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4]);
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
+ call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
return Variant();
}
@@ -947,8 +947,8 @@ Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable:
v[i] = *p_args[i + 2];
}
- static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5");
- call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4]);
+ static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
+ call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
return Variant();
}
@@ -1097,7 +1097,7 @@ Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) {
ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE);
}
- call_deferred("_change_scene", new_scene);
+ call_deferred(SNAME("_change_scene"), new_scene);
return OK;
}
@@ -1142,26 +1142,6 @@ Array SceneTree::get_processed_tweens() {
return ret;
}
-void SceneTree::_network_peer_connected(int p_id) {
- emit_signal("network_peer_connected", p_id);
-}
-
-void SceneTree::_network_peer_disconnected(int p_id) {
- emit_signal("network_peer_disconnected", p_id);
-}
-
-void SceneTree::_connected_to_server() {
- emit_signal("connected_to_server");
-}
-
-void SceneTree::_connection_failed() {
- emit_signal("connection_failed");
-}
-
-void SceneTree::_server_disconnected() {
- emit_signal("server_disconnected");
-}
-
Ref<MultiplayerAPI> SceneTree::get_multiplayer() const {
return multiplayer;
}
@@ -1177,58 +1157,8 @@ bool SceneTree::is_multiplayer_poll_enabled() const {
void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
ERR_FAIL_COND(!p_multiplayer.is_valid());
- if (multiplayer.is_valid()) {
- multiplayer->disconnect("network_peer_connected", callable_mp(this, &SceneTree::_network_peer_connected));
- multiplayer->disconnect("network_peer_disconnected", callable_mp(this, &SceneTree::_network_peer_disconnected));
- multiplayer->disconnect("connected_to_server", callable_mp(this, &SceneTree::_connected_to_server));
- multiplayer->disconnect("connection_failed", callable_mp(this, &SceneTree::_connection_failed));
- multiplayer->disconnect("server_disconnected", callable_mp(this, &SceneTree::_server_disconnected));
- }
-
multiplayer = p_multiplayer;
multiplayer->set_root_node(root);
-
- multiplayer->connect("network_peer_connected", callable_mp(this, &SceneTree::_network_peer_connected));
- multiplayer->connect("network_peer_disconnected", callable_mp(this, &SceneTree::_network_peer_disconnected));
- multiplayer->connect("connected_to_server", callable_mp(this, &SceneTree::_connected_to_server));
- multiplayer->connect("connection_failed", callable_mp(this, &SceneTree::_connection_failed));
- multiplayer->connect("server_disconnected", callable_mp(this, &SceneTree::_server_disconnected));
-}
-
-void SceneTree::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer) {
- multiplayer->set_network_peer(p_network_peer);
-}
-
-Ref<NetworkedMultiplayerPeer> SceneTree::get_network_peer() const {
- return multiplayer->get_network_peer();
-}
-
-bool SceneTree::is_network_server() const {
- return multiplayer->is_network_server();
-}
-
-bool SceneTree::has_network_peer() const {
- return multiplayer->has_network_peer();
-}
-
-int SceneTree::get_network_unique_id() const {
- return multiplayer->get_network_unique_id();
-}
-
-Vector<int> SceneTree::get_network_connected_peers() const {
- return multiplayer->get_network_connected_peers();
-}
-
-int SceneTree::get_rpc_sender_id() const {
- return multiplayer->get_rpc_sender_id();
-}
-
-void SceneTree::set_refuse_new_network_connections(bool p_refuse) {
- multiplayer->set_refuse_new_network_connections(p_refuse);
-}
-
-bool SceneTree::is_refusing_new_network_connections() const {
- return multiplayer->is_refusing_new_network_connections();
}
void SceneTree::_bind_methods() {
@@ -1297,24 +1227,12 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer);
ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled);
- ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &SceneTree::set_network_peer);
- ClassDB::bind_method(D_METHOD("get_network_peer"), &SceneTree::get_network_peer);
- ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server);
- ClassDB::bind_method(D_METHOD("has_network_peer"), &SceneTree::has_network_peer);
- ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &SceneTree::get_network_connected_peers);
- ClassDB::bind_method(D_METHOD("get_network_unique_id"), &SceneTree::get_network_unique_id);
- ClassDB::bind_method(D_METHOD("get_rpc_sender_id"), &SceneTree::get_rpc_sender_id);
- ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections);
- ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
- ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", PROPERTY_USAGE_NONE), "set_network_peer", "get_network_peer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_root");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_multiplayer", "get_multiplayer");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
@@ -1330,11 +1248,6 @@ void SceneTree::_bind_methods() {
ADD_SIGNAL(MethodInfo("physics_frame"));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen")));
- ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("connected_to_server"));
- ADD_SIGNAL(MethodInfo("connection_failed"));
- ADD_SIGNAL(MethodInfo("server_disconnected"));
BIND_ENUM_CONSTANT(GROUP_CALL_DEFAULT);
BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE);
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 0e9ffb0f5f..0be0e185a5 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -159,13 +159,6 @@ private:
Ref<MultiplayerAPI> multiplayer;
bool multiplayer_poll = true;
- void _network_peer_connected(int p_id);
- void _network_peer_disconnected(int p_id);
-
- void _connected_to_server();
- void _connection_failed();
- void _server_disconnected();
-
static SceneTree *singleton;
friend class Node;
@@ -337,16 +330,6 @@ public:
void set_multiplayer_poll_enabled(bool p_enabled);
bool is_multiplayer_poll_enabled() const;
void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
- void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer);
- Ref<NetworkedMultiplayerPeer> get_network_peer() const;
- bool is_network_server() const;
- bool has_network_peer() const;
- int get_network_unique_id() const;
- Vector<int> get_network_connected_peers() const;
- int get_rpc_sender_id() const;
-
- void set_refuse_new_network_connections(bool p_refuse);
- bool is_refusing_new_network_connections() const;
static void add_idle_callback(IdleCallback p_callback);
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index 3d65c12cb7..d22a6b2875 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -63,7 +63,12 @@ bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_valu
if (o) {
o->override = p_value;
if (active) {
- RS::get_singleton()->global_variable_set_override(*r, p_value);
+ if (o->override.get_type() == Variant::OBJECT) {
+ RID tex_rid = p_value;
+ RS::get_singleton()->global_variable_set_override(*r, tex_rid);
+ } else {
+ RS::get_singleton()->global_variable_set_override(*r, p_value);
+ }
}
o->in_use = p_value.get_type() != Variant::NIL;
return true;
@@ -228,7 +233,12 @@ void ShaderGlobalsOverride::_activate() {
while ((K = overrides.next(K))) {
Override *o = overrides.getptr(*K);
if (o->in_use && o->override.get_type() != Variant::NIL) {
- RS::get_singleton()->global_variable_set_override(*K, o->override);
+ if (o->override.get_type() == Variant::OBJECT) {
+ RID tex_rid = o->override;
+ RS::get_singleton()->global_variable_set_override(*K, tex_rid);
+ } else {
+ RS::get_singleton()->global_variable_set_override(*K, o->override);
+ }
}
}
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index a5ceec9c8b..ef8245076f 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -37,7 +37,7 @@ void Timer::_notification(int p_what) {
case NOTIFICATION_READY: {
if (autostart) {
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) {
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
break;
}
#endif
@@ -58,7 +58,7 @@ void Timer::_notification(int p_what) {
stop();
}
- emit_signal("timeout");
+ emit_signal(SNAME("timeout"));
}
} break;
@@ -74,7 +74,7 @@ void Timer::_notification(int p_what) {
} else {
stop();
}
- emit_signal("timeout");
+ emit_signal(SNAME("timeout"));
}
} break;
@@ -207,7 +207,7 @@ void Timer::_bind_methods() {
ADD_SIGNAL(MethodInfo("timeout"));
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_timer_process_callback", "get_timer_process_callback");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.001,4096,0.001,or_greater"), "set_wait_time", "get_wait_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wait_time", PROPERTY_HINT_RANGE, "0.001,4096,0.001,or_greater,exp"), "set_wait_time", "get_wait_time");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "is_one_shot");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "has_autostart");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_paused", "is_paused");
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 4c9c1c0055..5a0a27520b 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -37,6 +37,7 @@
#include "core/os/os.h"
#include "core/string/translation.h"
+#include "scene/2d/camera_2d.h"
#include "scene/2d/collision_object_2d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_object_3d.h"
@@ -195,7 +196,7 @@ void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera
return; //discarded
}
}
- p_object->_input_event(camera, p_input_event, p_pos, p_normal, p_shape);
+ p_object->_input_event(camera_3d, p_input_event, p_pos, p_normal, p_shape);
physics_last_object_transform = object_transform;
physics_last_camera_transform = camera_transform;
physics_last_id = id;
@@ -248,16 +249,16 @@ void Viewport::_sub_window_update(Window *p_window) {
Rect2i r = Rect2i(p_window->get_position(), sw.window->get_size());
if (!p_window->get_flag(Window::FLAG_BORDERLESS)) {
- Ref<StyleBox> panel = p_window->get_theme_stylebox("panel_window");
+ Ref<StyleBox> panel = p_window->get_theme_stylebox(SNAME("panel_window"));
panel->draw(sw.canvas_item, r);
// Draw the title bar text.
- Ref<Font> title_font = p_window->get_theme_font("title_font");
- int font_size = p_window->get_theme_font_size("title_font_size");
- Color title_color = p_window->get_theme_color("title_color");
- int title_height = p_window->get_theme_constant("title_height");
- int close_h_ofs = p_window->get_theme_constant("close_h_ofs");
- int close_v_ofs = p_window->get_theme_constant("close_v_ofs");
+ Ref<Font> title_font = p_window->get_theme_font(SNAME("title_font"));
+ int font_size = p_window->get_theme_font_size(SNAME("title_font_size"));
+ Color title_color = p_window->get_theme_color(SNAME("title_color"));
+ int title_height = p_window->get_theme_constant(SNAME("title_height"));
+ int close_h_ofs = p_window->get_theme_constant(SNAME("close_h_ofs"));
+ int close_v_ofs = p_window->get_theme_constant(SNAME("close_v_ofs"));
TextLine title_text = TextLine(p_window->get_title(), title_font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs);
@@ -265,8 +266,8 @@ void Viewport::_sub_window_update(Window *p_window) {
int x = (r.size.width - title_text.get_size().x) / 2;
int y = (-title_height - title_text.get_size().y) / 2;
- Color font_outline_color = p_window->get_theme_color("title_outline_modulate");
- int outline_size = p_window->get_theme_constant("title_outline_size");
+ Color font_outline_color = p_window->get_theme_color(SNAME("title_outline_modulate"));
+ int outline_size = p_window->get_theme_constant(SNAME("title_outline_size"));
if (outline_size > 0 && font_outline_color.a > 0) {
title_text.draw_outline(sw.canvas_item, r.position + Point2(x, y), outline_size, font_outline_color);
}
@@ -444,6 +445,7 @@ void Viewport::_notification(int p_what) {
RenderingServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh);
RenderingServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world_3d()->get_scenario());
//RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
+ set_physics_process_internal(true);
}
} break;
@@ -462,7 +464,7 @@ void Viewport::_notification(int p_what) {
}
}
- if (cameras.size() && !camera) {
+ if (cameras.size() && !camera_3d) {
//there are cameras but no current camera, pick first in tree and make it current
Camera3D *first = nullptr;
for (Set<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
@@ -477,10 +479,6 @@ void Viewport::_notification(int p_what) {
}
#endif
- // Enable processing for tooltips, collision debugging, physics object picking, etc.
- set_process_internal(true);
- set_physics_process_internal(true);
-
} break;
case NOTIFICATION_EXIT_TREE: {
_gui_cancel_tooltip();
@@ -500,6 +498,7 @@ void Viewport::_notification(int p_what) {
}
remove_from_group("_viewports");
+ set_physics_process_internal(false);
RS::get_singleton()->viewport_set_active(viewport, false);
RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, RID());
@@ -510,6 +509,7 @@ void Viewport::_notification(int p_what) {
gui.tooltip_timer -= get_process_delta_time();
if (gui.tooltip_timer < 0) {
_gui_show_tooltip();
+ set_process_internal(false);
}
}
@@ -706,7 +706,6 @@ void Viewport::_process_picking() {
bool send_event = true;
if (is_mouse) {
Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
-
if (!F) {
physics_2d_mouseover.insert(res[i].collider_id, frame);
co->_mouse_enter();
@@ -717,6 +716,13 @@ void Viewport::_process_picking() {
send_event = false;
}
}
+ Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *SF = physics_2d_shape_mouseover.find(Pair(res[i].collider_id, res[i].shape));
+ if (!SF) {
+ physics_2d_shape_mouseover.insert(Pair(res[i].collider_id, res[i].shape), frame);
+ co->_mouse_shape_enter(res[i].shape);
+ } else {
+ SF->get() = frame;
+ }
}
if (send_event) {
@@ -728,25 +734,7 @@ void Viewport::_process_picking() {
}
if (is_mouse) {
- List<Map<ObjectID, uint64_t>::Element *> to_erase;
-
- for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
- if (E->get() != frame) {
- Object *o = ObjectDB::get_instance(E->key());
- if (o) {
- CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
- if (co) {
- co->_mouse_exit();
- }
- }
- to_erase.push_back(E);
- }
- }
-
- while (to_erase.size()) {
- physics_2d_mouseover.erase(to_erase.front()->get());
- to_erase.pop_front();
- }
+ _cleanup_mouseover_colliders(false, false, frame);
}
}
@@ -755,8 +743,8 @@ void Viewport::_process_picking() {
if (physics_object_capture.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture));
- if (co && camera) {
- _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0);
+ if (co && camera_3d) {
+ _collision_object_input_event(co, camera_3d, ev, Vector3(), Vector3(), 0);
captured = true;
if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
physics_object_capture = ObjectID();
@@ -773,16 +761,16 @@ void Viewport::_process_picking() {
if (last_id.is_valid()) {
if (ObjectDB::get_instance(last_id) && last_object) {
//good, exists
- _collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape);
+ _collision_object_input_event(last_object, camera_3d, ev, result.position, result.normal, result.shape);
if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
physics_object_capture = last_id;
}
}
}
} else {
- if (camera) {
- Vector3 from = camera->project_ray_origin(pos);
- Vector3 dir = camera->project_ray_normal(pos);
+ if (camera_3d) {
+ Vector3 from = camera_3d->project_ray_origin(pos);
+ Vector3 dir = camera_3d->project_ray_normal(pos);
PhysicsDirectSpaceState3D *space = PhysicsServer3D::get_singleton()->space_get_direct_state(find_world_3d()->get_space());
if (space) {
@@ -790,8 +778,8 @@ void Viewport::_process_picking() {
ObjectID new_collider;
if (col) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider);
- if (co && co->can_process()) {
- _collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape);
+ if (co) {
+ _collision_object_input_event(co, camera_3d, ev, result.position, result.normal, result.shape);
last_object = co;
last_id = result.collider_id;
new_collider = last_id;
@@ -859,7 +847,7 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
update_canvas_items();
- emit_signal("size_changed");
+ emit_signal(SNAME("size_changed"));
}
Size2i Viewport::_get_size() const {
@@ -929,6 +917,15 @@ bool Viewport::is_audio_listener_2d() const {
return audio_listener_2d;
}
+void Viewport::set_disable_3d(bool p_disable) {
+ disable_3d = p_disable;
+ RenderingServer::get_singleton()->viewport_set_disable_3d(viewport, disable_3d);
+}
+
+bool Viewport::is_3d_disabled() const {
+ return disable_3d;
+}
+
void Viewport::enable_canvas_transform_override(bool p_enable) {
if (override_canvas_transform == p_enable) {
return;
@@ -1036,64 +1033,68 @@ void Viewport::_listener_make_next_current(Listener3D *p_exclude) {
}
} else {
// Attempt to reset listener to the camera position
- if (camera != nullptr) {
+ if (camera_3d != nullptr) {
_update_listener();
- _camera_transform_changed_notify();
+ _camera_3d_transform_changed_notify();
}
}
}
#endif
-void Viewport::_camera_transform_changed_notify() {
+void Viewport::_camera_3d_transform_changed_notify() {
#ifndef _3D_DISABLED
#endif
}
-void Viewport::_camera_set(Camera3D *p_camera) {
+void Viewport::_camera_3d_set(Camera3D *p_camera) {
#ifndef _3D_DISABLED
- if (camera == p_camera) {
+ if (camera_3d == p_camera) {
return;
}
- if (camera) {
- camera->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ if (camera_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
}
- camera = p_camera;
+ camera_3d = p_camera;
if (!camera_override) {
- if (camera) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
+ if (camera_3d) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
} else {
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
}
}
- if (camera) {
- camera->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
+ if (camera_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
}
_update_listener();
- _camera_transform_changed_notify();
+ _camera_3d_transform_changed_notify();
#endif
}
-bool Viewport::_camera_add(Camera3D *p_camera) {
+void Viewport::_camera_2d_set(Camera2D *p_camera_2d) {
+ camera_2d = p_camera_2d;
+}
+
+bool Viewport::_camera_3d_add(Camera3D *p_camera) {
cameras.insert(p_camera);
return cameras.size() == 1;
}
-void Viewport::_camera_remove(Camera3D *p_camera) {
+void Viewport::_camera_3d_remove(Camera3D *p_camera) {
cameras.erase(p_camera);
- if (camera == p_camera) {
- camera->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
- camera = nullptr;
+ if (camera_3d == p_camera) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ camera_3d = nullptr;
}
}
#ifndef _3D_DISABLED
-void Viewport::_camera_make_next_current(Camera3D *p_exclude) {
+void Viewport::_camera_3d_make_next_current(Camera3D *p_exclude) {
for (Set<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
if (p_exclude == E->get()) {
continue;
@@ -1101,7 +1102,7 @@ void Viewport::_camera_make_next_current(Camera3D *p_exclude) {
if (!E->get()->is_inside_tree()) {
continue;
}
- if (camera != nullptr) {
+ if (camera_3d != nullptr) {
return;
}
@@ -1290,8 +1291,12 @@ Listener3D *Viewport::get_listener() const {
return listener;
}
-Camera3D *Viewport::get_camera() const {
- return camera;
+Camera3D *Viewport::get_camera_3d() const {
+ return camera_3d;
+}
+
+Camera2D *Viewport::get_camera_2d() const {
+ return camera_2d;
}
void Viewport::enable_camera_override(bool p_enable) {
@@ -1309,8 +1314,8 @@ void Viewport::enable_camera_override(bool p_enable) {
if (p_enable) {
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid);
- } else if (camera) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
+ } else if (camera_3d) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
} else {
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
}
@@ -1485,6 +1490,7 @@ void Viewport::_gui_sort_roots() {
void Viewport::_gui_cancel_tooltip() {
gui.tooltip_control = nullptr;
gui.tooltip_timer = -1;
+ set_process_internal(false);
if (gui.tooltip_popup) {
gui.tooltip_popup->queue_delete();
gui.tooltip_popup = nullptr;
@@ -1553,6 +1559,9 @@ void Viewport::_gui_show_tooltip() {
return;
}
+ // Popup window which houses the tooltip content.
+ TooltipPanel *panel = memnew(TooltipPanel);
+
// Controls can implement `make_custom_tooltip` to provide their own tooltip.
// This should be a Control node which will be added as child to a TooltipPanel.
Control *base_tooltip = tooltip_owner->make_custom_tooltip(tooltip_text);
@@ -1562,11 +1571,11 @@ void Viewport::_gui_show_tooltip() {
gui.tooltip_label = memnew(TooltipLabel);
gui.tooltip_label->set_text(tooltip_text);
base_tooltip = gui.tooltip_label;
+ panel->connect("mouse_entered", callable_mp(this, &Viewport::_gui_cancel_tooltip));
}
base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
- TooltipPanel *panel = memnew(TooltipPanel);
panel->set_transient(false);
panel->set_flag(Window::FLAG_NO_FOCUS, true);
panel->set_wrap_controls(true);
@@ -1770,7 +1779,7 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
}
Control *drag_preview = _gui_get_drag_preview();
- if (!drag_preview || (c != drag_preview && !drag_preview->is_a_parent_of(c))) {
+ if (!drag_preview || (c != drag_preview && !drag_preview->is_ancestor_of(c))) {
r_inv_xform = matrix;
return c;
}
@@ -2133,6 +2142,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.tooltip_control = over;
gui.tooltip_pos = over->get_screen_transform().xform(pos);
gui.tooltip_timer = gui.tooltip_delay;
+ set_process_internal(true);
}
}
@@ -2214,7 +2224,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Window *sw = embedder->gui.sub_windows[i].window;
Rect2 swrect = Rect2i(sw->get_position(), sw->get_size());
if (!sw->get_flag(Window::FLAG_BORDERLESS)) {
- int title_height = sw->get_theme_constant("title_height");
+ int title_height = sw->get_theme_constant(SNAME("title_height"));
swrect.position.y -= title_height;
swrect.size.y += title_height;
}
@@ -2563,7 +2573,7 @@ void Viewport::_gui_control_grab_focus(Control *p_control) {
}
get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus_for_window", (Node *)get_base_window());
gui.key_focus = p_control;
- emit_signal("gui_focus_changed", p_control);
+ emit_signal(SNAME("gui_focus_changed"), p_control);
p_control->notification(Control::NOTIFICATION_FOCUS_ENTER);
p_control->update();
}
@@ -2598,20 +2608,41 @@ void Viewport::_drop_mouse_focus() {
void Viewport::_drop_physics_mouseover(bool p_paused_only) {
physics_has_last_mousepos = false;
+ _cleanup_mouseover_colliders(true, p_paused_only);
+
+#ifndef _3D_DISABLED
+ if (physics_object_over.is_valid()) {
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
+ if (co) {
+ if (!(p_paused_only && co->can_process())) {
+ co->_mouse_exit();
+ physics_object_over = ObjectID();
+ physics_object_capture = ObjectID();
+ }
+ }
+ }
+#endif
+}
+
+void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference) {
List<Map<ObjectID, uint64_t>::Element *> to_erase;
for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
+ if (!p_clean_all_frames && E->get() == p_frame_reference) {
+ continue;
+ }
+
Object *o = ObjectDB::get_instance(E->key());
if (o) {
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
if (co) {
- if (p_paused_only && co->can_process()) {
+ if (p_clean_all_frames && p_paused_only && co->can_process()) {
continue;
}
co->_mouse_exit();
- to_erase.push_back(E);
}
}
+ to_erase.push_back(E);
}
while (to_erase.size()) {
@@ -2619,18 +2650,31 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
to_erase.pop_front();
}
-#ifndef _3D_DISABLED
- if (physics_object_over.is_valid()) {
- CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
- if (co) {
- if (!(p_paused_only && co->can_process())) {
- co->_mouse_exit();
- physics_object_over = ObjectID();
- physics_object_capture = ObjectID();
+ // Per-shape
+ List<Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *> shapes_to_erase;
+
+ for (Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *E = physics_2d_shape_mouseover.front(); E; E = E->next()) {
+ if (!p_clean_all_frames && E->get() == p_frame_reference) {
+ continue;
+ }
+
+ Object *o = ObjectDB::get_instance(E->key().first);
+ if (o) {
+ CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
+ if (co) {
+ if (p_clean_all_frames && p_paused_only && co->can_process()) {
+ continue;
+ }
+ co->_mouse_shape_exit(E->key().second);
}
}
+ shapes_to_erase.push_back(E);
+ }
+
+ while (shapes_to_erase.size()) {
+ physics_2d_shape_mouseover.erase(shapes_to_erase.front()->get());
+ shapes_to_erase.pop_front();
}
-#endif
}
Control *Viewport::_gui_get_focus_owner() {
@@ -2639,7 +2683,7 @@ Control *Viewport::_gui_get_focus_owner() {
void Viewport::_gui_grab_click_focus(Control *p_control) {
gui.mouse_click_grabber = p_control;
- call_deferred("_post_gui_grab_click_focus");
+ call_deferred(SNAME("_post_gui_grab_click_focus"));
}
void Viewport::_post_gui_grab_click_focus() {
@@ -2712,7 +2756,7 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw
Rect2i r = Rect2i(p_subwindow->get_position(), p_subwindow->get_size());
- int title_height = p_subwindow->get_theme_constant("title_height");
+ int title_height = p_subwindow->get_theme_constant(SNAME("title_height"));
r.position.y -= title_height;
r.size.y += title_height;
@@ -2724,7 +2768,7 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw
int dist_x = p_point.x < r.position.x ? (p_point.x - r.position.x) : (p_point.x > (r.position.x + r.size.x) ? (p_point.x - (r.position.x + r.size.x)) : 0);
int dist_y = p_point.y < r.position.y ? (p_point.y - r.position.y) : (p_point.y > (r.position.y + r.size.y) ? (p_point.y - (r.position.y + r.size.y)) : 0);
- int limit = p_subwindow->get_theme_constant("resize_margin");
+ int limit = p_subwindow->get_theme_constant(SNAME("resize_margin"));
if (ABS(dist_x) > limit) {
return SUB_WINDOW_RESIZE_DISABLED;
@@ -2806,7 +2850,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
new_rect.position.x = 0;
}
- int title_height = gui.subwindow_focused->get_flag(Window::FLAG_BORDERLESS) ? 0 : gui.subwindow_focused->get_theme_constant("title_height");
+ int title_height = gui.subwindow_focused->get_flag(Window::FLAG_BORDERLESS) ? 0 : gui.subwindow_focused->get_theme_constant(SNAME("title_height"));
if (new_rect.position.y < title_height) {
new_rect.position.y = title_height;
@@ -2910,7 +2954,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
if (!sw.window->get_flag(Window::FLAG_BORDERLESS)) {
//check top bar
- int title_height = sw.window->get_theme_constant("title_height");
+ int title_height = sw.window->get_theme_constant(SNAME("title_height"));
Rect2i title_bar = r;
title_bar.position.y -= title_height;
title_bar.size.y = title_height;
@@ -2918,9 +2962,9 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
if (title_bar.has_point(mb->get_position())) {
click_on_window = true;
- int close_h_ofs = sw.window->get_theme_constant("close_h_ofs");
- int close_v_ofs = sw.window->get_theme_constant("close_v_ofs");
- Ref<Texture2D> close_icon = sw.window->get_theme_icon("close");
+ int close_h_ofs = sw.window->get_theme_constant(SNAME("close_h_ofs"));
+ int close_v_ofs = sw.window->get_theme_constant(SNAME("close_v_ofs"));
+ Ref<Texture2D> close_icon = sw.window->get_theme_icon(SNAME("close"));
Rect2 close_rect;
close_rect.position = Vector2(r.position.x + r.size.x - close_v_ofs, r.position.y - close_h_ofs);
@@ -3023,7 +3067,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
return;
}
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this)) {
return;
}
@@ -3065,7 +3109,7 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
return;
}
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this)) {
return;
}
@@ -3138,8 +3182,13 @@ bool Viewport::is_using_own_world_3d() const {
void Viewport::set_physics_object_picking(bool p_enable) {
physics_object_picking = p_enable;
- if (!physics_object_picking) {
+ if (physics_object_picking) {
+ add_to_group("_picking_viewports");
+ } else {
physics_picking_events.clear();
+ if (is_in_group("_picking_viewports")) {
+ remove_from_group("_picking_viewports");
+ }
}
}
@@ -3259,8 +3308,8 @@ Viewport::DebugDraw Viewport::get_debug_draw() const {
return debug_draw;
}
-int Viewport::get_render_info(RenderInfo p_info) {
- return RS::get_singleton()->viewport_get_render_info(viewport, RS::ViewportRenderInfo(p_info));
+int Viewport::get_render_info(RenderInfoType p_type, RenderInfo p_info) {
+ return RS::get_singleton()->viewport_get_render_info(viewport, RS::ViewportRenderInfoType(p_type), RS::ViewportRenderInfo(p_info));
}
void Viewport::set_snap_controls_to_pixels(bool p_enable) {
@@ -3490,7 +3539,7 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw);
ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw);
- ClassDB::bind_method(D_METHOD("get_render_info", "info"), &Viewport::get_render_info);
+ ClassDB::bind_method(D_METHOD("get_render_info", "type", "info"), &Viewport::get_render_info);
ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr);
ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
@@ -3508,7 +3557,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &Viewport::set_use_own_world_3d);
ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &Viewport::is_using_own_world_3d);
- ClassDB::bind_method(D_METHOD("get_camera"), &Viewport::get_camera);
+ ClassDB::bind_method(D_METHOD("get_camera_3d"), &Viewport::get_camera_3d);
+ ClassDB::bind_method(D_METHOD("get_camera_2d"), &Viewport::get_camera_2d);
ClassDB::bind_method(D_METHOD("set_as_audio_listener", "enable"), &Viewport::set_as_audio_listener);
ClassDB::bind_method(D_METHOD("is_audio_listener"), &Viewport::is_audio_listener);
@@ -3516,6 +3566,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d);
+ ClassDB::bind_method(D_METHOD("set_disable_3d", "disable"), &Viewport::set_disable_3d);
+ ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
+
ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position);
ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse);
@@ -3582,6 +3635,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");
ADD_GROUP("Rendering", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"), "set_msaa", "get_msaa");
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), "set_screen_space_aa", "get_screen_space_aa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
@@ -3637,13 +3691,14 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(SCREEN_SPACE_AA_MAX);
BIND_ENUM_CONSTANT(RENDER_INFO_OBJECTS_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_VERTICES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_SHADER_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_SURFACE_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDER_INFO_PRIMITIVES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_MAX);
+ BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_VISIBLE);
+ BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_SHADOW);
+ BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_MAX);
+
BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLED);
BIND_ENUM_CONSTANT(DEBUG_DRAW_UNSHADED);
BIND_ENUM_CONSTANT(DEBUG_DRAW_LIGHTING);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index d905e44a82..7b7f1c3818 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -32,6 +32,7 @@
#define VIEWPORT_H
#include "core/math/transform_2d.h"
+#include "core/templates/pair.h"
#include "scene/main/node.h"
#include "scene/resources/texture.h"
#include "scene/resources/world_2d.h"
@@ -115,14 +116,17 @@ public:
enum RenderInfo {
RENDER_INFO_OBJECTS_IN_FRAME,
- RENDER_INFO_VERTICES_IN_FRAME,
- RENDER_INFO_MATERIAL_CHANGES_IN_FRAME,
- RENDER_INFO_SHADER_CHANGES_IN_FRAME,
- RENDER_INFO_SURFACE_CHANGES_IN_FRAME,
+ RENDER_INFO_PRIMITIVES_IN_FRAME,
RENDER_INFO_DRAW_CALLS_IN_FRAME,
RENDER_INFO_MAX
};
+ enum RenderInfoType {
+ RENDER_INFO_TYPE_VISIBLE,
+ RENDER_INFO_TYPE_SHADOW,
+ RENDER_INFO_TYPE_MAX
+ };
+
enum DebugDraw {
DEBUG_DRAW_DISABLED,
DEBUG_DRAW_UNSHADED,
@@ -210,7 +214,8 @@ private:
}
} camera_override;
- Camera3D *camera = nullptr;
+ Camera3D *camera_3d = nullptr;
+ Camera2D *camera_2d = nullptr;
Set<Camera3D *> cameras;
Set<CanvasLayer *> canvas_layers;
@@ -273,7 +278,12 @@ private:
bool handle_input_locally = true;
bool local_input_handled = false;
+ // Collider to frame
Map<ObjectID, uint64_t> physics_2d_mouseover;
+ // Collider & shape to frame
+ Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>> physics_2d_shape_mouseover;
+ // Cleans up colliders corresponding to old frames or all of them.
+ void _cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference = 0);
Ref<World2D> world_2d;
Ref<World3D> world_3d;
@@ -288,6 +298,8 @@ private:
void _update_listener();
void _update_listener_2d();
+ bool disable_3d = false;
+
void _propagate_enter_world(Node *p_node);
void _propagate_exit_world(Node *p_node);
void _propagate_viewport_notification(Node *p_node, int p_what);
@@ -439,11 +451,14 @@ private:
void _listener_make_next_current(Listener3D *p_exclude);
friend class Camera3D;
- void _camera_transform_changed_notify();
- void _camera_set(Camera3D *p_camera);
- bool _camera_add(Camera3D *p_camera); //true if first
- void _camera_remove(Camera3D *p_camera);
- void _camera_make_next_current(Camera3D *p_exclude);
+ void _camera_3d_transform_changed_notify();
+ void _camera_3d_set(Camera3D *p_camera);
+ bool _camera_3d_add(Camera3D *p_camera); //true if first
+ void _camera_3d_remove(Camera3D *p_camera);
+ void _camera_3d_make_next_current(Camera3D *p_exclude);
+
+ friend class Camera2D;
+ void _camera_2d_set(Camera2D *p_camera_2d);
friend class CanvasLayer;
void _canvas_layer_add(CanvasLayer *p_canvas_layer);
@@ -486,7 +501,8 @@ public:
uint64_t get_processed_events_count() const { return event_count; }
Listener3D *get_listener() const;
- Camera3D *get_camera() const;
+ Camera3D *get_camera_3d() const;
+ Camera2D *get_camera_2d() const;
void enable_camera_override(bool p_enable);
bool is_camera_override_enabled() const;
@@ -503,6 +519,9 @@ public:
void set_as_audio_listener_2d(bool p_enable);
bool is_audio_listener_2d() const;
+ void set_disable_3d(bool p_disable);
+ bool is_3d_disabled() const;
+
void update_canvas_items();
Rect2 get_visible_rect() const;
@@ -591,7 +610,7 @@ public:
void set_debug_draw(DebugDraw p_debug_draw);
DebugDraw get_debug_draw() const;
- int get_render_info(RenderInfo p_info);
+ int get_render_info(RenderInfoType p_type, RenderInfo p_info);
void set_snap_controls_to_pixels(bool p_enable);
bool is_snap_controls_to_pixels_enabled() const;
@@ -694,6 +713,7 @@ VARIANT_ENUM_CAST(Viewport::SDFScale);
VARIANT_ENUM_CAST(Viewport::SDFOversize);
VARIANT_ENUM_CAST(SubViewport::ClearMode);
VARIANT_ENUM_CAST(Viewport::RenderInfo);
+VARIANT_ENUM_CAST(Viewport::RenderInfoType);
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter);
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureRepeat);
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index d793be1869..bf7512e8eb 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -115,7 +115,7 @@ Size2i Window::get_max_size() const {
void Window::set_min_size(const Size2i &p_min_size) {
min_size = p_min_size;
- if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ if (!wrap_controls && window_id != DisplayServer::INVALID_WINDOW_ID) {
DisplayServer::get_singleton()->window_set_min_size(min_size, window_id);
}
_update_window_size();
@@ -227,7 +227,8 @@ void Window::_make_window() {
}
}
- window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), f, Rect2i(position, size));
+ DisplayServer::VSyncMode vsync_mode = DisplayServer::get_singleton()->window_get_vsync_mode(DisplayServer::MAIN_WINDOW_ID);
+ window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size));
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id);
DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
@@ -312,39 +313,39 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
switch (p_event) {
case DisplayServer::WINDOW_EVENT_MOUSE_ENTER: {
_propagate_window_notification(this, NOTIFICATION_WM_MOUSE_ENTER);
- emit_signal("mouse_entered");
+ emit_signal(SNAME("mouse_entered"));
DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_ARROW); //restore cursor shape
} break;
case DisplayServer::WINDOW_EVENT_MOUSE_EXIT: {
_propagate_window_notification(this, NOTIFICATION_WM_MOUSE_EXIT);
- emit_signal("mouse_exited");
+ emit_signal(SNAME("mouse_exited"));
} break;
case DisplayServer::WINDOW_EVENT_FOCUS_IN: {
focused = true;
_propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_IN);
- emit_signal("focus_entered");
+ emit_signal(SNAME("focus_entered"));
} break;
case DisplayServer::WINDOW_EVENT_FOCUS_OUT: {
focused = false;
_propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_OUT);
- emit_signal("focus_exited");
+ emit_signal(SNAME("focus_exited"));
} break;
case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: {
if (exclusive_child != nullptr) {
break; //has an exclusive child, can't get events until child is closed
}
_propagate_window_notification(this, NOTIFICATION_WM_CLOSE_REQUEST);
- emit_signal("close_requested");
+ emit_signal(SNAME("close_requested"));
} break;
case DisplayServer::WINDOW_EVENT_GO_BACK_REQUEST: {
_propagate_window_notification(this, NOTIFICATION_WM_GO_BACK_REQUEST);
- emit_signal("go_back_requested");
+ emit_signal(SNAME("go_back_requested"));
} break;
case DisplayServer::WINDOW_EVENT_DPI_CHANGE: {
_update_viewport_size();
_propagate_window_notification(this, NOTIFICATION_WM_DPI_CHANGE);
- emit_signal("dpi_changed");
+ emit_signal(SNAME("dpi_changed"));
} break;
}
}
@@ -541,6 +542,7 @@ void Window::_update_window_size() {
embedder->_sub_window_update(this);
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
DisplayServer::get_singleton()->window_set_size(size, window_id);
+ DisplayServer::get_singleton()->window_set_min_size(size_limit, window_id);
}
//update the viewport
@@ -880,7 +882,7 @@ void Window::child_controls_changed() {
}
updating_child_controls = true;
- call_deferred("_update_child_controls");
+ call_deferred(SNAME("_update_child_controls"));
}
bool Window::_can_consume_input_events() const {
@@ -923,7 +925,7 @@ void Window::_window_input_text(const String &p_text) {
}
void Window::_window_drop_files(const Vector<String> &p_files) {
- emit_signal("files_dropped", p_files, current_screen);
+ emit_signal(SNAME("files_dropped"), p_files, current_screen);
}
Viewport *Window::get_parent_viewport() const {
@@ -1041,7 +1043,7 @@ void Window::popup_centered_ratio(float p_ratio) {
}
void Window::popup(const Rect2i &p_screen_rect) {
- emit_signal("about_to_popup");
+ emit_signal(SNAME("about_to_popup"));
// Update window size to calculate the actual window size based on contents minimum size and minimum size.
_update_window_size();
@@ -1169,23 +1171,24 @@ Ref<Theme> Window::get_theme() const {
return theme;
}
-void Window::set_theme_custom_type(const StringName &p_theme_type) {
- theme_custom_type = p_theme_type;
+void Window::set_theme_type_variation(const StringName &p_theme_type) {
+ theme_type_variation = p_theme_type;
Control::_propagate_theme_changed(this, theme_owner, theme_owner_window);
}
-StringName Window::get_theme_custom_type() const {
- return theme_custom_type;
+StringName Window::get_theme_type_variation() const {
+ return theme_type_variation;
}
void Window::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_custom_type) {
- if (theme_custom_type != StringName()) {
- p_list->push_back(theme_custom_type);
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
+ if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(theme_type_variation) != StringName()) {
+ Theme::get_project_default()->get_type_dependencies(get_class_name(), theme_type_variation, p_list);
+ } else {
+ Theme::get_default()->get_type_dependencies(get_class_name(), theme_type_variation, p_list);
}
- Theme::get_type_dependencies(get_class_name(), p_list);
} else {
- Theme::get_type_dependencies(p_theme_type, p_list);
+ Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list);
}
}
@@ -1322,14 +1325,14 @@ bool Window::is_layout_rtl() const {
if (parent) {
return parent->is_layout_rtl();
} else {
- if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
}
} else if (layout_dir == LAYOUT_DIRECTION_LOCALE) {
- if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
@@ -1339,6 +1342,34 @@ bool Window::is_layout_rtl() const {
}
}
+void Window::_validate_property(PropertyInfo &property) const {
+ if (property.name == "theme_type_variation") {
+ List<StringName> names;
+
+ // Only the default theme and the project theme are used for the list of options.
+ // This is an imposed limitation to simplify the logic needed to leverage those options.
+ Theme::get_default()->get_type_variation_list(get_class_name(), &names);
+ if (Theme::get_project_default().is_valid()) {
+ Theme::get_project_default()->get_type_variation_list(get_class_name(), &names);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+
+ Vector<StringName> unique_names;
+ String hint_string;
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ // Skip duplicate values.
+ if (unique_names.has(E->get())) {
+ continue;
+ }
+
+ hint_string += String(E->get()) + ",";
+ unique_names.append(E->get());
+ }
+
+ property.hint_string = hint_string;
+ }
+}
+
void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
@@ -1393,6 +1424,8 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_embedded"), &Window::is_embedded);
+ ClassDB::bind_method(D_METHOD("get_contents_minimum_size"), &Window::get_contents_minimum_size);
+
ClassDB::bind_method(D_METHOD("set_content_scale_size", "size"), &Window::set_content_scale_size);
ClassDB::bind_method(D_METHOD("get_content_scale_size"), &Window::get_content_scale_size);
@@ -1414,8 +1447,8 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme);
ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme);
- ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Window::set_theme_custom_type);
- ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Window::get_theme_custom_type);
+ ClassDB::bind_method(D_METHOD("set_theme_type_variation", "theme_type"), &Window::set_theme_type_variation);
+ ClassDB::bind_method(D_METHOD("get_theme_type_variation"), &Window::get_theme_type_variation);
ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Window::get_theme_icon, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Window::get_theme_stylebox, DEFVAL(""));
@@ -1465,7 +1498,7 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
ADD_GROUP("Theme", "theme_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_type_variation", PROPERTY_HINT_ENUM_SUGGESTION), "set_theme_type_variation", "get_theme_type_variation");
ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
diff --git a/scene/main/window.h b/scene/main/window.h
index 494c386606..e92b5e22ed 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -130,7 +130,7 @@ private:
Ref<Theme> theme;
Control *theme_owner = nullptr;
Window *theme_owner_window = nullptr;
- StringName theme_custom_type;
+ StringName theme_type_variation;
Viewport *embedder = nullptr;
@@ -151,6 +151,7 @@ protected:
virtual Size2 _get_contents_minimum_size() const;
static void _bind_methods();
void _notification(int p_what);
+ virtual void _validate_property(PropertyInfo &property) const override;
virtual void add_child_notify(Node *p_child) override;
virtual void remove_child_notify(Node *p_child) override;
@@ -242,8 +243,8 @@ public:
void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;
- void set_theme_custom_type(const StringName &p_theme_type);
- StringName get_theme_custom_type() const;
+ void set_theme_type_variation(const StringName &p_theme_type);
+ StringName get_theme_type_variation() const;
_FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
Size2 get_contents_minimum_size() const;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 3a2b34c6c8..2d83f59bb5 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -31,6 +31,7 @@
#include "register_scene_types.h"
#include "core/config/project_settings.h"
+#include "core/extension/native_extension_manager.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
#include "scene/2d/animated_sprite_2d.h"
@@ -146,6 +147,7 @@
#include "scene/resources/font.h"
#include "scene/resources/gradient.h"
#include "scene/resources/height_map_shape_3d.h"
+#include "scene/resources/immediate_mesh.h"
#include "scene/resources/line_shape_2d.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
@@ -203,7 +205,6 @@
#include "scene/3d/decal.h"
#include "scene/3d/gpu_particles_3d.h"
#include "scene/3d/gpu_particles_collision_3d.h"
-#include "scene/3d/immediate_geometry_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/lightmap_gi.h"
#include "scene/3d/lightmap_probe.h"
@@ -291,108 +292,108 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<Object>();
+ GDREGISTER_CLASS(Object);
- ClassDB::register_class<Node>();
- ClassDB::register_virtual_class<InstancePlaceholder>();
+ GDREGISTER_CLASS(Node);
+ GDREGISTER_VIRTUAL_CLASS(InstancePlaceholder);
- ClassDB::register_virtual_class<Viewport>();
- ClassDB::register_class<SubViewport>();
- ClassDB::register_class<ViewportTexture>();
- ClassDB::register_class<HTTPRequest>();
- ClassDB::register_class<Timer>();
- ClassDB::register_class<CanvasLayer>();
- ClassDB::register_class<CanvasModulate>();
- ClassDB::register_class<ResourcePreloader>();
- ClassDB::register_class<Window>();
+ GDREGISTER_VIRTUAL_CLASS(Viewport);
+ GDREGISTER_CLASS(SubViewport);
+ GDREGISTER_CLASS(ViewportTexture);
+ GDREGISTER_CLASS(HTTPRequest);
+ GDREGISTER_CLASS(Timer);
+ GDREGISTER_CLASS(CanvasLayer);
+ GDREGISTER_CLASS(CanvasModulate);
+ GDREGISTER_CLASS(ResourcePreloader);
+ GDREGISTER_CLASS(Window);
/* REGISTER GUI */
- ClassDB::register_class<ButtonGroup>();
- ClassDB::register_virtual_class<BaseButton>();
+ GDREGISTER_CLASS(ButtonGroup);
+ GDREGISTER_VIRTUAL_CLASS(BaseButton);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<Shortcut>();
- ClassDB::register_class<Control>();
- ClassDB::register_class<Button>();
- ClassDB::register_class<Label>();
- ClassDB::register_virtual_class<ScrollBar>();
- ClassDB::register_class<HScrollBar>();
- ClassDB::register_class<VScrollBar>();
- ClassDB::register_class<ProgressBar>();
- ClassDB::register_virtual_class<Slider>();
- ClassDB::register_class<HSlider>();
- ClassDB::register_class<VSlider>();
- ClassDB::register_class<Popup>();
- ClassDB::register_class<PopupPanel>();
- ClassDB::register_class<MenuButton>();
- ClassDB::register_class<CheckBox>();
- ClassDB::register_class<CheckButton>();
- ClassDB::register_class<LinkButton>();
- ClassDB::register_class<Panel>();
- ClassDB::register_virtual_class<Range>();
+ GDREGISTER_CLASS(Shortcut);
+ GDREGISTER_CLASS(Control);
+ GDREGISTER_CLASS(Button);
+ GDREGISTER_CLASS(Label);
+ GDREGISTER_VIRTUAL_CLASS(ScrollBar);
+ GDREGISTER_CLASS(HScrollBar);
+ GDREGISTER_CLASS(VScrollBar);
+ GDREGISTER_CLASS(ProgressBar);
+ GDREGISTER_VIRTUAL_CLASS(Slider);
+ GDREGISTER_CLASS(HSlider);
+ GDREGISTER_CLASS(VSlider);
+ GDREGISTER_CLASS(Popup);
+ GDREGISTER_CLASS(PopupPanel);
+ GDREGISTER_CLASS(MenuButton);
+ GDREGISTER_CLASS(CheckBox);
+ GDREGISTER_CLASS(CheckButton);
+ GDREGISTER_CLASS(LinkButton);
+ GDREGISTER_CLASS(Panel);
+ GDREGISTER_VIRTUAL_CLASS(Range);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<TextureRect>();
- ClassDB::register_class<ColorRect>();
- ClassDB::register_class<NinePatchRect>();
- ClassDB::register_class<ReferenceRect>();
- ClassDB::register_class<AspectRatioContainer>();
- ClassDB::register_class<TabContainer>();
- ClassDB::register_class<Tabs>();
- ClassDB::register_virtual_class<Separator>();
- ClassDB::register_class<HSeparator>();
- ClassDB::register_class<VSeparator>();
- ClassDB::register_class<TextureButton>();
- ClassDB::register_class<Container>();
- ClassDB::register_virtual_class<BoxContainer>();
- ClassDB::register_class<HBoxContainer>();
- ClassDB::register_class<VBoxContainer>();
- ClassDB::register_class<GridContainer>();
- ClassDB::register_class<CenterContainer>();
- ClassDB::register_class<ScrollContainer>();
- ClassDB::register_class<PanelContainer>();
+ GDREGISTER_CLASS(TextureRect);
+ GDREGISTER_CLASS(ColorRect);
+ GDREGISTER_CLASS(NinePatchRect);
+ GDREGISTER_CLASS(ReferenceRect);
+ GDREGISTER_CLASS(AspectRatioContainer);
+ GDREGISTER_CLASS(TabContainer);
+ GDREGISTER_CLASS(Tabs);
+ GDREGISTER_VIRTUAL_CLASS(Separator);
+ GDREGISTER_CLASS(HSeparator);
+ GDREGISTER_CLASS(VSeparator);
+ GDREGISTER_CLASS(TextureButton);
+ GDREGISTER_CLASS(Container);
+ GDREGISTER_VIRTUAL_CLASS(BoxContainer);
+ GDREGISTER_CLASS(HBoxContainer);
+ GDREGISTER_CLASS(VBoxContainer);
+ GDREGISTER_CLASS(GridContainer);
+ GDREGISTER_CLASS(CenterContainer);
+ GDREGISTER_CLASS(ScrollContainer);
+ GDREGISTER_CLASS(PanelContainer);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<TextureProgressBar>();
- ClassDB::register_class<ItemList>();
+ GDREGISTER_CLASS(TextureProgressBar);
+ GDREGISTER_CLASS(ItemList);
- ClassDB::register_class<LineEdit>();
- ClassDB::register_class<VideoPlayer>();
+ GDREGISTER_CLASS(LineEdit);
+ GDREGISTER_CLASS(VideoPlayer);
#ifndef ADVANCED_GUI_DISABLED
- ClassDB::register_class<FileDialog>();
-
- ClassDB::register_class<PopupMenu>();
- ClassDB::register_class<Tree>();
-
- ClassDB::register_class<TextEdit>();
- ClassDB::register_class<CodeEdit>();
- ClassDB::register_class<SyntaxHighlighter>();
- ClassDB::register_class<CodeHighlighter>();
-
- ClassDB::register_virtual_class<TreeItem>();
- ClassDB::register_class<OptionButton>();
- ClassDB::register_class<SpinBox>();
- ClassDB::register_class<ColorPicker>();
- ClassDB::register_class<ColorPickerButton>();
- ClassDB::register_class<RichTextLabel>();
- ClassDB::register_class<RichTextEffect>();
- ClassDB::register_class<CharFXTransform>();
-
- ClassDB::register_class<AcceptDialog>();
- ClassDB::register_class<ConfirmationDialog>();
-
- ClassDB::register_class<MarginContainer>();
- ClassDB::register_class<SubViewportContainer>();
- ClassDB::register_virtual_class<SplitContainer>();
- ClassDB::register_class<HSplitContainer>();
- ClassDB::register_class<VSplitContainer>();
- ClassDB::register_class<GraphNode>();
- ClassDB::register_class<GraphEdit>();
+ GDREGISTER_CLASS(FileDialog);
+
+ GDREGISTER_CLASS(PopupMenu);
+ GDREGISTER_CLASS(Tree);
+
+ GDREGISTER_CLASS(TextEdit);
+ GDREGISTER_CLASS(CodeEdit);
+ GDREGISTER_CLASS(SyntaxHighlighter);
+ GDREGISTER_CLASS(CodeHighlighter);
+
+ GDREGISTER_VIRTUAL_CLASS(TreeItem);
+ GDREGISTER_CLASS(OptionButton);
+ GDREGISTER_CLASS(SpinBox);
+ GDREGISTER_CLASS(ColorPicker);
+ GDREGISTER_CLASS(ColorPickerButton);
+ GDREGISTER_CLASS(RichTextLabel);
+ GDREGISTER_CLASS(RichTextEffect);
+ GDREGISTER_CLASS(CharFXTransform);
+
+ GDREGISTER_CLASS(AcceptDialog);
+ GDREGISTER_CLASS(ConfirmationDialog);
+
+ GDREGISTER_CLASS(MarginContainer);
+ GDREGISTER_CLASS(SubViewportContainer);
+ GDREGISTER_VIRTUAL_CLASS(SplitContainer);
+ GDREGISTER_CLASS(HSplitContainer);
+ GDREGISTER_CLASS(VSplitContainer);
+ GDREGISTER_CLASS(GraphNode);
+ GDREGISTER_CLASS(GraphEdit);
OS::get_singleton()->yield(); //may take time to init
@@ -405,449 +406,451 @@ void register_scene_types() {
/* REGISTER ANIMATION */
- ClassDB::register_class<AnimationPlayer>();
- ClassDB::register_class<Tween>();
- ClassDB::register_virtual_class<Tweener>();
- ClassDB::register_class<PropertyTweener>();
- ClassDB::register_class<IntervalTweener>();
- ClassDB::register_class<CallbackTweener>();
- ClassDB::register_class<MethodTweener>();
-
- ClassDB::register_class<AnimationTree>();
- ClassDB::register_class<AnimationNode>();
- ClassDB::register_class<AnimationRootNode>();
- ClassDB::register_class<AnimationNodeBlendTree>();
- ClassDB::register_class<AnimationNodeBlendSpace1D>();
- ClassDB::register_class<AnimationNodeBlendSpace2D>();
- ClassDB::register_class<AnimationNodeStateMachine>();
- ClassDB::register_class<AnimationNodeStateMachinePlayback>();
-
- ClassDB::register_class<AnimationNodeStateMachineTransition>();
- ClassDB::register_class<AnimationNodeOutput>();
- ClassDB::register_class<AnimationNodeOneShot>();
- ClassDB::register_class<AnimationNodeAnimation>();
- ClassDB::register_class<AnimationNodeAdd2>();
- ClassDB::register_class<AnimationNodeAdd3>();
- ClassDB::register_class<AnimationNodeBlend2>();
- ClassDB::register_class<AnimationNodeBlend3>();
- ClassDB::register_class<AnimationNodeTimeScale>();
- ClassDB::register_class<AnimationNodeTimeSeek>();
- ClassDB::register_class<AnimationNodeTransition>();
-
- ClassDB::register_class<ShaderGlobalsOverride>(); //can be used in any shader
+ GDREGISTER_CLASS(AnimationPlayer);
+ GDREGISTER_CLASS(Tween);
+ GDREGISTER_VIRTUAL_CLASS(Tweener);
+ GDREGISTER_CLASS(PropertyTweener);
+ GDREGISTER_CLASS(IntervalTweener);
+ GDREGISTER_CLASS(CallbackTweener);
+ GDREGISTER_CLASS(MethodTweener);
+
+ GDREGISTER_CLASS(AnimationTree);
+ GDREGISTER_CLASS(AnimationNode);
+ GDREGISTER_CLASS(AnimationRootNode);
+ GDREGISTER_CLASS(AnimationNodeBlendTree);
+ GDREGISTER_CLASS(AnimationNodeBlendSpace1D);
+ GDREGISTER_CLASS(AnimationNodeBlendSpace2D);
+ GDREGISTER_CLASS(AnimationNodeStateMachine);
+ GDREGISTER_CLASS(AnimationNodeStateMachinePlayback);
+
+ GDREGISTER_CLASS(AnimationNodeStateMachineTransition);
+ GDREGISTER_CLASS(AnimationNodeOutput);
+ GDREGISTER_CLASS(AnimationNodeOneShot);
+ GDREGISTER_CLASS(AnimationNodeAnimation);
+ GDREGISTER_CLASS(AnimationNodeAdd2);
+ GDREGISTER_CLASS(AnimationNodeAdd3);
+ GDREGISTER_CLASS(AnimationNodeBlend2);
+ GDREGISTER_CLASS(AnimationNodeBlend3);
+ GDREGISTER_CLASS(AnimationNodeTimeScale);
+ GDREGISTER_CLASS(AnimationNodeTimeSeek);
+ GDREGISTER_CLASS(AnimationNodeTransition);
+
+ GDREGISTER_CLASS(ShaderGlobalsOverride); //can be used in any shader
OS::get_singleton()->yield(); //may take time to init
/* REGISTER 3D */
#ifndef _3D_DISABLED
- ClassDB::register_class<Node3D>();
- ClassDB::register_virtual_class<Node3DGizmo>();
- ClassDB::register_class<Skin>();
- ClassDB::register_virtual_class<SkinReference>();
- ClassDB::register_class<Skeleton3D>();
- ClassDB::register_virtual_class<VisualInstance3D>();
- ClassDB::register_virtual_class<GeometryInstance3D>();
- ClassDB::register_class<Camera3D>();
- ClassDB::register_class<ClippedCamera3D>();
- ClassDB::register_class<Listener3D>();
- ClassDB::register_class<XRCamera3D>();
- ClassDB::register_class<XRController3D>();
- ClassDB::register_class<XRAnchor3D>();
- ClassDB::register_class<XROrigin3D>();
- ClassDB::register_class<MeshInstance3D>();
- ClassDB::register_class<OccluderInstance3D>();
- ClassDB::register_class<Occluder3D>();
- ClassDB::register_class<ImmediateGeometry3D>();
- ClassDB::register_virtual_class<SpriteBase3D>();
- ClassDB::register_class<Sprite3D>();
- ClassDB::register_class<AnimatedSprite3D>();
- ClassDB::register_virtual_class<Light3D>();
- ClassDB::register_class<DirectionalLight3D>();
- ClassDB::register_class<OmniLight3D>();
- ClassDB::register_class<SpotLight3D>();
- ClassDB::register_class<ReflectionProbe>();
- ClassDB::register_class<Decal>();
- ClassDB::register_class<VoxelGI>();
- ClassDB::register_class<VoxelGIData>();
- ClassDB::register_class<LightmapGI>();
- ClassDB::register_class<LightmapGIData>();
- ClassDB::register_class<LightmapProbe>();
- ClassDB::register_virtual_class<Lightmapper>();
- ClassDB::register_class<GPUParticles3D>();
- ClassDB::register_virtual_class<GPUParticlesCollision3D>();
- ClassDB::register_class<GPUParticlesCollisionBox>();
- ClassDB::register_class<GPUParticlesCollisionSphere>();
- ClassDB::register_class<GPUParticlesCollisionSDF>();
- ClassDB::register_class<GPUParticlesCollisionHeightField>();
- ClassDB::register_virtual_class<GPUParticlesAttractor3D>();
- ClassDB::register_class<GPUParticlesAttractorBox>();
- ClassDB::register_class<GPUParticlesAttractorSphere>();
- ClassDB::register_class<GPUParticlesAttractorVectorField>();
- ClassDB::register_class<CPUParticles3D>();
- ClassDB::register_class<Position3D>();
-
- ClassDB::register_class<RootMotionView>();
+ GDREGISTER_CLASS(Node3D);
+ GDREGISTER_VIRTUAL_CLASS(Node3DGizmo);
+ GDREGISTER_CLASS(Skin);
+ GDREGISTER_VIRTUAL_CLASS(SkinReference);
+ GDREGISTER_CLASS(Skeleton3D);
+ GDREGISTER_VIRTUAL_CLASS(VisualInstance3D);
+ GDREGISTER_VIRTUAL_CLASS(GeometryInstance3D);
+ GDREGISTER_CLASS(Camera3D);
+ GDREGISTER_CLASS(ClippedCamera3D);
+ GDREGISTER_CLASS(Listener3D);
+ GDREGISTER_CLASS(XRCamera3D);
+ GDREGISTER_CLASS(XRController3D);
+ GDREGISTER_CLASS(XRAnchor3D);
+ GDREGISTER_CLASS(XROrigin3D);
+ GDREGISTER_CLASS(MeshInstance3D);
+ GDREGISTER_CLASS(OccluderInstance3D);
+ GDREGISTER_CLASS(Occluder3D);
+ GDREGISTER_VIRTUAL_CLASS(SpriteBase3D);
+ GDREGISTER_CLASS(Sprite3D);
+ GDREGISTER_CLASS(AnimatedSprite3D);
+ GDREGISTER_VIRTUAL_CLASS(Light3D);
+ GDREGISTER_CLASS(DirectionalLight3D);
+ GDREGISTER_CLASS(OmniLight3D);
+ GDREGISTER_CLASS(SpotLight3D);
+ GDREGISTER_CLASS(ReflectionProbe);
+ GDREGISTER_CLASS(Decal);
+ GDREGISTER_CLASS(VoxelGI);
+ GDREGISTER_CLASS(VoxelGIData);
+ GDREGISTER_CLASS(LightmapGI);
+ GDREGISTER_CLASS(LightmapGIData);
+ GDREGISTER_CLASS(LightmapProbe);
+ GDREGISTER_VIRTUAL_CLASS(Lightmapper);
+ GDREGISTER_CLASS(GPUParticles3D);
+ GDREGISTER_VIRTUAL_CLASS(GPUParticlesCollision3D);
+ GDREGISTER_CLASS(GPUParticlesCollisionBox);
+ GDREGISTER_CLASS(GPUParticlesCollisionSphere);
+ GDREGISTER_CLASS(GPUParticlesCollisionSDF);
+ GDREGISTER_CLASS(GPUParticlesCollisionHeightField);
+ GDREGISTER_VIRTUAL_CLASS(GPUParticlesAttractor3D);
+ GDREGISTER_CLASS(GPUParticlesAttractorBox);
+ GDREGISTER_CLASS(GPUParticlesAttractorSphere);
+ GDREGISTER_CLASS(GPUParticlesAttractorVectorField);
+ GDREGISTER_CLASS(CPUParticles3D);
+ GDREGISTER_CLASS(Position3D);
+
+ GDREGISTER_CLASS(RootMotionView);
ClassDB::set_class_enabled("RootMotionView", false); //disabled by default, enabled by editor
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_virtual_class<CollisionObject3D>();
- ClassDB::register_virtual_class<PhysicsBody3D>();
- ClassDB::register_class<StaticBody3D>();
- ClassDB::register_class<RigidBody3D>();
- ClassDB::register_class<KinematicCollision3D>();
- ClassDB::register_class<CharacterBody3D>();
- ClassDB::register_class<SpringArm3D>();
-
- ClassDB::register_class<PhysicalBone3D>();
- ClassDB::register_class<SoftBody3D>();
-
- ClassDB::register_class<SkeletonIK3D>();
- ClassDB::register_class<BoneAttachment3D>();
-
- ClassDB::register_class<VehicleBody3D>();
- ClassDB::register_class<VehicleWheel3D>();
- ClassDB::register_class<Area3D>();
- ClassDB::register_class<ProximityGroup3D>();
- ClassDB::register_class<CollisionShape3D>();
- ClassDB::register_class<CollisionPolygon3D>();
- ClassDB::register_class<RayCast3D>();
- ClassDB::register_class<MultiMeshInstance3D>();
-
- ClassDB::register_class<Curve3D>();
- ClassDB::register_class<Path3D>();
- ClassDB::register_class<PathFollow3D>();
- ClassDB::register_class<VisibleOnScreenNotifier3D>();
- ClassDB::register_class<VisibleOnScreenEnabler3D>();
- ClassDB::register_class<WorldEnvironment>();
- ClassDB::register_class<RemoteTransform3D>();
-
- ClassDB::register_virtual_class<Joint3D>();
- ClassDB::register_class<PinJoint3D>();
- ClassDB::register_class<HingeJoint3D>();
- ClassDB::register_class<SliderJoint3D>();
- ClassDB::register_class<ConeTwistJoint3D>();
- ClassDB::register_class<Generic6DOFJoint3D>();
-
- ClassDB::register_class<NavigationRegion3D>();
- ClassDB::register_class<NavigationAgent3D>();
- ClassDB::register_class<NavigationObstacle3D>();
+ GDREGISTER_VIRTUAL_CLASS(CollisionObject3D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D);
+ GDREGISTER_CLASS(StaticBody3D);
+ GDREGISTER_CLASS(RigidBody3D);
+ GDREGISTER_CLASS(KinematicCollision3D);
+ GDREGISTER_CLASS(CharacterBody3D);
+ GDREGISTER_CLASS(SpringArm3D);
+
+ GDREGISTER_CLASS(PhysicalBone3D);
+ GDREGISTER_CLASS(SoftBody3D);
+
+ GDREGISTER_CLASS(SkeletonIK3D);
+ GDREGISTER_CLASS(BoneAttachment3D);
+
+ GDREGISTER_CLASS(VehicleBody3D);
+ GDREGISTER_CLASS(VehicleWheel3D);
+ GDREGISTER_CLASS(Area3D);
+ GDREGISTER_CLASS(ProximityGroup3D);
+ GDREGISTER_CLASS(CollisionShape3D);
+ GDREGISTER_CLASS(CollisionPolygon3D);
+ GDREGISTER_CLASS(RayCast3D);
+ GDREGISTER_CLASS(MultiMeshInstance3D);
+
+ GDREGISTER_CLASS(Curve3D);
+ GDREGISTER_CLASS(Path3D);
+ GDREGISTER_CLASS(PathFollow3D);
+ GDREGISTER_CLASS(VisibleOnScreenNotifier3D);
+ GDREGISTER_CLASS(VisibleOnScreenEnabler3D);
+ GDREGISTER_CLASS(WorldEnvironment);
+ GDREGISTER_CLASS(RemoteTransform3D);
+
+ GDREGISTER_VIRTUAL_CLASS(Joint3D);
+ GDREGISTER_CLASS(PinJoint3D);
+ GDREGISTER_CLASS(HingeJoint3D);
+ GDREGISTER_CLASS(SliderJoint3D);
+ GDREGISTER_CLASS(ConeTwistJoint3D);
+ GDREGISTER_CLASS(Generic6DOFJoint3D);
+
+ GDREGISTER_CLASS(NavigationRegion3D);
+ GDREGISTER_CLASS(NavigationAgent3D);
+ GDREGISTER_CLASS(NavigationObstacle3D);
OS::get_singleton()->yield(); //may take time to init
#endif
/* REGISTER SHADER */
- ClassDB::register_class<Shader>();
- ClassDB::register_class<VisualShader>();
- ClassDB::register_virtual_class<VisualShaderNode>();
- ClassDB::register_class<VisualShaderNodeCustom>();
- ClassDB::register_class<VisualShaderNodeInput>();
- ClassDB::register_virtual_class<VisualShaderNodeOutput>();
- ClassDB::register_virtual_class<VisualShaderNodeResizableBase>();
- ClassDB::register_virtual_class<VisualShaderNodeGroupBase>();
- ClassDB::register_virtual_class<VisualShaderNodeConstant>();
- ClassDB::register_class<VisualShaderNodeComment>();
- ClassDB::register_class<VisualShaderNodeFloatConstant>();
- ClassDB::register_class<VisualShaderNodeIntConstant>();
- ClassDB::register_class<VisualShaderNodeBooleanConstant>();
- ClassDB::register_class<VisualShaderNodeColorConstant>();
- ClassDB::register_class<VisualShaderNodeVec3Constant>();
- ClassDB::register_class<VisualShaderNodeTransformConstant>();
- ClassDB::register_class<VisualShaderNodeFloatOp>();
- ClassDB::register_class<VisualShaderNodeIntOp>();
- ClassDB::register_class<VisualShaderNodeVectorOp>();
- ClassDB::register_class<VisualShaderNodeColorOp>();
- ClassDB::register_class<VisualShaderNodeTransformMult>();
- ClassDB::register_class<VisualShaderNodeTransformVecMult>();
- ClassDB::register_class<VisualShaderNodeFloatFunc>();
- ClassDB::register_class<VisualShaderNodeIntFunc>();
- ClassDB::register_class<VisualShaderNodeVectorFunc>();
- ClassDB::register_class<VisualShaderNodeColorFunc>();
- ClassDB::register_class<VisualShaderNodeTransformFunc>();
- ClassDB::register_class<VisualShaderNodeUVFunc>();
- ClassDB::register_class<VisualShaderNodeDotProduct>();
- ClassDB::register_class<VisualShaderNodeVectorLen>();
- ClassDB::register_class<VisualShaderNodeDeterminant>();
- ClassDB::register_class<VisualShaderNodeScalarDerivativeFunc>();
- ClassDB::register_class<VisualShaderNodeVectorDerivativeFunc>();
- ClassDB::register_class<VisualShaderNodeClamp>();
- ClassDB::register_class<VisualShaderNodeFaceForward>();
- ClassDB::register_class<VisualShaderNodeOuterProduct>();
- ClassDB::register_class<VisualShaderNodeSmoothStep>();
- ClassDB::register_class<VisualShaderNodeStep>();
- ClassDB::register_class<VisualShaderNodeVectorDistance>();
- ClassDB::register_class<VisualShaderNodeVectorRefract>();
- ClassDB::register_class<VisualShaderNodeMix>();
- ClassDB::register_class<VisualShaderNodeVectorCompose>();
- ClassDB::register_class<VisualShaderNodeTransformCompose>();
- ClassDB::register_class<VisualShaderNodeVectorDecompose>();
- ClassDB::register_class<VisualShaderNodeTransformDecompose>();
- ClassDB::register_class<VisualShaderNodeTexture>();
- ClassDB::register_class<VisualShaderNodeCurveTexture>();
- ClassDB::register_virtual_class<VisualShaderNodeSample3D>();
- ClassDB::register_class<VisualShaderNodeTexture2DArray>();
- ClassDB::register_class<VisualShaderNodeTexture3D>();
- ClassDB::register_class<VisualShaderNodeCubemap>();
- ClassDB::register_virtual_class<VisualShaderNodeUniform>();
- ClassDB::register_class<VisualShaderNodeUniformRef>();
- ClassDB::register_class<VisualShaderNodeFloatUniform>();
- ClassDB::register_class<VisualShaderNodeIntUniform>();
- ClassDB::register_class<VisualShaderNodeBooleanUniform>();
- ClassDB::register_class<VisualShaderNodeColorUniform>();
- ClassDB::register_class<VisualShaderNodeVec3Uniform>();
- ClassDB::register_class<VisualShaderNodeTransformUniform>();
- ClassDB::register_class<VisualShaderNodeTextureUniform>();
- ClassDB::register_class<VisualShaderNodeTextureUniformTriplanar>();
- ClassDB::register_class<VisualShaderNodeTexture2DArrayUniform>();
- ClassDB::register_class<VisualShaderNodeTexture3DUniform>();
- ClassDB::register_class<VisualShaderNodeCubemapUniform>();
- ClassDB::register_class<VisualShaderNodeIf>();
- ClassDB::register_class<VisualShaderNodeSwitch>();
- ClassDB::register_class<VisualShaderNodeFresnel>();
- ClassDB::register_class<VisualShaderNodeExpression>();
- ClassDB::register_class<VisualShaderNodeGlobalExpression>();
- ClassDB::register_class<VisualShaderNodeIs>();
- ClassDB::register_class<VisualShaderNodeCompare>();
- ClassDB::register_class<VisualShaderNodeMultiplyAdd>();
- ClassDB::register_class<VisualShaderNodeBillboard>();
-
- ClassDB::register_class<VisualShaderNodeSDFToScreenUV>();
- ClassDB::register_class<VisualShaderNodeScreenUVToSDF>();
- ClassDB::register_class<VisualShaderNodeTextureSDF>();
- ClassDB::register_class<VisualShaderNodeTextureSDFNormal>();
- ClassDB::register_class<VisualShaderNodeSDFRaymarch>();
-
- ClassDB::register_class<VisualShaderNodeParticleOutput>();
- ClassDB::register_virtual_class<VisualShaderNodeParticleEmitter>();
- ClassDB::register_class<VisualShaderNodeParticleSphereEmitter>();
- ClassDB::register_class<VisualShaderNodeParticleBoxEmitter>();
- ClassDB::register_class<VisualShaderNodeParticleRingEmitter>();
- ClassDB::register_class<VisualShaderNodeParticleMultiplyByAxisAngle>();
- ClassDB::register_class<VisualShaderNodeParticleConeVelocity>();
- ClassDB::register_class<VisualShaderNodeParticleRandomness>();
- ClassDB::register_class<VisualShaderNodeParticleAccelerator>();
- ClassDB::register_class<VisualShaderNodeParticleEmit>();
-
- ClassDB::register_class<ShaderMaterial>();
- ClassDB::register_virtual_class<CanvasItem>();
- ClassDB::register_class<CanvasTexture>();
- ClassDB::register_class<CanvasItemMaterial>();
+ GDREGISTER_CLASS(Shader);
+ GDREGISTER_CLASS(VisualShader);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNode);
+ GDREGISTER_CLASS(VisualShaderNodeCustom);
+ GDREGISTER_CLASS(VisualShaderNodeInput);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeOutput);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeResizableBase);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeGroupBase);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeConstant);
+ GDREGISTER_CLASS(VisualShaderNodeComment);
+ GDREGISTER_CLASS(VisualShaderNodeFloatConstant);
+ GDREGISTER_CLASS(VisualShaderNodeIntConstant);
+ GDREGISTER_CLASS(VisualShaderNodeBooleanConstant);
+ GDREGISTER_CLASS(VisualShaderNodeColorConstant);
+ GDREGISTER_CLASS(VisualShaderNodeVec3Constant);
+ GDREGISTER_CLASS(VisualShaderNodeTransformConstant);
+ GDREGISTER_CLASS(VisualShaderNodeFloatOp);
+ GDREGISTER_CLASS(VisualShaderNodeIntOp);
+ GDREGISTER_CLASS(VisualShaderNodeVectorOp);
+ GDREGISTER_CLASS(VisualShaderNodeColorOp);
+ GDREGISTER_CLASS(VisualShaderNodeTransformMult);
+ GDREGISTER_CLASS(VisualShaderNodeTransformVecMult);
+ GDREGISTER_CLASS(VisualShaderNodeFloatFunc);
+ GDREGISTER_CLASS(VisualShaderNodeIntFunc);
+ GDREGISTER_CLASS(VisualShaderNodeVectorFunc);
+ GDREGISTER_CLASS(VisualShaderNodeColorFunc);
+ GDREGISTER_CLASS(VisualShaderNodeTransformFunc);
+ GDREGISTER_CLASS(VisualShaderNodeUVFunc);
+ GDREGISTER_CLASS(VisualShaderNodeDotProduct);
+ GDREGISTER_CLASS(VisualShaderNodeVectorLen);
+ GDREGISTER_CLASS(VisualShaderNodeDeterminant);
+ GDREGISTER_CLASS(VisualShaderNodeScalarDerivativeFunc);
+ GDREGISTER_CLASS(VisualShaderNodeVectorDerivativeFunc);
+ GDREGISTER_CLASS(VisualShaderNodeClamp);
+ GDREGISTER_CLASS(VisualShaderNodeFaceForward);
+ GDREGISTER_CLASS(VisualShaderNodeOuterProduct);
+ GDREGISTER_CLASS(VisualShaderNodeSmoothStep);
+ GDREGISTER_CLASS(VisualShaderNodeStep);
+ GDREGISTER_CLASS(VisualShaderNodeVectorDistance);
+ GDREGISTER_CLASS(VisualShaderNodeVectorRefract);
+ GDREGISTER_CLASS(VisualShaderNodeMix);
+ GDREGISTER_CLASS(VisualShaderNodeVectorCompose);
+ GDREGISTER_CLASS(VisualShaderNodeTransformCompose);
+ GDREGISTER_CLASS(VisualShaderNodeVectorDecompose);
+ GDREGISTER_CLASS(VisualShaderNodeTransformDecompose);
+ GDREGISTER_CLASS(VisualShaderNodeTexture);
+ GDREGISTER_CLASS(VisualShaderNodeCurveTexture);
+ GDREGISTER_CLASS(VisualShaderNodeCurveXYZTexture);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeSample3D);
+ GDREGISTER_CLASS(VisualShaderNodeTexture2DArray);
+ GDREGISTER_CLASS(VisualShaderNodeTexture3D);
+ GDREGISTER_CLASS(VisualShaderNodeCubemap);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeUniform);
+ GDREGISTER_CLASS(VisualShaderNodeUniformRef);
+ GDREGISTER_CLASS(VisualShaderNodeFloatUniform);
+ GDREGISTER_CLASS(VisualShaderNodeIntUniform);
+ GDREGISTER_CLASS(VisualShaderNodeBooleanUniform);
+ GDREGISTER_CLASS(VisualShaderNodeColorUniform);
+ GDREGISTER_CLASS(VisualShaderNodeVec3Uniform);
+ GDREGISTER_CLASS(VisualShaderNodeTransformUniform);
+ GDREGISTER_CLASS(VisualShaderNodeTextureUniform);
+ GDREGISTER_CLASS(VisualShaderNodeTextureUniformTriplanar);
+ GDREGISTER_CLASS(VisualShaderNodeTexture2DArrayUniform);
+ GDREGISTER_CLASS(VisualShaderNodeTexture3DUniform);
+ GDREGISTER_CLASS(VisualShaderNodeCubemapUniform);
+ GDREGISTER_CLASS(VisualShaderNodeIf);
+ GDREGISTER_CLASS(VisualShaderNodeSwitch);
+ GDREGISTER_CLASS(VisualShaderNodeFresnel);
+ GDREGISTER_CLASS(VisualShaderNodeExpression);
+ GDREGISTER_CLASS(VisualShaderNodeGlobalExpression);
+ GDREGISTER_CLASS(VisualShaderNodeIs);
+ GDREGISTER_CLASS(VisualShaderNodeCompare);
+ GDREGISTER_CLASS(VisualShaderNodeMultiplyAdd);
+ GDREGISTER_CLASS(VisualShaderNodeBillboard);
+
+ GDREGISTER_CLASS(VisualShaderNodeSDFToScreenUV);
+ GDREGISTER_CLASS(VisualShaderNodeScreenUVToSDF);
+ GDREGISTER_CLASS(VisualShaderNodeTextureSDF);
+ GDREGISTER_CLASS(VisualShaderNodeTextureSDFNormal);
+ GDREGISTER_CLASS(VisualShaderNodeSDFRaymarch);
+
+ GDREGISTER_CLASS(VisualShaderNodeParticleOutput);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeParticleEmitter);
+ GDREGISTER_CLASS(VisualShaderNodeParticleSphereEmitter);
+ GDREGISTER_CLASS(VisualShaderNodeParticleBoxEmitter);
+ GDREGISTER_CLASS(VisualShaderNodeParticleRingEmitter);
+ GDREGISTER_CLASS(VisualShaderNodeParticleMultiplyByAxisAngle);
+ GDREGISTER_CLASS(VisualShaderNodeParticleConeVelocity);
+ GDREGISTER_CLASS(VisualShaderNodeParticleRandomness);
+ GDREGISTER_CLASS(VisualShaderNodeParticleAccelerator);
+ GDREGISTER_CLASS(VisualShaderNodeParticleEmit);
+
+ GDREGISTER_CLASS(ShaderMaterial);
+ GDREGISTER_VIRTUAL_CLASS(CanvasItem);
+ GDREGISTER_CLASS(CanvasTexture);
+ GDREGISTER_CLASS(CanvasItemMaterial);
SceneTree::add_idle_callback(CanvasItemMaterial::flush_changes);
CanvasItemMaterial::init_shaders();
/* REGISTER 2D */
- ClassDB::register_class<Node2D>();
- ClassDB::register_class<CanvasGroup>();
- ClassDB::register_class<CPUParticles2D>();
- ClassDB::register_class<GPUParticles2D>();
- ClassDB::register_class<Sprite2D>();
- ClassDB::register_class<SpriteFrames>();
- ClassDB::register_class<AnimatedSprite2D>();
- ClassDB::register_class<Position2D>();
- ClassDB::register_class<Line2D>();
- ClassDB::register_class<MeshInstance2D>();
- ClassDB::register_class<MultiMeshInstance2D>();
- ClassDB::register_virtual_class<CollisionObject2D>();
- ClassDB::register_virtual_class<PhysicsBody2D>();
- ClassDB::register_class<StaticBody2D>();
- ClassDB::register_class<RigidBody2D>();
- ClassDB::register_class<CharacterBody2D>();
- ClassDB::register_class<KinematicCollision2D>();
- ClassDB::register_class<Area2D>();
- ClassDB::register_class<CollisionShape2D>();
- ClassDB::register_class<CollisionPolygon2D>();
- ClassDB::register_class<RayCast2D>();
- ClassDB::register_class<VisibleOnScreenNotifier2D>();
- ClassDB::register_class<VisibleOnScreenEnabler2D>();
- ClassDB::register_class<Polygon2D>();
- ClassDB::register_class<Skeleton2D>();
- ClassDB::register_class<Bone2D>();
- ClassDB::register_virtual_class<Light2D>();
- ClassDB::register_class<PointLight2D>();
- ClassDB::register_class<DirectionalLight2D>();
- ClassDB::register_class<LightOccluder2D>();
- ClassDB::register_class<OccluderPolygon2D>();
- ClassDB::register_class<BackBufferCopy>();
+ GDREGISTER_CLASS(Node2D);
+ GDREGISTER_CLASS(CanvasGroup);
+ GDREGISTER_CLASS(CPUParticles2D);
+ GDREGISTER_CLASS(GPUParticles2D);
+ GDREGISTER_CLASS(Sprite2D);
+ GDREGISTER_CLASS(SpriteFrames);
+ GDREGISTER_CLASS(AnimatedSprite2D);
+ GDREGISTER_CLASS(Position2D);
+ GDREGISTER_CLASS(Line2D);
+ GDREGISTER_CLASS(MeshInstance2D);
+ GDREGISTER_CLASS(MultiMeshInstance2D);
+ GDREGISTER_VIRTUAL_CLASS(CollisionObject2D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsBody2D);
+ GDREGISTER_CLASS(StaticBody2D);
+ GDREGISTER_CLASS(RigidBody2D);
+ GDREGISTER_CLASS(CharacterBody2D);
+ GDREGISTER_CLASS(KinematicCollision2D);
+ GDREGISTER_CLASS(Area2D);
+ GDREGISTER_CLASS(CollisionShape2D);
+ GDREGISTER_CLASS(CollisionPolygon2D);
+ GDREGISTER_CLASS(RayCast2D);
+ GDREGISTER_CLASS(VisibleOnScreenNotifier2D);
+ GDREGISTER_CLASS(VisibleOnScreenEnabler2D);
+ GDREGISTER_CLASS(Polygon2D);
+ GDREGISTER_CLASS(Skeleton2D);
+ GDREGISTER_CLASS(Bone2D);
+ GDREGISTER_VIRTUAL_CLASS(Light2D);
+ GDREGISTER_CLASS(PointLight2D);
+ GDREGISTER_CLASS(DirectionalLight2D);
+ GDREGISTER_CLASS(LightOccluder2D);
+ GDREGISTER_CLASS(OccluderPolygon2D);
+ GDREGISTER_CLASS(BackBufferCopy);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<Camera2D>();
- ClassDB::register_virtual_class<Joint2D>();
- ClassDB::register_class<PinJoint2D>();
- ClassDB::register_class<GrooveJoint2D>();
- ClassDB::register_class<DampedSpringJoint2D>();
- ClassDB::register_class<TileSet>();
- ClassDB::register_virtual_class<TileSetSource>();
- ClassDB::register_class<TileSetAtlasSource>();
- ClassDB::register_class<TileSetScenesCollectionSource>();
- ClassDB::register_class<TileData>();
- ClassDB::register_class<TileMap>();
- ClassDB::register_class<ParallaxBackground>();
- ClassDB::register_class<ParallaxLayer>();
- ClassDB::register_class<TouchScreenButton>();
- ClassDB::register_class<RemoteTransform2D>();
-
- ClassDB::register_class<SkeletonModificationStack2D>();
- ClassDB::register_class<SkeletonModification2D>();
- ClassDB::register_class<SkeletonModification2DLookAt>();
- ClassDB::register_class<SkeletonModification2DCCDIK>();
- ClassDB::register_class<SkeletonModification2DFABRIK>();
- ClassDB::register_class<SkeletonModification2DJiggle>();
- ClassDB::register_class<SkeletonModification2DTwoBoneIK>();
- ClassDB::register_class<SkeletonModification2DStackHolder>();
-
- ClassDB::register_class<PhysicalBone2D>();
- ClassDB::register_class<SkeletonModification2DPhysicalBones>();
+ GDREGISTER_CLASS(Camera2D);
+ GDREGISTER_VIRTUAL_CLASS(Joint2D);
+ GDREGISTER_CLASS(PinJoint2D);
+ GDREGISTER_CLASS(GrooveJoint2D);
+ GDREGISTER_CLASS(DampedSpringJoint2D);
+ GDREGISTER_CLASS(TileSet);
+ GDREGISTER_VIRTUAL_CLASS(TileSetSource);
+ GDREGISTER_CLASS(TileSetAtlasSource);
+ GDREGISTER_CLASS(TileSetScenesCollectionSource);
+ GDREGISTER_CLASS(TileData);
+ GDREGISTER_CLASS(TileMap);
+ GDREGISTER_CLASS(ParallaxBackground);
+ GDREGISTER_CLASS(ParallaxLayer);
+ GDREGISTER_CLASS(TouchScreenButton);
+ GDREGISTER_CLASS(RemoteTransform2D);
+
+ GDREGISTER_CLASS(SkeletonModificationStack2D);
+ GDREGISTER_CLASS(SkeletonModification2D);
+ GDREGISTER_CLASS(SkeletonModification2DLookAt);
+ GDREGISTER_CLASS(SkeletonModification2DCCDIK);
+ GDREGISTER_CLASS(SkeletonModification2DFABRIK);
+ GDREGISTER_CLASS(SkeletonModification2DJiggle);
+ GDREGISTER_CLASS(SkeletonModification2DTwoBoneIK);
+ GDREGISTER_CLASS(SkeletonModification2DStackHolder);
+
+ GDREGISTER_CLASS(PhysicalBone2D);
+ GDREGISTER_CLASS(SkeletonModification2DPhysicalBones);
OS::get_singleton()->yield(); //may take time to init
/* REGISTER RESOURCES */
- ClassDB::register_virtual_class<Shader>();
- ClassDB::register_class<ParticlesMaterial>();
+ GDREGISTER_VIRTUAL_CLASS(Shader);
+ GDREGISTER_CLASS(ParticlesMaterial);
SceneTree::add_idle_callback(ParticlesMaterial::flush_changes);
ParticlesMaterial::init_shaders();
- ClassDB::register_class<ProceduralSkyMaterial>();
- ClassDB::register_class<PanoramaSkyMaterial>();
- ClassDB::register_class<PhysicalSkyMaterial>();
+ GDREGISTER_CLASS(ProceduralSkyMaterial);
+ GDREGISTER_CLASS(PanoramaSkyMaterial);
+ GDREGISTER_CLASS(PhysicalSkyMaterial);
- ClassDB::register_virtual_class<Mesh>();
- ClassDB::register_class<ArrayMesh>();
- ClassDB::register_class<MultiMesh>();
- ClassDB::register_class<SurfaceTool>();
- ClassDB::register_class<MeshDataTool>();
+ GDREGISTER_VIRTUAL_CLASS(Mesh);
+ GDREGISTER_CLASS(ArrayMesh);
+ GDREGISTER_CLASS(ImmediateMesh);
+ GDREGISTER_CLASS(MultiMesh);
+ GDREGISTER_CLASS(SurfaceTool);
+ GDREGISTER_CLASS(MeshDataTool);
#ifndef _3D_DISABLED
- ClassDB::register_virtual_class<PrimitiveMesh>();
- ClassDB::register_class<BoxMesh>();
- ClassDB::register_class<CapsuleMesh>();
- ClassDB::register_class<CylinderMesh>();
- ClassDB::register_class<PlaneMesh>();
- ClassDB::register_class<PrismMesh>();
- ClassDB::register_class<QuadMesh>();
- ClassDB::register_class<SphereMesh>();
- ClassDB::register_class<TubeTrailMesh>();
- ClassDB::register_class<RibbonTrailMesh>();
- ClassDB::register_class<PointMesh>();
- ClassDB::register_virtual_class<Material>();
- ClassDB::register_virtual_class<BaseMaterial3D>();
- ClassDB::register_class<StandardMaterial3D>();
- ClassDB::register_class<ORMMaterial3D>();
+ GDREGISTER_VIRTUAL_CLASS(PrimitiveMesh);
+ GDREGISTER_CLASS(BoxMesh);
+ GDREGISTER_CLASS(CapsuleMesh);
+ GDREGISTER_CLASS(CylinderMesh);
+ GDREGISTER_CLASS(PlaneMesh);
+ GDREGISTER_CLASS(PrismMesh);
+ GDREGISTER_CLASS(QuadMesh);
+ GDREGISTER_CLASS(SphereMesh);
+ GDREGISTER_CLASS(TubeTrailMesh);
+ GDREGISTER_CLASS(RibbonTrailMesh);
+ GDREGISTER_CLASS(PointMesh);
+ GDREGISTER_VIRTUAL_CLASS(Material);
+ GDREGISTER_VIRTUAL_CLASS(BaseMaterial3D);
+ GDREGISTER_CLASS(StandardMaterial3D);
+ GDREGISTER_CLASS(ORMMaterial3D);
SceneTree::add_idle_callback(BaseMaterial3D::flush_changes);
BaseMaterial3D::init_shaders();
- ClassDB::register_class<MeshLibrary>();
+ GDREGISTER_CLASS(MeshLibrary);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_virtual_class<Shape3D>();
- ClassDB::register_class<RayShape3D>();
- ClassDB::register_class<SphereShape3D>();
- ClassDB::register_class<BoxShape3D>();
- ClassDB::register_class<CapsuleShape3D>();
- ClassDB::register_class<CylinderShape3D>();
- ClassDB::register_class<HeightMapShape3D>();
- ClassDB::register_class<WorldMarginShape3D>();
- ClassDB::register_class<ConvexPolygonShape3D>();
- ClassDB::register_class<ConcavePolygonShape3D>();
+ GDREGISTER_VIRTUAL_CLASS(Shape3D);
+ GDREGISTER_CLASS(RayShape3D);
+ GDREGISTER_CLASS(SphereShape3D);
+ GDREGISTER_CLASS(BoxShape3D);
+ GDREGISTER_CLASS(CapsuleShape3D);
+ GDREGISTER_CLASS(CylinderShape3D);
+ GDREGISTER_CLASS(HeightMapShape3D);
+ GDREGISTER_CLASS(WorldMarginShape3D);
+ GDREGISTER_CLASS(ConvexPolygonShape3D);
+ GDREGISTER_CLASS(ConcavePolygonShape3D);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<VelocityTracker3D>();
+ GDREGISTER_CLASS(VelocityTracker3D);
#endif
- ClassDB::register_class<PhysicsMaterial>();
- ClassDB::register_class<World3D>();
- ClassDB::register_class<Environment>();
- ClassDB::register_class<CameraEffects>();
- ClassDB::register_class<World2D>();
- ClassDB::register_virtual_class<Texture>();
- ClassDB::register_virtual_class<Texture2D>();
- ClassDB::register_class<Sky>();
- ClassDB::register_class<StreamTexture2D>();
- ClassDB::register_class<ImageTexture>();
- ClassDB::register_class<AtlasTexture>();
- ClassDB::register_class<MeshTexture>();
- ClassDB::register_class<CurveTexture>();
- ClassDB::register_class<GradientTexture>();
- ClassDB::register_class<ProxyTexture>();
- ClassDB::register_class<AnimatedTexture>();
- ClassDB::register_class<CameraTexture>();
- ClassDB::register_virtual_class<TextureLayered>();
- ClassDB::register_virtual_class<ImageTextureLayered>();
- ClassDB::register_virtual_class<Texture3D>();
- ClassDB::register_class<ImageTexture3D>();
- ClassDB::register_class<StreamTexture3D>();
- ClassDB::register_class<Cubemap>();
- ClassDB::register_class<CubemapArray>();
- ClassDB::register_class<Texture2DArray>();
- ClassDB::register_virtual_class<StreamTextureLayered>();
- ClassDB::register_class<StreamCubemap>();
- ClassDB::register_class<StreamCubemapArray>();
- ClassDB::register_class<StreamTexture2DArray>();
-
- ClassDB::register_class<Animation>();
- ClassDB::register_class<FontData>();
- ClassDB::register_class<Font>();
- ClassDB::register_class<Curve>();
-
- ClassDB::register_class<TextFile>();
- ClassDB::register_class<TextLine>();
- ClassDB::register_class<TextParagraph>();
-
- ClassDB::register_virtual_class<StyleBox>();
- ClassDB::register_class<StyleBoxEmpty>();
- ClassDB::register_class<StyleBoxTexture>();
- ClassDB::register_class<StyleBoxFlat>();
- ClassDB::register_class<StyleBoxLine>();
- ClassDB::register_class<Theme>();
-
- ClassDB::register_class<PolygonPathFinder>();
- ClassDB::register_class<BitMap>();
- ClassDB::register_class<Gradient>();
+ GDREGISTER_CLASS(PhysicsMaterial);
+ GDREGISTER_CLASS(World3D);
+ GDREGISTER_CLASS(Environment);
+ GDREGISTER_CLASS(CameraEffects);
+ GDREGISTER_CLASS(World2D);
+ GDREGISTER_VIRTUAL_CLASS(Texture);
+ GDREGISTER_VIRTUAL_CLASS(Texture2D);
+ GDREGISTER_CLASS(Sky);
+ GDREGISTER_CLASS(StreamTexture2D);
+ GDREGISTER_CLASS(ImageTexture);
+ GDREGISTER_CLASS(AtlasTexture);
+ GDREGISTER_CLASS(MeshTexture);
+ GDREGISTER_CLASS(CurveTexture);
+ GDREGISTER_CLASS(CurveXYZTexture);
+ GDREGISTER_CLASS(GradientTexture);
+ GDREGISTER_CLASS(ProxyTexture);
+ GDREGISTER_CLASS(AnimatedTexture);
+ GDREGISTER_CLASS(CameraTexture);
+ GDREGISTER_VIRTUAL_CLASS(TextureLayered);
+ GDREGISTER_VIRTUAL_CLASS(ImageTextureLayered);
+ GDREGISTER_VIRTUAL_CLASS(Texture3D);
+ GDREGISTER_CLASS(ImageTexture3D);
+ GDREGISTER_CLASS(StreamTexture3D);
+ GDREGISTER_CLASS(Cubemap);
+ GDREGISTER_CLASS(CubemapArray);
+ GDREGISTER_CLASS(Texture2DArray);
+ GDREGISTER_VIRTUAL_CLASS(StreamTextureLayered);
+ GDREGISTER_CLASS(StreamCubemap);
+ GDREGISTER_CLASS(StreamCubemapArray);
+ GDREGISTER_CLASS(StreamTexture2DArray);
+
+ GDREGISTER_CLASS(Animation);
+ GDREGISTER_CLASS(FontData);
+ GDREGISTER_CLASS(Font);
+ GDREGISTER_CLASS(Curve);
+
+ GDREGISTER_CLASS(TextFile);
+ GDREGISTER_CLASS(TextLine);
+ GDREGISTER_CLASS(TextParagraph);
+
+ GDREGISTER_VIRTUAL_CLASS(StyleBox);
+ GDREGISTER_CLASS(StyleBoxEmpty);
+ GDREGISTER_CLASS(StyleBoxTexture);
+ GDREGISTER_CLASS(StyleBoxFlat);
+ GDREGISTER_CLASS(StyleBoxLine);
+ GDREGISTER_CLASS(Theme);
+
+ GDREGISTER_CLASS(PolygonPathFinder);
+ GDREGISTER_CLASS(BitMap);
+ GDREGISTER_CLASS(Gradient);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_class<AudioStreamPlayer>();
- ClassDB::register_class<AudioStreamPlayer2D>();
+ GDREGISTER_CLASS(AudioStreamPlayer);
+ GDREGISTER_CLASS(AudioStreamPlayer2D);
#ifndef _3D_DISABLED
- ClassDB::register_class<AudioStreamPlayer3D>();
+ GDREGISTER_CLASS(AudioStreamPlayer3D);
#endif
- ClassDB::register_virtual_class<VideoStream>();
- ClassDB::register_class<AudioStreamSample>();
+ GDREGISTER_VIRTUAL_CLASS(VideoStream);
+ GDREGISTER_CLASS(AudioStreamSample);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_virtual_class<Shape2D>();
- ClassDB::register_class<LineShape2D>();
- ClassDB::register_class<SegmentShape2D>();
- ClassDB::register_class<RayShape2D>();
- ClassDB::register_class<CircleShape2D>();
- ClassDB::register_class<RectangleShape2D>();
- ClassDB::register_class<CapsuleShape2D>();
- ClassDB::register_class<ConvexPolygonShape2D>();
- ClassDB::register_class<ConcavePolygonShape2D>();
- ClassDB::register_class<Curve2D>();
- ClassDB::register_class<Path2D>();
- ClassDB::register_class<PathFollow2D>();
-
- ClassDB::register_class<NavigationMesh>();
- ClassDB::register_class<NavigationPolygon>();
- ClassDB::register_class<NavigationRegion2D>();
- ClassDB::register_class<NavigationAgent2D>();
- ClassDB::register_class<NavigationObstacle2D>();
+ GDREGISTER_VIRTUAL_CLASS(Shape2D);
+ GDREGISTER_CLASS(LineShape2D);
+ GDREGISTER_CLASS(SegmentShape2D);
+ GDREGISTER_CLASS(RayShape2D);
+ GDREGISTER_CLASS(CircleShape2D);
+ GDREGISTER_CLASS(RectangleShape2D);
+ GDREGISTER_CLASS(CapsuleShape2D);
+ GDREGISTER_CLASS(ConvexPolygonShape2D);
+ GDREGISTER_CLASS(ConcavePolygonShape2D);
+ GDREGISTER_CLASS(Curve2D);
+ GDREGISTER_CLASS(Path2D);
+ GDREGISTER_CLASS(PathFollow2D);
+
+ GDREGISTER_CLASS(NavigationMesh);
+ GDREGISTER_CLASS(NavigationPolygon);
+ GDREGISTER_CLASS(NavigationRegion2D);
+ GDREGISTER_CLASS(NavigationAgent2D);
+ GDREGISTER_CLASS(NavigationObstacle2D);
OS::get_singleton()->yield(); //may take time to init
- ClassDB::register_virtual_class<SceneState>();
- ClassDB::register_class<PackedScene>();
+ GDREGISTER_VIRTUAL_CLASS(SceneState);
+ GDREGISTER_CLASS(PackedScene);
- ClassDB::register_class<SceneTree>();
- ClassDB::register_virtual_class<SceneTreeTimer>(); //sorry, you can't create it
+ GDREGISTER_CLASS(SceneTree);
+ GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); //sorry, you can't create it
#ifndef DISABLE_DEPRECATED
// Dropped in 4.0, near approximation.
@@ -935,14 +938,12 @@ void register_scene_types() {
ClassDB::add_compatibility_class("Physics2DServerSW", "PhysicsServer2DSW");
ClassDB::add_compatibility_class("Physics2DServer", "PhysicsServer2D");
ClassDB::add_compatibility_class("Physics2DShapeQueryParameters", "PhysicsShapeQueryParameters2D");
- ClassDB::add_compatibility_class("Physics2DShapeQueryResult", "PhysicsShapeQueryResult2D");
ClassDB::add_compatibility_class("Physics2DTestMotionResult", "PhysicsTestMotionResult2D");
ClassDB::add_compatibility_class("PhysicsBody", "PhysicsBody3D");
ClassDB::add_compatibility_class("PhysicsDirectBodyState", "PhysicsDirectBodyState3D");
ClassDB::add_compatibility_class("PhysicsDirectSpaceState", "PhysicsDirectSpaceState3D");
ClassDB::add_compatibility_class("PhysicsServer", "PhysicsServer3D");
ClassDB::add_compatibility_class("PhysicsShapeQueryParameters", "PhysicsShapeQueryParameters3D");
- ClassDB::add_compatibility_class("PhysicsShapeQueryResult", "PhysicsShapeQueryResult3D");
ClassDB::add_compatibility_class("PinJoint", "PinJoint3D");
ClassDB::add_compatibility_class("PlaneShape", "WorldMarginShape3D");
ClassDB::add_compatibility_class("ProceduralSky", "Sky");
@@ -1040,9 +1041,13 @@ void register_scene_types() {
}
}
SceneDebugger::initialize();
+
+ NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
}
void unregister_scene_types() {
+ NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
+
SceneDebugger::deinitialize();
clear_default_theme();
diff --git a/scene/resources/camera_effects.cpp b/scene/resources/camera_effects.cpp
index 34c6bc05bc..b633196424 100644
--- a/scene/resources/camera_effects.cpp
+++ b/scene/resources/camera_effects.cpp
@@ -175,11 +175,11 @@ void CameraEffects::_bind_methods() {
ADD_GROUP("DOF Blur", "dof_blur_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
// Override exposure
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 846da39221..53979e16df 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -286,7 +286,7 @@ void Curve::set_min_value(float p_min) {
}
// Note: min and max are indicative values,
// it's still possible that existing points are out of range at this point.
- emit_signal(SIGNAL_RANGE_CHANGED);
+ emit_signal(SNAME(SIGNAL_RANGE_CHANGED));
}
void Curve::set_max_value(float p_max) {
@@ -296,7 +296,7 @@ void Curve::set_max_value(float p_max) {
_minmax_set_once |= 0b01; // second bit is "max set"
_max_value = p_max;
}
- emit_signal(SIGNAL_RANGE_CHANGED);
+ emit_signal(SNAME(SIGNAL_RANGE_CHANGED));
}
real_t Curve::interpolate(real_t offset) const {
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 5464a46df4..1bbb84f43d 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -390,6 +390,15 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("shadow_outline_size", "Label", 1 * scale);
theme->set_constant("line_spacing", "Label", 3 * scale);
+ theme->set_type_variation("HeaderSmall", "Label");
+ theme->set_font_size("font_size", "HeaderSmall", default_font_size + 4);
+
+ theme->set_type_variation("HeaderMedium", "Label");
+ theme->set_font_size("font_size", "HeaderMedium", default_font_size + 8);
+
+ theme->set_type_variation("HeaderLarge", "Label");
+ theme->set_font_size("font_size", "HeaderLarge", default_font_size + 12);
+
// LineEdit
theme->set_stylebox("normal", "LineEdit", make_stylebox(line_edit_png, 5, 5, 5, 5));
@@ -984,7 +993,7 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) {
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
- int default_font_size = 16;
+
if (p_font.is_valid()) {
// Use the custom font defined in the Project Settings.
default_font = p_font;
diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h
index a7b2bec5a4..4cd781e814 100644
--- a/scene/resources/default_theme/default_theme.h
+++ b/scene/resources/default_theme/default_theme.h
@@ -33,6 +33,8 @@
#include "scene/resources/theme.h"
+const int default_font_size = 16;
+
void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
void make_default_theme(bool p_hidpi, Ref<Font> p_font);
void clear_default_theme();
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index c04b271d81..8550af8bcb 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -1329,7 +1329,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_density", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater"), "set_volumetric_fog_density", "get_volumetric_fog_density");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "volumetric_fog_light", PROPERTY_HINT_COLOR_NO_ALPHA), "set_volumetric_fog_light", "get_volumetric_fog_light");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_light_energy", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_light_energy", "get_volumetric_fog_light_energy");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_gi_inject", PROPERTY_HINT_EXP_RANGE, "0.00,16,0.01"), "set_volumetric_fog_gi_inject", "get_volumetric_fog_gi_inject");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_gi_inject", PROPERTY_HINT_RANGE, "0.00,16,0.01,exp"), "set_volumetric_fog_gi_inject", "get_volumetric_fog_gi_inject");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread");
ADD_SUBGROUP("Temporal Reprojection", "volumetric_fog_temporal_reprojection_");
diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp
new file mode 100644
index 0000000000..ebe65605f8
--- /dev/null
+++ b/scene/resources/immediate_mesh.cpp
@@ -0,0 +1,416 @@
+/*************************************************************************/
+/* immediate_mesh.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "immediate_mesh.h"
+
+void ImmediateMesh::surface_begin(PrimitiveType p_primitive, const Ref<Material> &p_material) {
+ ERR_FAIL_COND_MSG(surface_active, "Already creating a new surface.");
+ active_surface_data.primitive = p_primitive;
+ active_surface_data.material = p_material;
+ surface_active = true;
+}
+void ImmediateMesh::surface_set_color(const Color &p_color) {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+
+ if (!uses_colors) {
+ colors.resize(vertices.size());
+ for (uint32_t i = 0; i < colors.size(); i++) {
+ colors[i] = p_color;
+ }
+ uses_colors = true;
+ }
+
+ current_color = p_color;
+}
+void ImmediateMesh::surface_set_normal(const Vector3 &p_normal) {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+
+ if (!uses_normals) {
+ normals.resize(vertices.size());
+ for (uint32_t i = 0; i < normals.size(); i++) {
+ normals[i] = p_normal;
+ }
+ uses_normals = true;
+ }
+
+ current_normal = p_normal;
+}
+void ImmediateMesh::surface_set_tangent(const Plane &p_tangent) {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+ if (!uses_tangents) {
+ tangents.resize(vertices.size());
+ for (uint32_t i = 0; i < tangents.size(); i++) {
+ tangents[i] = p_tangent;
+ }
+ uses_tangents = true;
+ }
+
+ current_tangent = p_tangent;
+}
+void ImmediateMesh::surface_set_uv(const Vector2 &p_uv) {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+ if (!uses_uvs) {
+ uvs.resize(vertices.size());
+ for (uint32_t i = 0; i < uvs.size(); i++) {
+ uvs[i] = p_uv;
+ }
+ uses_uvs = true;
+ }
+
+ current_uv = p_uv;
+}
+void ImmediateMesh::surface_set_uv2(const Vector2 &p_uv2) {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+ if (!uses_uv2s) {
+ uv2s.resize(vertices.size());
+ for (uint32_t i = 0; i < uv2s.size(); i++) {
+ uv2s[i] = p_uv2;
+ }
+ uses_uv2s = true;
+ }
+
+ current_uv2 = p_uv2;
+}
+void ImmediateMesh::surface_add_vertex(const Vector3 &p_vertex) {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+ ERR_FAIL_COND_MSG(vertices.size() && active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface.");
+
+ if (uses_colors) {
+ colors.push_back(current_color);
+ }
+ if (uses_normals) {
+ normals.push_back(current_normal);
+ }
+ if (uses_tangents) {
+ tangents.push_back(current_tangent);
+ }
+ if (uses_uvs) {
+ uvs.push_back(current_uv);
+ }
+ if (uses_uv2s) {
+ uv2s.push_back(current_uv2);
+ }
+ vertices.push_back(p_vertex);
+}
+
+void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+ ERR_FAIL_COND_MSG(vertices.size() && !active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface.");
+
+ if (uses_colors) {
+ colors.push_back(current_color);
+ }
+ if (uses_normals) {
+ normals.push_back(current_normal);
+ }
+ if (uses_tangents) {
+ tangents.push_back(current_tangent);
+ }
+ if (uses_uvs) {
+ uvs.push_back(current_uv);
+ }
+ if (uses_uv2s) {
+ uv2s.push_back(current_uv2);
+ }
+ Vector3 v(p_vertex.x, p_vertex.y, 0);
+ vertices.push_back(v);
+
+ active_surface_data.vertex_2d = true;
+}
+void ImmediateMesh::surface_end() {
+ ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
+ ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface cant be created.");
+
+ uint32_t format = ARRAY_FORMAT_VERTEX;
+
+ uint32_t vertex_stride = 0;
+ if (active_surface_data.vertex_2d) {
+ format |= ARRAY_FLAG_USE_2D_VERTICES;
+ vertex_stride = sizeof(float) * 2;
+ } else {
+ vertex_stride = sizeof(float) * 3;
+ }
+
+ uint32_t normal_offset = 0;
+ if (uses_normals) {
+ format |= ARRAY_FORMAT_NORMAL;
+ normal_offset = vertex_stride;
+ vertex_stride += sizeof(uint32_t);
+ }
+ uint32_t tangent_offset = 0;
+ if (uses_tangents) {
+ format |= ARRAY_FORMAT_TANGENT;
+ tangent_offset += vertex_stride;
+ vertex_stride += sizeof(uint32_t);
+ }
+
+ AABB aabb;
+
+ {
+ surface_vertex_create_cache.resize(vertex_stride * vertices.size());
+ uint8_t *surface_vertex_ptr = surface_vertex_create_cache.ptrw();
+ for (uint32_t i = 0; i < vertices.size(); i++) {
+ {
+ float *vtx = (float *)&surface_vertex_ptr[i * vertex_stride];
+ vtx[0] = vertices[i].x;
+ vtx[1] = vertices[i].y;
+ if (!active_surface_data.vertex_2d) {
+ vtx[2] = vertices[i].z;
+ }
+ if (i == 0) {
+ aabb.position = vertices[i];
+ } else {
+ aabb.expand_to(vertices[i]);
+ }
+ }
+ if (uses_normals) {
+ uint32_t *normal = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + normal_offset];
+
+ Vector3 n = normals[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
+
+ uint32_t value = 0;
+ value |= CLAMP(int(n.x * 1023.0), 0, 1023);
+ value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
+
+ *normal = value;
+ }
+ if (uses_tangents) {
+ uint32_t *tangent = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + tangent_offset];
+ Plane t = tangents[i];
+ uint32_t value = 0;
+ value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023);
+ value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
+ if (t.d > 0) {
+ value |= 3 << 30;
+ }
+
+ *tangent = value;
+ }
+ }
+ }
+
+ if (uses_colors || uses_uvs || uses_uv2s) {
+ uint32_t attribute_stride = 0;
+
+ if (uses_colors) {
+ format |= ARRAY_FORMAT_COLOR;
+ attribute_stride += sizeof(uint8_t) * 4;
+ }
+ uint32_t uv_offset = 0;
+ if (uses_uvs) {
+ format |= ARRAY_FORMAT_TEX_UV;
+ uv_offset = attribute_stride;
+ attribute_stride += sizeof(float) * 2;
+ }
+ uint32_t uv2_offset = 0;
+ if (uses_uv2s) {
+ format |= ARRAY_FORMAT_TEX_UV2;
+ uv2_offset = attribute_stride;
+ attribute_stride += sizeof(float) * 2;
+ }
+
+ surface_attribute_create_cache.resize(vertices.size() * attribute_stride);
+
+ uint8_t *surface_attribute_ptr = surface_attribute_create_cache.ptrw();
+
+ for (uint32_t i = 0; i < vertices.size(); i++) {
+ if (uses_colors) {
+ uint8_t *color8 = (uint8_t *)&surface_attribute_ptr[i * attribute_stride];
+
+ color8[0] = uint8_t(CLAMP(colors[i].r * 255.0, 0.0, 255.0));
+ color8[1] = uint8_t(CLAMP(colors[i].g * 255.0, 0.0, 255.0));
+ color8[2] = uint8_t(CLAMP(colors[i].b * 255.0, 0.0, 255.0));
+ color8[3] = uint8_t(CLAMP(colors[i].a * 255.0, 0.0, 255.0));
+ }
+ if (uses_uvs) {
+ float *uv = (float *)&surface_attribute_ptr[i * attribute_stride + uv_offset];
+
+ uv[0] = uvs[i].x;
+ uv[1] = uvs[i].y;
+ }
+
+ if (uses_uv2s) {
+ float *uv2 = (float *)&surface_attribute_ptr[i * attribute_stride + uv2_offset];
+
+ uv2[0] = uv2s[i].x;
+ uv2[1] = uv2s[i].y;
+ }
+ }
+ }
+
+ RS::SurfaceData sd;
+
+ sd.primitive = RS::PrimitiveType(active_surface_data.primitive);
+ sd.format = format;
+ sd.vertex_data = surface_vertex_create_cache;
+ if (uses_colors || uses_uvs || uses_uv2s) {
+ sd.attribute_data = surface_attribute_create_cache;
+ }
+ sd.vertex_count = vertices.size();
+ sd.aabb = aabb;
+ if (active_surface_data.material.is_valid()) {
+ sd.material = active_surface_data.material->get_rid();
+ }
+
+ RS::get_singleton()->mesh_add_surface(mesh, sd);
+
+ active_surface_data.aabb = aabb;
+
+ active_surface_data.format = format;
+ active_surface_data.array_len = vertices.size();
+
+ surfaces.push_back(active_surface_data);
+
+ colors.clear();
+ normals.clear();
+ tangents.clear();
+ uvs.clear();
+ uv2s.clear();
+ vertices.clear();
+
+ uses_colors = false;
+ uses_normals = false;
+ uses_tangents = false;
+ uses_uvs = false;
+ uses_uv2s = false;
+
+ surface_active = false;
+}
+
+void ImmediateMesh::clear_surfaces() {
+ RS::get_singleton()->mesh_clear(mesh);
+ surfaces.clear();
+ surface_active = false;
+
+ colors.clear();
+ normals.clear();
+ tangents.clear();
+ uvs.clear();
+ uv2s.clear();
+ vertices.clear();
+
+ uses_colors = false;
+ uses_normals = false;
+ uses_tangents = false;
+ uses_uvs = false;
+ uses_uv2s = false;
+}
+
+int ImmediateMesh::get_surface_count() const {
+ return surfaces.size();
+}
+int ImmediateMesh::surface_get_array_len(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), -1);
+ return surfaces[p_idx].array_len;
+}
+int ImmediateMesh::surface_get_array_index_len(int p_idx) const {
+ return 0;
+}
+bool ImmediateMesh::surface_is_softbody_friendly(int p_idx) const {
+ return false;
+}
+Array ImmediateMesh::surface_get_arrays(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, int(surfaces.size()), Array());
+ return RS::get_singleton()->mesh_surface_get_arrays(mesh, p_surface);
+}
+Array ImmediateMesh::surface_get_blend_shape_arrays(int p_surface) const {
+ return Array();
+}
+Dictionary ImmediateMesh::surface_get_lods(int p_surface) const {
+ return Dictionary();
+}
+uint32_t ImmediateMesh::surface_get_format(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), 0);
+ return surfaces[p_idx].format;
+}
+Mesh::PrimitiveType ImmediateMesh::surface_get_primitive_type(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), PRIMITIVE_MAX);
+ return surfaces[p_idx].primitive;
+}
+void ImmediateMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
+ ERR_FAIL_INDEX(p_idx, int(surfaces.size()));
+ surfaces[p_idx].material = p_material;
+ RID mat;
+ if (p_material.is_valid()) {
+ mat = p_material->get_rid();
+ }
+ RS::get_singleton()->mesh_surface_set_material(mesh, p_idx, mat);
+}
+Ref<Material> ImmediateMesh::surface_get_material(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), Ref<Material>());
+ return surfaces[p_idx].material;
+}
+int ImmediateMesh::get_blend_shape_count() const {
+ return 0;
+}
+StringName ImmediateMesh::get_blend_shape_name(int p_index) const {
+ return StringName();
+}
+void ImmediateMesh::set_blend_shape_name(int p_index, const StringName &p_name) {
+}
+
+AABB ImmediateMesh::get_aabb() const {
+ AABB aabb;
+ for (uint32_t i = 0; i < surfaces.size(); i++) {
+ if (i == 0) {
+ aabb = surfaces[i].aabb;
+ } else {
+ aabb.merge(surfaces[i].aabb);
+ }
+ }
+ return aabb;
+}
+
+void ImmediateMesh::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("surface_begin", "primitive", "material"), &ImmediateMesh::surface_begin, DEFVAL(Ref<Material>()));
+ ClassDB::bind_method(D_METHOD("surface_set_color", "color"), &ImmediateMesh::surface_set_color);
+ ClassDB::bind_method(D_METHOD("surface_set_normal", "normal"), &ImmediateMesh::surface_set_normal);
+ ClassDB::bind_method(D_METHOD("surface_set_tangent", "tangent"), &ImmediateMesh::surface_set_tangent);
+ ClassDB::bind_method(D_METHOD("surface_set_uv", "uv"), &ImmediateMesh::surface_set_uv);
+ ClassDB::bind_method(D_METHOD("surface_set_uv2", "uv2"), &ImmediateMesh::surface_set_uv2);
+ ClassDB::bind_method(D_METHOD("surface_add_vertex", "vertex"), &ImmediateMesh::surface_add_vertex);
+ ClassDB::bind_method(D_METHOD("surface_add_vertex_2d", "vertex"), &ImmediateMesh::surface_add_vertex_2d);
+ ClassDB::bind_method(D_METHOD("surface_end"), &ImmediateMesh::surface_end);
+
+ ClassDB::bind_method(D_METHOD("clear_surfaces"), &ImmediateMesh::clear_surfaces);
+}
+
+RID ImmediateMesh::get_rid() const {
+ return mesh;
+}
+
+ImmediateMesh::ImmediateMesh() {
+ mesh = RS::get_singleton()->mesh_create();
+}
+ImmediateMesh::~ImmediateMesh() {
+ RS::get_singleton()->free(mesh);
+}
diff --git a/scene/resources/immediate_mesh.h b/scene/resources/immediate_mesh.h
new file mode 100644
index 0000000000..7010d40719
--- /dev/null
+++ b/scene/resources/immediate_mesh.h
@@ -0,0 +1,117 @@
+/*************************************************************************/
+/* immediate_mesh.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef IMMEDIATE_MESH_H
+#define IMMEDIATE_MESH_H
+
+#include "core/templates/local_vector.h"
+#include "scene/resources/mesh.h"
+
+class ImmediateMesh : public Mesh {
+ GDCLASS(ImmediateMesh, Mesh)
+
+ RID mesh;
+
+ bool uses_colors = false;
+ bool uses_normals = false;
+ bool uses_tangents = false;
+ bool uses_uvs = false;
+ bool uses_uv2s = false;
+
+ Color current_color;
+ Vector3 current_normal;
+ Plane current_tangent;
+ Vector2 current_uv;
+ Vector2 current_uv2;
+
+ LocalVector<Color> colors;
+ LocalVector<Vector3> normals;
+ LocalVector<Plane> tangents;
+ LocalVector<Vector2> uvs;
+ LocalVector<Vector2> uv2s;
+ LocalVector<Vector3> vertices;
+
+ struct Surface {
+ PrimitiveType primitive;
+ Ref<Material> material;
+ bool vertex_2d = false;
+ int array_len = 0;
+ uint32_t format = 0;
+ AABB aabb;
+ };
+
+ LocalVector<Surface> surfaces;
+
+ bool surface_active = false;
+ Surface active_surface_data;
+
+ Vector<uint8_t> surface_vertex_create_cache;
+ Vector<uint8_t> surface_attribute_create_cache;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void surface_begin(PrimitiveType p_primitive, const Ref<Material> &p_material = Ref<Material>());
+ void surface_set_color(const Color &p_color);
+ void surface_set_normal(const Vector3 &p_normal);
+ void surface_set_tangent(const Plane &p_tangent);
+ void surface_set_uv(const Vector2 &p_uv);
+ void surface_set_uv2(const Vector2 &p_uv2);
+ void surface_add_vertex(const Vector3 &p_vertex);
+ void surface_add_vertex_2d(const Vector2 &p_vertex);
+ void surface_end();
+
+ void clear_surfaces();
+
+ virtual int get_surface_count() const override;
+ virtual int surface_get_array_len(int p_idx) const override;
+ virtual int surface_get_array_index_len(int p_idx) const override;
+ virtual bool surface_is_softbody_friendly(int p_idx) const override;
+ virtual Array surface_get_arrays(int p_surface) const override;
+ virtual Array surface_get_blend_shape_arrays(int p_surface) const override;
+ virtual Dictionary surface_get_lods(int p_surface) const override;
+ virtual uint32_t surface_get_format(int p_idx) const override;
+ virtual PrimitiveType surface_get_primitive_type(int p_idx) const override;
+ virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override;
+ virtual Ref<Material> surface_get_material(int p_idx) const override;
+ virtual int get_blend_shape_count() const override;
+ virtual StringName get_blend_shape_name(int p_index) const override;
+ virtual void set_blend_shape_name(int p_index, const StringName &p_name) override;
+
+ virtual AABB get_aabb() const override;
+
+ virtual RID get_rid() const override;
+
+ ImmediateMesh();
+ ~ImmediateMesh();
+};
+
+#endif // IMMEDIATEMESH_H
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 7027319554..7d49533afd 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -77,7 +77,7 @@ RID Material::get_rid() const {
void Material::_validate_property(PropertyInfo &property) const {
if (!_can_do_next_pass() && property.name == "next_pass") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -130,7 +130,7 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) {
}
}
if (pr) {
- RenderingServer::get_singleton()->material_set_param(_get_material(), pr, p_value);
+ set_shader_param(pr, p_value);
return true;
}
}
@@ -152,7 +152,12 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const {
}
if (pr) {
- r_ret = RenderingServer::get_singleton()->material_get_param(_get_material(), pr);
+ const Map<StringName, Variant>::Element *E = param_cache.find(pr);
+ if (E) {
+ r_ret = E->get();
+ } else {
+ r_ret = Variant();
+ }
return true;
}
}
@@ -219,11 +224,31 @@ Ref<Shader> ShaderMaterial::get_shader() const {
}
void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) {
- RS::get_singleton()->material_set_param(_get_material(), p_param, p_value);
+ if (p_value.get_type() == Variant::NIL) {
+ param_cache.erase(p_param);
+ RS::get_singleton()->material_set_param(_get_material(), p_param, Variant());
+ } else {
+ param_cache[p_param] = p_value;
+ if (p_value.get_type() == Variant::OBJECT) {
+ RID tex_rid = p_value;
+ if (tex_rid == RID()) {
+ param_cache.erase(p_param);
+ RS::get_singleton()->material_set_param(_get_material(), p_param, Variant());
+ } else {
+ RS::get_singleton()->material_set_param(_get_material(), p_param, tex_rid);
+ }
+ } else {
+ RS::get_singleton()->material_set_param(_get_material(), p_param, p_value);
+ }
+ }
}
Variant ShaderMaterial::get_shader_param(const StringName &p_param) const {
- return RS::get_singleton()->material_get_param(_get_material(), p_param);
+ if (param_cache.has(p_param)) {
+ return param_cache[p_param];
+ } else {
+ return Variant();
+ }
}
void ShaderMaterial::_shader_changed() {
@@ -345,7 +370,6 @@ void BaseMaterial3D::init_shaders() {
shader_names->refraction_texture_channel = "refraction_texture_channel";
shader_names->transmittance_color = "transmittance_color";
- shader_names->transmittance_curve = "transmittance_curve";
shader_names->transmittance_depth = "transmittance_depth";
shader_names->transmittance_boost = "transmittance_boost";
@@ -692,7 +716,6 @@ void BaseMaterial3D::_update_shader() {
code += "uniform vec4 transmittance_color : hint_color;\n";
code += "uniform float transmittance_depth;\n";
code += "uniform sampler2D texture_subsurface_transmittance : hint_white," + texfilter_str + ";\n";
- code += "uniform float transmittance_curve;\n";
code += "uniform float transmittance_boost;\n";
}
@@ -734,463 +757,476 @@ void BaseMaterial3D::_update_shader() {
code += "void vertex() {\n";
if (flags[FLAG_SRGB_VERTEX_COLOR]) {
- code += "\tif (!OUTPUT_IS_SRGB) {\n";
- code += "\t\tCOLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045)));\n";
- code += "\t}\n";
+ code += " if (!OUTPUT_IS_SRGB) {\n";
+ code += " COLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045)));\n";
+ code += " }\n";
}
if (flags[FLAG_USE_POINT_SIZE]) {
- code += "\tPOINT_SIZE=point_size;\n";
+ code += " POINT_SIZE=point_size;\n";
}
if (shading_mode == SHADING_MODE_PER_VERTEX) {
- code += "\tROUGHNESS=roughness;\n";
+ code += " ROUGHNESS=roughness;\n";
}
if (!flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tUV=UV*uv1_scale.xy+uv1_offset.xy;\n";
+ code += " UV=UV*uv1_scale.xy+uv1_offset.xy;\n";
}
switch (billboard_mode) {
case BILLBOARD_DISABLED: {
} break;
case BILLBOARD_ENABLED: {
- code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n";
+ code += " MODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n";
if (flags[FLAG_BILLBOARD_KEEP_SCALE]) {
- code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n";
}
} break;
case BILLBOARD_FIXED_Y: {
- code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)), 0.0),WORLD_MATRIX[3]);\n";
+ code += " MODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)), 0.0),WORLD_MATRIX[3]);\n";
if (flags[FLAG_BILLBOARD_KEEP_SCALE]) {
- code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, 1.0, 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, 1.0, 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
} else {
- code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(1.0, 0.0, 0.0, 0.0),vec4(0.0, 1.0/length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0),vec4(0.0, 0.0, 0.0 ,1.0));\n";
+ code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(1.0, 0.0, 0.0, 0.0),vec4(0.0, 1.0/length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0),vec4(0.0, 0.0, 0.0 ,1.0));\n";
}
} break;
case BILLBOARD_PARTICLES: {
//make billboard
- code += "\tmat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n";
+ code += " mat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n";
//rotate by rotation
- code += "\tmat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0),vec4(0.0, 0.0, 1.0, 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += " mat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0),vec4(0.0, 0.0, 1.0, 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n";
//set modelview
- code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n";
+ code += " MODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n";
//handle animation
- code += "\tfloat h_frames = float(particles_anim_h_frames);\n";
- code += "\tfloat v_frames = float(particles_anim_v_frames);\n";
- code += "\tfloat particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n";
- code += "\tfloat particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n";
- code += "\tif (!particles_anim_loop) {\n";
- code += "\t\tparticle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n";
- code += "\t} else {\n";
- code += "\t\tparticle_frame = mod(particle_frame, particle_total_frames);\n";
- code += "\t}";
- code += "\tUV /= vec2(h_frames, v_frames);\n";
- code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n";
+ code += " float h_frames = float(particles_anim_h_frames);\n";
+ code += " float v_frames = float(particles_anim_v_frames);\n";
+ code += " float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n";
+ code += " float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n";
+ code += " if (!particles_anim_loop) {\n";
+ code += " particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n";
+ code += " } else {\n";
+ code += " particle_frame = mod(particle_frame, particle_total_frames);\n";
+ code += " }";
+ code += " UV /= vec2(h_frames, v_frames);\n";
+ code += " UV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n";
} break;
case BILLBOARD_MAX:
break; // Internal value, skip.
}
if (flags[FLAG_FIXED_SIZE]) {
- code += "\tif (PROJECTION_MATRIX[3][3] != 0.0) {\n";
+ code += " if (PROJECTION_MATRIX[3][3] != 0.0) {\n";
//orthogonal matrix, try to do about the same
//with viewport size
- code += "\t\tfloat h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n";
- code += "\t\tfloat sc = (h * 2.0); //consistent with Y-fov\n";
- code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n";
- code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n";
- code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n";
- code += "\t} else {\n";
+ code += " float h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n";
+ code += " float sc = (h * 2.0); //consistent with Y-fov\n";
+ code += " MODELVIEW_MATRIX[0]*=sc;\n";
+ code += " MODELVIEW_MATRIX[1]*=sc;\n";
+ code += " MODELVIEW_MATRIX[2]*=sc;\n";
+ code += " } else {\n";
//just scale by depth
- code += "\t\tfloat sc = -(MODELVIEW_MATRIX)[3].z;\n";
- code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n";
- code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n";
- code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n";
- code += "\t}\n";
+ code += " float sc = -(MODELVIEW_MATRIX)[3].z;\n";
+ code += " MODELVIEW_MATRIX[0]*=sc;\n";
+ code += " MODELVIEW_MATRIX[1]*=sc;\n";
+ code += " MODELVIEW_MATRIX[2]*=sc;\n";
+ code += " }\n";
}
if (detail_uv == DETAIL_UV_2 && !flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += "\tUV2=UV2*uv2_scale.xy+uv2_offset.xy;\n";
+ code += " UV2=UV2*uv2_scale.xy+uv2_offset.xy;\n";
}
if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) {
//generate tangent and binormal in world space
- code += "\tTANGENT = vec3(0.0,0.0,-1.0) * abs(NORMAL.x);\n";
- code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.y);\n";
- code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.z);\n";
- code += "\tTANGENT = normalize(TANGENT);\n";
+ code += " TANGENT = vec3(0.0,0.0,-1.0) * abs(NORMAL.x);\n";
+ code += " TANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.y);\n";
+ code += " TANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.z);\n";
+ code += " TANGENT = normalize(TANGENT);\n";
- code += "\tBINORMAL = vec3(0.0,-1.0,0.0) * abs(NORMAL.x);\n";
- code += "\tBINORMAL+= vec3(0.0,0.0,1.0) * abs(NORMAL.y);\n";
- code += "\tBINORMAL+= vec3(0.0,-1.0,0.0) * abs(NORMAL.z);\n";
- code += "\tBINORMAL = normalize(BINORMAL);\n";
+ code += " BINORMAL = vec3(0.0,1.0,0.0) * abs(NORMAL.x);\n";
+ code += " BINORMAL+= vec3(0.0,0.0,-1.0) * abs(NORMAL.y);\n";
+ code += " BINORMAL+= vec3(0.0,1.0,0.0) * abs(NORMAL.z);\n";
+ code += " BINORMAL = normalize(BINORMAL);\n";
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
if (flags[FLAG_UV1_USE_WORLD_TRIPLANAR]) {
- code += "\tuv1_power_normal=pow(abs(mat3(WORLD_MATRIX) * NORMAL),vec3(uv1_blend_sharpness));\n";
- code += "\tuv1_triplanar_pos = (WORLD_MATRIX * vec4(VERTEX, 1.0f)).xyz * uv1_scale + uv1_offset;\n";
+ code += " uv1_power_normal=pow(abs(mat3(WORLD_MATRIX) * NORMAL),vec3(uv1_blend_sharpness));\n";
+ code += " uv1_triplanar_pos = (WORLD_MATRIX * vec4(VERTEX, 1.0f)).xyz * uv1_scale + uv1_offset;\n";
} else {
- code += "\tuv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n";
- code += "\tuv1_triplanar_pos = VERTEX * uv1_scale + uv1_offset;\n";
+ code += " uv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n";
+ code += " uv1_triplanar_pos = VERTEX * uv1_scale + uv1_offset;\n";
}
- code += "\tuv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n";
- code += "\tuv1_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n";
+ code += " uv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n";
+ code += " uv1_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n";
}
if (flags[FLAG_UV2_USE_TRIPLANAR]) {
if (flags[FLAG_UV2_USE_WORLD_TRIPLANAR]) {
- code += "\tuv2_power_normal=pow(abs(mat3(WORLD_MATRIX) * NORMAL), vec3(uv2_blend_sharpness));\n";
- code += "\tuv2_triplanar_pos = (WORLD_MATRIX * vec4(VERTEX, 1.0f)).xyz * uv2_scale + uv2_offset;\n";
+ code += " uv2_power_normal=pow(abs(mat3(WORLD_MATRIX) * NORMAL), vec3(uv2_blend_sharpness));\n";
+ code += " uv2_triplanar_pos = (WORLD_MATRIX * vec4(VERTEX, 1.0f)).xyz * uv2_scale + uv2_offset;\n";
} else {
- code += "\tuv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n";
- code += "\tuv2_triplanar_pos = VERTEX * uv2_scale + uv2_offset;\n";
+ code += " uv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n";
+ code += " uv2_triplanar_pos = VERTEX * uv2_scale + uv2_offset;\n";
}
- code += "\tuv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n";
- code += "\tuv2_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n";
+ code += " uv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n";
+ code += " uv2_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n";
}
if (grow_enabled) {
- code += "\tVERTEX+=NORMAL*grow;\n";
+ code += " VERTEX+=NORMAL*grow;\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 += "\tvec4 samp=vec4(0.0);\n";
- code += "\tsamp+= texture(p_sampler,p_triplanar_pos.xy) * p_weights.z;\n";
- code += "\tsamp+= texture(p_sampler,p_triplanar_pos.xz) * p_weights.y;\n";
- code += "\tsamp+= texture(p_sampler,p_triplanar_pos.zy * vec2(-1.0,1.0)) * p_weights.x;\n";
- code += "\treturn samp;\n";
+ code += " vec4 samp=vec4(0.0);\n";
+ code += " samp+= texture(p_sampler,p_triplanar_pos.xy) * p_weights.z;\n";
+ code += " samp+= texture(p_sampler,p_triplanar_pos.xz) * p_weights.y;\n";
+ code += " samp+= texture(p_sampler,p_triplanar_pos.zy * vec2(-1.0,1.0)) * p_weights.x;\n";
+ code += " return samp;\n";
code += "}\n";
}
code += "\n\n";
code += "void fragment() {\n";
if (!flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec2 base_uv = UV;\n";
+ code += " vec2 base_uv = UV;\n";
}
if ((features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) || (features[FEATURE_AMBIENT_OCCLUSION] && flags[FLAG_AO_ON_UV2]) || (features[FEATURE_EMISSION] && flags[FLAG_EMISSION_ON_UV2])) {
- code += "\tvec2 base_uv2 = UV2;\n";
+ code += " vec2 base_uv2 = UV2;\n";
+ }
+
+ if (features[FEATURE_HEIGHT_MAPPING] && flags[FLAG_UV1_USE_TRIPLANAR]) {
+ // Display both resource name and albedo texture name.
+ // Materials are often built-in to scenes, so displaying the resource name alone may not be meaningful.
+ // On the other hand, albedo textures are almost always external to the scene.
+ if (textures[TEXTURE_ALBEDO].is_valid()) {
+ WARN_PRINT(vformat("%s (albedo %s): Height mapping is not supported on triplanar materials. Ignoring height mapping in favor of triplanar mapping.", get_path(), textures[TEXTURE_ALBEDO]->get_path()));
+ } else if (!get_path().is_empty()) {
+ WARN_PRINT(vformat("%s: Height mapping is not supported on triplanar materials. Ignoring height mapping in favor of triplanar mapping.", get_path()));
+ } else {
+ // Resource wasn't saved yet.
+ WARN_PRINT("Height mapping is not supported on triplanar materials. Ignoring height mapping in favor of triplanar mapping.");
+ }
}
if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_HEIGHT_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //heightmap not supported with triplanar
- code += "\t{\n";
- code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*heightmap_flip.x,-BINORMAL*heightmap_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-)
+ code += " {\n";
+ code += " vec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*heightmap_flip.x,-BINORMAL*heightmap_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-)
if (deep_parallax) {
- code += "\t\tfloat num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
- code += "\t\tfloat layer_depth = 1.0 / num_layers;\n";
- code += "\t\tfloat current_layer_depth = 0.0;\n";
- code += "\t\tvec2 P = view_dir.xy * heightmap_scale;\n";
- code += "\t\tvec2 delta = P / num_layers;\n";
- code += "\t\tvec2 ofs = base_uv;\n";
+ code += " float num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
+ code += " float layer_depth = 1.0 / num_layers;\n";
+ code += " float current_layer_depth = 0.0;\n";
+ code += " vec2 P = view_dir.xy * heightmap_scale;\n";
+ code += " vec2 delta = P / num_layers;\n";
+ code += " vec2 ofs = base_uv;\n";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
- code += "\t\tfloat depth = texture(texture_heightmap, ofs).r;\n";
+ code += " float depth = texture(texture_heightmap, ofs).r;\n";
} else {
- code += "\t\tfloat depth = 1.0 - texture(texture_heightmap, ofs).r;\n";
+ code += " float depth = 1.0 - texture(texture_heightmap, ofs).r;\n";
}
- code += "\t\tfloat current_depth = 0.0;\n";
- code += "\t\twhile(current_depth < depth) {\n";
- code += "\t\t\tofs -= delta;\n";
+ code += " float current_depth = 0.0;\n";
+ code += " while(current_depth < depth) {\n";
+ code += " ofs -= delta;\n";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
- code += "\t\t\tdepth = texture(texture_heightmap, ofs).r;\n";
+ code += " depth = texture(texture_heightmap, ofs).r;\n";
} else {
- code += "\t\t\tdepth = 1.0 - texture(texture_heightmap, ofs).r;\n";
+ code += " depth = 1.0 - texture(texture_heightmap, ofs).r;\n";
}
- code += "\t\t\tcurrent_depth += layer_depth;\n";
- code += "\t\t}\n";
- code += "\t\tvec2 prev_ofs = ofs + delta;\n";
- code += "\t\tfloat after_depth = depth - current_depth;\n";
+ code += " current_depth += layer_depth;\n";
+ code += " }\n";
+ code += " vec2 prev_ofs = ofs + delta;\n";
+ code += " float after_depth = depth - current_depth;\n";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
- code += "\t\tfloat before_depth = texture(texture_heightmap, prev_ofs).r - current_depth + layer_depth;\n";
+ code += " float before_depth = texture(texture_heightmap, prev_ofs).r - current_depth + layer_depth;\n";
} else {
- code += "\t\tfloat before_depth = ( 1.0 - texture(texture_heightmap, prev_ofs).r ) - current_depth + layer_depth;\n";
+ code += " float before_depth = ( 1.0 - texture(texture_heightmap, prev_ofs).r ) - current_depth + layer_depth;\n";
}
- code += "\t\tfloat weight = after_depth / (after_depth - before_depth);\n";
- code += "\t\tofs = mix(ofs,prev_ofs,weight);\n";
+ code += " float weight = after_depth / (after_depth - before_depth);\n";
+ code += " ofs = mix(ofs,prev_ofs,weight);\n";
} else {
if (flags[FLAG_INVERT_HEIGHTMAP]) {
- code += "\t\tfloat depth = texture(texture_heightmap, base_uv).r;\n";
+ code += " float depth = texture(texture_heightmap, base_uv).r;\n";
} else {
- code += "\t\tfloat depth = 1.0 - texture(texture_heightmap, base_uv).r;\n";
+ code += " float depth = 1.0 - texture(texture_heightmap, base_uv).r;\n";
}
- code += "\t\tvec2 ofs = base_uv - view_dir.xy / view_dir.z * (depth * heightmap_scale);\n";
+ code += " vec2 ofs = base_uv - view_dir.xy / view_dir.z * (depth * heightmap_scale);\n";
}
- code += "\t\tbase_uv=ofs;\n";
+ code += " base_uv=ofs;\n";
if (features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) {
- code += "\t\tbase_uv2-=ofs;\n";
+ code += " base_uv2-=ofs;\n";
}
- code += "\t}\n";
+ code += " }\n";
}
if (flags[FLAG_USE_POINT_SIZE]) {
- code += "\tvec4 albedo_tex = texture(texture_albedo,POINT_COORD);\n";
+ code += " vec4 albedo_tex = texture(texture_albedo,POINT_COORD);\n";
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec4 albedo_tex = triplanar_texture(texture_albedo,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += " vec4 albedo_tex = triplanar_texture(texture_albedo,uv1_power_normal,uv1_triplanar_pos);\n";
} else {
- code += "\tvec4 albedo_tex = texture(texture_albedo,base_uv);\n";
+ code += " vec4 albedo_tex = texture(texture_albedo,base_uv);\n";
}
}
if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) {
- code += "\talbedo_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";
+ 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";
}
if (flags[FLAG_ALBEDO_FROM_VERTEX_COLOR]) {
- code += "\talbedo_tex *= COLOR;\n";
+ code += " albedo_tex *= COLOR;\n";
}
- code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n";
+ code += " ALBEDO = albedo.rgb * albedo_tex.rgb;\n";
if (!orm) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tfloat metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n";
+ code += " float metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n";
} else {
- code += "\tfloat metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n";
+ code += " float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n";
}
- code += "\tMETALLIC = metallic_tex * metallic;\n";
+ code += " METALLIC = metallic_tex * metallic;\n";
switch (roughness_texture_channel) {
case TEXTURE_CHANNEL_RED: {
- code += "\tvec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);\n";
+ code += " vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);\n";
} break;
case TEXTURE_CHANNEL_GREEN: {
- code += "\tvec4 roughness_texture_channel = vec4(0.0,1.0,0.0,0.0);\n";
+ code += " vec4 roughness_texture_channel = vec4(0.0,1.0,0.0,0.0);\n";
} break;
case TEXTURE_CHANNEL_BLUE: {
- code += "\tvec4 roughness_texture_channel = vec4(0.0,0.0,1.0,0.0);\n";
+ code += " vec4 roughness_texture_channel = vec4(0.0,0.0,1.0,0.0);\n";
} break;
case TEXTURE_CHANNEL_ALPHA: {
- code += "\tvec4 roughness_texture_channel = vec4(0.0,0.0,0.0,1.0);\n";
+ code += " vec4 roughness_texture_channel = vec4(0.0,0.0,0.0,1.0);\n";
} break;
case TEXTURE_CHANNEL_GRAYSCALE: {
- code += "\tvec4 roughness_texture_channel = vec4(0.333333,0.333333,0.333333,0.0);\n";
+ code += " vec4 roughness_texture_channel = vec4(0.333333,0.333333,0.333333,0.0);\n";
} break;
case TEXTURE_CHANNEL_MAX:
break; // Internal value, skip.
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tfloat roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n";
+ code += " float roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n";
} else {
- code += "\tfloat roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n";
+ code += " float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n";
}
- code += "\tROUGHNESS = roughness_tex * roughness;\n";
- code += "\tSPECULAR = specular;\n";
+ code += " ROUGHNESS = roughness_tex * roughness;\n";
+ code += " SPECULAR = specular;\n";
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tfloat orm_tex = triplanar_texture(texture_orm,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += " vec4 orm_tex = triplanar_texture(texture_orm,uv1_power_normal,uv1_triplanar_pos);\n";
} else {
- code += "\tfloat orm_tex = texture(texture_orm,base_uv);\n";
+ code += " vec4 orm_tex = texture(texture_orm,base_uv);\n";
}
- code += "\tROUGHNESS = orm_tex.g;\n";
- code += "\tMETALLIC = orm_tex.b;\n";
+ code += " ROUGHNESS = orm_tex.g;\n";
+ code += " METALLIC = orm_tex.b;\n";
}
if (features[FEATURE_NORMAL_MAPPING]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tNORMAL_MAP = triplanar_texture(texture_normal,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
+ code += " NORMAL_MAP = triplanar_texture(texture_normal,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
} else {
- code += "\tNORMAL_MAP = texture(texture_normal,base_uv).rgb;\n";
+ code += " NORMAL_MAP = texture(texture_normal,base_uv).rgb;\n";
}
- code += "\tNORMAL_MAP_DEPTH = normal_scale;\n";
+ code += " NORMAL_MAP_DEPTH = normal_scale;\n";
}
if (features[FEATURE_EMISSION]) {
if (flags[FLAG_EMISSION_ON_UV2]) {
if (flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv2_power_normal,uv2_triplanar_pos).rgb;\n";
+ code += " vec3 emission_tex = triplanar_texture(texture_emission,uv2_power_normal,uv2_triplanar_pos).rgb;\n";
} else {
- code += "\tvec3 emission_tex = texture(texture_emission,base_uv2).rgb;\n";
+ code += " vec3 emission_tex = texture(texture_emission,base_uv2).rgb;\n";
}
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
+ code += " vec3 emission_tex = triplanar_texture(texture_emission,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
} else {
- code += "\tvec3 emission_tex = texture(texture_emission,base_uv).rgb;\n";
+ code += " vec3 emission_tex = texture(texture_emission,base_uv).rgb;\n";
}
}
if (emission_op == EMISSION_OP_ADD) {
- code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n";
+ code += " EMISSION = (emission.rgb+emission_tex)*emission_energy;\n";
} else {
- code += "\tEMISSION = (emission.rgb*emission_tex)*emission_energy;\n";
+ code += " EMISSION = (emission.rgb*emission_tex)*emission_energy;\n";
}
}
if (features[FEATURE_REFRACTION]) {
if (features[FEATURE_NORMAL_MAPPING]) {
- code += "\tvec3 unpacked_normal = NORMAL_MAP;\n";
- code += "\tunpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;\n";
- code += "\tunpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));\n";
- code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,NORMAL_MAP_DEPTH) );\n";
+ code += " vec3 unpacked_normal = NORMAL_MAP;\n";
+ code += " unpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;\n";
+ code += " unpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));\n";
+ code += " vec3 ref_normal = normalize( mix(NORMAL,TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,NORMAL_MAP_DEPTH) );\n";
} else {
- code += "\tvec3 ref_normal = NORMAL;\n";
+ code += " vec3 ref_normal = NORMAL;\n";
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction,uv1_power_normal,uv1_triplanar_pos),refraction_texture_channel) * refraction;\n";
+ code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction,uv1_power_normal,uv1_triplanar_pos),refraction_texture_channel) * refraction;\n";
} else {
- code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n";
+ code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n";
}
- code += "\tfloat ref_amount = 1.0 - albedo.a * albedo_tex.a;\n";
- code += "\tEMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n";
- code += "\tALBEDO *= 1.0 - ref_amount;\n";
- code += "\tALPHA = 1.0;\n";
+ code += " float ref_amount = 1.0 - albedo.a * albedo_tex.a;\n";
+ code += " EMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n";
+ code += " ALBEDO *= 1.0 - ref_amount;\n";
+ code += " ALPHA = 1.0;\n";
} else if (transparency != TRANSPARENCY_DISABLED || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) {
- code += "\tALPHA = albedo.a * albedo_tex.a;\n";
+ code += " ALPHA = albedo.a * albedo_tex.a;\n";
}
if (transparency == TRANSPARENCY_ALPHA_HASH) {
- code += "\tALPHA_HASH_SCALE = alpha_hash_scale;\n";
+ code += " ALPHA_HASH_SCALE = alpha_hash_scale;\n";
} else if (transparency == TRANSPARENCY_ALPHA_SCISSOR) {
- code += "\tALPHA_SCISSOR_THRESHOLD = alpha_scissor_threshold;\n";
+ code += " ALPHA_SCISSOR_THRESHOLD = alpha_scissor_threshold;\n";
}
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF && (transparency == TRANSPARENCY_ALPHA_HASH || transparency == TRANSPARENCY_ALPHA_SCISSOR)) {
- code += "\tALPHA_ANTIALIASING_EDGE = alpha_antialiasing_edge;\n";
- code += "\tALPHA_TEXTURE_COORDINATE = UV * vec2(albedo_texture_size);\n";
+ code += " ALPHA_ANTIALIASING_EDGE = alpha_antialiasing_edge;\n";
+ code += " ALPHA_TEXTURE_COORDINATE = UV * vec2(albedo_texture_size);\n";
}
if (proximity_fade_enabled) {
- code += "\tfloat depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n";
- code += "\tvec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex*2.0-1.0,1.0);\n";
- code += "\tworld_pos.xyz/=world_pos.w;\n";
- code += "\tALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n";
+ code += " float depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n";
+ code += " vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex*2.0-1.0,1.0);\n";
+ code += " world_pos.xyz/=world_pos.w;\n";
+ code += " ALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n";
}
if (distance_fade != DISTANCE_FADE_DISABLED) {
if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) {
if (!RenderingServer::get_singleton()->is_low_end()) {
- code += "\t{\n";
+ code += " {\n";
if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) {
- code += "\t\tfloat fade_distance = abs((INV_CAMERA_MATRIX * WORLD_MATRIX[3]).z);\n";
+ code += " float fade_distance = abs((INV_CAMERA_MATRIX * WORLD_MATRIX[3]).z);\n";
} else {
- code += "\t\tfloat fade_distance=-VERTEX.z;\n";
+ code += " float fade_distance=-VERTEX.z;\n";
}
- code += "\t\tfloat fade=clamp(smoothstep(distance_fade_min,distance_fade_max,fade_distance),0.0,1.0);\n";
- code += "\t\tint x = int(FRAGCOORD.x) % 4;\n";
- code += "\t\tint y = int(FRAGCOORD.y) % 4;\n";
- code += "\t\tint index = x + y * 4;\n";
- code += "\t\tfloat limit = 0.0;\n\n";
- code += "\t\tif (x < 8) {\n";
- code += "\t\t\tif (index == 0) limit = 0.0625;\n";
- code += "\t\t\tif (index == 1) limit = 0.5625;\n";
- code += "\t\t\tif (index == 2) limit = 0.1875;\n";
- code += "\t\t\tif (index == 3) limit = 0.6875;\n";
- code += "\t\t\tif (index == 4) limit = 0.8125;\n";
- code += "\t\t\tif (index == 5) limit = 0.3125;\n";
- code += "\t\t\tif (index == 6) limit = 0.9375;\n";
- code += "\t\t\tif (index == 7) limit = 0.4375;\n";
- code += "\t\t\tif (index == 8) limit = 0.25;\n";
- code += "\t\t\tif (index == 9) limit = 0.75;\n";
- code += "\t\t\tif (index == 10) limit = 0.125;\n";
- code += "\t\t\tif (index == 11) limit = 0.625;\n";
- code += "\t\t\tif (index == 12) limit = 1.0;\n";
- code += "\t\t\tif (index == 13) limit = 0.5;\n";
- code += "\t\t\tif (index == 14) limit = 0.875;\n";
- code += "\t\t\tif (index == 15) limit = 0.375;\n";
- code += "\t\t}\n\n";
- code += "\tif (fade < limit)\n";
- code += "\t\tdiscard;\n";
- code += "\t}\n\n";
+ code += " float fade=clamp(smoothstep(distance_fade_min,distance_fade_max,fade_distance),0.0,1.0);\n";
+ code += " int x = int(FRAGCOORD.x) % 4;\n";
+ code += " int y = int(FRAGCOORD.y) % 4;\n";
+ code += " int index = x + y * 4;\n";
+ code += " float limit = 0.0;\n\n";
+ code += " if (x < 8) {\n";
+ code += " if (index == 0) limit = 0.0625;\n";
+ code += " if (index == 1) limit = 0.5625;\n";
+ code += " if (index == 2) limit = 0.1875;\n";
+ code += " if (index == 3) limit = 0.6875;\n";
+ code += " if (index == 4) limit = 0.8125;\n";
+ code += " if (index == 5) limit = 0.3125;\n";
+ code += " if (index == 6) limit = 0.9375;\n";
+ code += " if (index == 7) limit = 0.4375;\n";
+ code += " if (index == 8) limit = 0.25;\n";
+ code += " if (index == 9) limit = 0.75;\n";
+ code += " if (index == 10) limit = 0.125;\n";
+ code += " if (index == 11) limit = 0.625;\n";
+ code += " if (index == 12) limit = 1.0;\n";
+ code += " if (index == 13) limit = 0.5;\n";
+ code += " if (index == 14) limit = 0.875;\n";
+ code += " if (index == 15) limit = 0.375;\n";
+ code += " }\n\n";
+ code += " if (fade < limit)\n";
+ code += " discard;\n";
+ code += " }\n\n";
}
} else {
- code += "\tALPHA*=clamp(smoothstep(distance_fade_min,distance_fade_max,-VERTEX.z),0.0,1.0);\n";
+ code += " ALPHA*=clamp(smoothstep(distance_fade_min,distance_fade_max,-VERTEX.z),0.0,1.0);\n";
}
}
if (features[FEATURE_RIM]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_triplanar_pos).xy;\n";
+ code += " vec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_triplanar_pos).xy;\n";
} else {
- code += "\tvec2 rim_tex = texture(texture_rim,base_uv).xy;\n";
+ code += " vec2 rim_tex = texture(texture_rim,base_uv).xy;\n";
}
- code += "\tRIM = rim*rim_tex.x;";
- code += "\tRIM_TINT = rim_tint*rim_tex.y;\n";
+ code += " RIM = rim*rim_tex.x;";
+ code += " RIM_TINT = rim_tint*rim_tex.y;\n";
}
if (features[FEATURE_CLEARCOAT]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec2 clearcoat_tex = triplanar_texture(texture_clearcoat,uv1_power_normal,uv1_triplanar_pos).xy;\n";
+ code += " vec2 clearcoat_tex = triplanar_texture(texture_clearcoat,uv1_power_normal,uv1_triplanar_pos).xy;\n";
} else {
- code += "\tvec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n";
+ code += " vec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n";
}
- code += "\tCLEARCOAT = clearcoat*clearcoat_tex.x;";
- code += "\tCLEARCOAT_GLOSS = clearcoat_gloss*clearcoat_tex.y;\n";
+ code += " CLEARCOAT = clearcoat*clearcoat_tex.x;";
+ code += " CLEARCOAT_GLOSS = clearcoat_gloss*clearcoat_tex.y;\n";
}
if (features[FEATURE_ANISOTROPY]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec3 anisotropy_tex = triplanar_texture(texture_flowmap,uv1_power_normal,uv1_triplanar_pos).rga;\n";
+ code += " vec3 anisotropy_tex = triplanar_texture(texture_flowmap,uv1_power_normal,uv1_triplanar_pos).rga;\n";
} else {
- code += "\tvec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n";
+ code += " vec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n";
}
- code += "\tANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n";
- code += "\tANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n";
+ code += " ANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n";
+ code += " ANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n";
}
if (features[FEATURE_AMBIENT_OCCLUSION]) {
if (!orm) {
if (flags[FLAG_AO_ON_UV2]) {
if (flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n";
+ code += " AO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n";
} else {
- code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n";
+ code += " AO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n";
}
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n";
+ code += " AO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n";
} else {
- code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n";
+ code += " AO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n";
}
}
} else {
- code += "\tAO = orm_tex.r;\n";
+ code += " AO = orm_tex.r;\n";
}
- code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n";
+ code += " AO_LIGHT_AFFECT = ao_light_affect;\n";
}
if (features[FEATURE_SUBSURFACE_SCATTERING]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n";
+ code += " float sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n";
} else {
- code += "\tfloat sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n";
+ code += " float sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n";
}
- code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n";
+ code += " SSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n";
}
if (features[FEATURE_SUBSURFACE_TRANSMITTANCE]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec4 trans_color_tex = triplanar_texture(texture_subsurface_transmittance,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += " vec4 trans_color_tex = triplanar_texture(texture_subsurface_transmittance,uv1_power_normal,uv1_triplanar_pos);\n";
} else {
- code += "\tvec4 trans_color_tex = texture(texture_subsurface_transmittance,base_uv);\n";
+ code += " vec4 trans_color_tex = texture(texture_subsurface_transmittance,base_uv);\n";
}
- code += "\tSSS_TRANSMITTANCE_COLOR=transmittance_color*trans_color_tex;\n";
+ code += " SSS_TRANSMITTANCE_COLOR=transmittance_color*trans_color_tex;\n";
- code += "\tSSS_TRANSMITTANCE_DEPTH=transmittance_depth;\n";
- code += "\tSSS_TRANSMITTANCE_CURVE=transmittance_curve;\n";
- code += "\tSSS_TRANSMITTANCE_BOOST=transmittance_boost;\n";
+ code += " SSS_TRANSMITTANCE_DEPTH=transmittance_depth;\n";
+ code += " SSS_TRANSMITTANCE_BOOST=transmittance_boost;\n";
}
if (features[FEATURE_BACKLIGHT]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec3 backlight_tex = triplanar_texture(texture_backlight,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
+ code += " vec3 backlight_tex = triplanar_texture(texture_backlight,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
} else {
- code += "\tvec3 backlight_tex = texture(texture_backlight,base_uv).rgb;\n";
+ code += " vec3 backlight_tex = texture(texture_backlight,base_uv).rgb;\n";
}
- code += "\tBACKLIGHT = (backlight.rgb+backlight_tex);\n";
+ code += " BACKLIGHT = (backlight.rgb+backlight_tex);\n";
}
if (features[FEATURE_DETAIL]) {
@@ -1198,41 +1234,41 @@ void BaseMaterial3D::_update_shader() {
if (triplanar) {
String tp_uv = detail_uv == DETAIL_UV_1 ? "uv1" : "uv2";
- code += "\tvec4 detail_tex = triplanar_texture(texture_detail_albedo," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n";
- code += "\tvec4 detail_norm_tex = triplanar_texture(texture_detail_normal," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n";
+ code += " vec4 detail_tex = triplanar_texture(texture_detail_albedo," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n";
+ code += " vec4 detail_norm_tex = triplanar_texture(texture_detail_normal," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n";
} else {
String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2";
- code += "\tvec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n";
- code += "\tvec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n";
+ code += " vec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n";
+ code += " vec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n";
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tvec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += " vec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal,uv1_triplanar_pos);\n";
} else {
- code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n";
+ code += " vec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n";
}
switch (detail_blend_mode) {
case BLEND_MODE_MIX: {
- code += "\tvec3 detail = mix(ALBEDO.rgb,detail_tex.rgb,detail_tex.a);\n";
+ code += " vec3 detail = mix(ALBEDO.rgb,detail_tex.rgb,detail_tex.a);\n";
} break;
case BLEND_MODE_ADD: {
- code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb+detail_tex.rgb,detail_tex.a);\n";
+ code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb+detail_tex.rgb,detail_tex.a);\n";
} break;
case BLEND_MODE_SUB: {
- code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb-detail_tex.rgb,detail_tex.a);\n";
+ code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb-detail_tex.rgb,detail_tex.a);\n";
} break;
case BLEND_MODE_MUL: {
- code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n";
+ code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n";
} break;
case BLEND_MODE_MAX:
break; // Internal value, skip.
}
- code += "\tvec3 detail_norm = mix(NORMAL_MAP,detail_norm_tex.rgb,detail_tex.a);\n";
- code += "\tNORMAL_MAP = mix(NORMAL_MAP,detail_norm,detail_mask_tex.r);\n";
- code += "\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
+ code += " vec3 detail_norm = mix(NORMAL_MAP,detail_norm_tex.rgb,detail_tex.a);\n";
+ code += " NORMAL_MAP = mix(NORMAL_MAP,detail_norm,detail_mask_tex.r);\n";
+ code += " ALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
}
code += "}\n";
@@ -1424,15 +1460,6 @@ float BaseMaterial3D::get_transmittance_depth() const {
return transmittance_depth;
}
-void BaseMaterial3D::set_transmittance_curve(float p_curve) {
- transmittance_curve = p_curve;
- RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_curve, p_curve);
-}
-
-float BaseMaterial3D::get_transmittance_curve() const {
- return transmittance_curve;
-}
-
void BaseMaterial3D::set_transmittance_boost(float p_boost) {
transmittance_boost = p_boost;
RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_boost, p_boost);
@@ -1696,7 +1723,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
_validate_high_end("heightmap", property);
if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "billboard_keep_scale" && billboard_mode == BILLBOARD_DISABLED) {
@@ -1726,33 +1753,33 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
// alpha scissor slider isn't needed when alpha antialiasing is enabled
if (property.name == "alpha_scissor_threshold" && transparency != TRANSPARENCY_ALPHA_SCISSOR) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
// alpha hash scale slider is only needed if transparency is alpha hash
if (property.name == "alpha_hash_scale" && transparency != TRANSPARENCY_ALPHA_HASH) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "alpha_antialiasing_mode" && !can_select_aa) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
// we can't choose an antialiasing mode if alpha isn't possible
if (property.name == "alpha_antialiasing_edge" && !alpha_aa_enabled) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "blend_mode" && alpha_aa_enabled) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if ((property.name == "heightmap_min_layers" || property.name == "heightmap_max_layers") && !deep_parallax) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
- if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (property.name == "subsurf_scatter_transmittance_color" || property.name == "subsurf_scatter_transmittance_texture" || property.name == "subsurf_scatter_transmittance_curve")) {
- property.usage = 0;
+ if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (property.name == "subsurf_scatter_transmittance_color" || property.name == "subsurf_scatter_transmittance_texture")) {
+ property.usage = PROPERTY_USAGE_NONE;
}
if (orm) {
@@ -1761,12 +1788,12 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
property.hint_string = "Unshaded,Per-Pixel";
}
if (property.name.begins_with("roughness") || property.name.begins_with("metallic") || property.name.begins_with("ao_texture")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
} else {
if (property.name == "orm_texture") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -1774,47 +1801,47 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
if (shading_mode != SHADING_MODE_PER_VERTEX) {
//these may still work per vertex
if (property.name.begins_with("ao")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("emission")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("metallic")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("rim")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("roughness")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("subsurf_scatter")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
//these definitely only need per pixel
if (property.name.begins_with("anisotropy")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("clearcoat")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("normal")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("backlight")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("transmittance")) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
}
@@ -2063,7 +2090,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel()
return refraction_texture_channel;
}
-RID BaseMaterial3D::get_material_rid_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) {
+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;
if (p_shaded) {
version = 1;
@@ -2088,7 +2115,10 @@ RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, b
}
if (materials_for_2d[version].is_valid()) {
- return materials_for_2d[version]->get_rid();
+ if (r_shader_rid) {
+ *r_shader_rid = materials_for_2d[version]->get_shader_rid();
+ }
+ return materials_for_2d[version];
}
Ref<StandardMaterial3D> material;
@@ -2106,7 +2136,11 @@ RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, b
materials_for_2d[version] = material;
- return materials_for_2d[version]->get_rid();
+ if (r_shader_rid) {
+ *r_shader_rid = materials_for_2d[version]->get_shader_rid();
+ }
+
+ return materials_for_2d[version];
}
void BaseMaterial3D::set_on_top_of_alpha() {
@@ -2175,6 +2209,8 @@ BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const {
}
RID BaseMaterial3D::get_shader_rid() const {
+ MutexLock lock(material_mutex);
+ ((BaseMaterial3D *)this)->_update_shader();
ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
return shader_map[current_key].shader;
}
@@ -2246,9 +2282,6 @@ void BaseMaterial3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transmittance_depth", "depth"), &BaseMaterial3D::set_transmittance_depth);
ClassDB::bind_method(D_METHOD("get_transmittance_depth"), &BaseMaterial3D::get_transmittance_depth);
- ClassDB::bind_method(D_METHOD("set_transmittance_curve", "curve"), &BaseMaterial3D::set_transmittance_curve);
- ClassDB::bind_method(D_METHOD("get_transmittance_curve"), &BaseMaterial3D::get_transmittance_curve);
-
ClassDB::bind_method(D_METHOD("set_transmittance_boost", "boost"), &BaseMaterial3D::set_transmittance_boost);
ClassDB::bind_method(D_METHOD("get_transmittance_boost"), &BaseMaterial3D::get_transmittance_boost);
@@ -2483,7 +2516,6 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "subsurf_scatter_transmittance_color"), "set_transmittance_color", "get_transmittance_color");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_transmittance_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_TRANSMITTANCE);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_depth", PROPERTY_HINT_RANGE, "0.001,8,0.001,or_greater"), "set_transmittance_depth", "get_transmittance_depth");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_curve", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_transmittance_curve", "get_transmittance_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_boost", PROPERTY_HINT_RANGE, "0.00,1.0,0.01"), "set_transmittance_boost", "get_transmittance_boost");
ADD_GROUP("Back Lighting", "backlight_");
@@ -2700,7 +2732,6 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_backlight(Color(0, 0, 0));
set_transmittance_color(Color(1, 1, 1, 1));
set_transmittance_depth(0.1);
- set_transmittance_curve(1.0);
set_transmittance_boost(0.0);
set_refraction(0.05);
set_point_size(1);
diff --git a/scene/resources/material.h b/scene/resources/material.h
index dc3ecdb5de..e2838e1399 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -79,6 +79,8 @@ class ShaderMaterial : public Material {
GDCLASS(ShaderMaterial, Material);
Ref<Shader> shader;
+ Map<StringName, Variant> param_cache;
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -389,7 +391,6 @@ private:
StringName heightmap_scale;
StringName subsurface_scattering_strength;
StringName transmittance_color;
- StringName transmittance_curve;
StringName transmittance_depth;
StringName transmittance_boost;
StringName backlight;
@@ -458,7 +459,6 @@ private:
float transmittance_amount;
Color transmittance_color;
float transmittance_depth;
- float transmittance_curve;
float transmittance_boost;
Color backlight;
@@ -602,9 +602,6 @@ public:
void set_transmittance_depth(float p_depth);
float get_transmittance_depth() const;
- void set_transmittance_curve(float p_curve);
- float get_transmittance_curve() const;
-
void set_transmittance_boost(float p_boost);
float get_transmittance_boost() const;
@@ -738,7 +735,7 @@ public:
static void finish_shaders();
static void flush_changes();
- static RID get_material_rid_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);
+ 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);
virtual RID get_shader_rid() const override;
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index cf59c6fa22..2f92872ad5 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -30,6 +30,7 @@
#include "mesh.h"
+#include "core/math/convex_hull.h"
#include "core/templates/pair.h"
#include "scene/resources/concave_polygon_shape_3d.h"
#include "scene/resources/convex_polygon_shape_3d.h"
@@ -221,9 +222,17 @@ Vector<Face3> Mesh::get_faces() const {
*/
}
-Ref<Shape3D> Mesh::create_convex_shape() const {
- Vector<Vector3> vertices;
+Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
+ if (p_simplify) {
+ Vector<Ref<Shape3D>> decomposed = convex_decompose(1);
+ if (decomposed.size() == 1) {
+ return decomposed[0];
+ } else {
+ ERR_PRINT("Convex shape simplification failed, falling back to simpler process.");
+ }
+ }
+ Vector<Vector3> vertices;
for (int i = 0; i < get_surface_count(); i++) {
Array a = surface_get_arrays(i);
ERR_FAIL_COND_V(a.is_empty(), Ref<ConvexPolygonShape3D>());
@@ -232,6 +241,18 @@ Ref<Shape3D> Mesh::create_convex_shape() const {
}
Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D);
+
+ if (p_clean) {
+ Geometry3D::MeshData md;
+ Error err = ConvexHullComputer::convex_hull(vertices, md);
+ if (err == OK) {
+ shape->set_points(md.vertices);
+ return shape;
+ } else {
+ ERR_PRINT("Convex shape cleaning failed, falling back to simpler process.");
+ }
+ }
+
shape->set_points(vertices);
return shape;
}
@@ -543,12 +564,12 @@ void Mesh::clear_cache() const {
debug_lines.clear();
}
-Vector<Ref<Shape3D>> Mesh::convex_decompose() const {
+Vector<Ref<Shape3D>> Mesh::convex_decompose(int p_max_convex_hulls) const {
ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape3D>>());
const Vector<Face3> faces = get_faces();
- Vector<Vector<Face3>> decomposed = convex_composition_function(faces);
+ Vector<Vector<Face3>> decomposed = convex_composition_function(faces, p_max_convex_hulls);
Vector<Ref<Shape3D>> ret;
@@ -590,157 +611,320 @@ Transform3D Mesh::get_builtin_bind_pose(int p_index) const {
Mesh::Mesh() {
}
-#if 0
-static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) {
- enum ArrayType {
- OLD_ARRAY_VERTEX = 0,
- OLD_ARRAY_NORMAL = 1,
- OLD_ARRAY_TANGENT = 2,
- OLD_ARRAY_COLOR = 3,
- OLD_ARRAY_TEX_UV = 4,
- OLD_ARRAY_TEX_UV2 = 5,
- OLD_ARRAY_BONES = 6,
- OLD_ARRAY_WEIGHTS = 7,
- OLD_ARRAY_INDEX = 8,
- OLD_ARRAY_MAX = 9
- };
-
- enum ArrayFormat {
- /* OLD_ARRAY FORMAT FLAGS */
- OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory
- OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL,
- OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT,
- OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR,
- OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV,
- OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2,
- OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES,
- OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS,
- OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX,
-
- OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1),
- OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE),
- OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE),
- OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE),
- OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE),
- OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE),
- OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE),
- OLD_ARRAY_COMPRESS_DEFAULT = OLD_ARRAY_COMPRESS_NORMAL | OLD_ARRAY_COMPRESS_TANGENT | OLD_ARRAY_COMPRESS_COLOR | OLD_ARRAY_COMPRESS_TEX_UV | OLD_ARRAY_COMPRESS_TEX_UV2,
-
- OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1,
- OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3,
- };
-
- bool vertex_16bit = p_format & ((1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE)));
- bool has_bones = (p_format & OLD_ARRAY_FORMAT_BONES);
- bool bone_8 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_INDEX << 2));
- bool weight_32 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_TEX_UV2 << 2));
-
- print_line("convert vertex16: " + itos(vertex_16bit) + " convert bone 8 " + itos(bone_8) + " convert weight 32 " + itos(weight_32));
-
- if (!vertex_16bit && !bone_8 && !weight_32) {
- return p_src;
- }
+enum OldArrayType {
+ OLD_ARRAY_VERTEX,
+ OLD_ARRAY_NORMAL,
+ OLD_ARRAY_TANGENT,
+ OLD_ARRAY_COLOR,
+ OLD_ARRAY_TEX_UV,
+ OLD_ARRAY_TEX_UV2,
+ OLD_ARRAY_BONES,
+ OLD_ARRAY_WEIGHTS,
+ OLD_ARRAY_INDEX,
+ OLD_ARRAY_MAX,
+};
+
+enum OldArrayFormat {
+ /* OLD_ARRAY FORMAT FLAGS */
+ OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory
+ OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL,
+ OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT,
+ OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR,
+ OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV,
+ OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2,
+ OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES,
+ OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS,
+ OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX,
+
+ OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1),
+ OLD_ARRAY_COMPRESS_VERTEX = 1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE), // mandatory
+ OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_BONES = 1 << (OLD_ARRAY_BONES + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_WEIGHTS = 1 << (OLD_ARRAY_WEIGHTS + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE),
+
+ OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1,
+ OLD_ARRAY_FLAG_USE_16_BIT_BONES = OLD_ARRAY_COMPRESS_INDEX << 2,
+ OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3,
+
+};
- bool vertex_2d = (p_format & (OLD_ARRAY_COMPRESS_INDEX << 1));
+static Array _convert_old_array(const Array &p_old) {
+ Array new_array;
+ new_array.resize(Mesh::ARRAY_MAX);
+ new_array[Mesh::ARRAY_VERTEX] = p_old[OLD_ARRAY_VERTEX];
+ new_array[Mesh::ARRAY_NORMAL] = p_old[OLD_ARRAY_NORMAL];
+ new_array[Mesh::ARRAY_TANGENT] = p_old[OLD_ARRAY_TANGENT];
+ new_array[Mesh::ARRAY_COLOR] = p_old[OLD_ARRAY_COLOR];
+ new_array[Mesh::ARRAY_TEX_UV] = p_old[OLD_ARRAY_TEX_UV];
+ new_array[Mesh::ARRAY_TEX_UV2] = p_old[OLD_ARRAY_TEX_UV2];
+ new_array[Mesh::ARRAY_BONES] = p_old[OLD_ARRAY_BONES];
+ new_array[Mesh::ARRAY_WEIGHTS] = p_old[OLD_ARRAY_WEIGHTS];
+ new_array[Mesh::ARRAY_INDEX] = p_old[OLD_ARRAY_INDEX];
+ return new_array;
+}
+
+static Mesh::PrimitiveType _old_primitives[7] = {
+ Mesh::PRIMITIVE_POINTS,
+ Mesh::PRIMITIVE_LINES,
+ Mesh::PRIMITIVE_LINE_STRIP,
+ Mesh::PRIMITIVE_LINES,
+ Mesh::PRIMITIVE_TRIANGLES,
+ Mesh::PRIMITIVE_TRIANGLE_STRIP,
+ Mesh::PRIMITIVE_TRIANGLE_STRIP
+};
- uint32_t src_stride = p_src.size() / p_elements;
- uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) + (bone_8 ? 4 : 0) - (weight_32 ? 8 : 0);
+void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) {
+ uint32_t dst_vertex_stride;
+ uint32_t dst_attribute_stride;
+ uint32_t dst_skin_stride;
+ uint32_t dst_offsets[Mesh::ARRAY_MAX];
+ RenderingServer::get_singleton()->mesh_surface_make_offsets_from_format(p_new_format & (~RS::ARRAY_FORMAT_INDEX), p_elements, 0, dst_offsets, dst_vertex_stride, dst_attribute_stride, dst_skin_stride);
- Vector<uint8_t> ret = p_src;
+ vertex_data.resize(dst_vertex_stride * p_elements);
+ attribute_data.resize(dst_attribute_stride * p_elements);
+ skin_data.resize(dst_skin_stride * p_elements);
- ret.resize(dst_stride * p_elements);
- {
- uint8_t *w = ret.ptrw();
- const uint8_t *r = p_src.ptr();
-
- for (uint32_t i = 0; i < p_elements; i++) {
- uint32_t remaining = src_stride;
- const uint8_t *src = (const uint8_t *)(r + src_stride * i);
- uint8_t *dst = (uint8_t *)(w + dst_stride * i);
-
- if (!vertex_2d) { //3D
- if (vertex_16bit) {
- float *dstw = (float *)dst;
- const uint16_t *srcr = (const uint16_t *)src;
- dstw[0] = Math::half_to_float(srcr[0]);
- dstw[1] = Math::half_to_float(srcr[1]);
- dstw[2] = Math::half_to_float(srcr[2]);
- remaining -= 8;
- src += 8;
+ uint8_t *dst_vertex_ptr = vertex_data.ptrw();
+ uint8_t *dst_attribute_ptr = attribute_data.ptrw();
+ uint8_t *dst_skin_ptr = skin_data.ptrw();
+
+ const uint8_t *src_vertex_ptr = p_src.ptr();
+ uint32_t src_vertex_stride = p_src.size() / p_elements;
+
+ uint32_t src_offset = 0;
+ for (uint32_t j = 0; j < OLD_ARRAY_INDEX; j++) {
+ if (!(p_old_format & (1 << j))) {
+ continue;
+ }
+ switch (j) {
+ case OLD_ARRAY_VERTEX: {
+ if (p_old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) {
+ if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride];
+ float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride];
+ dst[0] = Math::half_to_float(src[0]);
+ dst[1] = Math::half_to_float(src[1]);
+ }
+ src_offset += sizeof(uint16_t) * 2;
+ } else {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride];
+ float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride];
+ dst[0] = src[0];
+ dst[1] = src[1];
+ }
+ src_offset += sizeof(float) * 2;
+ }
} else {
- src += 12;
- remaining -= 12;
+ if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride];
+ float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride];
+ dst[0] = Math::half_to_float(src[0]);
+ dst[1] = Math::half_to_float(src[1]);
+ dst[2] = Math::half_to_float(src[2]);
+ }
+ src_offset += sizeof(uint16_t) * 4; //+pad
+ } else {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride];
+ float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride];
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ }
+ src_offset += sizeof(float) * 3;
+ }
}
- dst += 12;
- } else {
- if (vertex_16bit) {
- float *dstw = (float *)dst;
- const uint16_t *srcr = (const uint16_t *)src;
- dstw[0] = Math::half_to_float(srcr[0]);
- dstw[1] = Math::half_to_float(srcr[1]);
- remaining -= 4;
- src += 4;
+ } break;
+ case OLD_ARRAY_NORMAL: {
+ if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) {
+ const float multiplier = 1.f / 127.f * 1023.0f;
+
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
+
+ *dst = 0;
+ *dst |= CLAMP(int(src[0] * multiplier), 0, 1023);
+ *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10;
+ *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20;
+ }
+ src_offset += sizeof(uint32_t);
} else {
- src += 8;
- remaining -= 8;
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
+
+ *dst = 0;
+ *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023);
+ *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10;
+ *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20;
+ }
+ src_offset += sizeof(float) * 3;
}
- dst += 8;
- }
-
- if (has_bones) {
- remaining -= bone_8 ? 4 : 8;
- remaining -= weight_32 ? 16 : 8;
- }
- for (uint32_t j = 0; j < remaining; j++) {
- dst[j] = src[j];
- }
-
- if (has_bones) {
- dst += remaining;
- src += remaining;
-
- if (bone_8) {
- const uint8_t *src_bones = (const uint8_t *)src;
- uint16_t *dst_bones = (uint16_t *)dst;
+ } break;
+ case OLD_ARRAY_TANGENT: {
+ if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) {
+ const float multiplier = 1.f / 127.f * 1023.0f;
+
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
+
+ *dst = 0;
+ *dst |= CLAMP(int(src[0] * multiplier), 0, 1023);
+ *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10;
+ *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20;
+ if (src[3] > 0) {
+ *dst |= 3 << 30;
+ }
+ }
+ src_offset += sizeof(uint32_t);
+ } else {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
+
+ *dst = 0;
+ *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023);
+ *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10;
+ *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20;
+ if (src[3] > 0) {
+ *dst |= 3 << 30;
+ }
+ }
+ src_offset += sizeof(float) * 4;
+ }
- dst_bones[0] = src_bones[0];
- dst_bones[1] = src_bones[1];
- dst_bones[2] = src_bones[2];
- dst_bones[3] = src_bones[3];
+ } break;
+ case OLD_ARRAY_COLOR: {
+ if (p_old_format & OLD_ARRAY_COMPRESS_COLOR) {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint32_t *src = (const uint32_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint32_t *dst = (uint32_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]];
- src += 4;
+ *dst = *src;
+ }
+ src_offset += sizeof(uint32_t);
} else {
- for (uint32_t j = 0; j < 8; j++) {
- dst[j] = src[j];
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint8_t *dst = (uint8_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]];
+
+ dst[0] = uint8_t(CLAMP(src[0] * 255.0, 0.0, 255.0));
+ dst[1] = uint8_t(CLAMP(src[1] * 255.0, 0.0, 255.0));
+ dst[2] = uint8_t(CLAMP(src[2] * 255.0, 0.0, 255.0));
+ dst[3] = uint8_t(CLAMP(src[3] * 255.0, 0.0, 255.0));
}
-
- src += 8;
+ src_offset += sizeof(float) * 4;
}
+ } break;
+ case OLD_ARRAY_TEX_UV: {
+ if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV) {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]];
+
+ dst[0] = Math::half_to_float(src[0]);
+ dst[1] = Math::half_to_float(src[1]);
+ }
+ src_offset += sizeof(uint16_t) * 2;
+ } else {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]];
- dst += 8;
+ dst[0] = src[0];
+ dst[1] = src[1];
+ }
+ src_offset += sizeof(float) * 2;
+ }
- if (weight_32) {
- const float *src_weights = (const float *)src;
- uint16_t *dst_weights = (uint16_t *)dst;
+ } break;
+ case OLD_ARRAY_TEX_UV2: {
+ if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV2) {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]];
- dst_weights[0] = CLAMP(src_weights[0] * 65535, 0, 65535); //16bits unorm
- dst_weights[1] = CLAMP(src_weights[1] * 65535, 0, 65535);
- dst_weights[2] = CLAMP(src_weights[2] * 65535, 0, 65535);
- dst_weights[3] = CLAMP(src_weights[3] * 65535, 0, 65535);
+ dst[0] = Math::half_to_float(src[0]);
+ dst[1] = Math::half_to_float(src[1]);
+ }
+ src_offset += sizeof(uint16_t) * 2;
+ } else {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]];
+ dst[0] = src[0];
+ dst[1] = src[1];
+ }
+ src_offset += sizeof(float) * 2;
+ }
+ } break;
+ case OLD_ARRAY_BONES: {
+ if (p_old_format & OLD_ARRAY_FLAG_USE_16_BIT_BONES) {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]];
+
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ }
+ src_offset += sizeof(uint16_t) * 4;
+ } else {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint8_t *src = (const uint8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]];
+
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ }
+ src_offset += sizeof(uint8_t) * 4;
+ }
+ } break;
+ case OLD_ARRAY_WEIGHTS: {
+ if (p_old_format & OLD_ARRAY_COMPRESS_WEIGHTS) {
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]];
+
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ }
+ src_offset += sizeof(uint16_t) * 4;
} else {
- for (uint32_t j = 0; j < 8; j++) {
- dst[j] = src[j];
+ for (uint32_t i = 0; i < p_elements; i++) {
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
+ uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]];
+
+ dst[0] = uint16_t(CLAMP(src[0] * 65535.0, 0, 65535.0));
+ dst[1] = uint16_t(CLAMP(src[1] * 65535.0, 0, 65535.0));
+ dst[2] = uint16_t(CLAMP(src[2] * 65535.0, 0, 65535.0));
+ dst[3] = uint16_t(CLAMP(src[3] * 65535.0, 0, 65535.0));
}
+ src_offset += sizeof(float) * 4;
}
+ } break;
+ default: {
}
}
}
-
- return ret;
}
-#endif
bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
String sname = p_name;
@@ -779,10 +963,13 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
if (d.has("arrays")) {
//oldest format (2.x)
ERR_FAIL_COND_V(!d.has("morph_arrays"), false);
- add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]);
+ Array morph_arrays = d["morph_arrays"];
+ for (int i = 0; i < morph_arrays.size(); i++) {
+ morph_arrays[i] = _convert_old_array(morph_arrays[i]);
+ }
+ add_surface_from_arrays(_old_primitives[int(d["primitive"])], _convert_old_array(d["arrays"]), morph_arrays);
} else if (d.has("array_data")) {
-#if 0
//print_line("array data (old style");
//older format (3.x)
Vector<uint8_t> array_data = d["array_data"];
@@ -792,48 +979,76 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
}
ERR_FAIL_COND_V(!d.has("format"), false);
- uint32_t format = d["format"];
+ uint32_t old_format = d["format"];
uint32_t primitive = d["primitive"];
- uint32_t primitive_remap[7] = {
- PRIMITIVE_POINTS,
- PRIMITIVE_LINES,
- PRIMITIVE_LINE_STRIP,
- PRIMITIVE_LINES,
- PRIMITIVE_TRIANGLES,
- PRIMITIVE_TRIANGLE_STRIP,
- PRIMITIVE_TRIANGLE_STRIP
- };
-
- primitive = primitive_remap[primitive]; //compatibility
+ primitive = _old_primitives[primitive]; //compatibility
ERR_FAIL_COND_V(!d.has("vertex_count"), false);
int vertex_count = d["vertex_count"];
- array_data = _fix_array_compatibility(array_data, format, vertex_count);
+ uint32_t new_format = ARRAY_FORMAT_VERTEX;
+
+ if (old_format & OLD_ARRAY_FORMAT_NORMAL) {
+ new_format |= ARRAY_FORMAT_NORMAL;
+ }
+ if (old_format & OLD_ARRAY_FORMAT_TANGENT) {
+ new_format |= ARRAY_FORMAT_TANGENT;
+ }
+ if (old_format & OLD_ARRAY_FORMAT_COLOR) {
+ new_format |= ARRAY_FORMAT_COLOR;
+ }
+ if (old_format & OLD_ARRAY_FORMAT_TEX_UV) {
+ new_format |= ARRAY_FORMAT_TEX_UV;
+ }
+ if (old_format & OLD_ARRAY_FORMAT_TEX_UV2) {
+ new_format |= ARRAY_FORMAT_TEX_UV2;
+ }
+ if (old_format & OLD_ARRAY_FORMAT_BONES) {
+ new_format |= ARRAY_FORMAT_BONES;
+ }
+ if (old_format & OLD_ARRAY_FORMAT_WEIGHTS) {
+ new_format |= ARRAY_FORMAT_WEIGHTS;
+ }
+ if (old_format & OLD_ARRAY_FORMAT_INDEX) {
+ new_format |= ARRAY_FORMAT_INDEX;
+ }
+ if (old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) {
+ new_format |= OLD_ARRAY_FLAG_USE_2D_VERTICES;
+ }
+
+ Vector<uint8_t> vertex_array;
+ Vector<uint8_t> attribute_array;
+ Vector<uint8_t> skin_array;
+
+ _fix_array_compatibility(array_data, old_format, new_format, vertex_count, vertex_array, attribute_array, skin_array);
int index_count = 0;
if (d.has("index_count")) {
index_count = d["index_count"];
}
- Vector<Vector<uint8_t>> blend_shapes;
+ Vector<uint8_t> blend_shapes;
if (d.has("blend_shape_data")) {
Array blend_shape_data = d["blend_shape_data"];
for (int i = 0; i < blend_shape_data.size(); i++) {
+ Vector<uint8_t> blend_vertex_array;
+ Vector<uint8_t> blend_attribute_array;
+ Vector<uint8_t> blend_skin_array;
+
Vector<uint8_t> shape = blend_shape_data[i];
- shape = _fix_array_compatibility(shape, format, vertex_count);
+ _fix_array_compatibility(shape, old_format, new_format, vertex_count, blend_vertex_array, blend_attribute_array, blend_skin_array);
- blend_shapes.push_back(shape);
+ blend_shapes.append_array(blend_vertex_array);
}
}
//clear unused flags
- print_line("format pre: " + itos(format));
- format &= ~uint32_t((1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE)) | (ARRAY_COMPRESS_INDEX << 2) | (ARRAY_COMPRESS_TEX_UV2 << 2));
- print_line("format post: " + itos(format));
+ print_line("format pre: " + itos(old_format));
+
+ print_line("format post: " + itos(new_format));
ERR_FAIL_COND_V(!d.has("aabb"), false);
AABB aabb = d["aabb"];
@@ -848,8 +1063,8 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
}
}
- add_surface(format, PrimitiveType(primitive), array_data, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb);
-#endif
+ add_surface(new_format, PrimitiveType(primitive), vertex_array, attribute_array, skin_array, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb);
+
} else {
ERR_FAIL_V(false);
}
@@ -1120,9 +1335,9 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < surfaces.size(); i++) {
p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
if (surfaces[i].is_2d) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial", PROPERTY_USAGE_EDITOR));
} else {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_EDITOR));
}
}
}
@@ -1335,9 +1550,21 @@ String ArrayMesh::surface_get_name(int p_idx) const {
return surfaces[p_idx].name;
}
-void ArrayMesh::surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+void ArrayMesh::surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ ERR_FAIL_INDEX(p_surface, surfaces.size());
+ RS::get_singleton()->mesh_surface_update_vertex_region(mesh, p_surface, p_offset, p_data);
+ emit_changed();
+}
+
+void ArrayMesh::surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ ERR_FAIL_INDEX(p_surface, surfaces.size());
+ RS::get_singleton()->mesh_surface_update_attribute_region(mesh, p_surface, p_offset, p_data);
+ emit_changed();
+}
+
+void ArrayMesh::surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
ERR_FAIL_INDEX(p_surface, surfaces.size());
- RS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data);
+ RS::get_singleton()->mesh_surface_update_skin_region(mesh, p_surface, p_offset, p_data);
emit_changed();
}
@@ -1635,7 +1862,9 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces);
- ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region);
+ ClassDB::bind_method(D_METHOD("surface_update_vertex_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_vertex_region);
+ ClassDB::bind_method(D_METHOD("surface_update_attribute_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_attribute_region);
+ ClassDB::bind_method(D_METHOD("surface_update_skin_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_skin_region);
ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len);
ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len);
ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format);
@@ -1644,7 +1873,7 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name);
ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name);
ClassDB::bind_method(D_METHOD("create_trimesh_shape"), &ArrayMesh::create_trimesh_shape);
- ClassDB::bind_method(D_METHOD("create_convex_shape"), &ArrayMesh::create_convex_shape);
+ ClassDB::bind_method(D_METHOD("create_convex_shape", "clean", "simplify"), &ArrayMesh::create_convex_shape, DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline);
ClassDB::bind_method(D_METHOD("regen_normal_maps"), &ArrayMesh::regen_normal_maps);
ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normal_maps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 2dfb46782b..27b0eb098b 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -149,7 +149,7 @@ public:
void generate_debug_mesh_indices(Vector<Vector3> &r_points);
Ref<Shape3D> create_trimesh_shape() const;
- Ref<Shape3D> create_convex_shape() const;
+ Ref<Shape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
Ref<Mesh> create_outline(float p_margin) const;
@@ -159,11 +159,11 @@ public:
Size2i get_lightmap_size_hint() const;
void clear_cache() const;
- typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &);
+ typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &p_faces, int p_max_convex_hulls);
static ConvexDecompositionFunc convex_composition_function;
- Vector<Ref<Shape3D>> convex_decompose() const;
+ Vector<Ref<Shape3D>> convex_decompose(int p_max_convex_hulls = -1) const;
virtual int get_builtin_bind_pose_count() const;
virtual Transform3D get_builtin_bind_pose(int p_index) const;
@@ -233,7 +233,9 @@ public:
void set_blend_shape_mode(BlendShapeMode p_mode);
BlendShapeMode get_blend_shape_mode() const;
- void surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ void surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ void surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ void surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
int get_surface_count() const override;
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index 0a25bb2ed1..d2be2bdba1 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -501,14 +501,14 @@ void NavigationMesh::_bind_methods() {
void NavigationMesh::_validate_property(PropertyInfo &property) const {
if (property.name == "geometry/collision_mask") {
if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
return;
}
}
if (property.name == "geometry/source_group_name") {
if (source_geometry_mode == SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
return;
}
}
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 913f1ca376..9bb2a4ddb8 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -471,7 +471,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
StringName type = p_node->get_class();
Ref<Script> script = p_node->get_script();
- if (script.is_valid()) {
+ if (Engine::get_singleton()->is_editor_hint() && script.is_valid()) {
+ // Should be called in the editor only and not at runtime,
+ // otherwise it can cause problems because of missing instance state support.
script->update_exports();
}
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index 60d5566f08..00bea312b3 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -569,7 +569,7 @@ void ParticlesMaterial::_update_shader() {
code += " vec4(1.250, -1.050, -0.203, 0.0),\n";
code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n";
if (color_ramp.is_valid()) {
- code += " COLOR = hue_rot_mat * textureLod(color_ramp, vec2(tv, 0.0), 0.0);\n";
+ code += " COLOR = hue_rot_mat * textureLod(color_ramp, vec2(tv, 0.0), 0.0) * color_value;\n";
} else {
code += " COLOR = hue_rot_mat * color_value;\n";
}
@@ -852,52 +852,54 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D
tex_parameters[p_param] = p_texture;
+ RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
+
switch (p_param) {
case PARAM_INITIAL_LINEAR_VELOCITY: {
//do none for this one
} break;
case PARAM_ANGULAR_VELOCITY: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, tex_rid);
_adjust_curve_range(p_texture, -360, 360);
} break;
case PARAM_ORBIT_VELOCITY: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, tex_rid);
_adjust_curve_range(p_texture, -500, 500);
} break;
case PARAM_LINEAR_ACCEL: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, tex_rid);
_adjust_curve_range(p_texture, -200, 200);
} break;
case PARAM_RADIAL_ACCEL: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, tex_rid);
_adjust_curve_range(p_texture, -200, 200);
} break;
case PARAM_TANGENTIAL_ACCEL: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, tex_rid);
_adjust_curve_range(p_texture, -200, 200);
} break;
case PARAM_DAMPING: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, tex_rid);
_adjust_curve_range(p_texture, 0, 100);
} break;
case PARAM_ANGLE: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, tex_rid);
_adjust_curve_range(p_texture, -360, 360);
} break;
case PARAM_SCALE: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, tex_rid);
_adjust_curve_range(p_texture, 0, 1);
} break;
case PARAM_HUE_VARIATION: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, tex_rid);
_adjust_curve_range(p_texture, -1, 1);
} break;
case PARAM_ANIM_SPEED: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, tex_rid);
_adjust_curve_range(p_texture, 0, 200);
} break;
case PARAM_ANIM_OFFSET: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, tex_rid);
} break;
case PARAM_MAX:
break; // Can't happen, but silences warning
@@ -923,7 +925,8 @@ Color ParticlesMaterial::get_color() const {
void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) {
color_ramp = p_texture;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture);
+ RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, tex_rid);
_queue_shader_change();
notify_property_list_changed();
}
@@ -965,17 +968,20 @@ void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) {
void ParticlesMaterial::set_emission_point_texture(const Ref<Texture2D> &p_points) {
emission_point_texture = p_points;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points);
+ RID tex_rid = p_points.is_valid() ? p_points->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, tex_rid);
}
void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture2D> &p_normals) {
emission_normal_texture = p_normals;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals);
+ RID tex_rid = p_normals.is_valid() ? p_normals->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, tex_rid);
}
void ParticlesMaterial::set_emission_color_texture(const Ref<Texture2D> &p_colors) {
emission_color_texture = p_colors;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors);
+ RID tex_rid = p_colors.is_valid() ? p_colors->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, tex_rid);
_queue_shader_change();
}
@@ -1040,40 +1046,36 @@ RID ParticlesMaterial::get_shader_rid() const {
}
void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
- if (property.name == "color" && color_ramp.is_valid()) {
- property.usage = 0;
- }
-
if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_normal_texture" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "emission_point_count" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "sub_emitter_frequency" && sub_emitter_mode != SUB_EMITTER_CONSTANT) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name == "sub_emitter_amount_at_end" && sub_emitter_mode != SUB_EMITTER_AT_END) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -1292,7 +1294,7 @@ void ParticlesMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_DAMPING);
ADD_GROUP("Angle", "");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater,degrees"), "set_param", "get_param", PARAM_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGLE);
ADD_GROUP("Scale", "");
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 2b2ebb5c16..dfa45cc810 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -207,7 +207,7 @@ void PrimitiveMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
}
@@ -714,7 +714,7 @@ int BoxMesh::get_subdivide_depth() const {
BoxMesh::BoxMesh() {}
/**
- CylinderMesh
+ CylinderMesh
*/
void CylinderMesh::_create_mesh_array(Array &p_arr) const {
@@ -955,7 +955,7 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
u /= (subdivide_w + 1.0);
v /= (subdivide_d + 1.0);
- points.push_back(Vector3(-x, 0.0, -z));
+ points.push_back(Vector3(-x, 0.0, -z) + center_offset);
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
@@ -993,10 +993,13 @@ void PlaneMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width);
ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth);
ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth);
+ ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset);
+ ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
}
void PlaneMesh::set_size(const Size2 &p_size) {
@@ -1026,6 +1029,15 @@ int PlaneMesh::get_subdivide_depth() const {
return subdivide_d;
}
+void PlaneMesh::set_center_offset(const Vector3 p_offset) {
+ center_offset = p_offset;
+ _request_update();
+}
+
+Vector3 PlaneMesh::get_center_offset() const {
+ return center_offset;
+}
+
PlaneMesh::PlaneMesh() {}
/**
@@ -1326,10 +1338,10 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f);
Vector3 quad_faces[4] = {
- Vector3(-_size.x, -_size.y, 0),
- Vector3(-_size.x, _size.y, 0),
- Vector3(_size.x, _size.y, 0),
- Vector3(_size.x, -_size.y, 0),
+ Vector3(-_size.x, -_size.y, 0) + center_offset,
+ Vector3(-_size.x, _size.y, 0) + center_offset,
+ Vector3(_size.x, _size.y, 0) + center_offset,
+ Vector3(_size.x, -_size.y, 0) + center_offset,
};
static const int indices[6] = {
@@ -1365,7 +1377,11 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
void QuadMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size);
+ ClassDB::bind_method(D_METHOD("set_center_offset", "center_offset"), &QuadMesh::set_center_offset);
+ ClassDB::bind_method(D_METHOD("get_center_offset"), &QuadMesh::get_center_offset);
+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
}
QuadMesh::QuadMesh() {
@@ -1381,6 +1397,15 @@ Size2 QuadMesh::get_size() const {
return size;
}
+void QuadMesh::set_center_offset(Vector3 p_center_offset) {
+ center_offset = p_center_offset;
+ _request_update();
+}
+
+Vector3 QuadMesh::get_center_offset() const {
+ return center_offset;
+}
+
/**
SphereMesh
*/
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index bd6f94921e..a3de34d3e3 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -211,6 +211,7 @@ private:
Size2 size = Size2(2.0, 2.0);
int subdivide_w = 0;
int subdivide_d = 0;
+ Vector3 center_offset;
protected:
static void _bind_methods();
@@ -226,6 +227,9 @@ public:
void set_subdivide_depth(const int p_divisions);
int get_subdivide_depth() const;
+ void set_center_offset(const Vector3 p_offset);
+ Vector3 get_center_offset() const;
+
PlaneMesh();
};
@@ -274,6 +278,7 @@ class QuadMesh : public PrimitiveMesh {
private:
Size2 size = Size2(1.0, 1.0);
+ Vector3 center_offset;
protected:
static void _bind_methods();
@@ -284,6 +289,9 @@ public:
void set_size(const Size2 &p_size);
Size2 get_size() const;
+
+ void set_center_offset(const Vector3 p_offset);
+ Vector3 get_center_offset() const;
};
/**
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 9d79c22159..b34d3feb47 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -181,68 +181,75 @@ void ProceduralSkyMaterial::_bind_methods() {
}
ProceduralSkyMaterial::ProceduralSkyMaterial() {
- String code = "shader_type sky;\n\n";
-
- code += "uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);\n";
- code += "uniform vec4 sky_horizon_color : hint_color = vec4(0.55, 0.69, 0.81, 1.0);\n";
- code += "uniform float sky_curve : hint_range(0, 1) = 0.09;\n";
- code += "uniform float sky_energy = 1.0;\n\n";
- code += "uniform vec4 ground_bottom_color : hint_color = vec4(0.12, 0.12, 0.13, 1.0);\n";
- code += "uniform vec4 ground_horizon_color : hint_color = vec4(0.37, 0.33, 0.31, 1.0);\n";
- code += "uniform float ground_curve : hint_range(0, 1) = 0.02;\n";
- code += "uniform float ground_energy = 1.0;\n\n";
- code += "uniform float sun_angle_max = 1.74;\n";
- code += "uniform float sun_curve : hint_range(0, 1) = 0.05;\n\n";
- code += "void sky() {\n";
- code += "\tfloat v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));\n";
- code += "\tfloat c = (1.0 - v_angle / (PI * 0.5));\n";
- code += "\tvec3 sky = mix(sky_horizon_color.rgb, sky_top_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / sky_curve), 0.0, 1.0));\n";
- code += "\tsky *= sky_energy;\n";
- code += "\tif (LIGHT0_ENABLED) {\n";
- code += "\t\tfloat sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR));\n";
- code += "\t\tif (sun_angle < LIGHT0_SIZE) {\n";
- code += "\t\t\tsky = LIGHT0_COLOR * LIGHT0_ENERGY;\n";
- code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
- code += "\t\t\tfloat c2 = (sun_angle - LIGHT0_SIZE) / (sun_angle_max - LIGHT0_SIZE);\n";
- code += "\t\t\tsky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
- code += "\t\t}\n";
- code += "\t}\n";
- code += "\tif (LIGHT1_ENABLED) {\n";
- code += "\t\tfloat sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR));\n";
- code += "\t\tif (sun_angle < LIGHT1_SIZE) {\n";
- code += "\t\t\tsky = LIGHT1_COLOR * LIGHT1_ENERGY;\n";
- code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
- code += "\t\t\tfloat c2 = (sun_angle - LIGHT1_SIZE) / (sun_angle_max - LIGHT1_SIZE);\n";
- code += "\t\t\tsky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
- code += "\t\t}\n";
- code += "\t}\n";
- code += "\tif (LIGHT2_ENABLED) {\n";
- code += "\t\tfloat sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR));\n";
- code += "\t\tif (sun_angle < LIGHT2_SIZE) {\n";
- code += "\t\t\tsky = LIGHT2_COLOR * LIGHT2_ENERGY;\n";
- code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
- code += "\t\t\tfloat c2 = (sun_angle - LIGHT2_SIZE) / (sun_angle_max - LIGHT2_SIZE);\n";
- code += "\t\t\tsky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
- code += "\t\t}\n";
- code += "\t}\n";
- code += "\tif (LIGHT3_ENABLED) {\n";
- code += "\t\tfloat sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR));\n";
- code += "\t\tif (sun_angle < LIGHT3_SIZE) {\n";
- code += "\t\t\tsky = LIGHT3_COLOR * LIGHT3_ENERGY;\n";
- code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
- code += "\t\t\tfloat c2 = (sun_angle - LIGHT3_SIZE) / (sun_angle_max - LIGHT3_SIZE);\n";
- code += "\t\t\tsky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
- code += "\t\t}\n";
- code += "\t}\n";
- code += "\tc = (v_angle - (PI * 0.5)) / (PI * 0.5);\n";
- code += "\tvec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0));\n";
- code += "\tground *= ground_energy;\n";
- code += "\tCOLOR = mix(ground, sky, step(0.0, EYEDIR.y));\n";
- code += "}\n";
-
shader = RS::get_singleton()->shader_create();
- RS::get_singleton()->shader_set_code(shader, code);
+ RS::get_singleton()->shader_set_code(shader, R"(
+shader_type sky;
+
+uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);
+uniform vec4 sky_horizon_color : hint_color = vec4(0.55, 0.69, 0.81, 1.0);
+uniform float sky_curve : hint_range(0, 1) = 0.09;
+uniform float sky_energy = 1.0;
+uniform vec4 ground_bottom_color : hint_color = vec4(0.12, 0.12, 0.13, 1.0);
+uniform vec4 ground_horizon_color : hint_color = vec4(0.37, 0.33, 0.31, 1.0);
+uniform float ground_curve : hint_range(0, 1) = 0.02;
+uniform float ground_energy = 1.0;
+uniform float sun_angle_max = 1.74;
+uniform float sun_curve : hint_range(0, 1) = 0.05;
+
+void sky() {
+ float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));
+ float c = (1.0 - v_angle / (PI * 0.5));
+ vec3 sky = mix(sky_horizon_color.rgb, sky_top_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / sky_curve), 0.0, 1.0));
+ sky *= sky_energy;
+
+ if (LIGHT0_ENABLED) {
+ float sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR));
+ if (sun_angle < LIGHT0_SIZE) {
+ sky = LIGHT0_COLOR * LIGHT0_ENERGY;
+ } else if (sun_angle < sun_angle_max) {
+ float c2 = (sun_angle - LIGHT0_SIZE) / (sun_angle_max - LIGHT0_SIZE);
+ sky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
+ }
+ }
+
+ if (LIGHT1_ENABLED) {
+ float sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR));
+ if (sun_angle < LIGHT1_SIZE) {
+ sky = LIGHT1_COLOR * LIGHT1_ENERGY;
+ } else if (sun_angle < sun_angle_max) {
+ float c2 = (sun_angle - LIGHT1_SIZE) / (sun_angle_max - LIGHT1_SIZE);
+ sky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
+ }
+ }
+
+ if (LIGHT2_ENABLED) {
+ float sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR));
+ if (sun_angle < LIGHT2_SIZE) {
+ sky = LIGHT2_COLOR * LIGHT2_ENERGY;
+ } else if (sun_angle < sun_angle_max) {
+ float c2 = (sun_angle - LIGHT2_SIZE) / (sun_angle_max - LIGHT2_SIZE);
+ sky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
+ }
+ }
+
+ if (LIGHT3_ENABLED) {
+ float sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR));
+ if (sun_angle < LIGHT3_SIZE) {
+ sky = LIGHT3_COLOR * LIGHT3_ENERGY;
+ } else if (sun_angle < sun_angle_max) {
+ float c2 = (sun_angle - LIGHT3_SIZE) / (sun_angle_max - LIGHT3_SIZE);
+ sky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
+ }
+ }
+
+ c = (v_angle - (PI * 0.5)) / (PI * 0.5);
+ vec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0));
+ ground *= ground_energy;
+
+ COLOR = mix(ground, sky, step(0.0, EYEDIR.y));
+}
+)");
RS::get_singleton()->material_set_shader(_get_material(), shader);
@@ -270,7 +277,8 @@ ProceduralSkyMaterial::~ProceduralSkyMaterial() {
void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) {
panorama = p_panorama;
- RS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama);
+ RID tex_rid = p_panorama.is_valid() ? p_panorama->get_rid() : RID();
+ RS::get_singleton()->material_set_param(_get_material(), "source_panorama", tex_rid);
}
Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const {
@@ -297,16 +305,17 @@ void PanoramaSkyMaterial::_bind_methods() {
}
PanoramaSkyMaterial::PanoramaSkyMaterial() {
- String code = "shader_type sky;\n\n";
+ shader = RS::get_singleton()->shader_create();
- code += "uniform sampler2D source_panorama : filter_linear;\n";
- code += "void sky() {\n";
- code += "\tCOLOR = texture(source_panorama, SKY_COORDS).rgb;\n";
- code += "}";
+ RS::get_singleton()->shader_set_code(shader, R"(
+shader_type sky;
- shader = RS::get_singleton()->shader_create();
+uniform sampler2D source_panorama : filter_linear;
- RS::get_singleton()->shader_set_code(shader, code);
+void sky() {
+ COLOR = texture(source_panorama, SKY_COORDS).rgb;
+}
+)");
RS::get_singleton()->material_set_shader(_get_material(), shader);
}
@@ -411,7 +420,8 @@ float PhysicalSkyMaterial::get_dither_strength() const {
void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) {
night_sky = p_night_sky;
- RS::get_singleton()->material_set_param(_get_material(), "night_sky", night_sky);
+ RID tex_rid = p_night_sky.is_valid() ? p_night_sky->get_rid() : RID();
+ RS::get_singleton()->material_set_param(_get_material(), "night_sky", tex_rid);
}
Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const {
@@ -482,102 +492,102 @@ void PhysicalSkyMaterial::_bind_methods() {
}
PhysicalSkyMaterial::PhysicalSkyMaterial() {
- String code = "shader_type sky;\n\n";
-
- code += "uniform float rayleigh : hint_range(0, 64) = 2.0;\n";
- code += "uniform vec4 rayleigh_color : hint_color = vec4(0.056, 0.14, 0.3, 1.0);\n";
- code += "uniform float mie : hint_range(0, 1) = 0.005;\n";
- code += "uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;\n";
- code += "uniform vec4 mie_color : hint_color = vec4(0.36, 0.56, 0.82, 1.0);\n\n";
-
- code += "uniform float turbidity : hint_range(0, 1000) = 10.0;\n";
- code += "uniform float sun_disk_scale : hint_range(0, 360) = 1.0;\n";
- code += "uniform vec4 ground_color : hint_color = vec4(1.0);\n";
- code += "uniform float exposure : hint_range(0, 128) = 0.1;\n";
- code += "uniform float dither_strength : hint_range(0, 10) = 1.0;\n\n";
-
- code += "uniform sampler2D night_sky : hint_black;";
-
- code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n";
-
- code += "// Sun constants\n";
- code += "const float SUN_ENERGY = 1000.0;\n\n";
-
- code += "// optical length at zenith for molecules\n";
- code += "const float rayleigh_zenith_size = 8.4e3;\n";
- code += "const float mie_zenith_size = 1.25e3;\n\n";
-
- code += "float henyey_greenstein(float cos_theta, float g) {\n";
- code += "\tconst float k = 0.0795774715459;\n";
- code += "\treturn k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));\n";
- code += "}\n\n";
-
- code += "// From: https://www.shadertoy.com/view/4sfGzS credit to iq\n";
- code += "float hash(vec3 p) {\n";
- code += "\tp = fract( p * 0.3183099 + 0.1 );\n";
- code += "\tp *= 17.0;\n";
- code += "\treturn fract(p.x * p.y * p.z * (p.x + p.y + p.z));\n";
- code += "}\n\n";
-
- code += "void sky() {\n";
- code += "\tif (LIGHT0_ENABLED) {\n";
- code += "\t\tfloat zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );\n";
- code += "\t\tfloat sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;\n";
- code += "\t\tfloat sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);\n\n";
-
- code += "\t\t// rayleigh coefficients\n";
- code += "\t\tfloat rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );\n";
- code += "\t\tvec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;\n";
- code += "\t\t// mie coefficients from Preetham\n";
- code += "\t\tvec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;\n\n";
-
- code += "\t\t// optical length\n";
- code += "\t\tfloat zenith = acos(max(0.0, dot(UP, EYEDIR)));\n";
- code += "\t\tfloat optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));\n";
- code += "\t\tfloat rayleigh_scatter = rayleigh_zenith_size * optical_mass;\n";
- code += "\t\tfloat mie_scatter = mie_zenith_size * optical_mass;\n\n";
-
- code += "\t\t// light extinction based on thickness of atmosphere\n";
- code += "\t\tvec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));\n\n";
-
- code += "\t\t// in scattering\n";
- code += "\t\tfloat cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));\n\n";
-
- code += "\t\tfloat rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));\n";
- code += "\t\tvec3 betaRTheta = rayleigh_beta * rayleigh_phase;\n\n";
-
- code += "\t\tfloat mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);\n";
- code += "\t\tvec3 betaMTheta = mie_beta * mie_phase;\n\n";
-
- code += "\t\tvec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));\n";
- code += "\t\t// Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js\n";
- code += "\t\tLin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));\n\n";
-
- code += "\t\t// Hack in the ground color\n";
- code += "\t\tLin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));\n\n";
-
- code += "\t\t// Solar disk and out-scattering\n";
- code += "\t\tfloat sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);\n";
- code += "\t\tfloat sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);\n";
- code += "\t\tfloat sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);\n";
- code += "\t\tvec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;\n";
- code += "\t\tL0 += texture(night_sky, SKY_COORDS).xyz * extinction;\n\n";
-
- code += "\t\tvec3 color = (Lin + L0) * 0.04;\n";
- code += "\t\tCOLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));\n";
- code += "\t\tCOLOR *= exposure;\n";
- code += "\t\t// Make optional, eliminates banding\n";
- code += "\t\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.016 * dither_strength;\n";
- code += "\t} else {\n";
- code += "\t\t// There is no sun, so display night_sky and nothing else\n";
- code += "\t\tCOLOR = texture(night_sky, SKY_COORDS).xyz * 0.04;\n";
- code += "\t\tCOLOR *= exposure;\n";
- code += "\t}\n";
- code += "}\n";
-
shader = RS::get_singleton()->shader_create();
- RS::get_singleton()->shader_set_code(shader, code);
+ RS::get_singleton()->shader_set_code(shader, R"(
+shader_type sky;
+
+uniform float rayleigh : hint_range(0, 64) = 2.0;
+uniform vec4 rayleigh_color : hint_color = vec4(0.056, 0.14, 0.3, 1.0);
+uniform float mie : hint_range(0, 1) = 0.005;
+uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;
+uniform vec4 mie_color : hint_color = vec4(0.36, 0.56, 0.82, 1.0);
+
+uniform float turbidity : hint_range(0, 1000) = 10.0;
+uniform float sun_disk_scale : hint_range(0, 360) = 1.0;
+uniform vec4 ground_color : hint_color = vec4(1.0);
+uniform float exposure : hint_range(0, 128) = 0.1;
+uniform float dither_strength : hint_range(0, 10) = 1.0;
+
+uniform sampler2D night_sky : hint_black;
+
+const vec3 UP = vec3( 0.0, 1.0, 0.0 );
+
+// Sun constants
+const float SUN_ENERGY = 1000.0;
+
+// Optical length at zenith for molecules.
+const float rayleigh_zenith_size = 8.4e3;
+const float mie_zenith_size = 1.25e3;
+
+float henyey_greenstein(float cos_theta, float g) {
+ const float k = 0.0795774715459;
+ return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
+}
+
+// From: https://www.shadertoy.com/view/4sfGzS credit to iq
+float hash(vec3 p) {
+ p = fract( p * 0.3183099 + 0.1 );
+ p *= 17.0;
+ return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
+}
+
+void sky() {
+ if (LIGHT0_ENABLED) {
+ float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );
+ float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;
+ float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);
+
+ // Rayleigh coefficients.
+ float rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );
+ vec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;
+ // mie coefficients from Preetham
+ vec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;
+
+ // Optical length.
+ float zenith = acos(max(0.0, dot(UP, EYEDIR)));
+ float optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));
+ float rayleigh_scatter = rayleigh_zenith_size * optical_mass;
+ float mie_scatter = mie_zenith_size * optical_mass;
+
+ // Light extinction based on thickness of atmosphere.
+ vec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));
+
+ // In scattering.
+ float cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));
+
+ float rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));
+ vec3 betaRTheta = rayleigh_beta * rayleigh_phase;
+
+ float mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);
+ vec3 betaMTheta = mie_beta * mie_phase;
+
+ vec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));
+ // Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js
+ Lin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));
+
+ // Hack in the ground color.
+ Lin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));
+
+ // Solar disk and out-scattering.
+ float sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);
+ float sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);
+ float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);
+ vec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;
+ L0 += texture(night_sky, SKY_COORDS).xyz * extinction;
+
+ vec3 color = (Lin + L0) * 0.04;
+ COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));
+ COLOR *= exposure;
+ // Make optional, eliminates banding.
+ COLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.016 * dither_strength;
+ } else {
+ // There is no sun, so display night_sky and nothing else.
+ COLOR = texture(night_sky, SKY_COORDS).xyz * 0.04;
+ COLOR *= exposure;
+ }
+}
+)");
RS::get_singleton()->material_set_shader(_get_material(), shader);
diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp
index 9dd00849f4..bf889d7a1c 100644
--- a/scene/resources/syntax_highlighter.cpp
+++ b/scene/resources/syntax_highlighter.cpp
@@ -405,7 +405,7 @@ void CodeHighlighter::_clear_highlighting_cache() {
}
void CodeHighlighter::_update_cache() {
- font_color = text_edit->get_theme_color("font_color");
+ font_color = text_edit->get_theme_color(SNAME("font_color"));
}
void CodeHighlighter::add_keyword_color(const String &p_keyword, const Color &p_color) {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index acc85cf7df..38042d84fd 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -173,7 +173,7 @@ Image::Format ImageTexture::get_format() const {
return format;
}
-void ImageTexture::update(const Ref<Image> &p_image, bool p_immediate) {
+void ImageTexture::update(const Ref<Image> &p_image) {
ERR_FAIL_COND_MSG(p_image.is_null(), "Invalid image");
ERR_FAIL_COND_MSG(texture.is_null(), "Texture is not initialized.");
ERR_FAIL_COND_MSG(p_image->get_width() != w || p_image->get_height() != h,
@@ -183,11 +183,7 @@ void ImageTexture::update(const Ref<Image> &p_image, bool p_immediate) {
ERR_FAIL_COND_MSG(mipmaps != p_image->has_mipmaps(),
"The new image mipmaps configuration must match the texture's image mipmaps configuration");
- if (p_immediate) {
- RenderingServer::get_singleton()->texture_2d_update_immediate(texture, p_image);
- } else {
- RenderingServer::get_singleton()->texture_2d_update(texture, p_image);
- }
+ RenderingServer::get_singleton()->texture_2d_update(texture, p_image);
notify_property_list_changed();
emit_changed();
@@ -305,7 +301,7 @@ void ImageTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_from_image", "image"), &ImageTexture::create_from_image);
ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format);
- ClassDB::bind_method(D_METHOD("update", "image", "immediate"), &ImageTexture::update, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("update", "image"), &ImageTexture::update);
ClassDB::bind_method(D_METHOD("set_size_override", "size"), &ImageTexture::set_size_override);
ClassDB::bind_method(D_METHOD("_reload_hook", "rid"), &ImageTexture::_reload_hook);
}
@@ -1411,14 +1407,26 @@ void CurveTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &CurveTexture::set_curve);
ClassDB::bind_method(D_METHOD("get_curve"), &CurveTexture::get_curve);
+ ClassDB::bind_method(D_METHOD("set_texture_mode", "texture_mode"), &CurveTexture::set_texture_mode);
+ ClassDB::bind_method(D_METHOD("get_texture_mode"), &CurveTexture::get_texture_mode);
+
ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "RGB,Red"), "set_texture_mode", "get_texture_mode");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
+
+ BIND_ENUM_CONSTANT(TEXTURE_MODE_RGB);
+ BIND_ENUM_CONSTANT(TEXTURE_MODE_RED);
}
void CurveTexture::set_width(int p_width) {
ERR_FAIL_COND(p_width < 32 || p_width > 4096);
+
+ if (_width == p_width) {
+ return;
+ }
+
_width = p_width;
_update();
}
@@ -1454,7 +1462,7 @@ void CurveTexture::set_curve(Ref<Curve> p_curve) {
void CurveTexture::_update() {
Vector<uint8_t> data;
- data.resize(_width * sizeof(float));
+ data.resize(_width * sizeof(float) * (texture_mode == TEXTURE_MODE_RGB ? 3 : 1));
// The array is locked in that scope
{
@@ -1465,24 +1473,42 @@ void CurveTexture::_update() {
Curve &curve = **_curve;
for (int i = 0; i < _width; ++i) {
float t = i / static_cast<float>(_width);
- wd[i] = curve.interpolate_baked(t);
+ if (texture_mode == TEXTURE_MODE_RGB) {
+ wd[i * 3 + 0] = curve.interpolate_baked(t);
+ wd[i * 3 + 1] = wd[i * 3 + 0];
+ wd[i * 3 + 2] = wd[i * 3 + 0];
+ } else {
+ wd[i] = curve.interpolate_baked(t);
+ }
}
} else {
for (int i = 0; i < _width; ++i) {
- wd[i] = 0;
+ if (texture_mode == TEXTURE_MODE_RGB) {
+ wd[i * 3 + 0] = 0;
+ wd[i * 3 + 1] = 0;
+ wd[i * 3 + 2] = 0;
+ } else {
+ wd[i] = 0;
+ }
}
}
}
- Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data));
+ Ref<Image> image = memnew(Image(_width, 1, false, texture_mode == TEXTURE_MODE_RGB ? Image::FORMAT_RGBF : Image::FORMAT_RF, data));
if (_texture.is_valid()) {
- RID new_texture = RS::get_singleton()->texture_2d_create(image);
- RS::get_singleton()->texture_replace(_texture, new_texture);
+ if (_current_texture_mode != texture_mode || _current_width != _width) {
+ RID new_texture = RS::get_singleton()->texture_2d_create(image);
+ RS::get_singleton()->texture_replace(_texture, new_texture);
+ } else {
+ RS::get_singleton()->texture_2d_update(_texture, image);
+ }
} else {
_texture = RS::get_singleton()->texture_2d_create(image);
}
+ _current_texture_mode = texture_mode;
+ _current_width = _width;
emit_changed();
}
@@ -1491,6 +1517,17 @@ Ref<Curve> CurveTexture::get_curve() const {
return _curve;
}
+void CurveTexture::set_texture_mode(TextureMode p_mode) {
+ if (texture_mode == p_mode) {
+ return;
+ }
+ texture_mode = p_mode;
+ _update();
+}
+CurveTexture::TextureMode CurveTexture::get_texture_mode() const {
+ return texture_mode;
+}
+
RID CurveTexture::get_rid() const {
if (!_texture.is_valid()) {
_texture = RS::get_singleton()->texture_2d_placeholder_create();
@@ -1508,6 +1545,204 @@ CurveTexture::~CurveTexture() {
//////////////////
+void CurveXYZTexture::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveXYZTexture::set_width);
+
+ ClassDB::bind_method(D_METHOD("set_curve_x", "curve"), &CurveXYZTexture::set_curve_x);
+ ClassDB::bind_method(D_METHOD("get_curve_x"), &CurveXYZTexture::get_curve_x);
+
+ ClassDB::bind_method(D_METHOD("set_curve_y", "curve"), &CurveXYZTexture::set_curve_y);
+ ClassDB::bind_method(D_METHOD("get_curve_y"), &CurveXYZTexture::get_curve_y);
+
+ ClassDB::bind_method(D_METHOD("set_curve_z", "curve"), &CurveXYZTexture::set_curve_z);
+ ClassDB::bind_method(D_METHOD("get_curve_z"), &CurveXYZTexture::get_curve_z);
+
+ ClassDB::bind_method(D_METHOD("_update"), &CurveXYZTexture::_update);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_x", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_x", "get_curve_x");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_y", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_y", "get_curve_y");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_z", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_z", "get_curve_z");
+}
+
+void CurveXYZTexture::set_width(int p_width) {
+ ERR_FAIL_COND(p_width < 32 || p_width > 4096);
+
+ if (_width == p_width) {
+ return;
+ }
+
+ _width = p_width;
+ _update();
+}
+
+int CurveXYZTexture::get_width() const {
+ return _width;
+}
+
+void CurveXYZTexture::ensure_default_setup(float p_min, float p_max) {
+ if (_curve_x.is_null()) {
+ Ref<Curve> curve = Ref<Curve>(memnew(Curve));
+ curve->add_point(Vector2(0, 1));
+ curve->add_point(Vector2(1, 1));
+ curve->set_min_value(p_min);
+ curve->set_max_value(p_max);
+ set_curve_x(curve);
+ }
+
+ if (_curve_y.is_null()) {
+ Ref<Curve> curve = Ref<Curve>(memnew(Curve));
+ curve->add_point(Vector2(0, 1));
+ curve->add_point(Vector2(1, 1));
+ curve->set_min_value(p_min);
+ curve->set_max_value(p_max);
+ set_curve_y(curve);
+ }
+
+ if (_curve_z.is_null()) {
+ Ref<Curve> curve = Ref<Curve>(memnew(Curve));
+ curve->add_point(Vector2(0, 1));
+ curve->add_point(Vector2(1, 1));
+ curve->set_min_value(p_min);
+ curve->set_max_value(p_max);
+ set_curve_z(curve);
+ }
+}
+
+void CurveXYZTexture::set_curve_x(Ref<Curve> p_curve) {
+ if (_curve_x != p_curve) {
+ if (_curve_x.is_valid()) {
+ _curve_x->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update));
+ }
+ _curve_x = p_curve;
+ if (_curve_x.is_valid()) {
+ _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ _update();
+ }
+}
+
+void CurveXYZTexture::set_curve_y(Ref<Curve> p_curve) {
+ if (_curve_y != p_curve) {
+ if (_curve_y.is_valid()) {
+ _curve_y->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update));
+ }
+ _curve_y = p_curve;
+ if (_curve_y.is_valid()) {
+ _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ _update();
+ }
+}
+
+void CurveXYZTexture::set_curve_z(Ref<Curve> p_curve) {
+ if (_curve_z != p_curve) {
+ if (_curve_z.is_valid()) {
+ _curve_z->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update));
+ }
+ _curve_z = p_curve;
+ if (_curve_z.is_valid()) {
+ _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ _update();
+ }
+}
+
+void CurveXYZTexture::_update() {
+ Vector<uint8_t> data;
+ data.resize(_width * sizeof(float) * 3);
+
+ // The array is locked in that scope
+ {
+ uint8_t *wd8 = data.ptrw();
+ float *wd = (float *)wd8;
+
+ if (_curve_x.is_valid()) {
+ Curve &curve_x = **_curve_x;
+ for (int i = 0; i < _width; ++i) {
+ float t = i / static_cast<float>(_width);
+ wd[i * 3 + 0] = curve_x.interpolate_baked(t);
+ }
+
+ } else {
+ for (int i = 0; i < _width; ++i) {
+ wd[i * 3 + 0] = 0;
+ }
+ }
+
+ if (_curve_y.is_valid()) {
+ Curve &curve_y = **_curve_y;
+ for (int i = 0; i < _width; ++i) {
+ float t = i / static_cast<float>(_width);
+ wd[i * 3 + 1] = curve_y.interpolate_baked(t);
+ }
+
+ } else {
+ for (int i = 0; i < _width; ++i) {
+ wd[i * 3 + 1] = 0;
+ }
+ }
+
+ if (_curve_z.is_valid()) {
+ Curve &curve_z = **_curve_z;
+ for (int i = 0; i < _width; ++i) {
+ float t = i / static_cast<float>(_width);
+ wd[i * 3 + 2] = curve_z.interpolate_baked(t);
+ }
+
+ } else {
+ for (int i = 0; i < _width; ++i) {
+ wd[i * 3 + 2] = 0;
+ }
+ }
+ }
+
+ Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RGBF, data));
+
+ if (_texture.is_valid()) {
+ if (_current_width != _width) {
+ RID new_texture = RS::get_singleton()->texture_2d_create(image);
+ RS::get_singleton()->texture_replace(_texture, new_texture);
+ } else {
+ RS::get_singleton()->texture_2d_update(_texture, image);
+ }
+ } else {
+ _texture = RS::get_singleton()->texture_2d_create(image);
+ }
+ _current_width = _width;
+
+ emit_changed();
+}
+
+Ref<Curve> CurveXYZTexture::get_curve_x() const {
+ return _curve_x;
+}
+
+Ref<Curve> CurveXYZTexture::get_curve_y() const {
+ return _curve_y;
+}
+
+Ref<Curve> CurveXYZTexture::get_curve_z() const {
+ return _curve_z;
+}
+
+RID CurveXYZTexture::get_rid() const {
+ if (!_texture.is_valid()) {
+ _texture = RS::get_singleton()->texture_2d_placeholder_create();
+ }
+ return _texture;
+}
+
+CurveXYZTexture::CurveXYZTexture() {}
+
+CurveXYZTexture::~CurveXYZTexture() {
+ if (_texture.is_valid()) {
+ RS::get_singleton()->free(_texture);
+ }
+}
+
+//////////////////
+
GradientTexture::GradientTexture() {
_queue_update();
}
@@ -1527,7 +1762,7 @@ void GradientTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
}
void GradientTexture::set_gradient(Ref<Gradient> p_gradient) {
@@ -1555,7 +1790,7 @@ void GradientTexture::_queue_update() {
}
update_pending = true;
- call_deferred("_update");
+ call_deferred(SNAME("_update"));
}
void GradientTexture::_update() {
@@ -1877,7 +2112,7 @@ void AnimatedTexture::_validate_property(PropertyInfo &property) const {
if (prop.begins_with("frame_")) {
int frame = prop.get_slicec('/', 0).get_slicec('_', 1).to_int();
if (frame >= frame_count) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
}
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 3b1815266d..98aa61138d 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -107,7 +107,7 @@ public:
Image::Format get_format() const;
- void update(const Ref<Image> &p_image, bool p_immediate = false);
+ void update(const Ref<Image> &p_image);
Ref<Image> get_image() const override;
int get_width() const override;
@@ -586,11 +586,19 @@ public:
class CurveTexture : public Texture2D {
GDCLASS(CurveTexture, Texture2D);
RES_BASE_EXTENSION("curvetex")
+public:
+ enum TextureMode {
+ TEXTURE_MODE_RGB,
+ TEXTURE_MODE_RED,
+ };
private:
mutable RID _texture;
Ref<Curve> _curve;
int _width = 2048;
+ int _current_width = 0;
+ TextureMode texture_mode = TEXTURE_MODE_RGB;
+ TextureMode _current_texture_mode = TEXTURE_MODE_RGB;
void _update();
@@ -601,6 +609,9 @@ public:
void set_width(int p_width);
int get_width() const override;
+ void set_texture_mode(TextureMode p_mode);
+ TextureMode get_texture_mode() const;
+
void ensure_default_setup(float p_min = 0, float p_max = 1);
void set_curve(Ref<Curve> p_curve);
@@ -614,18 +625,49 @@ public:
CurveTexture();
~CurveTexture();
};
-/*
- enum CubeMapSide {
- CUBEMAP_LEFT,
- CUBEMAP_RIGHT,
- CUBEMAP_BOTTOM,
- CUBEMAP_TOP,
- CUBEMAP_FRONT,
- CUBEMAP_BACK,
- };
-*/
-//VARIANT_ENUM_CAST( Texture::CubeMapSide );
+VARIANT_ENUM_CAST(CurveTexture::TextureMode)
+
+class CurveXYZTexture : public Texture2D {
+ GDCLASS(CurveXYZTexture, Texture2D);
+ RES_BASE_EXTENSION("curvetex")
+
+private:
+ mutable RID _texture;
+ Ref<Curve> _curve_x;
+ Ref<Curve> _curve_y;
+ Ref<Curve> _curve_z;
+ int _width = 2048;
+ int _current_width = 0;
+
+ void _update();
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_width(int p_width);
+ int get_width() const override;
+
+ void ensure_default_setup(float p_min = 0, float p_max = 1);
+
+ void set_curve_x(Ref<Curve> p_curve);
+ Ref<Curve> get_curve_x() const;
+
+ void set_curve_y(Ref<Curve> p_curve);
+ Ref<Curve> get_curve_y() const;
+
+ void set_curve_z(Ref<Curve> p_curve);
+ Ref<Curve> get_curve_z() const;
+
+ virtual RID get_rid() const override;
+
+ virtual int get_height() const override { return 1; }
+ virtual bool has_alpha() const override { return false; }
+
+ CurveXYZTexture();
+ ~CurveXYZTexture();
+};
class GradientTexture : public Texture2D {
GDCLASS(GradientTexture, Texture2D);
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 89ac033207..303bbf38f4 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -263,6 +263,21 @@ Vector<String> Theme::_get_theme_item_type_list(DataType p_data_type) const {
return Vector<String>();
}
+Vector<String> Theme::_get_type_variation_list(const StringName &p_theme_type) const {
+ Vector<String> ilret;
+ List<StringName> il;
+
+ get_type_variation_list(p_theme_type, &il);
+ ilret.resize(il.size());
+
+ int i = 0;
+ String *w = ilret.ptrw();
+ for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+ w[i] = E->get();
+ }
+ return ilret;
+}
+
Vector<String> Theme::_get_type_list() const {
Vector<String> ilret;
List<StringName> il;
@@ -292,10 +307,14 @@ bool Theme::_set(const StringName &p_name, const Variant &p_value) {
set_stylebox(name, theme_type, p_value);
} else if (type == "fonts") {
set_font(name, theme_type, p_value);
+ } else if (type == "font_sizes") {
+ set_font_size(name, theme_type, p_value);
} else if (type == "colors") {
set_color(name, theme_type, p_value);
} else if (type == "constants") {
set_constant(name, theme_type, p_value);
+ } else if (type == "base_type") {
+ set_type_variation(theme_type, p_value);
} else {
return false;
}
@@ -332,10 +351,14 @@ bool Theme::_get(const StringName &p_name, Variant &r_ret) const {
} else {
r_ret = get_font(name, theme_type);
}
+ } else if (type == "font_sizes") {
+ r_ret = get_font_size(name, theme_type);
} else if (type == "colors") {
r_ret = get_color(name, theme_type);
} else if (type == "constants") {
r_ret = get_constant(name, theme_type);
+ } else if (type == "base_type") {
+ r_ret = get_type_variation_base(theme_type);
} else {
return false;
}
@@ -351,6 +374,14 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
const StringName *key = nullptr;
+ // Type variations.
+ while ((key = variation_map.next(key))) {
+ list.push_back(PropertyInfo(Variant::STRING_NAME, String() + *key + "/base_type"));
+ }
+
+ key = nullptr;
+
+ // Icons.
while ((key = icon_map.next(key))) {
const StringName *key2 = nullptr;
@@ -361,6 +392,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
key = nullptr;
+ // Styles.
while ((key = style_map.next(key))) {
const StringName *key2 = nullptr;
@@ -371,6 +403,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
key = nullptr;
+ // Fonts.
while ((key = font_map.next(key))) {
const StringName *key2 = nullptr;
@@ -381,6 +414,18 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
key = nullptr;
+ // Font sizes.
+ while ((key = font_size_map.next(key))) {
+ const StringName *key2 = nullptr;
+
+ while ((key2 = font_size_map[*key].next(key2))) {
+ list.push_back(PropertyInfo(Variant::INT, String() + *key + "/font_sizes/" + *key2));
+ }
+ }
+
+ key = nullptr;
+
+ // Colors.
while ((key = color_map.next(key))) {
const StringName *key2 = nullptr;
@@ -391,6 +436,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
key = nullptr;
+ // Constants.
while ((key = constant_map.next(key))) {
const StringName *key2 = nullptr;
@@ -399,6 +445,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
+ // Sort and store properties.
list.sort();
for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) {
p_list->push_back(E->get());
@@ -1183,6 +1230,63 @@ void Theme::get_theme_item_type_list(DataType p_data_type, List<StringName> *p_l
}
}
+void Theme::set_type_variation(const StringName &p_theme_type, const StringName &p_base_type) {
+ ERR_FAIL_COND_MSG(p_theme_type == StringName(), "An empty theme type cannot be marked as a variation of another type.");
+ ERR_FAIL_COND_MSG(ClassDB::class_exists(p_theme_type), "A type associated with a built-in class cannot be marked as a variation of another type.");
+ ERR_FAIL_COND_MSG(p_base_type == StringName(), "An empty theme type cannot be the base type of a variation. Use clear_type_variation() instead if you want to unmark '" + String(p_theme_type) + "' as a variation.");
+
+ if (variation_map.has(p_theme_type)) {
+ StringName old_base = variation_map[p_theme_type];
+ variation_base_map[old_base].erase(p_theme_type);
+ }
+
+ variation_map[p_theme_type] = p_base_type;
+ variation_base_map[p_base_type].push_back(p_theme_type);
+
+ _emit_theme_changed();
+}
+
+bool Theme::is_type_variation(const StringName &p_theme_type, const StringName &p_base_type) const {
+ return (variation_map.has(p_theme_type) && variation_map[p_theme_type] == p_base_type);
+}
+
+void Theme::clear_type_variation(const StringName &p_theme_type) {
+ ERR_FAIL_COND_MSG(!variation_map.has(p_theme_type), "Cannot clear the type variation '" + String(p_theme_type) + "' because it does not exist.");
+
+ StringName base_type = variation_map[p_theme_type];
+ variation_base_map[base_type].erase(p_theme_type);
+ variation_map.erase(p_theme_type);
+
+ _emit_theme_changed();
+}
+
+StringName Theme::get_type_variation_base(const StringName &p_theme_type) const {
+ if (!variation_map.has(p_theme_type)) {
+ return StringName();
+ }
+
+ return variation_map[p_theme_type];
+}
+
+void Theme::get_type_variation_list(const StringName &p_base_type, List<StringName> *p_list) const {
+ ERR_FAIL_NULL(p_list);
+
+ if (!variation_base_map.has(p_base_type)) {
+ return;
+ }
+
+ for (const List<StringName>::Element *E = variation_base_map[p_base_type].front(); E; E = E->next()) {
+ // Prevent infinite loops if variants were set to be cross-dependent (that's still invalid usage, but handling for stability sake).
+ if (p_list->find(E->get())) {
+ continue;
+ }
+
+ p_list->push_back(E->get());
+ // Continue looking for sub-variations.
+ get_type_variation_list(E->get(), p_list);
+ }
+}
+
void Theme::_freeze_change_propagation() {
no_change_propagation = true;
}
@@ -1236,9 +1340,13 @@ void Theme::clear() {
icon_map.clear();
style_map.clear();
font_map.clear();
+ font_size_map.clear();
color_map.clear();
constant_map.clear();
+ variation_map.clear();
+ variation_base_map.clear();
+
_emit_theme_changed();
}
@@ -1291,6 +1399,9 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
color_map = p_other->color_map;
constant_map = p_other->constant_map;
+ variation_map = p_other->variation_map;
+ variation_base_map = p_other->variation_base_map;
+
_unfreeze_and_propagate_changes();
}
@@ -1300,30 +1411,42 @@ void Theme::get_type_list(List<StringName> *p_list) const {
Set<StringName> types;
const StringName *key = nullptr;
+ // Icons.
while ((key = icon_map.next(key))) {
types.insert(*key);
}
key = nullptr;
+ // StyleBoxes.
while ((key = style_map.next(key))) {
types.insert(*key);
}
key = nullptr;
+ // Fonts.
while ((key = font_map.next(key))) {
types.insert(*key);
}
key = nullptr;
+ // Font sizes.
+ while ((key = font_size_map.next(key))) {
+ types.insert(*key);
+ }
+
+ key = nullptr;
+
+ // Colors.
while ((key = color_map.next(key))) {
types.insert(*key);
}
key = nullptr;
+ // Constants.
while ((key = constant_map.next(key))) {
types.insert(*key);
}
@@ -1333,10 +1456,25 @@ void Theme::get_type_list(List<StringName> *p_list) const {
}
}
-void Theme::get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) {
+void Theme::get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variation, List<StringName> *p_list) {
ERR_FAIL_NULL(p_list);
- StringName class_name = p_theme_type;
+ // Build the dependency chain for type variations.
+ if (p_type_variation != StringName()) {
+ StringName variation_name = p_type_variation;
+ while (variation_name != StringName()) {
+ p_list->push_back(variation_name);
+ variation_name = get_type_variation_base(variation_name);
+
+ // If we have reached the base type dependency, it's safe to stop (assuming no funny business was done to the Theme).
+ if (variation_name == p_base_type) {
+ break;
+ }
+ }
+ }
+
+ // Continue building the chain using native class hierarchy.
+ StringName class_name = p_base_type;
while (class_name != StringName()) {
p_list->push_back(class_name);
class_name = ClassDB::get_parent_class_nocheck(class_name);
@@ -1346,6 +1484,7 @@ void Theme::get_type_dependencies(const StringName &p_theme_type, List<StringNam
void Theme::reset_state() {
clear();
}
+
void Theme::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_icon", "name", "theme_type", "texture"), &Theme::set_icon);
ClassDB::bind_method(D_METHOD("get_icon", "name", "theme_type"), &Theme::get_icon);
@@ -1411,6 +1550,12 @@ void Theme::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_theme_item_list", "data_type", "theme_type"), &Theme::_get_theme_item_list);
ClassDB::bind_method(D_METHOD("get_theme_item_type_list", "data_type"), &Theme::_get_theme_item_type_list);
+ ClassDB::bind_method(D_METHOD("set_type_variation", "theme_type", "base_type"), &Theme::set_type_variation);
+ ClassDB::bind_method(D_METHOD("is_type_variation", "theme_type", "base_type"), &Theme::is_type_variation);
+ ClassDB::bind_method(D_METHOD("clear_type_variation", "theme_type"), &Theme::clear_type_variation);
+ ClassDB::bind_method(D_METHOD("get_type_variation_base", "theme_type"), &Theme::get_type_variation_base);
+ ClassDB::bind_method(D_METHOD("get_type_variation_list", "base_type"), &Theme::_get_type_variation_list);
+
ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list);
ClassDB::bind_method("copy_default_theme", &Theme::copy_default_theme);
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index fe64fd7290..8a8fc28be1 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -69,6 +69,8 @@ private:
HashMap<StringName, HashMap<StringName, int>> font_size_map;
HashMap<StringName, HashMap<StringName, Color>> color_map;
HashMap<StringName, HashMap<StringName, int>> constant_map;
+ HashMap<StringName, StringName> variation_map;
+ HashMap<StringName, List<StringName>> variation_base_map;
Vector<String> _get_icon_list(const String &p_theme_type) const;
Vector<String> _get_icon_type_list() const;
@@ -85,6 +87,8 @@ private:
Vector<String> _get_theme_item_list(DataType p_data_type, const String &p_theme_type) const;
Vector<String> _get_theme_item_type_list(DataType p_data_type) const;
+
+ Vector<String> _get_type_variation_list(const StringName &p_theme_type) const;
Vector<String> _get_type_list() const;
protected:
@@ -197,8 +201,14 @@ public:
void add_theme_item_type(DataType p_data_type, const StringName &p_theme_type);
void get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const;
+ void set_type_variation(const StringName &p_theme_type, const StringName &p_base_type);
+ bool is_type_variation(const StringName &p_theme_type, const StringName &p_base_type) const;
+ void clear_type_variation(const StringName &p_theme_type);
+ StringName get_type_variation_base(const StringName &p_theme_type) const;
+ void get_type_variation_list(const StringName &p_base_type, List<StringName> *p_list) const;
+
void get_type_list(List<StringName> *p_list) const;
- static void get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list);
+ void get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variant, List<StringName> *p_list);
void copy_default_theme();
void copy_theme(const Ref<Theme> &p_other);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index ef4a53cb0d..deb5a50eb2 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -30,7 +30,10 @@
#include "tile_set.h"
+#include "core/core_string_names.h"
#include "core/math/geometry_2d.h"
+#include "core/templates/local_vector.h"
+
#include "scene/2d/navigation_region_2d.h"
#include "scene/gui/control.h"
#include "scene/resources/convex_polygon_shape_2d.h"
@@ -38,6 +41,25 @@
/////////////////////////////// TileSet //////////////////////////////////////
+const char *TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[] = {
+ "right_side",
+ "right_corner",
+ "bottom_right_side",
+ "bottom_right_corner",
+ "bottom_side",
+ "bottom_corner",
+ "bottom_left_side",
+ "bottom_left_corner",
+ "left_side",
+ "left_corner",
+ "top_left_side",
+ "top_left_corner",
+ "top_side",
+ "top_corner",
+ "top_right_side",
+ "top_right_corner"
+};
+
// --- Plugins ---
Vector<TileSetPlugin *> TileSet::get_tile_set_atlas_plugins() const {
return tile_set_plugins_vector;
@@ -51,6 +73,8 @@ void TileSet::set_tile_shape(TileSet::TileShape p_shape) {
E_source->get()->notify_tile_data_properties_should_change();
}
+ terrain_bits_meshes_dirty = true;
+ tile_meshes_dirty = true;
emit_changed();
}
TileSet::TileShape TileSet::get_tile_shape() const {
@@ -72,6 +96,8 @@ void TileSet::set_tile_offset_axis(TileSet::TileOffsetAxis p_alignment) {
E_source->get()->notify_tile_data_properties_should_change();
}
+ terrain_bits_meshes_dirty = true;
+ tile_meshes_dirty = true;
emit_changed();
}
TileSet::TileOffsetAxis TileSet::get_tile_offset_axis() const {
@@ -81,20 +107,14 @@ TileSet::TileOffsetAxis TileSet::get_tile_offset_axis() const {
void TileSet::set_tile_size(Size2i p_size) {
ERR_FAIL_COND(p_size.x < 1 || p_size.y < 1);
tile_size = p_size;
+ terrain_bits_meshes_dirty = true;
+ tile_meshes_dirty = true;
emit_changed();
}
Size2i TileSet::get_tile_size() const {
return tile_size;
}
-void TileSet::set_tile_skew(Vector2 p_skew) {
- emit_changed();
- tile_skew = p_skew;
-}
-Vector2 TileSet::get_tile_skew() const {
- return tile_skew;
-}
-
int TileSet::get_next_source_id() const {
return next_source_id;
}
@@ -117,7 +137,7 @@ int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source
p_tile_set_source->set_tile_set(this);
_compute_next_source_id();
- sources[new_source_id]->connect("changed", callable_mp(this, &TileSet::_source_changed));
+ sources[new_source_id]->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileSet::_source_changed));
emit_changed();
@@ -127,7 +147,7 @@ int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source
void TileSet::remove_source(int p_source_id) {
ERR_FAIL_COND_MSG(!sources.has(p_source_id), vformat("Cannot remove TileSet atlas source. No tileset atlas source with id %d.", p_source_id));
- sources[p_source_id]->disconnect("changed", callable_mp(this, &TileSet::_source_changed));
+ sources[p_source_id]->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileSet::_source_changed));
sources[p_source_id]->set_tile_set(nullptr);
sources.erase(p_source_id);
@@ -240,80 +260,6 @@ bool TileSet::get_occlusion_layer_sdf_collision(int p_layer_index) const {
return occlusion_layers[p_layer_index].sdf_collision;
}
-void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Rect2 p_region, Color p_color, bool p_filled, Ref<Texture2D> p_texture) {
- // TODO: optimize this with 2D meshes when they work again.
- if (get_tile_shape() == TileSet::TILE_SHAPE_SQUARE) {
- if (p_filled && p_texture.is_valid()) {
- p_canvas_item->draw_texture_rect(p_texture, p_region, false, p_color);
- } else {
- p_canvas_item->draw_rect(p_region, p_color, p_filled);
- }
- } else {
- float overlap = 0.0;
- switch (get_tile_shape()) {
- case TileSet::TILE_SHAPE_ISOMETRIC:
- overlap = 0.5;
- break;
- case TileSet::TILE_SHAPE_HEXAGON:
- overlap = 0.25;
- break;
- case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
- overlap = 0.0;
- break;
- default:
- break;
- }
-
- Vector<Vector2> uvs;
- uvs.append(Vector2(0.5, 0.0));
- uvs.append(Vector2(0.0, overlap));
- uvs.append(Vector2(0.0, 1.0 - overlap));
- uvs.append(Vector2(0.5, 1.0));
- uvs.append(Vector2(1.0, 1.0 - overlap));
- uvs.append(Vector2(1.0, overlap));
- uvs.append(Vector2(0.5, 0.0));
- if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < uvs.size(); i++) {
- uvs.write[i] = Vector2(uvs[i].y, uvs[i].x);
- }
- }
-
- Vector<Vector2> points;
- for (int i = 0; i < uvs.size(); i++) {
- points.append(p_region.position + uvs[i] * p_region.size);
- }
-
- if (p_filled) {
- // This does hurt performances a lot. We should use a mesh if possible instead.
- p_canvas_item->draw_colored_polygon(points, p_color, uvs, p_texture);
-
- // Should improve performances, but does not work as draw_primitive does not work with textures :/ :
- /*for (int i = 0; i < 6; i += 3) {
- Vector<Vector2> quad;
- quad.append(points[i]);
- quad.append(points[(i + 1) % points.size()]);
- quad.append(points[(i + 2) % points.size()]);
- quad.append(points[(i + 3) % points.size()]);
-
- Vector<Vector2> uv_quad;
- uv_quad.append(uvs[i]);
- uv_quad.append(uvs[(i + 1) % uvs.size()]);
- uv_quad.append(uvs[(i + 2) % uvs.size()]);
- uv_quad.append(uvs[(i + 3) % uvs.size()]);
-
- p_control->draw_primitive(quad, Vector<Color>(), uv_quad, p_texture);
- }*/
-
- } else {
- // This does hurt performances a lot. We should use a mesh if possible instead.
- // tile_shape_grid->draw_polyline(points, p_color);
- for (int i = 0; i < points.size() - 1; i++) {
- p_canvas_item->draw_line(points[i], points[i + 1], p_color);
- }
- }
- }
-}
-
// Physics
void TileSet::set_physics_layers_count(int p_physics_layers_count) {
ERR_FAIL_COND(p_physics_layers_count < 0);
@@ -459,14 +405,9 @@ Color TileSet::get_terrain_color(int p_terrain_set, int p_terrain_index) const {
return terrain_sets[p_terrain_set].terrains[p_terrain_index].color;
}
-bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const {
- if (p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count()) {
- return false;
- }
-
- TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set);
+bool TileSet::is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const {
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
@@ -474,7 +415,7 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
return true;
}
}
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
@@ -483,7 +424,7 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
}
}
} else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
@@ -491,7 +432,7 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
return true;
}
}
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
@@ -501,7 +442,7 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
}
} else {
if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
@@ -511,7 +452,7 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
return true;
}
}
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
@@ -522,7 +463,7 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
}
}
} else {
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
@@ -532,7 +473,7 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
return true;
}
}
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
@@ -547,6 +488,15 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
return false;
}
+bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const {
+ if (p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count()) {
+ return false;
+ }
+
+ TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set);
+ return is_valid_peering_bit_for_mode(terrain_mode, p_peering_bit);
+}
+
// Navigation
void TileSet::set_navigation_layers_count(int p_navigation_layers_count) {
ERR_FAIL_COND(p_navigation_layers_count < 0);
@@ -657,9 +607,926 @@ Variant::Type TileSet::get_custom_data_type(int p_layer_id) const {
return custom_data_layers[p_layer_id].type;
}
+Vector<Vector2> TileSet::get_tile_shape_polygon() {
+ Vector<Vector2> points;
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ points.append(Vector2(0.0, 0.0));
+ points.append(Vector2(1.0, 0.0));
+ points.append(Vector2(1.0, 1.0));
+ points.append(Vector2(0.0, 1.0));
+ } else {
+ float overlap = 0.0;
+ switch (tile_shape) {
+ case TileSet::TILE_SHAPE_ISOMETRIC:
+ overlap = 0.5;
+ break;
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+
+ points.append(Vector2(0.5, 0.0));
+ points.append(Vector2(0.0, overlap));
+ points.append(Vector2(0.0, 1.0 - overlap));
+ points.append(Vector2(0.5, 1.0));
+ points.append(Vector2(1.0, 1.0 - overlap));
+ points.append(Vector2(1.0, overlap));
+ points.append(Vector2(0.5, 0.0));
+ if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < points.size(); i++) {
+ points.write[i] = Vector2(points[i].y, points[i].x);
+ }
+ }
+ }
+ for (int i = 0; i < points.size(); i++) {
+ points.write[i] = points[i] * tile_size - tile_size / 2;
+ }
+ return points;
+}
+
+void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Rect2 p_region, Color p_color, bool p_filled, Ref<Texture2D> p_texture) {
+ if (tile_meshes_dirty) {
+ Vector<Vector2> uvs = get_tile_shape_polygon();
+ for (int i = 0; i < uvs.size(); i++) {
+ uvs.write[i] = (uvs[i] + tile_size / 2) / tile_size;
+ }
+
+ Vector<Color> colors;
+ colors.resize(uvs.size());
+ colors.fill(Color(1.0, 1.0, 1.0, 1.0));
+
+ // Filled mesh.
+ tile_filled_mesh->clear_surfaces();
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX] = uvs;
+ a[Mesh::ARRAY_TEX_UV] = uvs;
+ a[Mesh::ARRAY_COLOR] = colors;
+ a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(uvs);
+ tile_filled_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
+
+ // Lines mesh.
+ tile_lines_mesh->clear_surfaces();
+ a.clear();
+ a.resize(Mesh::ARRAY_MAX);
+ // Add the first point again when drawing lines.
+ uvs.push_back(uvs[0]);
+ colors.push_back(colors[0]);
+ a[Mesh::ARRAY_VERTEX] = uvs;
+ a[Mesh::ARRAY_COLOR] = colors;
+ tile_lines_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINE_STRIP, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
+
+ tile_meshes_dirty = false;
+ }
+
+ Transform2D xform;
+ xform.scale(p_region.size);
+ xform.set_origin(p_region.get_position());
+ if (p_filled) {
+ p_canvas_item->draw_mesh(tile_filled_mesh, p_texture, xform, p_color);
+ } else {
+ p_canvas_item->draw_mesh(tile_lines_mesh, Ref<Texture2D>(), xform, p_color);
+ }
+}
+
+Vector<Point2> TileSet::get_terrain_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit) {
+ ERR_FAIL_COND_V(p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count(), Vector<Point2>());
+
+ TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set);
+
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ return _get_square_corner_or_side_terrain_bit_polygon(tile_size, p_bit);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ return _get_square_corner_terrain_bit_polygon(tile_size, p_bit);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ return _get_square_side_terrain_bit_polygon(tile_size, p_bit);
+ }
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ return _get_isometric_corner_or_side_terrain_bit_polygon(tile_size, p_bit);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ return _get_isometric_corner_terrain_bit_polygon(tile_size, p_bit);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ return _get_isometric_side_terrain_bit_polygon(tile_size, p_bit);
+ }
+ } else {
+ float overlap = 0.0;
+ switch (tile_shape) {
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ return _get_half_offset_corner_or_side_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ return _get_half_offset_corner_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ return _get_half_offset_side_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis);
+ }
+ }
+}
+
+#define TERRAIN_ALPHA 0.6
+
+void TileSet::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, const TileData *p_tile_data) {
+ ERR_FAIL_COND(!p_tile_data);
+
+ if (terrain_bits_meshes_dirty) {
+ // Recompute the meshes.
+ terrain_bits_meshes.clear();
+
+ for (int terrain_mode_index = 0; terrain_mode_index < 3; terrain_mode_index++) {
+ TerrainMode terrain_mode = TerrainMode(terrain_mode_index);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ CellNeighbor bit = CellNeighbor(i);
+
+ if (is_valid_peering_bit_for_mode(terrain_mode, bit)) {
+ Vector<Vector2> polygon;
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ polygon = _get_square_corner_or_side_terrain_bit_polygon(tile_size, bit);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ polygon = _get_square_corner_terrain_bit_polygon(tile_size, bit);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ polygon = _get_square_side_terrain_bit_polygon(tile_size, bit);
+ }
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ polygon = _get_isometric_corner_or_side_terrain_bit_polygon(tile_size, bit);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ polygon = _get_isometric_corner_terrain_bit_polygon(tile_size, bit);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ polygon = _get_isometric_side_terrain_bit_polygon(tile_size, bit);
+ }
+ } else {
+ float overlap = 0.0;
+ switch (tile_shape) {
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ polygon = _get_half_offset_corner_or_side_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ polygon = _get_half_offset_corner_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ polygon = _get_half_offset_side_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis);
+ }
+ }
+
+ Ref<ArrayMesh> mesh;
+ mesh.instantiate();
+ Vector<Vector2> uvs;
+ uvs.resize(polygon.size());
+ Vector<Color> colors;
+ colors.resize(polygon.size());
+ colors.fill(Color(1.0, 1.0, 1.0, 1.0));
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX] = polygon;
+ a[Mesh::ARRAY_TEX_UV] = uvs;
+ a[Mesh::ARRAY_COLOR] = colors;
+ a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(polygon);
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
+ terrain_bits_meshes[terrain_mode][bit] = mesh;
+ }
+ }
+ }
+ terrain_bits_meshes_dirty = false;
+ }
+
+ int terrain_set = p_tile_data->get_terrain_set();
+ if (terrain_set < 0) {
+ return;
+ }
+ TileSet::TerrainMode terrain_mode = get_terrain_set_mode(terrain_set);
+
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ CellNeighbor bit = CellNeighbor(i);
+ if (is_valid_peering_bit_terrain(terrain_set, bit)) {
+ int terrain_id = p_tile_data->get_peering_bit_terrain(bit);
+ if (terrain_id >= 0) {
+ Color color = get_terrain_color(terrain_set, terrain_id);
+ color.a = TERRAIN_ALPHA;
+ p_canvas_item->draw_mesh(terrain_bits_meshes[terrain_mode][bit], Ref<Texture2D>(), Transform2D(), color);
+ }
+ }
+ }
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
+}
+
+Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) {
+ // Counts the number of matching terrain tiles and find the best matching icon.
+ struct Count {
+ int count = 0;
+ float probability = 0.0;
+ Ref<Texture2D> texture;
+ Rect2i region;
+ };
+ Vector<Vector<Ref<Texture2D>>> output;
+ LocalVector<LocalVector<Count>> counts;
+ output.resize(get_terrain_sets_count());
+ counts.resize(get_terrain_sets_count());
+ for (int terrain_set = 0; terrain_set < get_terrain_sets_count(); terrain_set++) {
+ output.write[terrain_set].resize(get_terrains_count(terrain_set));
+ counts[terrain_set].resize(get_terrains_count(terrain_set));
+ }
+
+ for (int source_index = 0; source_index < get_source_count(); source_index++) {
+ int source_id = get_source_id(source_index);
+ Ref<TileSetSource> source = get_source(source_id);
+
+ Ref<TileSetAtlasSource> atlas_source = source;
+ if (atlas_source.is_valid()) {
+ for (int tile_index = 0; tile_index < source->get_tiles_count(); tile_index++) {
+ Vector2i tile_id = source->get_tile_id(tile_index);
+ for (int alternative_index = 0; alternative_index < source->get_alternative_tiles_count(tile_id); alternative_index++) {
+ int alternative_id = source->get_alternative_tile_id(tile_id, alternative_index);
+
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(tile_id, alternative_id));
+ int terrain_set = tile_data->get_terrain_set();
+ if (terrain_set >= 0) {
+ ERR_FAIL_INDEX_V(terrain_set, get_terrain_sets_count(), Vector<Vector<Ref<Texture2D>>>());
+
+ LocalVector<int> bit_counts;
+ bit_counts.resize(get_terrains_count(terrain_set));
+ for (int terrain = 0; terrain < get_terrains_count(terrain_set); terrain++) {
+ bit_counts[terrain] = 0;
+ }
+ for (int terrain_bit = 0; terrain_bit < TileSet::CELL_NEIGHBOR_MAX; terrain_bit++) {
+ TileSet::CellNeighbor cell_neighbor = TileSet::CellNeighbor(terrain_bit);
+ if (is_valid_peering_bit_terrain(terrain_set, cell_neighbor)) {
+ int terrain = tile_data->get_peering_bit_terrain(cell_neighbor);
+ if (terrain >= 0) {
+ bit_counts[terrain] += 1;
+ }
+ }
+ }
+
+ for (int terrain = 0; terrain < get_terrains_count(terrain_set); terrain++) {
+ if ((bit_counts[terrain] > counts[terrain_set][terrain].count) || (bit_counts[terrain] == counts[terrain_set][terrain].count && tile_data->get_probability() > counts[terrain_set][terrain].probability)) {
+ counts[terrain_set][terrain].count = bit_counts[terrain];
+ counts[terrain_set][terrain].probability = tile_data->get_probability();
+ counts[terrain_set][terrain].texture = atlas_source->get_texture();
+ counts[terrain_set][terrain].region = atlas_source->get_tile_texture_region(tile_id);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Generate the icons.
+ for (int terrain_set = 0; terrain_set < get_terrain_sets_count(); terrain_set++) {
+ for (int terrain = 0; terrain < get_terrains_count(terrain_set); terrain++) {
+ Ref<Image> image;
+ image.instantiate();
+ if (counts[terrain_set][terrain].count > 0) {
+ // Get the best tile.
+ Ref<Texture2D> texture = counts[terrain_set][terrain].texture;
+ Rect2 region = counts[terrain_set][terrain].region;
+ image->create(region.size.x, region.size.y, false, Image::FORMAT_RGBA8);
+ image->blit_rect(texture->get_image(), region, Point2());
+ image->resize(p_size.x, p_size.y, Image::INTERPOLATE_NEAREST);
+ } else {
+ image->create(1, 1, false, Image::FORMAT_RGBA8);
+ image->set_pixel(0, 0, get_terrain_color(terrain_set, terrain));
+ }
+ Ref<ImageTexture> icon;
+ icon.instantiate();
+ icon->create_from_image(image);
+ icon->set_size_override(p_size);
+
+ output.write[terrain_set].write[terrain] = icon;
+ }
+ }
+ return output;
+}
+
void TileSet::_source_changed() {
emit_changed();
- notify_property_list_changed();
+}
+
+Vector<Point2> TileSet::_get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ Rect2 bit_rect;
+ bit_rect.size = Vector2(p_size) / 3;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ bit_rect.position = Vector2(1, -1);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ bit_rect.position = Vector2(1, 1);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ bit_rect.position = Vector2(-1, 1);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ bit_rect.position = Vector2(-3, 1);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ bit_rect.position = Vector2(-3, -1);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ bit_rect.position = Vector2(-3, -3);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ bit_rect.position = Vector2(-1, -3);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ bit_rect.position = Vector2(1, -3);
+ break;
+ default:
+ break;
+ }
+ bit_rect.position *= Vector2(p_size) / 6.0;
+ Vector<Vector2> polygon;
+ polygon.push_back(bit_rect.position);
+ polygon.push_back(Vector2(bit_rect.get_end().x, bit_rect.position.y));
+ polygon.push_back(bit_rect.get_end());
+ polygon.push_back(Vector2(bit_rect.position.x, bit_rect.get_end().y));
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ Vector2 unit = Vector2(p_size) / 6.0;
+ Vector<Vector2> polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(3, 3) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(1, 1) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(-3, 3) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-1, 1) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(-3, -3) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-1, -1) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(3, -3) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(1, -1) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ default:
+ break;
+ }
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_square_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ Vector2 unit = Vector2(p_size) / 6.0;
+ Vector<Vector2> polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ polygon.push_back(Vector2(1, -1) * unit);
+ polygon.push_back(Vector2(3, -3) * unit);
+ polygon.push_back(Vector2(3, 3) * unit);
+ polygon.push_back(Vector2(1, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ polygon.push_back(Vector2(-1, 1) * unit);
+ polygon.push_back(Vector2(-3, 3) * unit);
+ polygon.push_back(Vector2(3, 3) * unit);
+ polygon.push_back(Vector2(1, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ polygon.push_back(Vector2(-1, -1) * unit);
+ polygon.push_back(Vector2(-3, -3) * unit);
+ polygon.push_back(Vector2(-3, 3) * unit);
+ polygon.push_back(Vector2(-1, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ polygon.push_back(Vector2(-1, -1) * unit);
+ polygon.push_back(Vector2(-3, -3) * unit);
+ polygon.push_back(Vector2(3, -3) * unit);
+ polygon.push_back(Vector2(1, -1) * unit);
+ break;
+ default:
+ break;
+ }
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_isometric_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ Vector2 unit = Vector2(p_size) / 6.0;
+ Vector<Vector2> polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(2, -1) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(2, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(Vector2(0, 1) * unit);
+ polygon.push_back(Vector2(1, 2) * unit);
+ polygon.push_back(Vector2(2, 1) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(Vector2(0, 1) * unit);
+ polygon.push_back(Vector2(-1, 2) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(1, 2) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(Vector2(0, 1) * unit);
+ polygon.push_back(Vector2(-1, 2) * unit);
+ polygon.push_back(Vector2(-2, 1) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-2, -1) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-2, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(Vector2(0, -1) * unit);
+ polygon.push_back(Vector2(-1, -2) * unit);
+ polygon.push_back(Vector2(-2, -1) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(Vector2(0, -1) * unit);
+ polygon.push_back(Vector2(-1, -2) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(1, -2) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(Vector2(0, -1) * unit);
+ polygon.push_back(Vector2(1, -2) * unit);
+ polygon.push_back(Vector2(2, -1) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ break;
+ default:
+ break;
+ }
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_isometric_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ Vector2 unit = Vector2(p_size) / 6.0;
+ Vector<Vector2> polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(Vector2(0.5, -0.5) * unit);
+ polygon.push_back(Vector2(1.5, -1.5) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(1.5, 1.5) * unit);
+ polygon.push_back(Vector2(0.5, 0.5) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(Vector2(-0.5, 0.5) * unit);
+ polygon.push_back(Vector2(-1.5, 1.5) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(1.5, 1.5) * unit);
+ polygon.push_back(Vector2(0.5, 0.5) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(Vector2(-0.5, -0.5) * unit);
+ polygon.push_back(Vector2(-1.5, -1.5) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-1.5, 1.5) * unit);
+ polygon.push_back(Vector2(-0.5, 0.5) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(Vector2(-0.5, -0.5) * unit);
+ polygon.push_back(Vector2(-1.5, -1.5) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(1.5, -1.5) * unit);
+ polygon.push_back(Vector2(0.5, -0.5) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ default:
+ break;
+ }
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_isometric_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ Vector2 unit = Vector2(p_size) / 6.0;
+ Vector<Vector2> polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ default:
+ break;
+ }
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+ Vector<Vector2> point_list;
+ point_list.push_back(Vector2(3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+ point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(2, 3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(1, 3.0 - p_overlap * 2.0));
+ point_list.push_back(Vector2(0, 3));
+ point_list.push_back(Vector2(-1, 3.0 - p_overlap * 2.0));
+ point_list.push_back(Vector2(-2, 3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+ point_list.push_back(Vector2(-3, -(3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+ point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-2, -3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(-1, -(3.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(0, -3));
+ point_list.push_back(Vector2(1, -(3.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(2, -3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(3, -(3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
+
+ Vector<Vector2> polygon;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ polygon.push_back(point_list[17]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[12]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(point_list[12]);
+ polygon.push_back(point_list[13]);
+ polygon.push_back(point_list[14]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[14]);
+ polygon.push_back(point_list[15]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[15]);
+ polygon.push_back(point_list[16]);
+ polygon.push_back(point_list[17]);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
+ }
+ }
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ polygon.push_back(point_list[17]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[15]);
+ polygon.push_back(point_list[16]);
+ polygon.push_back(point_list[17]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[14]);
+ polygon.push_back(point_list[15]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(point_list[12]);
+ polygon.push_back(point_list[13]);
+ polygon.push_back(point_list[14]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[12]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ int half_polygon_size = polygon.size();
+ for (int i = 0; i < half_polygon_size; i++) {
+ polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
+ }
+
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+ Vector<Vector2> point_list;
+ point_list.push_back(Vector2(3, 0));
+ point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(1.5, (3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(0, 3));
+ point_list.push_back(Vector2(-1.5, (3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-3, 0));
+ point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-1.5, -(3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(0, -3));
+ point_list.push_back(Vector2(1.5, -(3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
+
+ Vector<Vector2> polygon;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[0]);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
+ }
+ }
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ int half_polygon_size = polygon.size();
+ for (int i = 0; i < half_polygon_size; i++) {
+ polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
+ }
+
+ return polygon;
+}
+
+Vector<Point2> TileSet::_get_half_offset_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+ Vector<Vector2> point_list;
+ point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(0, 3));
+ point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(0, -3));
+ point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
+
+ Vector<Vector2> polygon;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
+ }
+ }
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ int half_polygon_size = polygon.size();
+ for (int i = 0; i < half_polygon_size; i++) {
+ polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
+ }
+
+ return polygon;
}
void TileSet::reset_state() {
@@ -747,12 +1614,18 @@ void TileSet::compatibility_conversion() {
for (int k = 0; k < ctd->shapes.size(); k++) {
CompatibilityShapeData csd = ctd->shapes[k];
if (csd.autotile_coords == coords) {
- tile_data->set_collision_shapes_count(0, tile_data->get_collision_shapes_count(0) + 1);
- int index = tile_data->get_collision_shapes_count(0) - 1;
- tile_data->set_collision_shape_one_way(0, index, csd.one_way);
- tile_data->set_collision_shape_one_way_margin(0, index, csd.one_way_margin);
- tile_data->set_collision_shape_shape(0, index, csd.shape);
- // Ignores transform for now.
+ Ref<ConvexPolygonShape2D> convex_shape = csd.shape; // Only ConvexPolygonShape2D are supported, which is the default type used by the 3.x editor
+ if (convex_shape.is_valid()) {
+ Vector<Vector2> polygon = convex_shape->get_points();
+ for (int point_index = 0; point_index < polygon.size(); point_index++) {
+ polygon.write[point_index] = csd.transform.xform(polygon[point_index]);
+ }
+ tile_data->set_collision_polygons_count(0, tile_data->get_collision_polygons_count(0) + 1);
+ int index = tile_data->get_collision_polygons_count(0) - 1;
+ tile_data->set_collision_polygon_one_way(0, index, csd.one_way);
+ tile_data->set_collision_polygon_one_way_margin(0, index, csd.one_way_margin);
+ tile_data->set_collision_polygon_points(0, index, polygon);
+ }
}
}
@@ -1086,7 +1959,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
} else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_int()) {
- // Create source only if it does not exist.
+ // Create source only if it does not exists.
int source_id = components[1].to_int();
if (!has_source(source_id)) {
@@ -1287,14 +2160,11 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tile_offset_axis"), &TileSet::get_tile_offset_axis);
ClassDB::bind_method(D_METHOD("set_tile_size", "size"), &TileSet::set_tile_size);
ClassDB::bind_method(D_METHOD("get_tile_size"), &TileSet::get_tile_size);
- ClassDB::bind_method(D_METHOD("set_tile_skew", "skew"), &TileSet::set_tile_skew);
- ClassDB::bind_method(D_METHOD("get_tile_skew"), &TileSet::get_tile_skew);
ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_shape", PROPERTY_HINT_ENUM, "Square,Isometric,Half-Offset Square,Hexagon"), "set_tile_shape", "get_tile_shape");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_layout", PROPERTY_HINT_ENUM, "Stacked,Stacked Offset,Stairs Right,Stairs Down,Diamond Right,Diamond Down"), "set_tile_layout", "get_tile_layout");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_offset_axis", PROPERTY_HINT_ENUM, "Horizontal Offset,Vertical Offset"), "set_tile_offset_axis", "get_tile_offset_axis");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "tile_size"), "set_tile_size", "get_tile_size");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "tile_skew"), "set_tile_skew", "get_tile_skew");
// Rendering.
ClassDB::bind_method(D_METHOD("set_uv_clipping", "uv_clipping"), &TileSet::set_uv_clipping);
@@ -1375,22 +2245,22 @@ void TileSet::_bind_methods() {
BIND_ENUM_CONSTANT(TILE_OFFSET_AXIS_HORIZONTAL);
BIND_ENUM_CONSTANT(TILE_OFFSET_AXIS_VERTICAL);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_RIGHT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_RIGHT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_LEFT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_LEFT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_RIGHT_CORNER);
BIND_ENUM_CONSTANT(TERRAIN_MODE_MATCH_CORNERS_AND_SIDES);
BIND_ENUM_CONSTANT(TERRAIN_MODE_MATCH_CORNERS);
@@ -1398,10 +2268,13 @@ void TileSet::_bind_methods() {
}
TileSet::TileSet() {
- // Instanciatie and list all plugins.
+ // Instantiate the tile meshes.
+ tile_lines_mesh.instantiate();
+ tile_filled_mesh.instantiate();
+
+ // Instanciate and list all plugins.
tile_set_plugins_vector.append(memnew(TileSetPluginAtlasRendering));
tile_set_plugins_vector.append(memnew(TileSetPluginAtlasPhysics));
- tile_set_plugins_vector.append(memnew(TileSetPluginAtlasTerrain));
tile_set_plugins_vector.append(memnew(TileSetPluginAtlasNavigation));
tile_set_plugins_vector.append(memnew(TileSetPluginScenesCollections));
}
@@ -1696,7 +2569,7 @@ void TileSetAtlasSource::create_tile(const Vector2i p_atlas_coords, const Vector
}
}
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
void TileSetAtlasSource::remove_tile(Vector2i p_atlas_coords) {
@@ -1722,7 +2595,7 @@ void TileSetAtlasSource::remove_tile(Vector2i p_atlas_coords) {
tiles_ids.erase(p_atlas_coords);
tiles_ids.sort();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool TileSetAtlasSource::has_tile(Vector2i p_atlas_coords) const {
@@ -1850,7 +2723,7 @@ void TileSetAtlasSource::move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_
}
}
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool TileSetAtlasSource::has_tiles_outside_texture() {
@@ -1895,7 +2768,7 @@ int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, i
tiles[p_atlas_coords].alternatives_ids.sort();
_compute_next_alternative_id(p_atlas_coords);
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
return new_alternative_id;
}
@@ -1910,7 +2783,7 @@ void TileSetAtlasSource::remove_alternative_tile(const Vector2i p_atlas_coords,
tiles[p_atlas_coords].alternatives_ids.erase(p_alternative_tile);
tiles[p_atlas_coords].alternatives_ids.sort();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
void TileSetAtlasSource::set_alternative_tile_id(const Vector2i p_atlas_coords, int p_alternative_tile, int p_new_id) {
@@ -1927,7 +2800,7 @@ void TileSetAtlasSource::set_alternative_tile_id(const Vector2i p_atlas_coords,
tiles[p_atlas_coords].alternatives_ids.erase(p_alternative_tile);
tiles[p_atlas_coords].alternatives_ids.sort();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool TileSetAtlasSource::has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const {
@@ -2085,7 +2958,7 @@ int TileSetScenesCollectionSource::create_scene_tile(Ref<PackedScene> p_packed_s
set_scene_tile_scene(new_scene_id, p_packed_scene);
_compute_next_alternative_id();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
return new_scene_id;
}
@@ -2105,7 +2978,7 @@ void TileSetScenesCollectionSource::set_scene_tile_id(int p_id, int p_new_id) {
scenes.erase(p_id);
scenes_ids.erase(p_id);
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
void TileSetScenesCollectionSource::set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene) {
@@ -2124,7 +2997,7 @@ void TileSetScenesCollectionSource::set_scene_tile_scene(int p_id, Ref<PackedSce
} else {
scenes[p_id].scene = Ref<PackedScene>();
}
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
Ref<PackedScene> TileSetScenesCollectionSource::get_scene_tile_scene(int p_id) const {
@@ -2137,7 +3010,7 @@ void TileSetScenesCollectionSource::set_scene_tile_display_placeholder(int p_id,
scenes[p_id].display_placeholder = p_display_placeholder;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool TileSetScenesCollectionSource::get_scene_tile_display_placeholder(int p_id) const {
@@ -2150,7 +3023,7 @@ void TileSetScenesCollectionSource::remove_scene_tile(int p_id) {
scenes.erase(p_id);
scenes_ids.erase(p_id);
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
int TileSetScenesCollectionSource::get_next_scene_tile_id() const {
@@ -2237,16 +3110,14 @@ void TileSetScenesCollectionSource::_bind_methods() {
void TileData::set_tile_set(const TileSet *p_tile_set) {
tile_set = p_tile_set;
- if (tile_set) {
- occluders.resize(tile_set->get_occlusion_layers_count());
- physics.resize(tile_set->get_physics_layers_count());
- navigation.resize(tile_set->get_navigation_layers_count());
- custom_data.resize(tile_set->get_custom_data_layers_count());
- }
- notify_property_list_changed();
+ notify_tile_data_properties_should_change();
}
void TileData::notify_tile_data_properties_should_change() {
+ if (!tile_set) {
+ return;
+ }
+
occluders.resize(tile_set->get_occlusion_layers_count());
physics.resize(tile_set->get_physics_layers_count());
for (int bit_index = 0; bit_index < 16; bit_index++) {
@@ -2273,7 +3144,7 @@ void TileData::notify_tile_data_properties_should_change() {
}
notify_property_list_changed();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
void TileData::reset_state() {
@@ -2295,7 +3166,7 @@ bool TileData::is_allowing_transform() const {
void TileData::set_flip_h(bool p_flip_h) {
ERR_FAIL_COND_MSG(!allow_transform && p_flip_h, "Transform is only allowed for alternative tiles (with its alternative_id != 0)");
flip_h = p_flip_h;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool TileData::get_flip_h() const {
return flip_h;
@@ -2304,7 +3175,7 @@ bool TileData::get_flip_h() const {
void TileData::set_flip_v(bool p_flip_v) {
ERR_FAIL_COND_MSG(!allow_transform && p_flip_v, "Transform is only allowed for alternative tiles (with its alternative_id != 0)");
flip_v = p_flip_v;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool TileData::get_flip_v() const {
@@ -2314,7 +3185,7 @@ bool TileData::get_flip_v() const {
void TileData::set_transpose(bool p_transpose) {
ERR_FAIL_COND_MSG(!allow_transform && p_transpose, "Transform is only allowed for alternative tiles (with its alternative_id != 0)");
transpose = p_transpose;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
bool TileData::get_transpose() const {
return transpose;
@@ -2322,7 +3193,7 @@ bool TileData::get_transpose() const {
void TileData::set_texture_offset(Vector2i p_texture_offset) {
tex_offset = p_texture_offset;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
Vector2i TileData::get_texture_offset() const {
@@ -2331,7 +3202,7 @@ Vector2i TileData::get_texture_offset() const {
void TileData::tile_set_material(Ref<ShaderMaterial> p_material) {
material = p_material;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
Ref<ShaderMaterial> TileData::tile_get_material() const {
return material;
@@ -2339,7 +3210,7 @@ Ref<ShaderMaterial> TileData::tile_get_material() const {
void TileData::set_modulate(Color p_modulate) {
modulate = p_modulate;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
Color TileData::get_modulate() const {
return modulate;
@@ -2347,7 +3218,7 @@ Color TileData::get_modulate() const {
void TileData::set_z_index(int p_z_index) {
z_index = p_z_index;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
int TileData::get_z_index() const {
return z_index;
@@ -2355,7 +3226,7 @@ int TileData::get_z_index() const {
void TileData::set_y_sort_origin(int p_y_sort_origin) {
y_sort_origin = p_y_sort_origin;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
int TileData::get_y_sort_origin() const {
return y_sort_origin;
@@ -2364,7 +3235,7 @@ int TileData::get_y_sort_origin() const {
void TileData::set_occluder(int p_layer_id, Ref<OccluderPolygon2D> p_occluder_polygon) {
ERR_FAIL_INDEX(p_layer_id, occluders.size());
occluders.write[p_layer_id] = p_occluder_polygon;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
Ref<OccluderPolygon2D> TileData::get_occluder(int p_layer_id) const {
@@ -2373,80 +3244,116 @@ Ref<OccluderPolygon2D> TileData::get_occluder(int p_layer_id) const {
}
// Physics
-int TileData::get_collision_shapes_count(int p_layer_id) const {
+int TileData::get_collision_polygons_count(int p_layer_id) const {
ERR_FAIL_INDEX_V(p_layer_id, physics.size(), 0);
- return physics[p_layer_id].shapes.size();
+ return physics[p_layer_id].polygons.size();
}
-void TileData::set_collision_shapes_count(int p_layer_id, int p_shapes_count) {
+void TileData::set_collision_polygons_count(int p_layer_id, int p_polygons_count) {
ERR_FAIL_INDEX(p_layer_id, physics.size());
- ERR_FAIL_COND(p_shapes_count < 0);
- physics.write[p_layer_id].shapes.resize(p_shapes_count);
+ ERR_FAIL_COND(p_polygons_count < 0);
+ physics.write[p_layer_id].polygons.resize(p_polygons_count);
notify_property_list_changed();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
-void TileData::add_collision_shape(int p_layer_id) {
+void TileData::add_collision_polygon(int p_layer_id) {
ERR_FAIL_INDEX(p_layer_id, physics.size());
- physics.write[p_layer_id].shapes.push_back(PhysicsLayerTileData::ShapeTileData());
- emit_signal("changed");
+ physics.write[p_layer_id].polygons.push_back(PhysicsLayerTileData::PolygonShapeTileData());
+ emit_signal(SNAME("changed"));
}
-void TileData::remove_collision_shape(int p_layer_id, int p_shape_index) {
+void TileData::remove_collision_polygon(int p_layer_id, int p_polygon_index) {
ERR_FAIL_INDEX(p_layer_id, physics.size());
- ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
- physics.write[p_layer_id].shapes.remove(p_shape_index);
- emit_signal("changed");
+ ERR_FAIL_INDEX(p_polygon_index, physics[p_layer_id].polygons.size());
+ physics.write[p_layer_id].polygons.remove(p_polygon_index);
+ emit_signal(SNAME("changed"));
}
-void TileData::set_collision_shape_shape(int p_layer_id, int p_shape_index, Ref<Shape2D> p_shape) {
+void TileData::set_collision_polygon_points(int p_layer_id, int p_polygon_index, Vector<Vector2> p_polygon) {
ERR_FAIL_INDEX(p_layer_id, physics.size());
- ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
- physics.write[p_layer_id].shapes.write[p_shape_index].shape = p_shape;
- emit_signal("changed");
+ ERR_FAIL_INDEX(p_polygon_index, physics[p_layer_id].polygons.size());
+ ERR_FAIL_COND_MSG(p_polygon.size() != 0 && p_polygon.size() < 3, "Invalid polygon. Needs either 0 or more than 3 points.");
+
+ if (p_polygon.is_empty()) {
+ physics.write[p_layer_id].polygons.write[p_polygon_index].shapes.clear();
+ } else {
+ // Decompose into convex shapes.
+ Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(p_polygon);
+ ERR_FAIL_COND_MSG(decomp.is_empty(), "Could not decompose the polygon into convex shapes.");
+
+ physics.write[p_layer_id].polygons.write[p_polygon_index].shapes.resize(decomp.size());
+ for (int i = 0; i < decomp.size(); i++) {
+ Ref<ConvexPolygonShape2D> shape;
+ shape.instantiate();
+ shape->set_points(decomp[i]);
+ physics.write[p_layer_id].polygons.write[p_polygon_index].shapes[i] = shape;
+ }
+ }
+ physics.write[p_layer_id].polygons.write[p_polygon_index].polygon = p_polygon;
+ emit_signal(SNAME("changed"));
}
-Ref<Shape2D> TileData::get_collision_shape_shape(int p_layer_id, int p_shape_index) const {
- ERR_FAIL_INDEX_V(p_layer_id, physics.size(), Ref<Shape2D>());
- ERR_FAIL_INDEX_V(p_shape_index, physics[p_layer_id].shapes.size(), Ref<Shape2D>());
- return physics[p_layer_id].shapes[p_shape_index].shape;
+Vector<Vector2> TileData::get_collision_polygon_points(int p_layer_id, int p_polygon_index) const {
+ ERR_FAIL_INDEX_V(p_layer_id, physics.size(), Vector<Vector2>());
+ ERR_FAIL_INDEX_V(p_polygon_index, physics[p_layer_id].polygons.size(), Vector<Vector2>());
+ return physics[p_layer_id].polygons[p_polygon_index].polygon;
}
-void TileData::set_collision_shape_one_way(int p_layer_id, int p_shape_index, bool p_one_way) {
+void TileData::set_collision_polygon_one_way(int p_layer_id, int p_polygon_index, bool p_one_way) {
ERR_FAIL_INDEX(p_layer_id, physics.size());
- ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
- physics.write[p_layer_id].shapes.write[p_shape_index].one_way = p_one_way;
- emit_signal("changed");
+ ERR_FAIL_INDEX(p_polygon_index, physics[p_layer_id].polygons.size());
+ physics.write[p_layer_id].polygons.write[p_polygon_index].one_way = p_one_way;
+ emit_signal(SNAME("changed"));
}
-bool TileData::is_collision_shape_one_way(int p_layer_id, int p_shape_index) const {
+bool TileData::is_collision_polygon_one_way(int p_layer_id, int p_polygon_index) const {
ERR_FAIL_INDEX_V(p_layer_id, physics.size(), false);
- ERR_FAIL_INDEX_V(p_shape_index, physics[p_layer_id].shapes.size(), false);
- return physics[p_layer_id].shapes[p_shape_index].one_way;
+ ERR_FAIL_INDEX_V(p_polygon_index, physics[p_layer_id].polygons.size(), false);
+ return physics[p_layer_id].polygons[p_polygon_index].one_way;
}
-void TileData::set_collision_shape_one_way_margin(int p_layer_id, int p_shape_index, float p_one_way_margin) {
+void TileData::set_collision_polygon_one_way_margin(int p_layer_id, int p_polygon_index, float p_one_way_margin) {
ERR_FAIL_INDEX(p_layer_id, physics.size());
- ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
- physics.write[p_layer_id].shapes.write[p_shape_index].one_way_margin = p_one_way_margin;
- emit_signal("changed");
+ ERR_FAIL_INDEX(p_polygon_index, physics[p_layer_id].polygons.size());
+ physics.write[p_layer_id].polygons.write[p_polygon_index].one_way_margin = p_one_way_margin;
+ emit_signal(SNAME("changed"));
}
-float TileData::get_collision_shape_one_way_margin(int p_layer_id, int p_shape_index) const {
+float TileData::get_collision_polygon_one_way_margin(int p_layer_id, int p_polygon_index) const {
ERR_FAIL_INDEX_V(p_layer_id, physics.size(), 0.0);
- ERR_FAIL_INDEX_V(p_shape_index, physics[p_layer_id].shapes.size(), 0.0);
- return physics[p_layer_id].shapes[p_shape_index].one_way_margin;
+ ERR_FAIL_INDEX_V(p_polygon_index, physics[p_layer_id].polygons.size(), 0.0);
+ return physics[p_layer_id].polygons[p_polygon_index].one_way_margin;
+}
+
+int TileData::get_collision_polygon_shapes_count(int p_layer_id, int p_polygon_index) const {
+ ERR_FAIL_INDEX_V(p_layer_id, physics.size(), 0);
+ ERR_FAIL_INDEX_V(p_polygon_index, physics[p_layer_id].polygons.size(), 0);
+ return physics[p_layer_id].polygons[p_polygon_index].shapes.size();
+}
+
+Ref<ConvexPolygonShape2D> TileData::get_collision_polygon_shape(int p_layer_id, int p_polygon_index, int shape_index) const {
+ ERR_FAIL_INDEX_V(p_layer_id, physics.size(), 0);
+ ERR_FAIL_INDEX_V(p_polygon_index, physics[p_layer_id].polygons.size(), Ref<ConvexPolygonShape2D>());
+ ERR_FAIL_INDEX_V(shape_index, (int)physics[p_layer_id].polygons[shape_index].shapes.size(), Ref<ConvexPolygonShape2D>());
+ return physics[p_layer_id].polygons[shape_index].shapes[shape_index];
}
// Terrain
void TileData::set_terrain_set(int p_terrain_set) {
ERR_FAIL_COND(p_terrain_set < -1);
+ if (p_terrain_set == terrain_set) {
+ return;
+ }
if (tile_set) {
ERR_FAIL_COND(p_terrain_set >= tile_set->get_terrain_sets_count());
+ for (int i = 0; i < 16; i++) {
+ terrain_peering_bits[i] = -1;
+ }
}
terrain_set = p_terrain_set;
notify_property_list_changed();
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
int TileData::get_terrain_set() const {
@@ -2454,18 +3361,18 @@ int TileData::get_terrain_set() const {
}
void TileData::set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) {
- ERR_FAIL_INDEX(p_peering_bit, TileSet::CELL_NEIGHBOR_MAX);
+ ERR_FAIL_COND(terrain_set < 0);
ERR_FAIL_COND(p_terrain_index < -1);
if (tile_set) {
ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set));
ERR_FAIL_COND(!is_valid_peering_bit_terrain(p_peering_bit));
}
terrain_peering_bits[p_peering_bit] = p_terrain_index;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
int TileData::get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const {
- ERR_FAIL_INDEX_V(p_peering_bit, TileSet::CELL_NEIGHBOR_MAX, -1);
+ ERR_FAIL_COND_V(!is_valid_peering_bit_terrain(p_peering_bit), -1);
return terrain_peering_bits[p_peering_bit];
}
@@ -2479,7 +3386,7 @@ bool TileData::is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit)
void TileData::set_navigation_polygon(int p_layer_id, Ref<NavigationPolygon> p_navigation_polygon) {
ERR_FAIL_INDEX(p_layer_id, navigation.size());
navigation.write[p_layer_id] = p_navigation_polygon;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
Ref<NavigationPolygon> TileData::get_navigation_polygon(int p_layer_id) const {
@@ -2489,9 +3396,9 @@ Ref<NavigationPolygon> TileData::get_navigation_polygon(int p_layer_id) const {
// Misc
void TileData::set_probability(float p_probability) {
- ERR_FAIL_COND(p_probability <= 0.0);
+ ERR_FAIL_COND(p_probability < 0.0);
probability = p_probability;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
float TileData::get_probability() const {
return probability;
@@ -2515,7 +3422,7 @@ Variant TileData::get_custom_data(String p_layer_name) const {
void TileData::set_custom_data_by_layer_id(int p_layer_id, Variant p_value) {
ERR_FAIL_INDEX(p_layer_id, custom_data.size());
custom_data.write[p_layer_id] = p_value;
- emit_signal("changed");
+ emit_signal(SNAME("changed"));
}
Variant TileData::get_custom_data_by_layer_id(int p_layer_id) const {
@@ -2550,7 +3457,7 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
// Physics layers.
int layer_index = components[0].trim_prefix("physics_layer_").to_int();
ERR_FAIL_COND_V(layer_index < 0, false);
- if (components.size() == 2 && components[1] == "shapes_count") {
+ if (components.size() == 2 && components[1] == "polygons_count") {
if (p_value.get_type() != Variant::INT) {
return false;
}
@@ -2562,13 +3469,13 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
physics.resize(layer_index + 1);
}
}
- set_collision_shapes_count(layer_index, p_value);
+ set_collision_polygons_count(layer_index, p_value);
return true;
- } else if (components.size() == 3 && components[1].begins_with("shape_") && components[1].trim_prefix("shape_").is_valid_int()) {
- int shape_index = components[1].trim_prefix("shape_").to_int();
- ERR_FAIL_COND_V(shape_index < 0, false);
+ } else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
+ int polygon_index = components[1].trim_prefix("polygon_").to_int();
+ ERR_FAIL_COND_V(polygon_index < 0, false);
- if (components[2] == "shape" || components[2] == "one_way" || components[2] == "one_way_margin") {
+ if (components[2] == "points" || components[2] == "one_way" || components[2] == "one_way_margin") {
if (layer_index >= physics.size()) {
if (tile_set) {
return false;
@@ -2577,19 +3484,19 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
}
}
- if (shape_index >= physics[layer_index].shapes.size()) {
- physics.write[layer_index].shapes.resize(shape_index + 1);
+ if (polygon_index >= physics[layer_index].polygons.size()) {
+ physics.write[layer_index].polygons.resize(polygon_index + 1);
}
}
- if (components[2] == "shape") {
- Ref<Shape2D> shape = p_value;
- set_collision_shape_shape(layer_index, shape_index, shape);
+ if (components[2] == "points") {
+ Vector<Vector2> polygon = p_value;
+ set_collision_polygon_points(layer_index, polygon_index, polygon);
return true;
} else if (components[2] == "one_way") {
- set_collision_shape_one_way(layer_index, shape_index, p_value);
+ set_collision_polygon_one_way(layer_index, polygon_index, p_value);
return true;
} else if (components[2] == "one_way_margin") {
- set_collision_shape_one_way_margin(layer_index, shape_index, p_value);
+ set_collision_polygon_one_way_margin(layer_index, polygon_index, p_value);
return true;
}
}
@@ -2615,42 +3522,14 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
}
} else if (components.size() == 2 && components[0] == "terrains_peering_bit") {
// Terrains.
- if (components[1] == "right_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, p_value);
- } else if (components[1] == "right_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_CORNER, p_value);
- } else if (components[1] == "bottom_right_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, p_value);
- } else if (components[1] == "bottom_right_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, p_value);
- } else if (components[1] == "bottom_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, p_value);
- } else if (components[1] == "bottom_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER, p_value);
- } else if (components[1] == "bottom_left_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, p_value);
- } else if (components[1] == "bottom_left_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, p_value);
- } else if (components[1] == "left_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_SIDE, p_value);
- } else if (components[1] == "left_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_CORNER, p_value);
- } else if (components[1] == "top_left_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, p_value);
- } else if (components[1] == "top_left_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, p_value);
- } else if (components[1] == "top_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_SIDE, p_value);
- } else if (components[1] == "top_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_CORNER, p_value);
- } else if (components[1] == "top_right_side") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, p_value);
- } else if (components[1] == "top_right_corner") {
- set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, p_value);
- } else {
- return false;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (components[1] == TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]) {
+ set_peering_bit_terrain(bit, p_value);
+ return true;
+ }
}
- return true;
+ return false;
} else if (components.size() == 1 && components[0].begins_with("custom_data_") && components[0].trim_prefix("custom_data_").is_valid_int()) {
// Custom data layers.
int layer_index = components[0].trim_prefix("custom_data_").to_int();
@@ -2693,64 +3572,35 @@ bool TileData::_get(const StringName &p_name, Variant &r_ret) const {
if (layer_index >= physics.size()) {
return false;
}
- if (components.size() == 2 && components[1] == "shapes_count") {
- r_ret = get_collision_shapes_count(layer_index);
+ if (components.size() == 2 && components[1] == "polygons_count") {
+ r_ret = get_collision_polygons_count(layer_index);
return true;
- } else if (components.size() == 3 && components[1].begins_with("shape_") && components[1].trim_prefix("shape_").is_valid_int()) {
- int shape_index = components[1].trim_prefix("shape_").to_int();
- ERR_FAIL_COND_V(shape_index < 0, false);
- if (shape_index >= physics[layer_index].shapes.size()) {
+ } else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
+ int polygon_index = components[1].trim_prefix("polygon_").to_int();
+ ERR_FAIL_COND_V(polygon_index < 0, false);
+ if (polygon_index >= physics[layer_index].polygons.size()) {
return false;
}
- if (components[2] == "shape") {
- r_ret = get_collision_shape_shape(layer_index, shape_index);
+ if (components[2] == "points") {
+ r_ret = get_collision_polygon_points(layer_index, polygon_index);
return true;
} else if (components[2] == "one_way") {
- r_ret = is_collision_shape_one_way(layer_index, shape_index);
+ r_ret = is_collision_polygon_one_way(layer_index, polygon_index);
return true;
} else if (components[2] == "one_way_margin") {
- r_ret = get_collision_shape_one_way_margin(layer_index, shape_index);
+ r_ret = get_collision_polygon_one_way_margin(layer_index, polygon_index);
return true;
}
}
} else if (components.size() == 2 && components[0] == "terrains_peering_bit") {
// Terrains.
- if (components[1] == "right_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_RIGHT_SIDE];
- } else if (components[1] == "right_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_RIGHT_CORNER];
- } else if (components[1] == "bottom_right_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE];
- } else if (components[1] == "bottom_right_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER];
- } else if (components[1] == "bottom_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_SIDE];
- } else if (components[1] == "bottom_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_CORNER];
- } else if (components[1] == "bottom_left_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE];
- } else if (components[1] == "bottom_left_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER];
- } else if (components[1] == "left_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_LEFT_SIDE];
- } else if (components[1] == "left_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_LEFT_CORNER];
- } else if (components[1] == "top_left_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE];
- } else if (components[1] == "top_left_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER];
- } else if (components[1] == "top_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_SIDE];
- } else if (components[1] == "top_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_CORNER];
- } else if (components[1] == "top_right_side") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE];
- } else if (components[1] == "top_right_corner") {
- r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER];
- } else {
- return false;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ if (components[1] == TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]) {
+ r_ret = terrain_peering_bits[i];
+ return true;
+ }
}
- return true;
+ return false;
} else if (components.size() == 2 && components[0].begins_with("navigation_layer_") && components[0].trim_prefix("navigation_layer_").is_valid_int()) {
// Occlusion layers.
int layer_index = components[0].trim_prefix("navigation_layer_").to_int();
@@ -2795,26 +3645,26 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
// Physics layers.
p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < physics.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/shapes_count", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/polygons_count", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
- for (int j = 0; j < physics[i].shapes.size(); j++) {
- // physics_layer_%d/shapes_count
- property_info = PropertyInfo(Variant::OBJECT, vformat("physics_layer_%d/shape_%d/shape", i, j), PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_DEFAULT);
- if (!physics[i].shapes[j].shape.is_valid()) {
+ for (int j = 0; j < physics[i].polygons.size(); j++) {
+ // physics_layer_%d/points
+ property_info = PropertyInfo(Variant::ARRAY, vformat("physics_layer_%d/polygon_%d/points", i, j), PROPERTY_HINT_ARRAY_TYPE, "Vector2", PROPERTY_USAGE_DEFAULT);
+ if (physics[i].polygons[j].polygon.is_empty()) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
p_list->push_back(property_info);
- // physics_layer_%d/shape_%d/one_way
- property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/shape_%d/one_way", i, j));
- if (physics[i].shapes[j].one_way == false) {
+ // physics_layer_%d/polygon_%d/one_way
+ property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/polygon_%d/one_way", i, j));
+ if (physics[i].polygons[j].one_way == false) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
p_list->push_back(property_info);
- // physics_layer_%d/shape_%d/one_way_margin
- property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/shape_%d/one_way_margin", i, j));
- if (physics[i].shapes[j].one_way_margin == 1.0) {
+ // physics_layer_%d/polygon_%d/one_way_margin
+ property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/polygon_%d/one_way_margin", i, j));
+ if (physics[i].polygons[j].one_way_margin == 1.0) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
p_list->push_back(property_info);
@@ -2824,117 +3674,15 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
// Terrain data
if (terrain_set >= 0) {
p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/right_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/right_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_right_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_right_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_left_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_left_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/left_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/left_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_left_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_left_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_right_side");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
- }
- p_list->push_back(property_info);
- }
- if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER)) {
- property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_right_corner");
- if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) == -1) {
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
+ if (is_valid_peering_bit_terrain(bit)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]));
+ if (get_peering_bit_terrain(bit) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
}
- p_list->push_back(property_info);
}
}
@@ -2986,16 +3734,16 @@ void TileData::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_occluder", "layer_id"), &TileData::get_occluder);
// Physics.
- ClassDB::bind_method(D_METHOD("get_collision_shapes_count", "layer_id"), &TileData::get_collision_shapes_count);
- ClassDB::bind_method(D_METHOD("set_collision_shapes_count", "layer_id", "shapes_count"), &TileData::set_collision_shapes_count);
- ClassDB::bind_method(D_METHOD("add_collision_shape", "layer_id"), &TileData::add_collision_shape);
- ClassDB::bind_method(D_METHOD("remove_collision_shape", "layer_id", "shape_index"), &TileData::remove_collision_shape);
- ClassDB::bind_method(D_METHOD("set_collision_shape_shape", "layer_id", "shape_index", "shape"), &TileData::set_collision_shape_shape);
- ClassDB::bind_method(D_METHOD("get_collision_shape_shape", "layer_id", "shape_index"), &TileData::get_collision_shape_shape);
- ClassDB::bind_method(D_METHOD("set_collision_shape_one_way", "layer_id", "shape_index", "one_way"), &TileData::set_collision_shape_one_way);
- ClassDB::bind_method(D_METHOD("is_collision_shape_one_way", "layer_id", "shape_index"), &TileData::is_collision_shape_one_way);
- ClassDB::bind_method(D_METHOD("set_collision_shape_one_way_margin", "layer_id", "shape_index", "one_way_margin"), &TileData::set_collision_shape_one_way_margin);
- ClassDB::bind_method(D_METHOD("get_collision_shape_one_way_margin", "layer_id", "shape_index"), &TileData::get_collision_shape_one_way_margin);
+ ClassDB::bind_method(D_METHOD("get_collision_polygons_count", "layer_id"), &TileData::get_collision_polygons_count);
+ ClassDB::bind_method(D_METHOD("set_collision_polygons_count", "layer_id", "polygons_count"), &TileData::set_collision_polygons_count);
+ ClassDB::bind_method(D_METHOD("add_collision_polygon", "layer_id"), &TileData::add_collision_polygon);
+ ClassDB::bind_method(D_METHOD("remove_collision_polygon", "layer_id", "polygon_index"), &TileData::remove_collision_polygon);
+ ClassDB::bind_method(D_METHOD("set_collision_polygon_points", "layer_id", "polygon_index", "polygon"), &TileData::set_collision_polygon_points);
+ ClassDB::bind_method(D_METHOD("get_collision_polygon_points", "layer_id", "polygon_index"), &TileData::get_collision_polygon_points);
+ ClassDB::bind_method(D_METHOD("set_collision_polygon_one_way", "layer_id", "polygon_index", "one_way"), &TileData::set_collision_polygon_one_way);
+ ClassDB::bind_method(D_METHOD("is_collision_polygon_one_way", "layer_id", "polygon_index"), &TileData::is_collision_polygon_one_way);
+ ClassDB::bind_method(D_METHOD("set_collision_polygon_one_way_margin", "layer_id", "polygon_index", "one_way_margin"), &TileData::set_collision_polygon_one_way_margin);
+ ClassDB::bind_method(D_METHOD("get_collision_polygon_one_way_margin", "layer_id", "polygon_index"), &TileData::get_collision_polygon_one_way_margin);
// Terrain
ClassDB::bind_method(D_METHOD("set_terrain_set", "terrain_set"), &TileData::set_terrain_set);
@@ -3034,805 +3782,6 @@ void TileData::_bind_methods() {
ADD_SIGNAL(MethodInfo("changed"));
}
-
-/////////////////////////////// TileSetPluginAtlasTerrain //////////////////////////////////////
-
-// --- PLUGINS ---
-void TileSetPluginAtlasTerrain::_draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
- Rect2 bit_rect;
- bit_rect.size = Vector2(p_size) / 3;
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
- bit_rect.position = Vector2(1, -1);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- bit_rect.position = Vector2(1, 1);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
- bit_rect.position = Vector2(-1, 1);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- bit_rect.position = Vector2(-3, 1);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
- bit_rect.position = Vector2(-3, -1);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- bit_rect.position = Vector2(-3, -3);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_SIDE:
- bit_rect.position = Vector2(-1, -3);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- bit_rect.position = Vector2(1, -3);
- break;
- default:
- break;
- }
- bit_rect.position *= Vector2(p_size) / 6.0;
- p_canvas_item->draw_rect(bit_rect, p_color);
-}
-
-void TileSetPluginAtlasTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- Vector2 unit = Vector2(p_size) / 6.0;
- PackedVector2Array polygon;
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- polygon.push_back(Vector2(0, 3) * unit);
- polygon.push_back(Vector2(3, 3) * unit);
- polygon.push_back(Vector2(3, 0) * unit);
- polygon.push_back(Vector2(1, 0) * unit);
- polygon.push_back(Vector2(1, 1) * unit);
- polygon.push_back(Vector2(0, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- polygon.push_back(Vector2(0, 3) * unit);
- polygon.push_back(Vector2(-3, 3) * unit);
- polygon.push_back(Vector2(-3, 0) * unit);
- polygon.push_back(Vector2(-1, 0) * unit);
- polygon.push_back(Vector2(-1, 1) * unit);
- polygon.push_back(Vector2(0, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- polygon.push_back(Vector2(0, -3) * unit);
- polygon.push_back(Vector2(-3, -3) * unit);
- polygon.push_back(Vector2(-3, 0) * unit);
- polygon.push_back(Vector2(-1, 0) * unit);
- polygon.push_back(Vector2(-1, -1) * unit);
- polygon.push_back(Vector2(0, -1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- polygon.push_back(Vector2(0, -3) * unit);
- polygon.push_back(Vector2(3, -3) * unit);
- polygon.push_back(Vector2(3, 0) * unit);
- polygon.push_back(Vector2(1, 0) * unit);
- polygon.push_back(Vector2(1, -1) * unit);
- polygon.push_back(Vector2(0, -1) * unit);
- break;
- default:
- break;
- }
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-void TileSetPluginAtlasTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- Vector2 unit = Vector2(p_size) / 6.0;
- PackedVector2Array polygon;
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
- polygon.push_back(Vector2(1, -1) * unit);
- polygon.push_back(Vector2(3, -3) * unit);
- polygon.push_back(Vector2(3, 3) * unit);
- polygon.push_back(Vector2(1, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
- polygon.push_back(Vector2(-1, 1) * unit);
- polygon.push_back(Vector2(-3, 3) * unit);
- polygon.push_back(Vector2(3, 3) * unit);
- polygon.push_back(Vector2(1, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
- polygon.push_back(Vector2(-1, -1) * unit);
- polygon.push_back(Vector2(-3, -3) * unit);
- polygon.push_back(Vector2(-3, 3) * unit);
- polygon.push_back(Vector2(-1, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_SIDE:
- polygon.push_back(Vector2(-1, -1) * unit);
- polygon.push_back(Vector2(-3, -3) * unit);
- polygon.push_back(Vector2(3, -3) * unit);
- polygon.push_back(Vector2(1, -1) * unit);
- break;
- default:
- break;
- }
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-void TileSetPluginAtlasTerrain::_draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- Vector2 unit = Vector2(p_size) / 6.0;
- PackedVector2Array polygon;
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
- polygon.push_back(Vector2(1, 0) * unit);
- polygon.push_back(Vector2(2, -1) * unit);
- polygon.push_back(Vector2(3, 0) * unit);
- polygon.push_back(Vector2(2, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- polygon.push_back(Vector2(0, 1) * unit);
- polygon.push_back(Vector2(1, 2) * unit);
- polygon.push_back(Vector2(2, 1) * unit);
- polygon.push_back(Vector2(1, 0) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
- polygon.push_back(Vector2(0, 1) * unit);
- polygon.push_back(Vector2(-1, 2) * unit);
- polygon.push_back(Vector2(0, 3) * unit);
- polygon.push_back(Vector2(1, 2) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- polygon.push_back(Vector2(0, 1) * unit);
- polygon.push_back(Vector2(-1, 2) * unit);
- polygon.push_back(Vector2(-2, 1) * unit);
- polygon.push_back(Vector2(-1, 0) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
- polygon.push_back(Vector2(-1, 0) * unit);
- polygon.push_back(Vector2(-2, -1) * unit);
- polygon.push_back(Vector2(-3, 0) * unit);
- polygon.push_back(Vector2(-2, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- polygon.push_back(Vector2(0, -1) * unit);
- polygon.push_back(Vector2(-1, -2) * unit);
- polygon.push_back(Vector2(-2, -1) * unit);
- polygon.push_back(Vector2(-1, 0) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_CORNER:
- polygon.push_back(Vector2(0, -1) * unit);
- polygon.push_back(Vector2(-1, -2) * unit);
- polygon.push_back(Vector2(0, -3) * unit);
- polygon.push_back(Vector2(1, -2) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- polygon.push_back(Vector2(0, -1) * unit);
- polygon.push_back(Vector2(1, -2) * unit);
- polygon.push_back(Vector2(2, -1) * unit);
- polygon.push_back(Vector2(1, 0) * unit);
- break;
- default:
- break;
- }
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-void TileSetPluginAtlasTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- Vector2 unit = Vector2(p_size) / 6.0;
- PackedVector2Array polygon;
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
- polygon.push_back(Vector2(0.5, -0.5) * unit);
- polygon.push_back(Vector2(1.5, -1.5) * unit);
- polygon.push_back(Vector2(3, 0) * unit);
- polygon.push_back(Vector2(1.5, 1.5) * unit);
- polygon.push_back(Vector2(0.5, 0.5) * unit);
- polygon.push_back(Vector2(1, 0) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
- polygon.push_back(Vector2(-0.5, 0.5) * unit);
- polygon.push_back(Vector2(-1.5, 1.5) * unit);
- polygon.push_back(Vector2(0, 3) * unit);
- polygon.push_back(Vector2(1.5, 1.5) * unit);
- polygon.push_back(Vector2(0.5, 0.5) * unit);
- polygon.push_back(Vector2(0, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
- polygon.push_back(Vector2(-0.5, -0.5) * unit);
- polygon.push_back(Vector2(-1.5, -1.5) * unit);
- polygon.push_back(Vector2(-3, 0) * unit);
- polygon.push_back(Vector2(-1.5, 1.5) * unit);
- polygon.push_back(Vector2(-0.5, 0.5) * unit);
- polygon.push_back(Vector2(-1, 0) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_CORNER:
- polygon.push_back(Vector2(-0.5, -0.5) * unit);
- polygon.push_back(Vector2(-1.5, -1.5) * unit);
- polygon.push_back(Vector2(0, -3) * unit);
- polygon.push_back(Vector2(1.5, -1.5) * unit);
- polygon.push_back(Vector2(0.5, -0.5) * unit);
- polygon.push_back(Vector2(0, -1) * unit);
- break;
- default:
- break;
- }
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-void TileSetPluginAtlasTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- Vector2 unit = Vector2(p_size) / 6.0;
- PackedVector2Array polygon;
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- polygon.push_back(Vector2(1, 0) * unit);
- polygon.push_back(Vector2(3, 0) * unit);
- polygon.push_back(Vector2(0, 3) * unit);
- polygon.push_back(Vector2(0, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- polygon.push_back(Vector2(-1, 0) * unit);
- polygon.push_back(Vector2(-3, 0) * unit);
- polygon.push_back(Vector2(0, 3) * unit);
- polygon.push_back(Vector2(0, 1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- polygon.push_back(Vector2(-1, 0) * unit);
- polygon.push_back(Vector2(-3, 0) * unit);
- polygon.push_back(Vector2(0, -3) * unit);
- polygon.push_back(Vector2(0, -1) * unit);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- polygon.push_back(Vector2(1, 0) * unit);
- polygon.push_back(Vector2(3, 0) * unit);
- polygon.push_back(Vector2(0, -3) * unit);
- polygon.push_back(Vector2(0, -1) * unit);
- break;
- default:
- break;
- }
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-void TileSetPluginAtlasTerrain::_draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- PackedVector2Array point_list;
- point_list.push_back(Vector2(3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
- point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(2, 3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
- point_list.push_back(Vector2(1, 3.0 - p_overlap * 2.0));
- point_list.push_back(Vector2(0, 3));
- point_list.push_back(Vector2(-1, 3.0 - p_overlap * 2.0));
- point_list.push_back(Vector2(-2, 3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
- point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(-3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
- point_list.push_back(Vector2(-3, -(3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
- point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(-2, -3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
- point_list.push_back(Vector2(-1, -(3.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(0, -3));
- point_list.push_back(Vector2(1, -(3.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(2, -3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
- point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(3, -(3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
-
- Vector2 unit = Vector2(p_size) / 6.0;
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = point_list[i] * unit;
- }
-
- PackedVector2Array polygon;
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
- polygon.push_back(point_list[17]);
- polygon.push_back(point_list[0]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- polygon.push_back(point_list[0]);
- polygon.push_back(point_list[1]);
- polygon.push_back(point_list[2]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- polygon.push_back(point_list[2]);
- polygon.push_back(point_list[3]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
- polygon.push_back(point_list[3]);
- polygon.push_back(point_list[4]);
- polygon.push_back(point_list[5]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- polygon.push_back(point_list[5]);
- polygon.push_back(point_list[6]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- polygon.push_back(point_list[6]);
- polygon.push_back(point_list[7]);
- polygon.push_back(point_list[8]);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
- polygon.push_back(point_list[8]);
- polygon.push_back(point_list[9]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- polygon.push_back(point_list[9]);
- polygon.push_back(point_list[10]);
- polygon.push_back(point_list[11]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- polygon.push_back(point_list[11]);
- polygon.push_back(point_list[12]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_CORNER:
- polygon.push_back(point_list[12]);
- polygon.push_back(point_list[13]);
- polygon.push_back(point_list[14]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- polygon.push_back(point_list[14]);
- polygon.push_back(point_list[15]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- polygon.push_back(point_list[15]);
- polygon.push_back(point_list[16]);
- polygon.push_back(point_list[17]);
- break;
- default:
- break;
- }
- } else {
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
- }
- }
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
- polygon.push_back(point_list[3]);
- polygon.push_back(point_list[4]);
- polygon.push_back(point_list[5]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- polygon.push_back(point_list[2]);
- polygon.push_back(point_list[3]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- polygon.push_back(point_list[0]);
- polygon.push_back(point_list[1]);
- polygon.push_back(point_list[2]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
- polygon.push_back(point_list[17]);
- polygon.push_back(point_list[0]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- polygon.push_back(point_list[15]);
- polygon.push_back(point_list[16]);
- polygon.push_back(point_list[17]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- polygon.push_back(point_list[14]);
- polygon.push_back(point_list[15]);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
- polygon.push_back(point_list[12]);
- polygon.push_back(point_list[13]);
- polygon.push_back(point_list[14]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- polygon.push_back(point_list[11]);
- polygon.push_back(point_list[12]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- polygon.push_back(point_list[9]);
- polygon.push_back(point_list[10]);
- polygon.push_back(point_list[11]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_SIDE:
- polygon.push_back(point_list[8]);
- polygon.push_back(point_list[9]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- polygon.push_back(point_list[6]);
- polygon.push_back(point_list[7]);
- polygon.push_back(point_list[8]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- polygon.push_back(point_list[5]);
- polygon.push_back(point_list[6]);
- break;
- default:
- break;
- }
- }
-
- int half_polygon_size = polygon.size();
- for (int i = 0; i < half_polygon_size; i++) {
- polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
- }
-
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-void TileSetPluginAtlasTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- PackedVector2Array point_list;
- point_list.push_back(Vector2(3, 0));
- point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(1.5, (3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
- point_list.push_back(Vector2(0, 3));
- point_list.push_back(Vector2(-1.5, (3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
- point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(-3, 0));
- point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(-1.5, -(3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
- point_list.push_back(Vector2(0, -3));
- point_list.push_back(Vector2(1.5, -(3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
- point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
-
- Vector2 unit = Vector2(p_size) / 6.0;
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = point_list[i] * unit;
- }
-
- PackedVector2Array polygon;
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- polygon.push_back(point_list[0]);
- polygon.push_back(point_list[1]);
- polygon.push_back(point_list[2]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
- polygon.push_back(point_list[2]);
- polygon.push_back(point_list[3]);
- polygon.push_back(point_list[4]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- polygon.push_back(point_list[4]);
- polygon.push_back(point_list[5]);
- polygon.push_back(point_list[6]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- polygon.push_back(point_list[6]);
- polygon.push_back(point_list[7]);
- polygon.push_back(point_list[8]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_CORNER:
- polygon.push_back(point_list[8]);
- polygon.push_back(point_list[9]);
- polygon.push_back(point_list[10]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- polygon.push_back(point_list[10]);
- polygon.push_back(point_list[11]);
- polygon.push_back(point_list[0]);
- break;
- default:
- break;
- }
- } else {
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
- }
- }
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
- polygon.push_back(point_list[2]);
- polygon.push_back(point_list[3]);
- polygon.push_back(point_list[4]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- polygon.push_back(point_list[0]);
- polygon.push_back(point_list[1]);
- polygon.push_back(point_list[2]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- polygon.push_back(point_list[10]);
- polygon.push_back(point_list[11]);
- polygon.push_back(point_list[0]);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
- polygon.push_back(point_list[8]);
- polygon.push_back(point_list[9]);
- polygon.push_back(point_list[10]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- polygon.push_back(point_list[6]);
- polygon.push_back(point_list[7]);
- polygon.push_back(point_list[8]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- polygon.push_back(point_list[4]);
- polygon.push_back(point_list[5]);
- polygon.push_back(point_list[6]);
- break;
- default:
- break;
- }
- }
-
- int half_polygon_size = polygon.size();
- for (int i = 0; i < half_polygon_size; i++) {
- polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
- }
-
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-void TileSetPluginAtlasTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
- PackedColorArray color_array;
- color_array.push_back(p_color);
-
- PackedVector2Array point_list;
- point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(0, 3));
- point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
- point_list.push_back(Vector2(0, -3));
- point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
-
- Vector2 unit = Vector2(p_size) / 6.0;
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = point_list[i] * unit;
- }
-
- PackedVector2Array polygon;
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
- polygon.push_back(point_list[5]);
- polygon.push_back(point_list[0]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- polygon.push_back(point_list[0]);
- polygon.push_back(point_list[1]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- polygon.push_back(point_list[1]);
- polygon.push_back(point_list[2]);
- break;
- case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
- polygon.push_back(point_list[2]);
- polygon.push_back(point_list[3]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- polygon.push_back(point_list[3]);
- polygon.push_back(point_list[4]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- polygon.push_back(point_list[4]);
- polygon.push_back(point_list[5]);
- break;
- default:
- break;
- }
- } else {
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < point_list.size(); i++) {
- point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
- }
- }
- switch (p_bit) {
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
- polygon.push_back(point_list[0]);
- polygon.push_back(point_list[1]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
- polygon.push_back(point_list[5]);
- polygon.push_back(point_list[0]);
- break;
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
- polygon.push_back(point_list[4]);
- polygon.push_back(point_list[5]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
- polygon.push_back(point_list[3]);
- polygon.push_back(point_list[4]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_SIDE:
- polygon.push_back(point_list[2]);
- polygon.push_back(point_list[3]);
- break;
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
- polygon.push_back(point_list[1]);
- polygon.push_back(point_list[2]);
- break;
- default:
- break;
- }
- }
-
- int half_polygon_size = polygon.size();
- for (int i = 0; i < half_polygon_size; i++) {
- polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
- }
-
- if (!polygon.is_empty()) {
- p_canvas_item->draw_polygon(polygon, color_array);
- }
-}
-
-#define TERRAIN_ALPHA 0.8
-
-#define DRAW_TERRAIN_BIT(f, bit) \
- { \
- int terrain_id = p_tile_data->get_peering_bit_terrain((bit)); \
- if (terrain_id >= 0) { \
- Color color = p_tile_set->get_terrain_color(terrain_set, terrain_id); \
- color.a = TERRAIN_ALPHA; \
- f(p_canvas_item, color, size, (bit)); \
- } \
- }
-
-#define DRAW_HALF_OFFSET_TERRAIN_BIT(f, bit, overlap, half_offset_axis) \
- { \
- int terrain_id = p_tile_data->get_peering_bit_terrain((bit)); \
- if (terrain_id >= 0) { \
- Color color = p_tile_set->get_terrain_color(terrain_set, terrain_id); \
- color.a = TERRAIN_ALPHA; \
- f(p_canvas_item, color, size, (bit), overlap, half_offset_axis); \
- } \
- }
-
-void TileSetPluginAtlasTerrain::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data) {
- ERR_FAIL_COND(!p_tile_set);
- ERR_FAIL_COND(!p_tile_data);
-
- int terrain_set = p_tile_data->get_terrain_set();
- if (terrain_set < 0) {
- return;
- }
- TileSet::TerrainMode terrain_mode = p_tile_set->get_terrain_set_mode(terrain_set);
-
- TileSet::TileShape shape = p_tile_set->get_tile_shape();
- Vector2i size = p_tile_set->get_tile_size();
-
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
- if (shape == TileSet::TILE_SHAPE_SQUARE) {
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE);
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE);
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE);
- DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER);
- } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
- DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
- DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
- DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER);
- } else { // TileData::TERRAIN_MODE_MATCH_SIDES
- DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE);
- DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE);
- DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
- DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE);
- }
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
- } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER);
- DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER);
- } else { // TileData::TERRAIN_MODE_MATCH_SIDES
- DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
- DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
- DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
- DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
- }
- } else {
- TileSet::TileOffsetAxis offset_axis = p_tile_set->get_tile_offset_axis();
- float overlap = 0.0;
- switch (p_tile_set->get_tile_shape()) {
- case TileSet::TILE_SHAPE_HEXAGON:
- overlap = 0.25;
- break;
- case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
- overlap = 0.0;
- break;
- default:
- break;
- }
- if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
- if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
- } else {
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
- }
- } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
- if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
- } else {
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
- }
- } else { // TileData::TERRAIN_MODE_MATCH_SIDES
- if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
- } else {
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE, overlap, offset_axis);
- DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
- }
- }
- }
- RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
-}
-
/////////////////////////////// TileSetPluginAtlasRendering //////////////////////////////////////
void TileSetPluginAtlasRendering::tilemap_notification(TileMap *p_tile_map, int p_what) {
@@ -4218,15 +4167,17 @@ void TileSetPluginAtlasPhysics::update_dirty_quadrants(TileMap *p_tile_map, Self
for (int body_index = 0; body_index < q.bodies.size(); body_index++) {
// Add the shapes again.
- for (int shape_index = 0; shape_index < tile_data->get_collision_shapes_count(body_index); shape_index++) {
- bool one_way_collision = tile_data->is_collision_shape_one_way(body_index, shape_index);
- float one_way_collision_margin = tile_data->get_collision_shape_one_way_margin(body_index, shape_index);
- Ref<Shape2D> shape = tile_data->get_collision_shape_shape(body_index, shape_index);
- if (shape.is_valid()) {
+ for (int polygon_index = 0; polygon_index < tile_data->get_collision_polygons_count(body_index); polygon_index++) {
+ bool one_way_collision = tile_data->is_collision_polygon_one_way(body_index, polygon_index);
+ float one_way_collision_margin = tile_data->get_collision_polygon_one_way_margin(body_index, polygon_index);
+
+ int shapes_count = tile_data->get_collision_polygon_shapes_count(body_index, polygon_index);
+ for (int shape_index = 0; shape_index < shapes_count; shape_index++) {
Transform2D xform = Transform2D();
xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
// Add decomposed convex shapes.
+ Ref<ConvexPolygonShape2D> shape = tile_data->get_collision_polygon_shape(body_index, polygon_index, shape_index);
ps->body_add_shape(q.bodies[body_index], shape->get_rid(), xform);
ps->body_set_shape_metadata(q.bodies[body_index], shape_index, E_cell->get());
ps->body_set_shape_as_one_way_collision(q.bodies[body_index], shape_index, one_way_collision, one_way_collision_margin);
@@ -4343,11 +4294,13 @@ void TileSetPluginAtlasPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMap
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile));
for (int body_index = 0; body_index < p_quadrant->bodies.size(); body_index++) {
- for (int shape_index = 0; shape_index < tile_data->get_collision_shapes_count(body_index); shape_index++) {
- // Draw the debug shape.
- Ref<Shape2D> shape = tile_data->get_collision_shape_shape(body_index, shape_index);
- if (shape.is_valid()) {
- shape->draw(p_quadrant->debug_canvas_item, debug_collision_color);
+ for (int polygon_index = 0; polygon_index < tile_data->get_collision_polygons_count(body_index); polygon_index++) {
+ // Draw the debug polygon.
+ Vector<Vector2> polygon = tile_data->get_collision_polygon_points(body_index, polygon_index);
+ if (polygon.size() >= 3) {
+ Vector<Color> color;
+ color.push_back(debug_collision_color);
+ rs->canvas_item_add_polygon(p_quadrant->debug_canvas_item, polygon, color);
}
}
}
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 6cf4198f30..dbf6dbabe6 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -33,19 +33,18 @@
#include "core/io/resource.h"
#include "core/object/object.h"
+#include "core/templates/local_vector.h"
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/navigation_region_2d.h"
#include "scene/main/canvas_item.h"
+#include "scene/resources/concave_polygon_shape_2d.h"
#include "scene/resources/convex_polygon_shape_2d.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/physics_material.h"
#include "scene/resources/shape_2d.h"
#ifndef DISABLE_DEPRECATED
-#include "scene/2d/light_occluder_2d.h"
-#include "scene/2d/navigation_region_2d.h"
#include "scene/resources/shader.h"
-#include "scene/resources/shape_2d.h"
#include "scene/resources/texture.h"
#endif
@@ -60,7 +59,6 @@ class TileSetPlugin;
class TileSetPluginAtlasRendering;
class TileSetPluginAtlasPhysics;
class TileSetPluginAtlasNavigation;
-class TileSetPluginAtlasTerrain;
class TileSet : public Resource {
GDCLASS(TileSet, Resource);
@@ -138,6 +136,8 @@ public:
CELL_NEIGHBOR_MAX,
};
+ static const char *CELL_NEIGHBOR_ENUM_TO_TEXT[];
+
enum TerrainMode {
TERRAIN_MODE_MATCH_CORNERS_AND_SIDES = 0,
TERRAIN_MODE_MATCH_CORNERS,
@@ -194,6 +194,10 @@ private:
};
Vector<OcclusionLayer> occlusion_layers;
+ Ref<ArrayMesh> tile_lines_mesh;
+ Ref<ArrayMesh> tile_filled_mesh;
+ bool tile_meshes_dirty = true;
+
// Physics
struct PhysicsLayer {
uint32_t collision_layer = 1;
@@ -213,6 +217,9 @@ private:
};
Vector<TerrainSet> terrain_sets;
+ Map<TerrainMode, Map<CellNeighbor, Ref<ArrayMesh>>> terrain_bits_meshes;
+ bool terrain_bits_meshes_dirty = true;
+
// Navigation
struct Navigationlayer {
uint32_t layers = 1;
@@ -239,6 +246,19 @@ private:
void _compute_next_source_id();
void _source_changed();
+ // Helpers
+ Vector<Point2> _get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_square_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+
+ Vector<Point2> _get_isometric_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_isometric_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+ Vector<Point2> _get_isometric_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
+
+ Vector<Point2> _get_half_offset_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
+ Vector<Point2> _get_half_offset_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
+ Vector<Point2> _get_half_offset_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
+
protected:
static void _bind_methods();
@@ -257,8 +277,6 @@ public:
TileOffsetAxis get_tile_offset_axis() const;
void set_tile_size(Size2i p_size);
Size2i get_tile_size() const;
- void set_tile_skew(Vector2 p_skew);
- Vector2 get_tile_skew() const;
// -- Sources management --
int get_next_source_id() const;
@@ -305,6 +323,7 @@ public:
String get_terrain_name(int p_terrain_set, int p_terrain_index) const;
void set_terrain_color(int p_terrain_set, int p_terrain_index, Color p_color);
Color get_terrain_color(int p_terrain_set, int p_terrain_index) const;
+ bool is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const;
bool is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const;
// Navigation
@@ -323,8 +342,14 @@ public:
Variant::Type get_custom_data_type(int p_layer_id) const;
// Helpers
+ Vector<Vector2> get_tile_shape_polygon();
void draw_tile_shape(CanvasItem *p_canvas_item, Rect2 p_region, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
+ Vector<Point2> get_terrain_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit);
+ void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, const TileData *p_tile_data);
+ Vector<Vector<Ref<Texture2D>>> generate_terrains_icons(Size2i p_size);
+
+ // Resource management
virtual void reset_state() override;
TileSet();
@@ -509,13 +534,14 @@ private:
// Physics
struct PhysicsLayerTileData {
- struct ShapeTileData {
- Ref<Shape2D> shape = Ref<Shape2D>();
+ struct PolygonShapeTileData {
+ LocalVector<Vector2> polygon;
+ LocalVector<Ref<ConvexPolygonShape2D>> shapes;
bool one_way = false;
float one_way_margin = 1.0;
};
- Vector<ShapeTileData> shapes;
+ Vector<PolygonShapeTileData> polygons;
};
Vector<PhysicsLayerTileData> physics;
// TODO add support for areas.
@@ -570,16 +596,18 @@ public:
Ref<OccluderPolygon2D> get_occluder(int p_layer_id) const;
// Physics
- int get_collision_shapes_count(int p_layer_id) const;
- void set_collision_shapes_count(int p_layer_id, int p_shapes_count);
- void add_collision_shape(int p_layer_id);
- void remove_collision_shape(int p_layer_id, int p_shape_index);
- void set_collision_shape_shape(int p_layer_id, int p_shape_index, Ref<Shape2D> p_shape);
- Ref<Shape2D> get_collision_shape_shape(int p_layer_id, int p_shape_index) const;
- void set_collision_shape_one_way(int p_layer_id, int p_shape_index, bool p_one_way);
- bool is_collision_shape_one_way(int p_layer_id, int p_shape_index) const;
- void set_collision_shape_one_way_margin(int p_layer_id, int p_shape_index, float p_one_way_margin);
- float get_collision_shape_one_way_margin(int p_layer_id, int p_shape_index) const;
+ int get_collision_polygons_count(int p_layer_id) const;
+ void set_collision_polygons_count(int p_layer_id, int p_shapes_count);
+ void add_collision_polygon(int p_layer_id);
+ void remove_collision_polygon(int p_layer_id, int p_polygon_index);
+ void set_collision_polygon_points(int p_layer_id, int p_polygon_index, Vector<Vector2> p_polygon);
+ Vector<Vector2> get_collision_polygon_points(int p_layer_id, int p_polygon_index) const;
+ void set_collision_polygon_one_way(int p_layer_id, int p_polygon_index, bool p_one_way);
+ bool is_collision_polygon_one_way(int p_layer_id, int p_polygon_index) const;
+ void set_collision_polygon_one_way_margin(int p_layer_id, int p_polygon_index, float p_one_way_margin);
+ float get_collision_polygon_one_way_margin(int p_layer_id, int p_polygon_index) const;
+ int get_collision_polygon_shapes_count(int p_layer_id, int p_polygon_index) const;
+ Ref<ConvexPolygonShape2D> get_collision_polygon_shape(int p_layer_id, int p_polygon_index, int shape_index) const;
// Terrain
void set_terrain_set(int p_terrain_id);
@@ -637,26 +665,6 @@ public:
static void draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0));
};
-class TileSetPluginAtlasTerrain : public TileSetPlugin {
- GDCLASS(TileSetPluginAtlasTerrain, TileSetPlugin);
-
-private:
- static void _draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
- static void _draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
- static void _draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
-
- static void _draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
- static void _draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
- static void _draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
-
- static void _draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
- static void _draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
- static void _draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
-
-public:
- static void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data);
-};
-
class TileSetPluginAtlasPhysics : public TileSetPlugin {
GDCLASS(TileSetPluginAtlasPhysics, TileSetPlugin);
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 774c1a5c33..0f6412e6e9 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -352,14 +352,14 @@ String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader::
for (int i = 0; i < get_output_port_count(); i++) {
output_vars.push_back(p_output_vars[i]);
}
- String code = "\t{\n";
+ String code = " {\n";
String _code = (String)get_script_instance()->call("_get_code", input_vars, output_vars, (int)p_mode, (int)p_type);
bool nend = _code.ends_with("\n");
- _code = _code.insert(0, "\t\t");
- _code = _code.replace("\n", "\n\t\t");
+ _code = _code.insert(0, " ");
+ _code = _code.replace("\n", "\n ");
code += _code;
if (!nend) {
- code += "\n\t}";
+ code += "\n }";
} else {
code.remove(code.size() - 1);
code += "}";
@@ -900,7 +900,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
String expr = "";
expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n";
expr += global_expression->generate_global(get_mode(), Type(i), -1);
- expr = expr.replace("\n", "\n\t");
+ expr = expr.replace("\n", "\n ");
expr += "\n";
global_expressions += expr;
}
@@ -935,13 +935,13 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
ERR_FAIL_COND_V(err != OK, String());
if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR) {
- code += "\tCOLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " );\n";
+ code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " );\n";
} else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR_INT) {
- code += "\tCOLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n";
+ code += " COLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n";
} else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_BOOLEAN) {
- code += "\tCOLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n";
+ code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n";
} else {
- code += "\tCOLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n";
+ code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n";
}
code += "}\n";
@@ -1302,7 +1302,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (vsnode->is_disabled()) {
code += "// " + vsnode->get_caption() + ":" + itos(node) + "\n";
- code += "\t// Node is disabled and code is not generated.\n";
+ code += " // Node is disabled and code is not generated.\n";
return OK;
}
@@ -1432,19 +1432,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (defval.get_type() == Variant::FLOAT) {
float val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- node_code += "\tfloat " + inputs[i] + " = " + vformat("%.5f", val) + ";\n";
+ node_code += " float " + inputs[i] + " = " + vformat("%.5f", val) + ";\n";
} else if (defval.get_type() == Variant::INT) {
int val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- node_code += "\tint " + inputs[i] + " = " + itos(val) + ";\n";
+ node_code += " int " + inputs[i] + " = " + itos(val) + ";\n";
} else if (defval.get_type() == Variant::BOOL) {
bool val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- node_code += "\tbool " + inputs[i] + " = " + (val ? "true" : "false") + ";\n";
+ node_code += " bool " + inputs[i] + " = " + (val ? "true" : "false") + ";\n";
} else if (defval.get_type() == Variant::VECTOR3) {
Vector3 val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
- node_code += "\tvec3 " + inputs[i] + " = " + vformat("vec3(%.5f, %.5f, %.5f);\n", val.x, val.y, val.z);
+ node_code += " vec3 " + inputs[i] + " = " + vformat("vec3(%.5f, %.5f, %.5f);\n", val.x, val.y, val.z);
} else if (defval.get_type() == Variant::TRANSFORM3D) {
Transform3D val = defval;
val.basis.transpose();
@@ -1459,7 +1459,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
values.push_back(val.origin.y);
values.push_back(val.origin.z);
bool err = false;
- node_code += "\tmat4 " + inputs[i] + " = " + String("mat4(vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 1.0));\n").sprintf(values, &err);
+ node_code += " mat4 " + inputs[i] + " = " + String("mat4(vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 1.0));\n").sprintf(values, &err);
} else {
//will go empty, node is expected to know what it is doing at this point and handle it
}
@@ -1522,19 +1522,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
outputs[i] = "n_out" + itos(node) + "p" + itos(j);
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_SCALAR:
- code += "\tfloat " + outputs[i] + ";\n";
+ code += " float " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
- code += "\tint " + outputs[i] + ";\n";
+ code += " int " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_VECTOR:
- code += "\tvec3 " + outputs[i] + ";\n";
+ code += " vec3 " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
- code += "\tbool " + outputs[i] + ";\n";
+ code += " bool " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_TRANSFORM:
- code += "\tmat4 " + outputs[i] + ";\n";
+ code += " mat4 " + outputs[i] + ";\n";
break;
default: {
}
@@ -1564,7 +1564,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
new_line_inserted = true;
}
String r = "n_out" + itos(node) + "p" + itos(i + 1);
- code += "\tfloat " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
+ code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
outputs[i + 1] = r;
}
@@ -1574,7 +1574,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
new_line_inserted = true;
}
String g = "n_out" + itos(node) + "p" + itos(i + 2);
- code += "\tfloat " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
+ code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
outputs[i + 2] = g;
}
@@ -1584,7 +1584,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
new_line_inserted = true;
}
String b = "n_out" + itos(node) + "p" + itos(i + 3);
- code += "\tfloat " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
+ code += " float " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
outputs[i + 3] = b;
}
@@ -1701,7 +1701,7 @@ void VisualShader::_update_shader() const {
String expr = "";
expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n";
expr += global_expression->generate_global(get_mode(), Type(i), -1);
- expr = expr.replace("\n", "\n\t");
+ expr = expr.replace("\n", "\n ");
expr += "\n";
global_expressions += expr;
}
@@ -1752,6 +1752,11 @@ void VisualShader::_update_shader() const {
StringBuilder func_code;
+ bool is_empty_func = false;
+ if (shader_mode != Shader::MODE_PARTICLES && shader_mode != Shader::MODE_SKY) {
+ is_empty_func = true;
+ }
+
for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) {
ConnectionKey from_key;
from_key.node = E->get().from_node;
@@ -1764,7 +1769,16 @@ void VisualShader::_update_shader() const {
to_key.port = E->get().to_port;
input_connections.insert(to_key, E);
+
+ if (is_empty_func && to_key.node == NODE_ID_OUTPUT) {
+ is_empty_func = false;
+ }
}
+
+ if (is_empty_func) {
+ continue;
+ }
+
if (shader_mode != Shader::MODE_PARTICLES) {
func_code += "\nvoid " + String(func_name[i]) + "() {\n";
}
@@ -1800,112 +1814,112 @@ void VisualShader::_update_shader() const {
code += "void start() {\n";
if (has_start || has_start_custom) {
- code += "\tuint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
- code += "\tvec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
- code += "\tfloat __radians;\n";
- code += "\tvec3 __vec3_buff1;\n";
- code += "\tvec3 __vec3_buff2;\n";
- code += "\tfloat __scalar_buff1;\n";
- code += "\tfloat __scalar_buff2;\n";
- code += "\tvec3 __ndiff = normalize(__diff);\n\n";
+ code += " uint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
+ code += " vec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
+ code += " float __radians;\n";
+ code += " vec3 __vec3_buff1;\n";
+ code += " vec3 __vec3_buff2;\n";
+ code += " float __scalar_buff1;\n";
+ code += " float __scalar_buff2;\n";
+ code += " vec3 __ndiff = normalize(__diff);\n\n";
}
if (has_start) {
- code += "\t{\n";
- code += code_map[TYPE_START].replace("\n\t", "\n\t\t");
- code += "\t}\n";
+ code += " {\n";
+ code += code_map[TYPE_START].replace("\n ", "\n ");
+ code += " }\n";
if (has_start_custom) {
- code += "\t\n";
+ code += " \n";
}
}
if (has_start_custom) {
- code += "\t{\n";
- code += code_map[TYPE_START_CUSTOM].replace("\n\t", "\n\t\t");
- code += "\t}\n";
+ code += " {\n";
+ code += code_map[TYPE_START_CUSTOM].replace("\n ", "\n ");
+ code += " }\n";
}
code += "}\n\n";
code += "void process() {\n";
if (has_process || has_process_custom || has_collide) {
- code += "\tuint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
- code += "\tvec3 __vec3_buff1;\n";
- code += "\tvec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
- code += "\tvec3 __ndiff = normalize(__diff);\n\n";
+ code += " uint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
+ code += " vec3 __vec3_buff1;\n";
+ code += " vec3 __diff = TRANSFORM[3].xyz - EMISSION_TRANSFORM[3].xyz;\n";
+ code += " vec3 __ndiff = normalize(__diff);\n\n";
}
- code += "\t{\n";
- String tab = "\t";
+ code += " {\n";
+ String tab = " ";
if (has_collide) {
- code += "\t\tif (COLLIDED) {\n\n";
- code += code_map[TYPE_COLLIDE].replace("\n\t", "\n\t\t\t");
+ code += " if (COLLIDED) {\n\n";
+ code += code_map[TYPE_COLLIDE].replace("\n ", "\n ");
if (has_process) {
- code += "\t\t} else {\n\n";
- tab += "\t";
+ code += " } else {\n\n";
+ tab += " ";
}
}
if (has_process) {
- code += code_map[TYPE_PROCESS].replace("\n\t", "\n\t" + tab);
+ code += code_map[TYPE_PROCESS].replace("\n ", "\n " + tab);
}
if (has_collide) {
- code += "\t\t}\n";
+ code += " }\n";
}
- code += "\t}\n";
+ code += " }\n";
if (has_process_custom) {
- code += "\t{\n\n";
- code += code_map[TYPE_PROCESS_CUSTOM].replace("\n\t", "\n\t\t");
- code += "\t}\n";
+ code += " {\n\n";
+ code += code_map[TYPE_PROCESS_CUSTOM].replace("\n ", "\n ");
+ code += " }\n";
}
code += "}\n\n";
global_compute_code += "float __rand_from_seed(inout uint seed) {\n";
- global_compute_code += "\tint k;\n";
- global_compute_code += "\tint s = int(seed);\n";
- global_compute_code += "\tif (s == 0)\n";
- global_compute_code += "\ts = 305420679;\n";
- global_compute_code += "\tk = s / 127773;\n";
- global_compute_code += "\ts = 16807 * (s - k * 127773) - 2836 * k;\n";
- global_compute_code += "\tif (s < 0)\n";
- global_compute_code += "\t\ts += 2147483647;\n";
- global_compute_code += "\tseed = uint(s);\n";
- global_compute_code += "\treturn float(seed % uint(65536)) / 65535.0;\n";
+ global_compute_code += " int k;\n";
+ global_compute_code += " int s = int(seed);\n";
+ global_compute_code += " if (s == 0)\n";
+ global_compute_code += " s = 305420679;\n";
+ global_compute_code += " k = s / 127773;\n";
+ global_compute_code += " s = 16807 * (s - k * 127773) - 2836 * k;\n";
+ global_compute_code += " if (s < 0)\n";
+ global_compute_code += " s += 2147483647;\n";
+ global_compute_code += " seed = uint(s);\n";
+ global_compute_code += " return float(seed % uint(65536)) / 65535.0;\n";
global_compute_code += "}\n\n";
global_compute_code += "float __rand_from_seed_m1_p1(inout uint seed) {\n";
- global_compute_code += "\treturn __rand_from_seed(seed) * 2.0 - 1.0;\n";
+ global_compute_code += " return __rand_from_seed(seed) * 2.0 - 1.0;\n";
global_compute_code += "}\n\n";
global_compute_code += "float __randf_range(inout uint seed, float from, float to) {\n";
- global_compute_code += "\treturn __rand_from_seed(seed) * (to - from) + from;\n";
+ global_compute_code += " return __rand_from_seed(seed) * (to - from) + from;\n";
global_compute_code += "}\n\n";
global_compute_code += "vec3 __randv_range(inout uint seed, vec3 from, vec3 to) {\n";
- global_compute_code += "\treturn vec3(__randf_range(seed, from.x, to.x), __randf_range(seed, from.y, to.y), __randf_range(seed, from.z, to.z));\n";
+ global_compute_code += " return vec3(__randf_range(seed, from.x, to.x), __randf_range(seed, from.y, to.y), __randf_range(seed, from.z, to.z));\n";
global_compute_code += "}\n\n";
global_compute_code += "uint __hash(uint x) {\n";
- global_compute_code += "\tx = ((x >> uint(16)) ^ x) * uint(73244475);\n";
- global_compute_code += "\tx = ((x >> uint(16)) ^ x) * uint(73244475);\n";
- global_compute_code += "\tx = (x >> uint(16)) ^ x;\n";
- global_compute_code += "\treturn x;\n";
+ global_compute_code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
+ global_compute_code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
+ global_compute_code += " x = (x >> uint(16)) ^ x;\n";
+ global_compute_code += " return x;\n";
global_compute_code += "}\n\n";
global_compute_code += "mat3 __build_rotation_mat3(vec3 axis, float angle) {\n";
- global_compute_code += "\taxis = normalize(axis);\n";
- global_compute_code += "\tfloat s = sin(angle);\n";
- global_compute_code += "\tfloat c = cos(angle);\n";
- global_compute_code += "\tfloat oc = 1.0 - c;\n";
- global_compute_code += "\treturn mat3(vec3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s), vec3(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s), vec3(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c));\n";
+ global_compute_code += " axis = normalize(axis);\n";
+ global_compute_code += " float s = sin(angle);\n";
+ global_compute_code += " float c = cos(angle);\n";
+ global_compute_code += " float oc = 1.0 - c;\n";
+ global_compute_code += " return mat3(vec3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s), vec3(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s), vec3(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c));\n";
global_compute_code += "}\n\n";
global_compute_code += "mat4 __build_rotation_mat4(vec3 axis, float angle) {\n";
- global_compute_code += "\taxis = normalize(axis);\n";
- global_compute_code += "\tfloat s = sin(angle);\n";
- global_compute_code += "\tfloat c = cos(angle);\n";
- global_compute_code += "\tfloat oc = 1.0 - c;\n";
- global_compute_code += "\treturn mat4(vec4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0), vec4(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0), vec4(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0), vec4(0, 0, 0, 1));\n";
+ global_compute_code += " axis = normalize(axis);\n";
+ global_compute_code += " float s = sin(angle);\n";
+ global_compute_code += " float c = cos(angle);\n";
+ global_compute_code += " float oc = 1.0 - c;\n";
+ global_compute_code += " return mat4(vec4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0), vec4(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0), vec4(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0), vec4(0, 0, 0, 1));\n";
global_compute_code += "}\n\n";
global_compute_code += "vec3 __get_random_unit_vec3(inout uint seed) {\n";
- global_compute_code += "\treturn normalize(vec3(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n";
+ global_compute_code += " return normalize(vec3(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n";
global_compute_code += "}\n\n";
}
@@ -1929,7 +1943,7 @@ void VisualShader::_update_shader() const {
const_cast<VisualShader *>(this)->set_default_texture_param(default_tex_params[i].name, default_tex_params[i].param);
}
if (previous_code != final_code) {
- const_cast<VisualShader *>(this)->emit_signal("changed");
+ const_cast<VisualShader *>(this)->emit_signal(SNAME("changed"));
}
previous_code = final_code;
}
@@ -1940,7 +1954,7 @@ void VisualShader::_queue_update() {
}
dirty.set();
- call_deferred("_update_shader");
+ call_deferred(SNAME("_update_shader"));
}
void VisualShader::_input_type_changed(Type p_type, int p_id) {
@@ -2366,7 +2380,7 @@ String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::T
while (preview_ports[idx].mode != Shader::MODE_MAX) {
if (preview_ports[idx].mode == shader_mode && preview_ports[idx].shader_type == shader_type && preview_ports[idx].name == input_name) {
- code = "\t" + p_output_vars[0] + " = " + preview_ports[idx].string + ";\n";
+ code = " " + p_output_vars[0] + " = " + preview_ports[idx].string + ";\n";
break;
}
idx++;
@@ -2375,19 +2389,19 @@ String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::T
if (code == String()) {
switch (get_output_port_type(0)) {
case PORT_TYPE_SCALAR: {
- code = "\t" + p_output_vars[0] + " = 0.0;\n";
+ code = " " + p_output_vars[0] + " = 0.0;\n";
} break;
case PORT_TYPE_SCALAR_INT: {
- code = "\t" + p_output_vars[0] + " = 0;\n";
+ code = " " + p_output_vars[0] + " = 0;\n";
} break;
case PORT_TYPE_VECTOR: {
- code = "\t" + p_output_vars[0] + " = vec3(0.0);\n";
+ code = " " + p_output_vars[0] + " = vec3(0.0);\n";
} break;
case PORT_TYPE_TRANSFORM: {
- code = "\t" + p_output_vars[0] + " = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code = " " + p_output_vars[0] + " = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
} break;
case PORT_TYPE_BOOLEAN: {
- code = "\t" + p_output_vars[0] + " = false;\n";
+ code = " " + p_output_vars[0] + " = false;\n";
} break;
default: //default (none found) is scalar
break;
@@ -2403,14 +2417,14 @@ String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::T
while (ports[idx].mode != Shader::MODE_MAX) {
if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type && ports[idx].name == input_name) {
- code = "\t" + p_output_vars[0] + " = " + ports[idx].string + ";\n";
+ code = " " + p_output_vars[0] + " = " + ports[idx].string + ";\n";
break;
}
idx++;
}
if (code == String()) {
- code = "\t" + p_output_vars[0] + " = 0.0;\n"; //default (none found) is scalar
+ code = " " + p_output_vars[0] + " = 0.0;\n"; //default (none found) is scalar
}
return code;
@@ -2422,7 +2436,7 @@ void VisualShaderNodeInput::set_input_name(String p_name) {
input_name = p_name;
emit_changed();
if (get_input_type_by_name(input_name) != prev_type) {
- emit_signal("input_type_changed");
+ emit_signal(SNAME("input_type_changed"));
}
}
@@ -2533,6 +2547,14 @@ Vector<StringName> VisualShaderNodeInput::get_editable_properties() const {
return props;
}
+void VisualShaderNodeInput::set_shader_type(VisualShader::Type p_shader_type) {
+ shader_type = p_shader_type;
+}
+
+void VisualShaderNodeInput::set_shader_mode(Shader::Mode p_shader_mode) {
+ shader_mode = p_shader_mode;
+}
+
void VisualShaderNodeInput::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_input_name", "name"), &VisualShaderNodeInput::set_input_name);
ClassDB::bind_method(D_METHOD("get_input_name"), &VisualShaderNodeInput::get_input_name);
@@ -2700,24 +2722,46 @@ VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_
return UniformType::UNIFORM_TYPE_FLOAT;
}
+VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < uniforms.size()) {
+ switch (uniforms[p_idx].type) {
+ case UniformType::UNIFORM_TYPE_FLOAT:
+ return PORT_TYPE_SCALAR;
+ case UniformType::UNIFORM_TYPE_INT:
+ return PORT_TYPE_SCALAR_INT;
+ case UniformType::UNIFORM_TYPE_SAMPLER:
+ return PORT_TYPE_SAMPLER;
+ case UniformType::UNIFORM_TYPE_VECTOR:
+ return PORT_TYPE_VECTOR;
+ case UniformType::UNIFORM_TYPE_TRANSFORM:
+ return PORT_TYPE_TRANSFORM;
+ case UniformType::UNIFORM_TYPE_COLOR:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
+ }
+ }
+ return PORT_TYPE_SCALAR;
+}
+
String VisualShaderNodeUniformRef::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 {
switch (uniform_type) {
case UniformType::UNIFORM_TYPE_FLOAT:
if (uniform_name == "[None]") {
- return "\t" + p_output_vars[0] + " = 0.0;\n";
+ return " " + p_output_vars[0] + " = 0.0;\n";
}
- return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
case UniformType::UNIFORM_TYPE_INT:
- return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
case UniformType::UNIFORM_TYPE_BOOLEAN:
- return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
case UniformType::UNIFORM_TYPE_VECTOR:
- return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
case UniformType::UNIFORM_TYPE_TRANSFORM:
- return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
case UniformType::UNIFORM_TYPE_COLOR: {
- String code = "\t" + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n";
- code += "\t" + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n";
+ String code = " " + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n";
+ code += " " + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n";
return code;
} break;
case UniformType::UNIFORM_TYPE_SAMPLER:
@@ -2913,9 +2957,9 @@ String VisualShaderNodeOutput::generate_code(Shader::Mode p_mode, VisualShader::
if (p_input_vars[count] != String()) {
String s = ports[idx].string;
if (s.find(":") != -1) {
- code += "\t" + s.get_slicec(':', 0) + " = " + p_input_vars[count] + "." + s.get_slicec(':', 1) + ";\n";
+ code += " " + s.get_slicec(':', 0) + " = " + p_input_vars[count] + "." + s.get_slicec(':', 1) + ";\n";
} else {
- code += "\t" + s + " = " + p_input_vars[count] + ";\n";
+ code += " " + s + " = " + p_input_vars[count] + ";\n";
}
}
count++;
@@ -2933,7 +2977,7 @@ VisualShaderNodeOutput::VisualShaderNodeOutput() {
void VisualShaderNodeUniform::set_uniform_name(const String &p_name) {
uniform_name = p_name;
- emit_signal("name_changed");
+ emit_signal(SNAME("name_changed"));
emit_changed();
}
@@ -3590,11 +3634,11 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad
String _expression = expression;
_expression = _expression.insert(0, "\n");
- _expression = _expression.replace("\n", "\n\t\t");
+ _expression = _expression.replace("\n", "\n ");
static Vector<String> pre_symbols;
if (pre_symbols.is_empty()) {
- pre_symbols.push_back("\t");
+ pre_symbols.push_back(" ");
pre_symbols.push_back(",");
pre_symbols.push_back(";");
pre_symbols.push_back("{");
@@ -3614,7 +3658,7 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad
static Vector<String> post_symbols;
if (post_symbols.is_empty()) {
- post_symbols.push_back("\t");
+ post_symbols.push_back(" ");
post_symbols.push_back("\n");
post_symbols.push_back(",");
post_symbols.push_back(";");
@@ -3673,14 +3717,14 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad
default:
continue;
}
- output_initializer += "\t" + p_output_vars[i] + " = " + tk + ";\n";
+ output_initializer += " " + p_output_vars[i] + " = " + tk + ";\n";
}
String code;
code += output_initializer;
- code += "\t{";
+ code += " {";
code += _expression;
- code += "\n\t}\n";
+ code += "\n }\n";
return code;
}
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 53b165fe0f..880c401b29 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -350,6 +350,10 @@ class VisualShaderNodeInput : public VisualShaderNode {
String input_name = "[None]";
+public:
+ void set_shader_type(VisualShader::Type p_shader_type);
+ void set_shader_mode(Shader::Mode p_shader_mode);
+
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &property) const override;
@@ -513,6 +517,7 @@ public:
String get_uniform_name_by_index(int p_idx) const;
UniformType get_uniform_type_by_name(const String &p_name) const;
UniformType get_uniform_type_by_index(int p_idx) const;
+ PortType get_port_type_by_index(int p_idx) const;
virtual Vector<StringName> get_editable_properties() const override;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index d3b094de31..6fd6fd8f3b 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -66,7 +66,7 @@ String VisualShaderNodeFloatConstant::get_output_port_name(int p_port) const {
}
String VisualShaderNodeFloatConstant::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 "\t" + p_output_vars[0] + " = " + vformat("%.6f", constant) + ";\n";
+ return " " + p_output_vars[0] + " = " + vformat("%.6f", constant) + ";\n";
}
void VisualShaderNodeFloatConstant::set_constant(float p_value) {
@@ -125,7 +125,7 @@ String VisualShaderNodeIntConstant::get_output_port_name(int p_port) const {
}
String VisualShaderNodeIntConstant::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 "\t" + p_output_vars[0] + " = " + itos(constant) + ";\n";
+ return " " + p_output_vars[0] + " = " + itos(constant) + ";\n";
}
void VisualShaderNodeIntConstant::set_constant(int p_value) {
@@ -184,7 +184,7 @@ String VisualShaderNodeBooleanConstant::get_output_port_name(int p_port) const {
}
String VisualShaderNodeBooleanConstant::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 "\t" + p_output_vars[0] + " = " + (constant ? "true" : "false") + ";\n";
+ return " " + p_output_vars[0] + " = " + (constant ? "true" : "false") + ";\n";
}
void VisualShaderNodeBooleanConstant::set_constant(bool p_value) {
@@ -251,8 +251,8 @@ 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 += "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n";
- code += "\t" + p_output_vars[1] + " = " + vformat("%.6f", constant.a) + ";\n";
+ 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;
}
@@ -313,7 +313,7 @@ String VisualShaderNodeVec3Constant::get_output_port_name(int p_port) const {
}
String VisualShaderNodeVec3Constant::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 "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.x, constant.y, constant.z) + ";\n";
+ return " " + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.x, constant.y, constant.z) + ";\n";
}
void VisualShaderNodeVec3Constant::set_constant(Vector3 p_value) {
@@ -375,7 +375,7 @@ String VisualShaderNodeTransformConstant::generate_code(Shader::Mode p_mode, Vis
Transform3D t = constant;
t.basis.transpose();
- String code = "\t" + p_output_vars[0] + " = mat4(";
+ String code = " " + p_output_vars[0] + " = mat4(";
code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[0].x, t.basis[0].y, t.basis[0].z);
code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[1].x, t.basis[1].y, t.basis[1].z);
code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[2].x, t.basis[2].y, t.basis[2].z);
@@ -523,20 +523,20 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\tvec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += "\tvec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\tvec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
} else {
- code += "\tvec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
- code += "\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n";
- code += "\t" + p_output_vars[1] + " = " + id + "_read.a;\n";
+ code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n";
+ code += " " + p_output_vars[1] + " = " + id + "_read.a;\n";
return code;
}
@@ -544,98 +544,98 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
String id = p_input_vars[2];
String code;
- code += "\t{\n";
+ code += " {\n";
if (id == String()) {
- code += "\t\tvec4 " + id + "_tex_read = vec4(0.0);\n";
+ code += " vec4 " + id + "_tex_read = vec4(0.0);\n";
} else {
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
} else {
- code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
- code += "\t\t" + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = " + id + "_tex_read.a;\n";
+ code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n";
+ code += " " + p_output_vars[1] + " = " + id + "_tex_read.a;\n";
}
- code += "\t}\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 = "\t{\n";
+ String code = " {\n";
if (p_input_vars[0] == String() || p_for_preview) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0 );\n";
+ code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0 );\n";
} else {
- code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, 0.0);\n";
+ code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, 0.0);\n";
} else {
- code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
- code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = _tex_read.a;\n";
- code += "\t}\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 = "\t{\n";
+ String code = " {\n";
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tvec4 _tex_read = texture(TEXTURE, " + default_uv + ");\n";
+ code += " vec4 _tex_read = texture(TEXTURE, " + default_uv + ");\n";
} else {
- code += "\t\tvec4 _tex_read = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tvec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ".xy);\n";
} else {
- code += "\t\tvec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
- code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = _tex_read.a;\n";
- code += "\t}\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 = "\t{\n";
+ String code = " {\n";
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tvec4 _tex_read = texture(NORMAL_TEXTURE, " + default_uv + ");\n";
+ code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + default_uv + ");\n";
} else {
- code += "\t\tvec4 _tex_read = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tvec4 _tex_read = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n";
} else {
- code += "\t\tvec4 _tex_read = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
- code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = _tex_read.a;\n";
- code += "\t}\n";
+ code += " " + p_output_vars[0] + " = _tex_read.rgb;\n";
+ code += " " + p_output_vars[1] + " = _tex_read.a;\n";
+ code += " }\n";
return code;
}
@@ -643,44 +643,44 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
{
if (source == SOURCE_DEPTH) {
String code;
- code += "\t" + p_output_vars[0] + " = 0.0;\n";
- code += "\t" + p_output_vars[1] + " = 1.0;\n";
+ 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 = "\t{\n";
+ String code = " {\n";
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tfloat _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n";
+ code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n";
} else {
- code += "\t\tfloat _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n";
+ code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tfloat _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n";
+ code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n";
} else {
- code += "\t\tfloat _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n";
+ code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n";
}
- code += "\t\t" + p_output_vars[0] + " = _depth;\n";
- code += "\t\t" + p_output_vars[1] + " = 1.0;\n";
- code += "\t}\n";
+ 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 += "\t" + p_output_vars[0] + " = 0.0;\n";
- code += "\t" + p_output_vars[1] + " = 1.0;\n";
+ code += " " + p_output_vars[0] + " = 0.0;\n";
+ code += " " + p_output_vars[1] + " = 1.0;\n";
return code;
}
//none
String code;
- code += "\t" + p_output_vars[0] + " = vec3(0.0);\n";
- code += "\t" + p_output_vars[1] + " = 1.0;\n";
+ code += " " + p_output_vars[0] + " = vec3(0.0);\n";
+ code += " " + p_output_vars[1] + " = 1.0;\n";
return code;
}
@@ -707,7 +707,7 @@ void VisualShaderNodeTexture::set_source(Source p_source) {
break;
}
emit_changed();
- emit_signal("editor_refresh_request");
+ emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeTexture::Source VisualShaderNodeTexture::get_source() const {
@@ -805,7 +805,7 @@ void VisualShaderNodeTexture::_bind_methods() {
VisualShaderNodeTexture::VisualShaderNodeTexture() {
}
-////////////// Curve
+////////////// CurveTexture
String VisualShaderNodeCurveTexture::get_caption() const {
return "CurveTexture";
@@ -856,11 +856,11 @@ String VisualShaderNodeCurveTexture::generate_global(Shader::Mode p_mode, Visual
String VisualShaderNodeCurveTexture::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 (p_input_vars[0] == String()) {
- return "\t" + p_output_vars[0] + " = 0.0;\n";
+ return " " + p_output_vars[0] + " = 0.0;\n";
}
String id = make_unique_id(p_type, p_id, "curve");
String code;
- code += "\t" + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ")).r;\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ")).r;\n";
return code;
}
@@ -889,6 +889,90 @@ VisualShaderNodeCurveTexture::VisualShaderNodeCurveTexture() {
allow_v_resize = false;
}
+////////////// CurveXYZTexture
+
+String VisualShaderNodeCurveXYZTexture::get_caption() const {
+ return "CurveXYZTexture";
+}
+
+int VisualShaderNodeCurveXYZTexture::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeCurveXYZTexture::PortType VisualShaderNodeCurveXYZTexture::get_input_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeCurveXYZTexture::get_input_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeCurveXYZTexture::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeCurveXYZTexture::PortType VisualShaderNodeCurveXYZTexture::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeCurveXYZTexture::get_output_port_name(int p_port) const {
+ return String();
+}
+
+void VisualShaderNodeCurveXYZTexture::set_texture(Ref<CurveXYZTexture> p_texture) {
+ texture = p_texture;
+ emit_changed();
+}
+
+Ref<CurveXYZTexture> VisualShaderNodeCurveXYZTexture::get_texture() const {
+ return texture;
+}
+
+Vector<StringName> VisualShaderNodeCurveXYZTexture::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("texture");
+ return props;
+}
+
+String VisualShaderNodeCurveXYZTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return "uniform sampler2D " + make_unique_id(p_type, p_id, "curve3d") + ";\n";
+}
+
+String VisualShaderNodeCurveXYZTexture::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 (p_input_vars[0] == String()) {
+ return " " + p_output_vars[0] + " = vec3(0.0);\n";
+ }
+ String id = make_unique_id(p_type, p_id, "curve3d");
+ String code;
+ code += " " + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ")).rgb;\n";
+ return code;
+}
+
+Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurveXYZTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
+ VisualShader::DefaultTextureParam dtp;
+ dtp.name = make_unique_id(p_type, p_id, "curve3d");
+ dtp.param = texture;
+ Vector<VisualShader::DefaultTextureParam> ret;
+ ret.push_back(dtp);
+ return ret;
+}
+
+void VisualShaderNodeCurveXYZTexture::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_texture", "texture"), &VisualShaderNodeCurveXYZTexture::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeCurveXYZTexture::get_texture);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "CurveXYZTexture"), "set_texture", "get_texture");
+}
+
+bool VisualShaderNodeCurveXYZTexture::is_use_prop_slots() const {
+ return true;
+}
+
+VisualShaderNodeCurveXYZTexture::VisualShaderNodeCurveXYZTexture() {
+ simple_decl = true;
+ allow_v_resize = false;
+}
+
////////////// Sample3D
int VisualShaderNodeSample3D::get_input_port_count() const {
@@ -956,7 +1040,7 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader
String code;
if (source == SOURCE_TEXTURE || source == SOURCE_PORT) {
String id;
- code += "\t{\n";
+ code += " {\n";
if (source == SOURCE_TEXTURE) {
id = make_unique_id(p_type, p_id, "tex3d");
} else {
@@ -965,34 +1049,34 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader
if (id != String()) {
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
+ code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
} else {
- code += "\t\tvec4 " + id + "_tex_read = vec4(0.0);\n";
+ code += " vec4 " + id + "_tex_read = vec4(0.0);\n";
}
- code += "\t\t" + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = " + id + "_tex_read.a;\n";
- code += "\t}\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 += "\t" + p_output_vars[0] + " = vec3(0.0);\n";
- code += "\t" + p_output_vars[1] + " = 1.0;\n";
+ code += " " + p_output_vars[0] + " = vec3(0.0);\n";
+ code += " " + p_output_vars[1] + " = 1.0;\n";
return code;
}
void VisualShaderNodeSample3D::set_source(Source p_source) {
source = p_source;
emit_changed();
- emit_signal("editor_refresh_request");
+ emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeSample3D::Source VisualShaderNodeSample3D::get_source() const {
@@ -1241,33 +1325,33 @@ String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader:
return String();
}
- code += "\t{\n";
+ code += " {\n";
if (id == String()) {
- code += "\t\tvec4 " + id + "_read = vec4(0.0);\n";
- code += "\t\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = " + id + "_read.a;\n";
- code += "\t}\n";
+ 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";
return code;
}
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tvec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += "\t\tvec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + " );\n";
+ code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + " );\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tvec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
+ code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += "\t\tvec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
- code += "\t\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = " + id + "_read.a;\n";
- code += "\t}\n";
+ code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n";
+ code += " " + p_output_vars[1] + " = " + id + "_read.a;\n";
+ code += " }\n";
return code;
}
@@ -1282,7 +1366,7 @@ String VisualShaderNodeCubemap::get_input_port_default_hint(int p_port) const {
void VisualShaderNodeCubemap::set_source(Source p_source) {
source = p_source;
emit_changed();
- emit_signal("editor_refresh_request");
+ emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeCubemap::Source VisualShaderNodeCubemap::get_source() const {
@@ -1381,7 +1465,7 @@ String VisualShaderNodeFloatOp::get_output_port_name(int p_port) const {
}
String VisualShaderNodeFloatOp::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 = "\t" + p_output_vars[0] + " = ";
+ String code = " " + p_output_vars[0] + " = ";
switch (op) {
case OP_ADD:
code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n";
@@ -1487,7 +1571,7 @@ String VisualShaderNodeIntOp::get_output_port_name(int p_port) const {
}
String VisualShaderNodeIntOp::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 = "\t" + p_output_vars[0] + " = ";
+ String code = " " + p_output_vars[0] + " = ";
switch (op) {
case OP_ADD:
code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n";
@@ -1581,7 +1665,7 @@ String VisualShaderNodeVectorOp::get_output_port_name(int p_port) const {
}
String VisualShaderNodeVectorOp::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 = "\t" + p_output_vars[0] + " = ";
+ String code = " " + p_output_vars[0] + " = ";
switch (op) {
case OP_ADD:
code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n";
@@ -1699,64 +1783,64 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader:
static const char *axisn[3] = { "x", "y", "z" };
switch (op) {
case OP_SCREEN: {
- code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") * (vec3(1.0) - " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") * (vec3(1.0) - " + p_input_vars[1] + ");\n";
} break;
case OP_DIFFERENCE: {
- code += "\t" + p_output_vars[0] + " = abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ");\n";
} break;
case OP_DARKEN: {
- code += "\t" + p_output_vars[0] + " = min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
} break;
case OP_LIGHTEN: {
- code += "\t" + p_output_vars[0] + " = max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
} break;
case OP_OVERLAY: {
for (int i = 0; i < 3; i++) {
- code += "\t{\n";
- code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n";
- code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n";
- code += "\t\tif (base < 0.5) {\n";
- code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = 2.0 * base * blend;\n";
- code += "\t\t} else {\n";
- code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = 1.0 - 2.0 * (1.0 - blend) * (1.0 - base);\n";
- code += "\t\t}\n";
- code += "\t}\n";
+ code += " {\n";
+ code += " float base = " + p_input_vars[0] + "." + axisn[i] + ";\n";
+ code += " float blend = " + p_input_vars[1] + "." + axisn[i] + ";\n";
+ code += " if (base < 0.5) {\n";
+ code += " " + p_output_vars[0] + "." + axisn[i] + " = 2.0 * base * blend;\n";
+ code += " } else {\n";
+ code += " " + p_output_vars[0] + "." + axisn[i] + " = 1.0 - 2.0 * (1.0 - blend) * (1.0 - base);\n";
+ code += " }\n";
+ code += " }\n";
}
} break;
case OP_DODGE: {
- code += "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + ") / (vec3(1.0) - " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = (" + p_input_vars[0] + ") / (vec3(1.0) - " + p_input_vars[1] + ");\n";
} break;
case OP_BURN: {
- code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") / (" + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") / (" + p_input_vars[1] + ");\n";
} break;
case OP_SOFT_LIGHT: {
for (int i = 0; i < 3; i++) {
- code += "\t{\n";
- code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n";
- code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n";
- code += "\t\tif (base < 0.5) {\n";
- code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (blend + 0.5));\n";
- code += "\t\t} else {\n";
- code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - (blend - 0.5)));\n";
- code += "\t\t}\n";
- code += "\t}\n";
+ code += " {\n";
+ code += " float base = " + p_input_vars[0] + "." + axisn[i] + ";\n";
+ code += " float blend = " + p_input_vars[1] + "." + axisn[i] + ";\n";
+ code += " if (base < 0.5) {\n";
+ code += " " + p_output_vars[0] + "." + axisn[i] + " = (base * (blend + 0.5));\n";
+ code += " } else {\n";
+ code += " " + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - (blend - 0.5)));\n";
+ code += " }\n";
+ code += " }\n";
}
} break;
case OP_HARD_LIGHT: {
for (int i = 0; i < 3; i++) {
- code += "\t{\n";
- code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n";
- code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n";
- code += "\t\tif (base < 0.5) {\n";
- code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (2.0 * blend));\n";
- code += "\t\t} else {\n";
- code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - 2.0 * (blend - 0.5)));\n";
- code += "\t\t}\n";
- code += "\t}\n";
+ code += " {\n";
+ code += " float base = " + p_input_vars[0] + "." + axisn[i] + ";\n";
+ code += " float blend = " + p_input_vars[1] + "." + axisn[i] + ";\n";
+ code += " if (base < 0.5) {\n";
+ code += " " + p_output_vars[0] + "." + axisn[i] + " = (base * (2.0 * blend));\n";
+ code += " } else {\n";
+ code += " " + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - 2.0 * (blend - 0.5)));\n";
+ code += " }\n";
+ code += " }\n";
}
} break;
@@ -1863,13 +1947,13 @@ String VisualShaderNodeTransformMult::get_output_port_name(int p_port) const {
String VisualShaderNodeTransformMult::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 (op == OP_AxB) {
- return "\t" + p_output_vars[0] + " = " + p_input_vars[0] + " * " + p_input_vars[1] + ";\n";
+ return " " + p_output_vars[0] + " = " + p_input_vars[0] + " * " + p_input_vars[1] + ";\n";
} else if (op == OP_BxA) {
- return "\t" + p_output_vars[0] + " = " + p_input_vars[1] + " * " + p_input_vars[0] + ";\n";
+ return " " + p_output_vars[0] + " = " + p_input_vars[1] + " * " + p_input_vars[0] + ";\n";
} else if (op == OP_AxB_COMP) {
- return "\t" + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ return " " + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
} else {
- return "\t" + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[1] + ", " + p_input_vars[0] + ");\n";
+ return " " + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[1] + ", " + p_input_vars[0] + ");\n";
}
}
@@ -1937,13 +2021,13 @@ String VisualShaderNodeTransformVecMult::get_output_port_name(int p_port) const
String VisualShaderNodeTransformVecMult::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 (op == OP_AxB) {
- return "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 1.0)).xyz;\n";
+ return " " + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 1.0)).xyz;\n";
} else if (op == OP_BxA) {
- return "\t" + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 1.0) * " + p_input_vars[0] + ").xyz;\n";
+ return " " + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 1.0) * " + p_input_vars[0] + ").xyz;\n";
} else if (op == OP_3x3_AxB) {
- return "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 0.0)).xyz;\n";
+ return " " + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 0.0)).xyz;\n";
} else {
- return "\t" + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 0.0) * " + p_input_vars[0] + ").xyz;\n";
+ return " " + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 0.0) * " + p_input_vars[0] + ").xyz;\n";
}
}
@@ -2045,7 +2129,7 @@ String VisualShaderNodeFloatFunc::generate_code(Shader::Mode p_mode, VisualShade
"1.0 - $"
};
- return "\t" + p_output_vars[0] + " = " + String(scalar_func_id[func]).replace("$", p_input_vars[0]) + ";\n";
+ return " " + p_output_vars[0] + " = " + String(scalar_func_id[func]).replace("$", p_input_vars[0]) + ";\n";
}
void VisualShaderNodeFloatFunc::set_function(Function p_func) {
@@ -2144,7 +2228,7 @@ String VisualShaderNodeIntFunc::generate_code(Shader::Mode p_mode, VisualShader:
"sign($)"
};
- return "\t" + p_output_vars[0] + " = " + String(int_func_id[func]).replace("$", p_input_vars[0]) + ";\n";
+ return " " + p_output_vars[0] + " = " + String(int_func_id[func]).replace("$", p_input_vars[0]) + ";\n";
}
void VisualShaderNodeIntFunc::set_function(Function p_func) {
@@ -2249,25 +2333,25 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
String code;
if (func == FUNC_RGB2HSV) {
- code += "\t{\n";
- code += "\t\tvec3 c = " + p_input_vars[0] + ";\n";
- code += "\t\tvec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n";
- code += "\t\tvec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n";
- code += "\t\tvec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n";
- code += "\t\tfloat d = q.x - min(q.w, q.y);\n";
- code += "\t\tfloat e = 1.0e-10;\n";
- code += "\t\t" + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n";
- code += "\t}\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";
+ code += " vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n";
+ code += " vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n";
+ code += " float d = q.x - min(q.w, q.y);\n";
+ code += " float e = 1.0e-10;\n";
+ 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) {
- code += "\t{\n";
- code += "\t\tvec3 c = " + p_input_vars[0] + ";\n";
- code += "\t\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n";
- code += "\t\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n";
- code += "\t\t" + p_output_vars[0] + " = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n";
- code += "\t}\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";
+ code += " vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n";
+ code += " " + p_output_vars[0] + " = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n";
+ code += " }\n";
} else {
- code += "\t" + p_output_vars[0] + " = " + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n";
}
return code;
@@ -2377,22 +2461,22 @@ String VisualShaderNodeColorFunc::generate_code(Shader::Mode p_mode, VisualShade
switch (func) {
case FUNC_GRAYSCALE:
- code += "\t{\n";
- code += "\t\tvec3 c = " + p_input_vars[0] + ";\n";
- code += "\t\tfloat max1 = max(c.r, c.g);\n";
- code += "\t\tfloat max2 = max(max1, c.b);\n";
- code += "\t\tfloat max3 = max(max1, max2);\n";
- code += "\t\t" + p_output_vars[0] + " = vec3(max3, max3, max3);\n";
- code += "\t}\n";
+ code += " {\n";
+ code += " vec3 c = " + p_input_vars[0] + ";\n";
+ code += " float max1 = max(c.r, c.g);\n";
+ code += " float max2 = max(max1, c.b);\n";
+ code += " float max3 = max(max1, max2);\n";
+ code += " " + p_output_vars[0] + " = vec3(max3, max3, max3);\n";
+ code += " }\n";
break;
case FUNC_SEPIA:
- code += "\t{\n";
- code += "\t\tvec3 c = " + p_input_vars[0] + ";\n";
- code += "\t\tfloat r = (c.r * .393) + (c.g *.769) + (c.b * .189);\n";
- code += "\t\tfloat g = (c.r * .349) + (c.g *.686) + (c.b * .168);\n";
- code += "\t\tfloat b = (c.r * .272) + (c.g *.534) + (c.b * .131);\n";
- code += "\t\t" + p_output_vars[0] + " = vec3(r, g, b);\n";
- code += "\t}\n";
+ code += " {\n";
+ code += " vec3 c = " + p_input_vars[0] + ";\n";
+ code += " float r = (c.r * .393) + (c.g *.769) + (c.b * .189);\n";
+ code += " float g = (c.r * .349) + (c.g *.686) + (c.b * .168);\n";
+ code += " float b = (c.r * .272) + (c.g *.534) + (c.b * .131);\n";
+ code += " " + p_output_vars[0] + " = vec3(r, g, b);\n";
+ code += " }\n";
break;
}
@@ -2466,7 +2550,7 @@ String VisualShaderNodeTransformFunc::generate_code(Shader::Mode p_mode, VisualS
};
String code;
- code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
return code;
}
@@ -2584,10 +2668,10 @@ String VisualShaderNodeUVFunc::generate_code(Shader::Mode p_mode, VisualShader::
switch (func) {
case FUNC_PANNING: {
- code += vformat("\t%s = fma(%s, %s, %s);\n", p_output_vars[0], offset_pivot, scale, uv);
+ code += vformat(" %s = fma(%s, %s, %s);\n", p_output_vars[0], offset_pivot, scale, uv);
} break;
case FUNC_SCALING: {
- code += vformat("\t%s = fma((%s - %s), %s, %s);\n", p_output_vars[0], uv, offset_pivot, scale, offset_pivot);
+ code += vformat(" %s = fma((%s - %s), %s, %s);\n", p_output_vars[0], uv, offset_pivot, scale, offset_pivot);
} break;
case FUNC_MAX:
break;
@@ -2667,7 +2751,7 @@ String VisualShaderNodeDotProduct::get_output_port_name(int p_port) const {
}
String VisualShaderNodeDotProduct::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 "\t" + p_output_vars[0] + " = dot(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ return " " + p_output_vars[0] + " = dot(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
VisualShaderNodeDotProduct::VisualShaderNodeDotProduct() {
@@ -2706,7 +2790,7 @@ String VisualShaderNodeVectorLen::get_output_port_name(int p_port) const {
}
String VisualShaderNodeVectorLen::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 "\t" + p_output_vars[0] + " = length(" + p_input_vars[0] + ");\n";
+ return " " + p_output_vars[0] + " = length(" + p_input_vars[0] + ");\n";
}
VisualShaderNodeVectorLen::VisualShaderNodeVectorLen() {
@@ -2744,7 +2828,7 @@ String VisualShaderNodeDeterminant::get_output_port_name(int p_port) const {
}
String VisualShaderNodeDeterminant::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 "\t" + p_output_vars[0] + " = determinant(" + p_input_vars[0] + ");\n";
+ return " " + p_output_vars[0] + " = determinant(" + p_input_vars[0] + ");\n";
}
VisualShaderNodeDeterminant::VisualShaderNodeDeterminant() {
@@ -2789,7 +2873,7 @@ String VisualShaderNodeScalarDerivativeFunc::generate_code(Shader::Mode p_mode,
};
String code;
- code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
return code;
}
@@ -2861,7 +2945,7 @@ String VisualShaderNodeVectorDerivativeFunc::generate_code(Shader::Mode p_mode,
};
String code;
- code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
return code;
}
@@ -2949,7 +3033,7 @@ String VisualShaderNodeClamp::get_output_port_name(int p_port) const {
}
String VisualShaderNodeClamp::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 "\t" + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ return " " + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
void VisualShaderNodeClamp::set_op_type(OpType p_op_type) {
@@ -3048,7 +3132,7 @@ String VisualShaderNodeFaceForward::get_output_port_name(int p_port) const {
}
String VisualShaderNodeFaceForward::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 "\t" + p_output_vars[0] + " = faceforward(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ return " " + p_output_vars[0] + " = faceforward(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
VisualShaderNodeFaceForward::VisualShaderNodeFaceForward() {
@@ -3095,7 +3179,7 @@ String VisualShaderNodeOuterProduct::get_output_port_name(int p_port) const {
}
String VisualShaderNodeOuterProduct::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 "\t" + p_output_vars[0] + " = outerProduct(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0));\n";
+ return " " + p_output_vars[0] + " = outerProduct(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0));\n";
}
VisualShaderNodeOuterProduct::VisualShaderNodeOuterProduct() {
@@ -3199,7 +3283,7 @@ VisualShaderNodeStep::OpType VisualShaderNodeStep::get_op_type() const {
}
String VisualShaderNodeStep::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 "\t" + p_output_vars[0] + " = step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ return " " + p_output_vars[0] + " = step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
Vector<StringName> VisualShaderNodeStep::get_editable_properties() const {
@@ -3326,7 +3410,7 @@ VisualShaderNodeSmoothStep::OpType VisualShaderNodeSmoothStep::get_op_type() con
}
String VisualShaderNodeSmoothStep::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 "\t" + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ return " " + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
Vector<StringName> VisualShaderNodeSmoothStep::get_editable_properties() const {
@@ -3389,7 +3473,7 @@ String VisualShaderNodeVectorDistance::get_output_port_name(int p_port) const {
}
String VisualShaderNodeVectorDistance::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 "\t" + p_output_vars[0] + " = distance(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ return " " + p_output_vars[0] + " = distance(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
VisualShaderNodeVectorDistance::VisualShaderNodeVectorDistance() {
@@ -3439,7 +3523,7 @@ String VisualShaderNodeVectorRefract::get_output_port_name(int p_port) const {
}
String VisualShaderNodeVectorRefract::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 "\t" + p_output_vars[0] + " = refract(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ return " " + p_output_vars[0] + " = refract(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
VisualShaderNodeVectorRefract::VisualShaderNodeVectorRefract() {
@@ -3542,7 +3626,7 @@ VisualShaderNodeMix::OpType VisualShaderNodeMix::get_op_type() const {
}
String VisualShaderNodeMix::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 "\t" + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ return " " + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
Vector<StringName> VisualShaderNodeMix::get_editable_properties() const {
@@ -3606,7 +3690,7 @@ String VisualShaderNodeVectorCompose::get_output_port_name(int p_port) const {
}
String VisualShaderNodeVectorCompose::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 "\t" + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ return " " + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
VisualShaderNodeVectorCompose::VisualShaderNodeVectorCompose() {
@@ -3654,7 +3738,7 @@ String VisualShaderNodeTransformCompose::get_output_port_name(int p_port) const
}
String VisualShaderNodeTransformCompose::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 "\t" + p_output_vars[0] + " = mat4(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0), vec4(" + p_input_vars[2] + ", 0.0), vec4(" + p_input_vars[3] + ", 1.0));\n";
+ return " " + p_output_vars[0] + " = mat4(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0), vec4(" + p_input_vars[2] + ", 0.0), vec4(" + p_input_vars[3] + ", 1.0));\n";
}
VisualShaderNodeTransformCompose::VisualShaderNodeTransformCompose() {
@@ -3701,9 +3785,9 @@ String VisualShaderNodeVectorDecompose::get_output_port_name(int p_port) const {
String VisualShaderNodeVectorDecompose::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 += "\t" + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n";
- code += "\t" + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n";
- code += "\t" + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n";
+ 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";
return code;
}
@@ -3751,10 +3835,10 @@ String VisualShaderNodeTransformDecompose::get_output_port_name(int p_port) cons
String VisualShaderNodeTransformDecompose::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 += "\t" + p_output_vars[0] + " = " + p_input_vars[0] + "[0].xyz;\n";
- code += "\t" + p_output_vars[1] + " = " + p_input_vars[0] + "[1].xyz;\n";
- code += "\t" + p_output_vars[2] + " = " + p_input_vars[0] + "[2].xyz;\n";
- code += "\t" + p_output_vars[3] + " = " + p_input_vars[0] + "[3].xyz;\n";
+ code += " " + p_output_vars[0] + " = " + p_input_vars[0] + "[0].xyz;\n";
+ code += " " + p_output_vars[1] + " = " + p_input_vars[0] + "[1].xyz;\n";
+ code += " " + p_output_vars[2] + " = " + p_input_vars[0] + "[2].xyz;\n";
+ code += " " + p_output_vars[3] + " = " + p_input_vars[0] + "[3].xyz;\n";
return code;
}
@@ -3809,7 +3893,7 @@ String VisualShaderNodeFloatUniform::generate_global(Shader::Mode p_mode, Visual
}
String VisualShaderNodeFloatUniform::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 "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
}
bool VisualShaderNodeFloatUniform::is_show_prop_names() const {
@@ -3980,7 +4064,7 @@ String VisualShaderNodeIntUniform::generate_global(Shader::Mode p_mode, VisualSh
}
String VisualShaderNodeIntUniform::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 "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
}
bool VisualShaderNodeIntUniform::is_show_prop_names() const {
@@ -4166,7 +4250,7 @@ String VisualShaderNodeBooleanUniform::generate_global(Shader::Mode p_mode, Visu
}
String VisualShaderNodeBooleanUniform::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 "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
}
bool VisualShaderNodeBooleanUniform::is_show_prop_names() const {
@@ -4266,8 +4350,8 @@ String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, Visual
}
String VisualShaderNodeColorUniform::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 = "\t" + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n";
- code += "\t" + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n";
+ String code = " " + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n";
+ code += " " + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n";
return code;
}
@@ -4364,7 +4448,7 @@ String VisualShaderNodeVec3Uniform::generate_global(Shader::Mode p_mode, VisualS
}
String VisualShaderNodeVec3Uniform::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 "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
}
void VisualShaderNodeVec3Uniform::_bind_methods() {
@@ -4468,7 +4552,7 @@ String VisualShaderNodeTransformUniform::generate_global(Shader::Mode p_mode, Vi
}
String VisualShaderNodeTransformUniform::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 "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
}
void VisualShaderNodeTransformUniform::_bind_methods() {
@@ -4600,23 +4684,23 @@ String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, Visual
}
String id = get_uniform_name();
- String code = "\t{\n";
+ String code = " {\n";
if (p_input_vars[0] == String()) { // Use UV by default.
if (p_input_vars[1] == String()) {
- code += "\t\tvec4 n_tex_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " vec4 n_tex_read = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += "\t\tvec4 n_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 n_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1] == String()) {
//no lod
- code += "\t\tvec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
} else {
- code += "\t\tvec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
- code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = n_tex_read.a;\n";
- code += "\t}\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;
}
@@ -4721,20 +4805,20 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader:
String code;
code += "// TRIPLANAR FUNCTION GLOBAL CODE\n";
- code += "\tvec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n";
- code += "\t\tvec4 samp = vec4(0.0);\n";
- code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n";
- code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;\n";
- code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;\n";
- code += "\t\treturn samp;\n";
- code += "\t}\n";
+ code += " vec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n";
+ code += " vec4 samp = vec4(0.0);\n";
+ code += " samp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n";
+ code += " samp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;\n";
+ code += " samp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;\n";
+ code += " return samp;\n";
+ code += " }\n";
code += "\n";
- code += "\tuniform vec3 triplanar_scale = vec3(1.0, 1.0, 1.0);\n";
- code += "\tuniform vec3 triplanar_offset;\n";
- code += "\tuniform float triplanar_sharpness = 0.5;\n";
+ code += " uniform vec3 triplanar_scale = vec3(1.0, 1.0, 1.0);\n";
+ code += " uniform vec3 triplanar_offset;\n";
+ code += " uniform float triplanar_sharpness = 0.5;\n";
code += "\n";
- code += "\tvarying vec3 triplanar_power_normal;\n";
- code += "\tvarying vec3 triplanar_pos;\n";
+ code += " varying vec3 triplanar_power_normal;\n";
+ code += " varying vec3 triplanar_pos;\n";
return code;
}
@@ -4743,11 +4827,11 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader:
String code;
if (p_type == VisualShader::TYPE_VERTEX) {
- code += "\t// TRIPLANAR FUNCTION VERTEX CODE\n";
- code += "\t\ttriplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n";
- code += "\t\ttriplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n";
- code += "\t\ttriplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n";
- code += "\t\ttriplanar_pos *= vec3(1.0, -1.0, 1.0);\n";
+ code += " // TRIPLANAR FUNCTION VERTEX CODE\n";
+ code += " triplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n";
+ code += " triplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n";
+ code += " triplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n";
+ code += " triplanar_pos *= vec3(1.0, -1.0, 1.0);\n";
}
return code;
@@ -4755,21 +4839,21 @@ 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 = "\t{\n";
+ String code = " {\n";
if (p_input_vars[0] == String() && p_input_vars[1] == String()) {
- code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n";
+ code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n";
} else if (p_input_vars[0] != String() && p_input_vars[1] == String()) {
- code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n";
+ code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n";
} else if (p_input_vars[0] == String() && p_input_vars[1] != String()) {
- code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n";
+ code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n";
} else {
- code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
- code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n";
- code += "\t\t" + p_output_vars[1] + " = n_tex_read.a;\n";
- code += "\t}\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;
}
@@ -5046,18 +5130,18 @@ String VisualShaderNodeIf::get_output_port_name(int p_port) const {
String VisualShaderNodeIf::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 += "\tif(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ")\n"; // abs(a - b) < tolerance eg. a == b
- code += "\t{\n";
- code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[3] + ";\n";
- code += "\t}\n";
- code += "\telse if(" + p_input_vars[0] + " < " + p_input_vars[1] + ")\n"; // a < b
- code += "\t{\n";
- code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[5] + ";\n";
- code += "\t}\n";
- code += "\telse\n"; // a > b (or a >= b if abs(a - b) < tolerance is false)
- code += "\t{\n";
- code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[4] + ";\n";
- code += "\t}\n";
+ code += " if(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ")\n"; // abs(a - b) < tolerance eg. a == b
+ code += " {\n";
+ code += " " + p_output_vars[0] + " = " + p_input_vars[3] + ";\n";
+ code += " }\n";
+ code += " else if(" + p_input_vars[0] + " < " + p_input_vars[1] + ")\n"; // a < b
+ code += " {\n";
+ code += " " + p_output_vars[0] + " = " + p_input_vars[5] + ";\n";
+ code += " }\n";
+ code += " else\n"; // a > b (or a >= b if abs(a - b) < tolerance is false)
+ code += " {\n";
+ code += " " + p_output_vars[0] + " = " + p_input_vars[4] + ";\n";
+ code += " }\n";
return code;
}
@@ -5198,14 +5282,14 @@ void VisualShaderNodeSwitch::_bind_methods() { // static
String VisualShaderNodeSwitch::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 += "\tif(" + p_input_vars[0] + ")\n";
- code += "\t{\n";
- code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[1] + ";\n";
- code += "\t}\n";
- code += "\telse\n";
- code += "\t{\n";
- code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[2] + ";\n";
- code += "\t}\n";
+ code += " if(" + p_input_vars[0] + ")\n";
+ code += " {\n";
+ code += " " + p_output_vars[0] + " = " + p_input_vars[1] + ";\n";
+ code += " }\n";
+ code += " else\n";
+ code += " {\n";
+ code += " " + p_output_vars[0] + " = " + p_input_vars[2] + ";\n";
+ code += " }\n";
return code;
}
@@ -5290,12 +5374,12 @@ String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader:
}
if (is_input_port_connected(2)) {
- return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));\n";
+ return " " + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));\n";
} else {
if (get_input_port_default_value(2)) {
- return "\t" + p_output_vars[0] + " = pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n";
+ return " " + p_output_vars[0] + " = pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n";
} else {
- return "\t" + p_output_vars[0] + " = pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n";
+ return " " + p_output_vars[0] + " = pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n";
}
}
}
@@ -5351,7 +5435,7 @@ String VisualShaderNodeIs::generate_code(Shader::Mode p_mode, VisualShader::Type
};
String code;
- code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
return code;
}
@@ -5478,37 +5562,37 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader:
switch (ctype) {
case CTYPE_SCALAR:
if (func == FUNC_EQUAL) {
- code += "\t" + p_output_vars[0] + " = (abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");";
+ code += " " + p_output_vars[0] + " = (abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");";
} else if (func == FUNC_NOT_EQUAL) {
- code += "\t" + p_output_vars[0] + " = !(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");";
+ code += " " + p_output_vars[0] + " = !(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");";
} else {
- code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
}
break;
case CTYPE_SCALAR_INT:
- code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
break;
case CTYPE_VECTOR:
- code += "\t{\n";
- code += "\t\tbvec3 _bv = " + String(funcs[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n";
- code += "\t\t" + p_output_vars[0] + " = " + String(conds[condition]).replace("$", "_bv") + ";\n";
- code += "\t}\n";
+ code += " {\n";
+ code += " bvec3 _bv = " + String(funcs[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(conds[condition]).replace("$", "_bv") + ";\n";
+ code += " }\n";
break;
case CTYPE_BOOLEAN:
if (func > FUNC_NOT_EQUAL) {
- return "\t" + p_output_vars[0] + " = false;\n";
+ return " " + p_output_vars[0] + " = false;\n";
}
- code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
break;
case CTYPE_TRANSFORM:
if (func > FUNC_NOT_EQUAL) {
- return "\t" + p_output_vars[0] + " = false;\n";
+ return " " + p_output_vars[0] + " = false;\n";
}
- code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n";
break;
default:
@@ -5664,7 +5748,7 @@ String VisualShaderNodeMultiplyAdd::get_output_port_name(int p_port) const {
}
String VisualShaderNodeMultiplyAdd::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 "\t" + p_output_vars[0] + " = fma(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ return " " + p_output_vars[0] + " = fma(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
void VisualShaderNodeMultiplyAdd::set_op_type(OpType p_op_type) {
@@ -5752,34 +5836,34 @@ String VisualShaderNodeBillboard::generate_code(Shader::Mode p_mode, VisualShade
switch (billboard_type) {
case BILLBOARD_TYPE_ENABLED:
- code += "\t{\n";
- code += "\t\tmat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], CAMERA_MATRIX[1], CAMERA_MATRIX[2], WORLD_MATRIX[3]);\n";
+ code += " {\n";
+ code += " mat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], CAMERA_MATRIX[1], CAMERA_MATRIX[2], WORLD_MATRIX[3]);\n";
if (keep_scale) {
- code += "\t\t__mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += " __mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
}
- code += "\t\t" + p_output_vars[0] + " = __mvm;\n";
- code += "\t}\n";
+ code += " " + p_output_vars[0] + " = __mvm;\n";
+ code += " }\n";
break;
case BILLBOARD_TYPE_FIXED_Y:
- code += "\t{\n";
- code += "\t\tmat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], WORLD_MATRIX[1], vec4(normalize(cross(CAMERA_MATRIX[0].xyz, WORLD_MATRIX[1].xyz)), 0.0), WORLD_MATRIX[3]);\n";
+ code += " {\n";
+ code += " mat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], WORLD_MATRIX[1], vec4(normalize(cross(CAMERA_MATRIX[0].xyz, WORLD_MATRIX[1].xyz)), 0.0), WORLD_MATRIX[3]);\n";
if (keep_scale) {
- code += "\t\t__mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += " __mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
} else {
- code += "\t\t__mvm = __mvm * mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0 / length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += " __mvm = __mvm * mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0 / length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
}
- code += "\t\t" + p_output_vars[0] + " = __mvm;\n";
- code += "\t}\n";
+ code += " " + p_output_vars[0] + " = __mvm;\n";
+ code += " }\n";
break;
case BILLBOARD_TYPE_PARTICLES:
- code += "\t{\n";
- code += "\t\tmat4 __wm = mat4(normalize(CAMERA_MATRIX[0]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[1]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[2]) * length(WORLD_MATRIX[2]), WORLD_MATRIX[3]);\n";
- code += "\t\t__wm = __wm * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
- code += "\t\t" + p_output_vars[0] + " = INV_CAMERA_MATRIX * __wm;\n";
- code += "\t}\n";
+ code += " {\n";
+ code += " mat4 __wm = mat4(normalize(CAMERA_MATRIX[0]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[1]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[2]) * length(WORLD_MATRIX[2]), WORLD_MATRIX[3]);\n";
+ code += " __wm = __wm * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += " " + p_output_vars[0] + " = INV_CAMERA_MATRIX * __wm;\n";
+ code += " }\n";
break;
default:
- code += "\t" + p_output_vars[0] + " = mat4(1.0);\n";
+ code += " " + p_output_vars[0] + " = mat4(1.0);\n";
break;
}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 5b44e9f776..33a45a4384 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -338,6 +338,39 @@ public:
///////////////////////////////////////
+class VisualShaderNodeCurveXYZTexture : public VisualShaderNodeResizableBase {
+ GDCLASS(VisualShaderNodeCurveXYZTexture, VisualShaderNodeResizableBase);
+ Ref<CurveXYZTexture> texture;
+
+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 Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) 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;
+
+ void set_texture(Ref<CurveXYZTexture> p_value);
+ Ref<CurveXYZTexture> get_texture() const;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+ virtual bool is_use_prop_slots() const override;
+
+ VisualShaderNodeCurveXYZTexture();
+};
+
+///////////////////////////////////////
+
class VisualShaderNodeSample3D : public VisualShaderNode {
GDCLASS(VisualShaderNodeSample3D, VisualShaderNode);
diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp
index 29d583a82a..2250cf8d95 100644
--- a/scene/resources/visual_shader_particle_nodes.cpp
+++ b/scene/resources/visual_shader_particle_nodes.cpp
@@ -76,14 +76,14 @@ String VisualShaderNodeParticleSphereEmitter::get_input_port_name(int p_port) co
String VisualShaderNodeParticleSphereEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code;
code += "vec3 __get_random_point_in_sphere(inout uint seed, float radius, float inner_radius) {\n";
- code += "\treturn __get_random_unit_vec3(seed) * __randf_range(seed, inner_radius, radius);\n";
+ code += " return __get_random_unit_vec3(seed) * __randf_range(seed, inner_radius, radius);\n";
code += "}\n\n";
return code;
}
String VisualShaderNodeParticleSphereEmitter::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 += "\t" + p_output_vars[0] + " = __get_random_point_in_sphere(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
+ code += " " + p_output_vars[0] + " = __get_random_point_in_sphere(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
return code;
}
@@ -119,15 +119,15 @@ String VisualShaderNodeParticleBoxEmitter::get_input_port_name(int p_port) const
String VisualShaderNodeParticleBoxEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code;
code += "vec3 __get_random_point_in_box(inout uint seed, vec3 extents) {\n";
- code += "\tvec3 half_extents = extents / 2.0;\n";
- code += "\treturn vec3(__randf_range(seed, -half_extents.x, half_extents.x), __randf_range(seed, -half_extents.y, half_extents.y), __randf_range(seed, -half_extents.z, half_extents.z));\n";
+ code += " vec3 half_extents = extents / 2.0;\n";
+ code += " return vec3(__randf_range(seed, -half_extents.x, half_extents.x), __randf_range(seed, -half_extents.y, half_extents.y), __randf_range(seed, -half_extents.z, half_extents.z));\n";
code += "}\n\n";
return code;
}
String VisualShaderNodeParticleBoxEmitter::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 += "\t" + p_output_vars[0] + " = __get_random_point_in_box(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ");\n";
+ code += " " + p_output_vars[0] + " = __get_random_point_in_box(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ");\n";
return code;
}
@@ -163,16 +163,16 @@ String VisualShaderNodeParticleRingEmitter::get_input_port_name(int p_port) cons
String VisualShaderNodeParticleRingEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code;
code += "vec3 __get_random_point_on_ring(inout uint seed, float radius, float inner_radius, float height) {\n";
- code += "\tfloat angle = __rand_from_seed(seed) * PI * 2.0;\n";
- code += "\tvec2 ring = vec2(sin(angle), cos(angle)) * __randf_range(seed, inner_radius, radius);\n";
- code += "\treturn vec3(ring.x, __randf_range(seed, min(0.0, height), max(0.0, height)), ring.y);\n";
+ code += " float angle = __rand_from_seed(seed) * PI * 2.0;\n";
+ code += " vec2 ring = vec2(sin(angle), cos(angle)) * __randf_range(seed, inner_radius, radius);\n";
+ code += " return vec3(ring.x, __randf_range(seed, min(0.0, height), max(0.0, height)), ring.y);\n";
code += "}\n\n";
return code;
}
String VisualShaderNodeParticleRingEmitter::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 = "\t" + p_output_vars[0] + " = __get_random_point_on_ring(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ");\n";
+ code = " " + p_output_vars[0] + " = __get_random_point_on_ring(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ");\n";
return code;
}
@@ -242,9 +242,9 @@ String VisualShaderNodeParticleMultiplyByAxisAngle::get_output_port_name(int p_p
String VisualShaderNodeParticleMultiplyByAxisAngle::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;
if (degrees_mode) {
- code += "\t" + p_output_vars[0] + " = __build_rotation_mat3(" + (p_input_vars[1].is_empty() ? ("vec3" + (String)get_input_port_default_value(1)) : p_input_vars[1]) + ", radians(" + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ")) * " + (p_input_vars[0].is_empty() ? "vec3(0.0)" : p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = __build_rotation_mat3(" + (p_input_vars[1].is_empty() ? ("vec3" + (String)get_input_port_default_value(1)) : p_input_vars[1]) + ", radians(" + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ")) * " + (p_input_vars[0].is_empty() ? "vec3(0.0)" : p_input_vars[0]) + ";\n";
} else {
- code += "\t" + p_output_vars[0] + " = __build_rotation_mat3(" + (p_input_vars[1].is_empty() ? ("vec3" + (String)get_input_port_default_value(1)) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ") * " + (p_input_vars[0].is_empty() ? "vec3(0.0)" : p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = __build_rotation_mat3(" + (p_input_vars[1].is_empty() ? ("vec3" + (String)get_input_port_default_value(1)) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ") * " + (p_input_vars[0].is_empty() ? "vec3(0.0)" : p_input_vars[0]) + ";\n";
}
return code;
}
@@ -315,16 +315,16 @@ String VisualShaderNodeParticleConeVelocity::get_output_port_name(int p_port) co
String VisualShaderNodeParticleConeVelocity::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 += "\t__radians = radians(" + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
- code += "\t__scalar_buff1 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
- code += "\t__scalar_buff2 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
- code += "\t__vec3_buff1 = " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + ";\n";
- code += "\t__scalar_buff1 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.x, __vec3_buff1.z) : sign(__vec3_buff1.x) * (PI / 2.0);\n";
- code += "\t__scalar_buff2 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.z)) : (__vec3_buff1.x != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.x)) : sign(__vec3_buff1.y) * (PI / 2.0));\n";
- code += "\t__vec3_buff1 = vec3(sin(__scalar_buff1), 0.0, cos(__scalar_buff1));\n";
- code += "\t__vec3_buff2 = vec3(0.0, sin(__scalar_buff2), cos(__scalar_buff2));\n";
- code += "\t__vec3_buff2.z = __vec3_buff2.z / max(0.0001, sqrt(abs(__vec3_buff2.z)));\n";
- code += "\t" + p_output_vars[0] + " = normalize(vec3(__vec3_buff1.x * __vec3_buff2.z, __vec3_buff2.y, __vec3_buff1.z * __vec3_buff2.z));\n";
+ code += " __radians = radians(" + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
+ code += " __scalar_buff1 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
+ code += " __scalar_buff2 = __rand_from_seed_m1_p1(__seed) * __radians;\n";
+ code += " __vec3_buff1 = " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + ";\n";
+ code += " __scalar_buff1 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.x, __vec3_buff1.z) : sign(__vec3_buff1.x) * (PI / 2.0);\n";
+ code += " __scalar_buff2 += __vec3_buff1.z != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.z)) : (__vec3_buff1.x != 0.0 ? atan(__vec3_buff1.y, abs(__vec3_buff1.x)) : sign(__vec3_buff1.y) * (PI / 2.0));\n";
+ code += " __vec3_buff1 = vec3(sin(__scalar_buff1), 0.0, cos(__scalar_buff1));\n";
+ code += " __vec3_buff2 = vec3(0.0, sin(__scalar_buff2), cos(__scalar_buff2));\n";
+ code += " __vec3_buff2.z = __vec3_buff2.z / max(0.0001, sqrt(abs(__vec3_buff2.z)));\n";
+ code += " " + p_output_vars[0] + " = normalize(vec3(__vec3_buff1.x * __vec3_buff2.z, __vec3_buff2.y, __vec3_buff1.z * __vec3_buff2.z));\n";
return code;
}
@@ -394,9 +394,9 @@ String VisualShaderNodeParticleRandomness::get_input_port_name(int p_port) const
String VisualShaderNodeParticleRandomness::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;
if (op_type == OP_TYPE_SCALAR) {
- code += vformat("\t%s = __randf_range(__seed, %s, %s);\n", p_output_vars[0], p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0], p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]);
+ code += vformat(" %s = __randf_range(__seed, %s, %s);\n", p_output_vars[0], p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0], p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]);
} else if (op_type == OP_TYPE_VECTOR) {
- code += vformat("\t%s = __randv_range(__seed, %s, %s);\n", p_output_vars[0], p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0], p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]);
+ code += vformat(" %s = __randv_range(__seed, %s, %s);\n", p_output_vars[0], p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0], p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]);
}
return code;
}
@@ -491,14 +491,14 @@ String VisualShaderNodeParticleAccelerator::generate_code(Shader::Mode p_mode, V
String code;
switch (mode) {
case MODE_LINEAR:
- code += "\t" + p_output_vars[0] + " = length(VELOCITY) > 0.0 ? " + "normalize(VELOCITY) * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
+ code += " " + p_output_vars[0] + " = length(VELOCITY) > 0.0 ? " + "normalize(VELOCITY) * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
break;
case MODE_RADIAL:
- code += "\t" + p_output_vars[0] + " = length(__diff) > 0.0 ? __ndiff * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
+ code += " " + p_output_vars[0] + " = length(__diff) > 0.0 ? __ndiff * " + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ") : vec3(0.0);\n";
break;
case MODE_TANGENTIAL:
- code += "\t__vec3_buff1 = cross(__ndiff, normalize(" + (p_input_vars[2].is_empty() ? "vec3" + (String)get_input_port_default_value(2) : p_input_vars[2]) + "));\n";
- code += "\t" + p_output_vars[0] + " = length(__vec3_buff1) > 0.0 ? normalize(__vec3_buff1) * (" + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ")) : vec3(0.0);\n";
+ code += " __vec3_buff1 = cross(__ndiff, normalize(" + (p_input_vars[2].is_empty() ? "vec3" + (String)get_input_port_default_value(2) : p_input_vars[2]) + "));\n";
+ code += " " + p_output_vars[0] + " = length(__vec3_buff1) > 0.0 ? normalize(__vec3_buff1) * (" + (p_input_vars[0].is_empty() ? "vec3" + (String)get_input_port_default_value(0) : p_input_vars[0]) + " * mix(1.0, __rand_from_seed(__seed), " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ")) : vec3(0.0);\n";
break;
case MODE_MAX:
break;
@@ -693,7 +693,7 @@ bool VisualShaderNodeParticleOutput::is_port_separator(int p_index) const {
String VisualShaderNodeParticleOutput::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;
- String tab = "\t";
+ String tab = " ";
if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) {
if (!p_input_vars[0].is_empty()) { // custom.rgb
@@ -718,7 +718,7 @@ String VisualShaderNodeParticleOutput::generate_code(Shader::Mode p_mode, Visual
if (!p_input_vars[0].is_empty()) { // active (begin)
code += tab + "ACTIVE = " + p_input_vars[0] + ";\n";
code += tab + "if(ACTIVE) {\n";
- tab += "\t";
+ tab += " ";
}
if (!p_input_vars[1].is_empty()) { // velocity
code += tab + "VELOCITY = " + p_input_vars[1] + ";\n";
@@ -734,14 +734,14 @@ String VisualShaderNodeParticleOutput::generate_code(Shader::Mode p_mode, Visual
if (shader_type == VisualShader::TYPE_START) {
code += tab + "if (RESTART_POSITION) {\n";
if (!p_input_vars[4].is_empty()) {
- code += tab + "\tTRANSFORM = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(" + p_input_vars[4] + ", 1.0));\n";
+ code += tab + " TRANSFORM = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(" + p_input_vars[4] + ", 1.0));\n";
} else {
- code += tab + "\tTRANSFORM = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += tab + " TRANSFORM = mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
}
- code += tab + "\tif (RESTART_VELOCITY) {\n";
- code += tab + "\t\tVELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n";
- code += tab + "\t}\n";
- code += tab + "\tTRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n";
+ code += tab + " if (RESTART_VELOCITY) {\n";
+ code += tab + " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n";
+ code += tab + " }\n";
+ code += tab + " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n";
code += tab + "}\n";
} else if (shader_type == VisualShader::TYPE_COLLIDE) { // position
if (!p_input_vars[4].is_empty()) {
@@ -779,7 +779,7 @@ String VisualShaderNodeParticleOutput::generate_code(Shader::Mode p_mode, Visual
}
}
if (!p_input_vars[0].is_empty()) { // active (end)
- code += "\t}\n";
+ code += " }\n";
}
}
return code;
@@ -926,12 +926,12 @@ String VisualShaderNodeParticleEmit::generate_code(Shader::Mode p_mode, VisualSh
if (!is_input_port_connected(0)) {
default_condition = true;
if (get_input_port_default_value(0)) {
- tab = "\t";
+ tab = " ";
} else {
return code;
}
} else {
- tab = "\t\t";
+ tab = " ";
}
String transform;
@@ -1008,13 +1008,13 @@ String VisualShaderNodeParticleEmit::generate_code(Shader::Mode p_mode, VisualSh
}
if (!default_condition) {
- code += "\tif (" + p_input_vars[0] + ") {\n";
+ code += " if (" + p_input_vars[0] + ") {\n";
}
code += tab + "emit_subparticle(" + transform + ", " + velocity + ", vec4(" + color + ", " + alpha + "), vec4(" + custom + ", " + custom_alpha + "), " + flags + ");\n";
if (!default_condition) {
- code += "\t}\n";
+ code += " }\n";
}
return code;
diff --git a/scene/resources/visual_shader_sdf_nodes.cpp b/scene/resources/visual_shader_sdf_nodes.cpp
index d25e32b070..14c655b129 100644
--- a/scene/resources/visual_shader_sdf_nodes.cpp
+++ b/scene/resources/visual_shader_sdf_nodes.cpp
@@ -61,7 +61,7 @@ String VisualShaderNodeSDFToScreenUV::get_output_port_name(int p_port) const {
}
String VisualShaderNodeSDFToScreenUV::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 "\t" + p_output_vars[0] + " = vec3(sdf_to_screen_uv(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
+ return " " + p_output_vars[0] + " = vec3(sdf_to_screen_uv(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
}
VisualShaderNodeSDFToScreenUV::VisualShaderNodeSDFToScreenUV() {
@@ -105,7 +105,7 @@ String VisualShaderNodeScreenUVToSDF::get_input_port_default_hint(int p_port) co
}
String VisualShaderNodeScreenUVToSDF::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 "\t" + p_output_vars[0] + " = vec3(screen_uv_to_sdf(" + (p_input_vars[0] == String() ? "SCREEN_UV" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
+ return " " + p_output_vars[0] + " = vec3(screen_uv_to_sdf(" + (p_input_vars[0] == String() ? "SCREEN_UV" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
}
VisualShaderNodeScreenUVToSDF::VisualShaderNodeScreenUVToSDF() {
@@ -142,7 +142,7 @@ String VisualShaderNodeTextureSDF::get_output_port_name(int p_port) const {
}
String VisualShaderNodeTextureSDF::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 "\t" + p_output_vars[0] + " = texture_sdf(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + ");\n";
+ return " " + p_output_vars[0] + " = texture_sdf(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + ");\n";
}
VisualShaderNodeTextureSDF::VisualShaderNodeTextureSDF() {
@@ -179,7 +179,7 @@ String VisualShaderNodeTextureSDFNormal::get_output_port_name(int p_port) const
}
String VisualShaderNodeTextureSDFNormal::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 "\t" + p_output_vars[0] + " = vec3(texture_sdf_normal(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
+ return " " + p_output_vars[0] + " = vec3(texture_sdf_normal(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
}
VisualShaderNodeTextureSDFNormal::VisualShaderNodeTextureSDFNormal() {
@@ -240,40 +240,40 @@ String VisualShaderNodeSDFRaymarch::get_output_port_name(int p_port) const {
String VisualShaderNodeSDFRaymarch::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 += "\t{\n";
+ code += " {\n";
if (p_input_vars[0] == String()) {
- code += "\t\tvec2 __from_pos = vec2(0.0f);\n";
+ code += " vec2 __from_pos = vec2(0.0f);\n";
} else {
- code += "\t\tvec2 __from_pos = " + p_input_vars[0] + ".xy;\n";
+ code += " vec2 __from_pos = " + p_input_vars[0] + ".xy;\n";
}
if (p_input_vars[1] == String()) {
- code += "\t\tvec2 __to_pos = vec2(0.0f);\n";
+ code += " vec2 __to_pos = vec2(0.0f);\n";
} else {
- code += "\t\tvec2 __to_pos = " + p_input_vars[1] + ".xy;\n";
+ code += " vec2 __to_pos = " + p_input_vars[1] + ".xy;\n";
}
- code += "\n\t\tvec2 __at = __from_pos;\n";
- code += "\t\tfloat __max_dist = distance(__from_pos, __to_pos);\n";
- code += "\t\tvec2 __dir = normalize(__to_pos - __from_pos);\n\n";
-
- code += "\t\tfloat __accum = 0.0f;\n";
- code += "\t\twhile(__accum < __max_dist) {\n";
- code += "\t\t\tfloat __d = texture_sdf(__at);\n";
- code += "\t\t\t__accum += __d;\n";
- code += "\t\t\tif (__d < 0.01f) {\n";
- code += "\t\t\t\tbreak;\n";
- code += "\t\t\t}\n";
- code += "\t\t\t__at += __d * __dir;\n";
- code += "\t\t}\n";
-
- code += "\t\tfloat __dist = min(__max_dist, __accum);\n";
- code += "\t\t" + p_output_vars[0] + " = __dist;\n";
- code += "\t\t" + p_output_vars[1] + " = __accum < __max_dist;\n";
- code += "\t\t" + p_output_vars[2] + " = vec3(__from_pos + __dir * __dist, 0.0f);\n";
-
- code += "\t}\n";
+ code += "\n vec2 __at = __from_pos;\n";
+ code += " float __max_dist = distance(__from_pos, __to_pos);\n";
+ code += " vec2 __dir = normalize(__to_pos - __from_pos);\n\n";
+
+ code += " float __accum = 0.0f;\n";
+ code += " while(__accum < __max_dist) {\n";
+ code += " float __d = texture_sdf(__at);\n";
+ code += " __accum += __d;\n";
+ code += " if (__d < 0.01f) {\n";
+ code += " break;\n";
+ code += " }\n";
+ code += " __at += __d * __dir;\n";
+ code += " }\n";
+
+ code += " float __dist = min(__max_dist, __accum);\n";
+ code += " " + p_output_vars[0] + " = __dist;\n";
+ code += " " + p_output_vars[1] + " = __accum < __max_dist;\n";
+ code += " " + p_output_vars[2] + " = vec3(__from_pos + __dir * __dist, 0.0f);\n";
+
+ code += " }\n";
return code;
}
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 2e0af89c1a..d53d155cce 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -66,6 +66,8 @@ SceneStringNames::SceneStringNames() {
mouse_entered = StaticCString::create("mouse_entered");
mouse_exited = StaticCString::create("mouse_exited");
+ mouse_shape_entered = StaticCString::create("mouse_shape_entered");
+ mouse_shape_exited = StaticCString::create("mouse_shape_exited");
focus_entered = StaticCString::create("focus_entered");
focus_exited = StaticCString::create("focus_exited");
@@ -143,7 +145,7 @@ SceneStringNames::SceneStringNames() {
v_offset = StaticCString::create("v_offset");
transform_pos = StaticCString::create("position");
- transform_rot = StaticCString::create("rotation_degrees");
+ transform_rot = StaticCString::create("rotation");
transform_scale = StaticCString::create("scale");
_update_remote = StaticCString::create("_update_remote");
@@ -169,6 +171,8 @@ SceneStringNames::SceneStringNames() {
_mouse_enter = StaticCString::create("_mouse_enter");
_mouse_exit = StaticCString::create("_mouse_exit");
+ _mouse_shape_enter = StaticCString::create("_mouse_shape_enter");
+ _mouse_shape_exit = StaticCString::create("_mouse_shape_exit");
_pressed = StaticCString::create("_pressed");
_toggled = StaticCString::create("_toggled");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 01865b0d2f..a141c2b3aa 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -84,6 +84,8 @@ public:
StringName mouse_entered;
StringName mouse_exited;
+ StringName mouse_shape_entered;
+ StringName mouse_shape_exited;
StringName focus_entered;
StringName focus_exited;
@@ -181,6 +183,8 @@ public:
StringName _mouse_enter;
StringName _mouse_exit;
+ StringName _mouse_shape_enter;
+ StringName _mouse_shape_exit;
StringName frame_changed;
StringName texture_changed;
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 54cd5ed0bf..9af3ed30cc 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -276,7 +276,7 @@ void AudioEffectChorus::_validate_property(PropertyInfo &property) const {
if (property.name.begins_with("voice/")) {
int voice_idx = property.name.get_slice("/", 1).to_int();
if (voice_idx > voice_count) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
}
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index 9aab97da29..1fa3df1570 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -100,7 +100,7 @@ class AudioEffectLowPassFilter : public AudioEffectFilter {
void _validate_property(PropertyInfo &property) const override {
if (property.name == "gain") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -113,7 +113,7 @@ class AudioEffectHighPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter);
void _validate_property(PropertyInfo &property) const override {
if (property.name == "gain") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -126,7 +126,7 @@ class AudioEffectBandPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter);
void _validate_property(PropertyInfo &property) const override {
if (property.name == "gain") {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NONE;
}
}
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 667087d1ec..076cbb58af 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -561,7 +561,7 @@ void AudioServer::set_bus_count(int p_count) {
unlock();
- emit_signal("bus_layout_changed");
+ emit_signal(SNAME("bus_layout_changed"));
}
void AudioServer::remove_bus(int p_index) {
@@ -576,7 +576,7 @@ void AudioServer::remove_bus(int p_index) {
buses.remove(p_index);
unlock();
- emit_signal("bus_layout_changed");
+ emit_signal(SNAME("bus_layout_changed"));
}
void AudioServer::add_bus(int p_at_pos) {
@@ -630,7 +630,7 @@ void AudioServer::add_bus(int p_at_pos) {
buses.insert(p_at_pos, bus);
}
- emit_signal("bus_layout_changed");
+ emit_signal(SNAME("bus_layout_changed"));
}
void AudioServer::move_bus(int p_bus, int p_to_pos) {
@@ -654,7 +654,7 @@ void AudioServer::move_bus(int p_bus, int p_to_pos) {
buses.insert(p_to_pos - 1, bus);
}
- emit_signal("bus_layout_changed");
+ emit_signal(SNAME("bus_layout_changed"));
}
int AudioServer::get_bus_count() const {
@@ -700,7 +700,7 @@ void AudioServer::set_bus_name(int p_bus, const String &p_name) {
bus_map[attempt] = buses[p_bus];
unlock();
- emit_signal("bus_layout_changed");
+ emit_signal(SNAME("bus_layout_changed"));
}
String AudioServer::get_bus_name(int p_bus) const {
diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp
index ee4a2e148b..6f506d0f7a 100644
--- a/servers/camera_server.cpp
+++ b/servers/camera_server.cpp
@@ -110,7 +110,7 @@ void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) {
#endif
// let whomever is interested know
- emit_signal("camera_feed_added", p_feed->get_id());
+ emit_signal(SNAME("camera_feed_added"), p_feed->get_id());
};
void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) {
@@ -127,7 +127,7 @@ void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) {
feeds.remove(i);
// let whomever is interested know
- emit_signal("camera_feed_removed", feed_id);
+ emit_signal(SNAME("camera_feed_removed"), feed_id);
return;
};
};
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index d746117884..be2a813fd1 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -35,7 +35,6 @@
#include "servers/display_server_headless.h"
DisplayServer *DisplayServer::singleton = nullptr;
-DisplayServer::SwitchVSyncCallbackInThread DisplayServer::switch_vsync_function = nullptr;
bool DisplayServer::hidpi_allowed = false;
@@ -185,7 +184,7 @@ bool DisplayServer::screen_is_kept_on() const {
return false;
}
-DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server.");
}
@@ -309,29 +308,13 @@ void DisplayServer::set_icon(const Ref<Image> &p_icon) {
WARN_PRINT("Icon not supported by this display server.");
}
-void DisplayServer::_set_use_vsync(bool p_enable) {
- WARN_PRINT("VSync not supported by this display server.");
+void DisplayServer::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ WARN_PRINT("Changing the VSync mode is not supported by this display server.");
}
-void DisplayServer::vsync_set_enabled(bool p_enable) {
- vsync_enabled = p_enable;
- if (switch_vsync_function) { //if a function was set, use function
- switch_vsync_function(p_enable);
- } else { //otherwise just call here
- _set_use_vsync(p_enable);
- }
-}
-
-bool DisplayServer::vsync_is_enabled() const {
- return vsync_enabled;
-}
-
-void DisplayServer::vsync_set_use_via_compositor(bool p_enable) {
- WARN_PRINT("VSync via compositor not supported by this display server.");
-}
-
-bool DisplayServer::vsync_is_using_via_compositor() const {
- return false;
+DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window) const {
+ WARN_PRINT("Changing the VSync mode is not supported by this display server.");
+ return VSyncMode::VSYNC_ENABLED;
}
void DisplayServer::set_context(Context p_context) {
@@ -394,7 +377,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list);
ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position);
- ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "flags", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i()));
+ ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "vsync_mode", "flags", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i()));
ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window);
ClassDB::bind_method(D_METHOD("window_set_title", "title", "window_id"), &DisplayServer::window_set_title, DEFVAL(MAIN_WINDOW_ID));
@@ -441,6 +424,9 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_ime_active", "active", "window_id"), &DisplayServer::window_set_ime_active, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_ime_position", "position", "window_id"), &DisplayServer::window_set_ime_position, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_set_vsync_mode", "vsync_mode", "window_id"), &DisplayServer::window_set_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_get_vsync_mode", "window_id"), &DisplayServer::window_get_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
+
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
@@ -472,12 +458,6 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events);
ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events);
- ClassDB::bind_method(D_METHOD("vsync_set_enabled", "enabled"), &DisplayServer::vsync_set_enabled);
- ClassDB::bind_method(D_METHOD("vsync_is_enabled"), &DisplayServer::vsync_is_enabled);
-
- ClassDB::bind_method(D_METHOD("vsync_set_use_via_compositor", "enabled"), &DisplayServer::vsync_set_use_via_compositor);
- ClassDB::bind_method(D_METHOD("vsync_is_using_via_compositor"), &DisplayServer::vsync_is_using_via_compositor);
-
ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &DisplayServer::set_native_icon);
ClassDB::bind_method(D_METHOD("set_icon", "image"), &DisplayServer::set_icon);
@@ -561,6 +541,11 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_EVENT_CLOSE_REQUEST);
BIND_ENUM_CONSTANT(WINDOW_EVENT_GO_BACK_REQUEST);
BIND_ENUM_CONSTANT(WINDOW_EVENT_DPI_CHANGE);
+
+ BIND_ENUM_CONSTANT(VSYNC_DISABLED);
+ BIND_ENUM_CONSTANT(VSYNC_ENABLED);
+ BIND_ENUM_CONSTANT(VSYNC_ADAPTIVE);
+ BIND_ENUM_CONSTANT(VSYNC_MAILBOX);
}
void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers) {
@@ -587,9 +572,9 @@ Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index)
return server_create_functions[p_index].get_rendering_drivers_function();
}
-DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
- return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_flags, p_resolution, r_error);
+ return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error);
}
void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) {
diff --git a/servers/display_server.h b/servers/display_server.h
index 7dab7b7481..8d289b10fd 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -42,7 +42,6 @@ class DisplayServer : public Object {
GDCLASS(DisplayServer, Object)
static DisplayServer *singleton;
- bool vsync_enabled = true;
static bool hidpi_allowed;
public:
@@ -57,7 +56,16 @@ public:
WINDOW_MODE_FULLSCREEN
};
- typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, uint32_t, const Size2i &, Error &r_error);
+ // Keep the VSyncMode enum values in sync with the `display/window/vsync/vsync_mode`
+ // project setting hint.
+ enum VSyncMode {
+ VSYNC_DISABLED,
+ VSYNC_ENABLED,
+ VSYNC_ADAPTIVE,
+ VSYNC_MAILBOX
+ };
+
+ typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Size2i &, Error &r_error);
typedef Vector<String> (*GetRenderingDriversFunction)();
private:
@@ -84,7 +92,6 @@ protected:
static int server_create_count;
friend class RendererViewport;
- virtual void _set_use_vsync(bool p_enable);
public:
enum Feature {
@@ -221,7 +228,7 @@ public:
WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS)
};
- virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
virtual void show_window(WindowID p_id);
virtual void delete_sub_window(WindowID p_id);
@@ -272,6 +279,9 @@ public:
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const = 0;
+ virtual void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID);
+ virtual VSyncMode window_get_vsync_mode(WindowID p_window) const;
+
virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) = 0;
@@ -352,18 +362,6 @@ public:
virtual void set_native_icon(const String &p_filename);
virtual void set_icon(const Ref<Image> &p_icon);
- typedef void (*SwitchVSyncCallbackInThread)(bool);
-
- static SwitchVSyncCallbackInThread switch_vsync_function;
-
- void vsync_set_enabled(bool p_enable);
- bool vsync_is_enabled() const;
-
- virtual void vsync_set_use_via_compositor(bool p_enable);
- virtual bool vsync_is_using_via_compositor() const;
-
- //real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed
-
enum Context {
CONTEXT_EDITOR,
CONTEXT_PROJECTMAN,
@@ -376,7 +374,7 @@ public:
static int get_create_function_count();
static const char *get_create_function_name(int p_index);
static Vector<String> get_create_function_rendering_drivers(int p_index);
- static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
DisplayServer();
~DisplayServer();
@@ -389,5 +387,6 @@ VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation)
VARIANT_ENUM_CAST(DisplayServer::WindowMode)
VARIANT_ENUM_CAST(DisplayServer::WindowFlags)
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
+VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
#endif // DISPLAY_SERVER_H
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index 8b386c8d9c..870401b180 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -45,7 +45,7 @@ private:
return drivers;
}
- static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
r_error = OK;
RasterizerDummy::make_current();
return memnew(DisplayServerHeadless());
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index ef2635c188..85b12f1585 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -158,7 +158,7 @@ static Ref<NavigationMesh> poly_to_mesh(Ref<NavigationPolygon> d) {
}
void NavigationServer2D::_emit_map_changed(RID p_map) {
- emit_signal("map_changed", p_map);
+ emit_signal(SNAME("map_changed"), p_map);
}
void NavigationServer2D::_bind_methods() {
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index eb9fc0e800..5ca16cb6fc 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -33,10 +33,7 @@
bool AreaPair2DSW::setup(real_t p_step) {
bool result = false;
-
- if (area->is_shape_set_as_disabled(area_shape) || body->is_shape_set_as_disabled(body_shape)) {
- result = false;
- } else if (area->test_collision_mask(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
+ if (area->interacts_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
result = true;
}
@@ -113,9 +110,7 @@ AreaPair2DSW::~AreaPair2DSW() {
bool Area2Pair2DSW::setup(real_t p_step) {
bool result = false;
- if (area_a->is_shape_set_as_disabled(shape_a) || area_b->is_shape_set_as_disabled(shape_b)) {
- result = false;
- } else if (area_a->test_collision_mask(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
+ if (area_a->interacts_with(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
result = true;
}
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index ff31825b83..71d985a6c5 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -229,7 +229,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
- if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
+ if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
}
@@ -244,11 +244,6 @@ bool BodyPair2DSW::setup(real_t p_step) {
}
}
- if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) {
- collided = false;
- return false;
- }
-
//use local A coordinates to avoid numerical issues on collision detection
offset_B = B->get_transform().get_origin() - A->get_transform().get_origin();
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index fa87dc1f3f..5d1ef83165 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -47,8 +47,6 @@ void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_tra
if (!pending_shape_update_list.in_list()) {
PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- // _update_shapes();
- // _shapes_changed();
}
void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
@@ -61,8 +59,6 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
if (!pending_shape_update_list.in_list()) {
PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- // _update_shapes();
- // _shapes_changed();
}
void CollisionObject2DSW::set_shape_metadata(int p_index, const Variant &p_metadata) {
@@ -79,11 +75,9 @@ void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_
if (!pending_shape_update_list.in_list()) {
PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- // _update_shapes();
- // _shapes_changed();
}
-void CollisionObject2DSW::set_shape_as_disabled(int p_idx, bool p_disabled) {
+void CollisionObject2DSW::set_shape_disabled(int p_idx, bool p_disabled) {
ERR_FAIL_INDEX(p_idx, shapes.size());
CollisionObject2DSW::Shape &shape = shapes.write[p_idx];
@@ -103,12 +97,10 @@ void CollisionObject2DSW::set_shape_as_disabled(int p_idx, bool p_disabled) {
if (!pending_shape_update_list.in_list()) {
PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- //_update_shapes();
} else if (!p_disabled && shape.bpid == 0) {
if (!pending_shape_update_list.in_list()) {
PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- //_update_shapes(); // automatically adds shape with bpid == 0
}
}
@@ -177,7 +169,6 @@ void CollisionObject2DSW::_update_shapes() {
for (int i = 0; i < shapes.size(); i++) {
Shape &s = shapes.write[i];
-
if (s.disabled) {
continue;
}
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index c395e59694..14adb0bb18 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -118,10 +118,6 @@ public:
void set_shape_metadata(int p_index, const Variant &p_metadata);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
- _FORCE_INLINE_ bool is_shape_disabled(int p_index) const {
- CRASH_BAD_INDEX(p_index, shapes.size());
- return shapes[p_index].disabled;
- }
_FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const {
CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].shape;
@@ -147,9 +143,9 @@ public:
_FORCE_INLINE_ const Transform2D &get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ Space2DSW *get_space() const { return space; }
- void set_shape_as_disabled(int p_idx, bool p_disabled);
- _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const {
- CRASH_BAD_INDEX(p_idx, shapes.size());
+ void set_shape_disabled(int p_idx, bool p_disabled);
+ _FORCE_INLINE_ bool is_shape_disabled(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
return shapes[p_idx].disabled;
}
@@ -190,7 +186,11 @@ public:
void set_pickable(bool p_pickable) { pickable = p_pickable; }
_FORCE_INLINE_ bool is_pickable() const { return pickable; }
- _FORCE_INLINE_ bool test_collision_mask(CollisionObject2DSW *p_other) const {
+ _FORCE_INLINE_ bool layer_in_mask(CollisionObject2DSW *p_other) const {
+ return collision_layer & p_other->collision_mask;
+ }
+
+ _FORCE_INLINE_ bool interacts_with(CollisionObject2DSW *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index 1c2dca0259..467c664302 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -366,7 +366,7 @@ void PhysicsServer2DSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_
ERR_FAIL_INDEX(p_shape, area->get_shape_count());
FLUSH_QUERY_CHECK(area);
- area->set_shape_as_disabled(p_shape, p_disabled);
+ area->set_shape_disabled(p_shape, p_disabled);
}
int PhysicsServer2DSW::area_get_shape_count(RID p_area) const {
@@ -663,7 +663,7 @@ void PhysicsServer2DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, boo
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
FLUSH_QUERY_CHECK(body);
- body->set_shape_as_disabled(p_shape_idx, p_disabled);
+ body->set_shape_disabled(p_shape_idx, p_disabled);
}
void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) {
@@ -946,7 +946,7 @@ void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) {
body->set_pickable(p_pickable);
}
-bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
Body2DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -954,7 +954,7 @@ bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from,
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes, p_exclude);
}
int PhysicsServer2DSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index 5002bf5fc8..f40b5a7c42 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -247,7 +247,7 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable) override;
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) override;
virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.08) override;
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h
index c776641699..fb7235c031 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.h
@@ -253,12 +253,12 @@ public:
FUNC2(body_set_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
+ bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
+ return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes, p_exclude);
}
- int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
+ int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.08) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
}
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 1380e57b57..43329fed2f 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -84,10 +84,6 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
Shape2DSW *shape = col_obj->get_shape(shape_idx);
Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point);
@@ -233,10 +229,6 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_margin)) {
continue;
}
@@ -280,10 +272,6 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) {
@@ -295,22 +283,38 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor
continue;
}
- //just do kinematic solving
- real_t low = 0;
- real_t hi = 1;
Vector2 mnormal = p_motion.normalized();
+ //just do kinematic solving
+ real_t low = 0.0;
+ real_t hi = 1.0;
+ real_t fraction_coeff = 0.5;
for (int j = 0; j < 8; j++) { //steps should be customizable..
-
- real_t ofs = (low + hi) * 0.5;
+ real_t fraction = low + (hi - low) * fraction_coeff;
Vector2 sep = mnormal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(shape, p_xform, p_motion * ofs, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_margin);
+ bool collided = CollisionSolver2DSW::solve(shape, p_xform, p_motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_margin);
if (collided) {
- hi = ofs;
+ hi = fraction;
+ if ((j == 0) || (low > 0.0)) { // Did it not collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When colliding again, converge faster towards low fraction
+ // for more accurate results with long motions that collide near the start.
+ fraction_coeff = 0.25;
+ }
} else {
- low = ofs;
+ low = fraction;
+ if ((j == 0) || (hi < 1.0)) { // Did it collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When not colliding again, converge faster towards high fraction
+ // for more accurate results with long motions that collide near the end.
+ fraction_coeff = 0.75;
+ }
}
}
@@ -365,10 +369,6 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
@@ -460,10 +460,6 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
rcd.valid_dir = Vector2();
rcd.object = col_obj;
rcd.shape = shape_idx;
@@ -512,12 +508,10 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObject2DSW::TYPE_AREA) {
keep = false;
- } else if ((static_cast<Body2DSW *>(intersection_query_results[i])->test_collision_mask(p_body)) == 0) {
+ } else if (!p_body->layer_in_mask(static_cast<Body2DSW *>(intersection_query_results[i]))) {
keep = false;
} else if (static_cast<Body2DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
- } else if (static_cast<Body2DSW *>(intersection_query_results[i])->is_shape_set_as_disabled(intersection_query_subindex_results[i])) {
- keep = false;
}
if (!keep) {
@@ -540,7 +534,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
bool shapes_found = false;
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (p_body->is_shape_set_as_disabled(i)) {
+ if (p_body->is_shape_disabled(i)) {
continue;
}
@@ -592,7 +586,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int j = 0; j < p_body->get_shape_count(); j++) {
- if (p_body->is_shape_set_as_disabled(j)) {
+ if (p_body->is_shape_disabled(j)) {
continue;
}
@@ -715,7 +709,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
return rays_found;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -732,7 +726,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool shapes_found = false;
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (p_body->is_shape_set_as_disabled(i)) {
+ if (p_body->is_shape_disabled(i)) {
continue;
}
@@ -795,7 +789,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int j = 0; j < p_body->get_shape_count(); j++) {
- if (p_body->is_shape_set_as_disabled(j)) {
+ if (p_body->is_shape_disabled(j)) {
continue;
}
@@ -807,6 +801,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
+ }
int shape_idx = intersection_query_subindex_results[i];
if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
@@ -918,7 +915,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int amount = _cull_aabb_for_body(p_body, motion_aabb);
for (int body_shape_idx = 0; body_shape_idx < p_body->get_shape_count(); body_shape_idx++) {
- if (p_body->is_shape_set_as_disabled(body_shape_idx)) {
+ if (p_body->is_shape_disabled(body_shape_idx)) {
continue;
}
@@ -936,6 +933,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
+ }
int col_shape_idx = intersection_query_subindex_results[i];
Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
@@ -979,20 +979,35 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
//just do kinematic solving
- real_t low = 0;
- real_t hi = 1;
-
+ real_t low = 0.0;
+ real_t hi = 1.0;
+ real_t fraction_coeff = 0.5;
for (int k = 0; k < 8; k++) { //steps should be customizable..
-
- real_t ofs = (low + hi) * 0.5;
+ real_t fraction = low + (hi - low) * fraction_coeff;
Vector2 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
if (collided) {
- hi = ofs;
+ hi = fraction;
+ if ((k == 0) || (low > 0.0)) { // Did it not collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When colliding again, converge faster towards low fraction
+ // for more accurate results with long motions that collide near the start.
+ fraction_coeff = 0.25;
+ }
} else {
- low = ofs;
+ low = fraction;
+ if ((k == 0) || (hi < 1.0)) { // Did it collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When not colliding again, converge faster towards high fraction
+ // for more accurate results with long motions that collide near the end.
+ fraction_coeff = 0.75;
+ }
}
}
@@ -1060,7 +1075,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
for (int j = from_shape; j < to_shape; j++) {
- if (p_body->is_shape_set_as_disabled(j)) {
+ if (p_body->is_shape_disabled(j)) {
continue;
}
@@ -1077,6 +1092,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
+ }
int shape_idx = intersection_query_subindex_results[i];
if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
@@ -1142,6 +1160,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
r_result->collision_local_shape = rcd.best_local_shape;
r_result->collision_normal = rcd.best_normal;
r_result->collision_point = rcd.best_contact;
+ r_result->collision_depth = rcd.best_len;
+ r_result->collision_safe_fraction = safe;
+ r_result->collision_unsafe_fraction = unsafe;
r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
const Body2DSW *body = static_cast<const Body2DSW *>(rcd.best_object);
@@ -1167,7 +1188,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
void *Space2DSW::_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_self) {
- if (!A->test_collision_mask(B)) {
+ if (!A->interacts_with(B)) {
return nullptr;
}
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 4d737d622f..f7224e4661 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -183,7 +183,7 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes = true);
+ bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>());
int test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, PhysicsServer2D::SeparationResult *r_results, int p_result_max, real_t p_margin);
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
diff --git a/servers/physics_3d/area_pair_3d_sw.cpp b/servers/physics_3d/area_pair_3d_sw.cpp
index 2073df7dee..f43c2c965e 100644
--- a/servers/physics_3d/area_pair_3d_sw.cpp
+++ b/servers/physics_3d/area_pair_3d_sw.cpp
@@ -33,10 +33,7 @@
bool AreaPair3DSW::setup(real_t p_step) {
bool result = false;
-
- if (area->is_shape_set_as_disabled(area_shape) || body->is_shape_set_as_disabled(body_shape)) {
- result = false;
- } else if (area->test_collision_mask(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
+ if (area->interacts_with(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
result = true;
}
@@ -113,9 +110,7 @@ AreaPair3DSW::~AreaPair3DSW() {
bool Area2Pair3DSW::setup(real_t p_step) {
bool result = false;
- if (area_a->is_shape_set_as_disabled(shape_a) || area_b->is_shape_set_as_disabled(shape_b)) {
- result = false;
- } else if (area_a->test_collision_mask(area_b) && CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
+ if (area_a->interacts_with(area_b) && CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
result = true;
}
diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp
index aed4815c5e..af680f23db 100644
--- a/servers/physics_3d/body_pair_3d_sw.cpp
+++ b/servers/physics_3d/body_pair_3d_sw.cpp
@@ -215,7 +215,7 @@ bool BodyPair3DSW::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
- if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
+ if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
}
@@ -230,11 +230,6 @@ bool BodyPair3DSW::setup(real_t p_step) {
}
}
- if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) {
- collided = false;
- return false;
- }
-
offset_B = B->get_transform().get_origin() - A->get_transform().get_origin();
validate_contacts();
@@ -602,12 +597,7 @@ void BodySoftBodyPair3DSW::validate_contacts() {
bool BodySoftBodyPair3DSW::setup(real_t p_step) {
body_dynamic = (body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
- if (!body->test_collision_mask(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) {
- collided = false;
- return false;
- }
-
- if (body->is_shape_set_as_disabled(body_shape)) {
+ if (!body->interacts_with(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) {
collided = false;
return false;
}
diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/collision_object_3d_sw.cpp
index 51e2432071..24c7d7b85c 100644
--- a/servers/physics_3d/collision_object_3d_sw.cpp
+++ b/servers/physics_3d/collision_object_3d_sw.cpp
@@ -45,8 +45,6 @@ void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform3D &p_tra
if (!pending_shape_update_list.in_list()) {
PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- //_update_shapes();
- //_shapes_changed();
}
void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) {
@@ -58,8 +56,6 @@ void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) {
if (!pending_shape_update_list.in_list()) {
PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- //_update_shapes();
- //_shapes_changed();
}
void CollisionObject3DSW::set_shape_transform(int p_index, const Transform3D &p_transform) {
@@ -70,14 +66,32 @@ void CollisionObject3DSW::set_shape_transform(int p_index, const Transform3D &p_
if (!pending_shape_update_list.in_list()) {
PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- //_update_shapes();
- //_shapes_changed();
}
-void CollisionObject3DSW::set_shape_as_disabled(int p_idx, bool p_enable) {
- shapes.write[p_idx].disabled = p_enable;
- if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+void CollisionObject3DSW::set_shape_disabled(int p_idx, bool p_disabled) {
+ ERR_FAIL_INDEX(p_idx, shapes.size());
+
+ CollisionObject3DSW::Shape &shape = shapes.write[p_idx];
+ if (shape.disabled == p_disabled) {
+ return;
+ }
+
+ shape.disabled = p_disabled;
+
+ if (!space) {
+ return;
+ }
+
+ if (p_disabled && shape.bpid != 0) {
+ space->get_broadphase()->remove(shape.bpid);
+ shape.bpid = 0;
+ if (!pending_shape_update_list.in_list()) {
+ PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ } else if (!p_disabled && shape.bpid == 0) {
+ if (!pending_shape_update_list.in_list()) {
+ PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ }
}
}
@@ -108,8 +122,6 @@ void CollisionObject3DSW::remove_shape(int p_index) {
if (!pending_shape_update_list.in_list()) {
PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
- //_update_shapes();
- //_shapes_changed();
}
void CollisionObject3DSW::_set_static(bool p_static) {
@@ -146,6 +158,9 @@ void CollisionObject3DSW::_update_shapes() {
for (int i = 0; i < shapes.size(); i++) {
Shape &s = shapes.write[i];
+ if (s.disabled) {
+ continue;
+ }
//not quite correct, should compute the next matrix..
AABB shape_aabb = s.shape->get_aabb();
@@ -173,6 +188,9 @@ void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) {
for (int i = 0; i < shapes.size(); i++) {
Shape &s = shapes.write[i];
+ if (s.disabled) {
+ continue;
+ }
//not quite correct, should compute the next matrix..
AABB shape_aabb = s.shape->get_aabb();
diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h
index 5505fec3da..fb8dca8bb4 100644
--- a/servers/physics_3d/collision_object_3d_sw.h
+++ b/servers/physics_3d/collision_object_3d_sw.h
@@ -120,15 +120,26 @@ public:
void set_shape(int p_index, Shape3DSW *p_shape);
void set_shape_transform(int p_index, const Transform3D &p_transform);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
- _FORCE_INLINE_ bool is_shape_disabled(int p_index) const {
+ _FORCE_INLINE_ Shape3DSW *get_shape(int p_index) const {
CRASH_BAD_INDEX(p_index, shapes.size());
- return shapes[p_index].disabled;
+ return shapes[p_index].shape;
+ }
+ _FORCE_INLINE_ const Transform3D &get_shape_transform(int p_index) const {
+ CRASH_BAD_INDEX(p_index, shapes.size());
+ return shapes[p_index].xform;
+ }
+ _FORCE_INLINE_ const Transform3D &get_shape_inv_transform(int p_index) const {
+ CRASH_BAD_INDEX(p_index, shapes.size());
+ return shapes[p_index].xform_inv;
+ }
+ _FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const {
+ CRASH_BAD_INDEX(p_index, shapes.size());
+ return shapes[p_index].aabb_cache;
+ }
+ _FORCE_INLINE_ real_t get_shape_area(int p_index) const {
+ CRASH_BAD_INDEX(p_index, shapes.size());
+ return shapes[p_index].area_cache;
}
- _FORCE_INLINE_ Shape3DSW *get_shape(int p_index) const { return shapes[p_index].shape; }
- _FORCE_INLINE_ const Transform3D &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
- _FORCE_INLINE_ const Transform3D &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
- _FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
- _FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
_FORCE_INLINE_ const Transform3D &get_transform() const { return transform; }
_FORCE_INLINE_ const Transform3D &get_inv_transform() const { return inv_transform; }
@@ -137,9 +148,9 @@ public:
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
- void set_shape_as_disabled(int p_idx, bool p_enable);
- _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const {
- CRASH_BAD_INDEX(p_idx, shapes.size());
+ void set_shape_disabled(int p_idx, bool p_disabled);
+ _FORCE_INLINE_ bool is_shape_disabled(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
return shapes[p_idx].disabled;
}
@@ -155,7 +166,11 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
- _FORCE_INLINE_ bool test_collision_mask(CollisionObject3DSW *p_other) const {
+ _FORCE_INLINE_ bool layer_in_mask(CollisionObject3DSW *p_other) const {
+ return collision_layer & p_other->collision_mask;
+ }
+
+ _FORCE_INLINE_ bool interacts_with(CollisionObject3DSW *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp
index b362f1ff17..6a7f2b73c5 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/collision_solver_3d_sat.cpp
@@ -629,9 +629,7 @@ public:
_FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) {
Vector3 axis = p_axis;
- if (Math::abs(axis.x) < CMP_EPSILON &&
- Math::abs(axis.y) < CMP_EPSILON &&
- Math::abs(axis.z) < CMP_EPSILON) {
+ if (axis.is_equal_approx(Vector3())) {
// strange case, try an upwards separator
axis = Vector3(0.0, 1.0, 0.0);
}
@@ -1024,7 +1022,7 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_tr
n1 *= -1.0;
}
- if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) {
+ if (!separator.test_axis(n1.normalized())) {
return;
}
@@ -1035,7 +1033,7 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_tr
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -1493,7 +1491,7 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -1509,7 +1507,7 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -1533,7 +1531,7 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans
axis_ab *= -1.0;
}
- if (!separator.test_axis(axis_ab.normalized(), !face_B->backface_collision)) {
+ if (!separator.test_axis(axis_ab.normalized())) {
return;
}
@@ -1548,7 +1546,7 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -1578,7 +1576,7 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -1812,7 +1810,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
@@ -1821,7 +1819,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t
dir_axis *= -1.0;
}
- if (!separator.test_axis(dir_axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(dir_axis)) {
return;
}
@@ -1834,7 +1832,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t
n1 *= -1.0;
}
- if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) {
+ if (!separator.test_axis(n1.normalized())) {
return;
}
@@ -1845,7 +1843,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t
axis *= -1.0;
}
- if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
+ if (!separator.test_axis(axis.normalized())) {
return;
}
}
@@ -1955,7 +1953,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
}
// Cylinder end caps.
- if (!separator.test_axis(cyl_axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(cyl_axis)) {
return;
}
@@ -1971,7 +1969,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
axis *= -1.0;
}
- if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
+ if (!separator.test_axis(axis.normalized())) {
return;
}
}
@@ -1984,7 +1982,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -2021,7 +2019,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
axis *= -1.0;
}
- if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
+ if (!separator.test_axis(axis.normalized())) {
return;
}
}
@@ -2175,7 +2173,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -2192,7 +2190,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -2209,7 +2207,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -2229,7 +2227,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
@@ -2248,7 +2246,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
axis *= -1.0;
}
- if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ if (!separator.test_axis(axis)) {
return;
}
}
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index 7a95a8abc8..c1a9d6259d 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -335,7 +335,7 @@ void PhysicsServer3DSW::area_set_shape_disabled(RID p_area, int p_shape_idx, boo
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
FLUSH_QUERY_CHECK(area);
- area->set_shape_as_disabled(p_shape_idx, p_disabled);
+ area->set_shape_disabled(p_shape_idx, p_disabled);
}
void PhysicsServer3DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
@@ -537,7 +537,7 @@ void PhysicsServer3DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, boo
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
FLUSH_QUERY_CHECK(body);
- body->set_shape_as_disabled(p_shape_idx, p_disabled);
+ body->set_shape_disabled(p_shape_idx, p_disabled);
}
Transform3D PhysicsServer3DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
@@ -1584,6 +1584,10 @@ void PhysicsServer3DSW::set_active(bool p_active) {
active = p_active;
};
+void PhysicsServer3DSW::set_collision_iterations(int p_iterations) {
+ iterations = p_iterations;
+};
+
void PhysicsServer3DSW::init() {
last_step = 0.001;
iterations = 8; // 8?
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 57b6385758..0ccd15fbb2 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -367,6 +367,8 @@ public:
virtual void end_sync() override;
virtual void finish() override;
+ virtual void set_collision_iterations(int p_iterations) override;
+
virtual bool is_flushing_queries() const override { return flushing_queries; }
int get_process_info(ProcessInfo p_info) override;
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h
index bda2e30dd1..9beec22bcd 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.h
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.h
@@ -377,6 +377,7 @@ public:
FUNC1(free, RID);
FUNC1(set_active, bool);
+ FUNC1(set_collision_iterations, int);
virtual void init() override;
virtual void step(real_t p_step) override;
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index 2ffab0c923..04a174f9c8 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -1783,7 +1783,7 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
int z = floor(local_begin.z);
// Workaround cases where the ray starts at an integer position.
- if (Math::abs(cross_x) < CMP_EPSILON) {
+ if (Math::is_zero_approx(cross_x)) {
cross_x += delta_x;
// If going backwards, we should ignore the position we would get by the above flooring,
// because the ray is not heading in that direction.
@@ -1792,7 +1792,7 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
}
}
- if (Math::abs(cross_z) < CMP_EPSILON) {
+ if (Math::is_zero_approx(cross_z)) {
cross_z += delta_z;
if (z_step == -1) {
z -= 1;
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index c1e09c9a22..bc149648d7 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -214,10 +214,6 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
if (!CollisionSolver3DSW::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_margin, 0)) {
continue;
}
@@ -259,6 +255,8 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
bool best_first = true;
+ Vector3 motion_normal = p_motion.normalized();
+
Vector3 closest_A, closest_B;
for (int i = 0; i < amount; i++) {
@@ -273,12 +271,8 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
Vector3 point_A, point_B;
- Vector3 sep_axis = p_motion.normalized();
+ Vector3 sep_axis = motion_normal;
Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
@@ -287,35 +281,47 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
}
//test initial overlap, ignore objects it's inside of.
- sep_axis = p_motion.normalized();
+ sep_axis = motion_normal;
if (!CollisionSolver3DSW::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) {
continue;
}
//just do kinematic solving
- real_t low = 0;
- real_t hi = 1;
- Vector3 mnormal = p_motion.normalized();
-
+ real_t low = 0.0;
+ real_t hi = 1.0;
+ real_t fraction_coeff = 0.5;
for (int j = 0; j < 8; j++) { //steps should be customizable..
+ real_t fraction = low + (hi - low) * fraction_coeff;
- real_t ofs = (low + hi) * 0.5;
-
- Vector3 sep = mnormal; //important optimization for this to work fast enough
-
- mshape.motion = xform_inv.basis.xform(p_motion * ofs);
+ mshape.motion = xform_inv.basis.xform(p_motion * fraction);
Vector3 lA, lB;
-
+ Vector3 sep = motion_normal; //important optimization for this to work fast enough
bool collided = !CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep);
if (collided) {
- hi = ofs;
+ hi = fraction;
+ if ((j == 0) || (low > 0.0)) { // Did it not collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When colliding again, converge faster towards low fraction
+ // for more accurate results with long motions that collide near the start.
+ fraction_coeff = 0.25;
+ }
} else {
point_A = lA;
point_B = lB;
- low = ofs;
+ low = fraction;
+ if ((j == 0) || (hi < 1.0)) { // Did it collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When not colliding again, converge faster towards high fraction
+ // for more accurate results with long motions that collide near the end.
+ fraction_coeff = 0.75;
+ }
}
}
@@ -385,10 +391,6 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D &
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
if (CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
collided = true;
}
@@ -460,10 +462,6 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh
int shape_idx = space->intersection_query_subindex_results[i];
- if (col_obj->is_shape_set_as_disabled(shape_idx)) {
- continue;
- }
-
rcd.object = col_obj;
rcd.shape = shape_idx;
bool sc = CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
@@ -508,7 +506,7 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob
bool shapes_found = false;
for (int i = 0; i < obj->get_shape_count(); i++) {
- if (obj->is_shape_set_as_disabled(i)) {
+ if (obj->is_shape_disabled(i)) {
continue;
}
@@ -551,12 +549,10 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) {
keep = false;
- } else if ((static_cast<Body3DSW *>(intersection_query_results[i])->test_collision_mask(p_body)) == 0) {
+ } else if (!p_body->layer_in_mask(static_cast<Body3DSW *>(intersection_query_results[i]))) {
keep = false;
} else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
- } else if (static_cast<Body3DSW *>(intersection_query_results[i])->is_shape_set_as_disabled(intersection_query_subindex_results[i])) {
- keep = false;
}
if (!keep) {
@@ -579,7 +575,7 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_t
bool shapes_found = false;
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (p_body->is_shape_set_as_disabled(i)) {
+ if (p_body->is_shape_disabled(i)) {
continue;
}
@@ -626,7 +622,7 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_t
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int j = 0; j < p_body->get_shape_count(); j++) {
- if (p_body->is_shape_set_as_disabled(j)) {
+ if (p_body->is_shape_disabled(j)) {
continue;
}
@@ -740,7 +736,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
bool shapes_found = false;
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (p_body->is_shape_set_as_disabled(i)) {
+ if (p_body->is_shape_disabled(i)) {
continue;
}
@@ -793,7 +789,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int j = 0; j < p_body->get_shape_count(); j++) {
- if (p_body->is_shape_set_as_disabled(j)) {
+ if (p_body->is_shape_disabled(j)) {
continue;
}
@@ -871,7 +867,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
int amount = _cull_aabb_for_body(p_body, motion_aabb);
for (int j = 0; j < p_body->get_shape_count(); j++) {
- if (p_body->is_shape_set_as_disabled(j)) {
+ if (p_body->is_shape_disabled(j)) {
continue;
}
@@ -920,27 +916,40 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
}
//just do kinematic solving
- real_t low = 0;
- real_t hi = 1;
-
+ real_t low = 0.0;
+ real_t hi = 1.0;
+ real_t fraction_coeff = 0.5;
for (int k = 0; k < 8; k++) { //steps should be customizable..
+ real_t fraction = low + (hi - low) * fraction_coeff;
- real_t ofs = (low + hi) * 0.5;
-
- Vector3 sep = motion_normal; //important optimization for this to work fast enough
-
- mshape.motion = body_shape_xform_inv.basis.xform(p_motion * ofs);
+ mshape.motion = body_shape_xform_inv.basis.xform(p_motion * fraction);
Vector3 lA, lB;
-
+ Vector3 sep = motion_normal; //important optimization for this to work fast enough
bool collided = !CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep);
if (collided) {
- hi = ofs;
+ hi = fraction;
+ if ((k == 0) || (low > 0.0)) { // Did it not collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When colliding again, converge faster towards low fraction
+ // for more accurate results with long motions that collide near the start.
+ fraction_coeff = 0.25;
+ }
} else {
point_A = lA;
point_B = lB;
- low = ofs;
+ low = fraction;
+ if ((k == 0) || (hi < 1.0)) { // Did it collide before?
+ // When alternating or first iteration, use dichotomy.
+ fraction_coeff = 0.5;
+ } else {
+ // When not colliding again, converge faster towards high fraction
+ // for more accurate results with long motions that collide near the end.
+ fraction_coeff = 0.75;
+ }
}
}
@@ -989,7 +998,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
for (int j = from_shape; j < to_shape; j++) {
- if (p_body->is_shape_set_as_disabled(j)) {
+ if (p_body->is_shape_disabled(j)) {
continue;
}
@@ -1032,6 +1041,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
r_result->collision_local_shape = rcd.best_local_shape;
r_result->collision_normal = rcd.best_normal;
r_result->collision_point = rcd.best_contact;
+ r_result->collision_depth = rcd.best_len;
+ r_result->collision_safe_fraction = safe;
+ r_result->collision_unsafe_fraction = unsafe;
//r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_object);
@@ -1058,7 +1070,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
}
void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self) {
- if (!A->test_collision_mask(B)) {
+ if (!A->interacts_with(B)) {
return nullptr;
}
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index faab4f43b8..e8272f377e 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -418,37 +418,6 @@ void PhysicsDirectSpaceState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState2D::_get_rest_info);
}
-int PhysicsShapeQueryResult2D::get_result_count() const {
- return result.size();
-}
-
-RID PhysicsShapeQueryResult2D::get_result_rid(int p_idx) const {
- return result[p_idx].rid;
-}
-
-ObjectID PhysicsShapeQueryResult2D::get_result_object_id(int p_idx) const {
- return result[p_idx].collider_id;
-}
-
-Object *PhysicsShapeQueryResult2D::get_result_object(int p_idx) const {
- return result[p_idx].collider;
-}
-
-int PhysicsShapeQueryResult2D::get_result_object_shape(int p_idx) const {
- return result[p_idx].shape;
-}
-
-PhysicsShapeQueryResult2D::PhysicsShapeQueryResult2D() {
-}
-
-void PhysicsShapeQueryResult2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_result_count"), &PhysicsShapeQueryResult2D::get_result_count);
- ClassDB::bind_method(D_METHOD("get_result_rid", "idx"), &PhysicsShapeQueryResult2D::get_result_rid);
- ClassDB::bind_method(D_METHOD("get_result_object_id", "idx"), &PhysicsShapeQueryResult2D::get_result_object_id);
- ClassDB::bind_method(D_METHOD("get_result_object", "idx"), &PhysicsShapeQueryResult2D::get_result_object);
- ClassDB::bind_method(D_METHOD("get_result_object_shape", "idx"), &PhysicsShapeQueryResult2D::get_result_object_shape);
-}
-
///////////////////////////////
Vector2 PhysicsTestMotionResult2D::get_motion() const {
@@ -487,6 +456,18 @@ int PhysicsTestMotionResult2D::get_collider_shape() const {
return result.collider_shape;
}
+real_t PhysicsTestMotionResult2D::get_collision_depth() const {
+ return result.collision_depth;
+}
+
+real_t PhysicsTestMotionResult2D::get_collision_safe_fraction() const {
+ return result.collision_safe_fraction;
+}
+
+real_t PhysicsTestMotionResult2D::get_collision_unsafe_fraction() const {
+ return result.collision_unsafe_fraction;
+}
+
void PhysicsTestMotionResult2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionResult2D::get_motion);
ClassDB::bind_method(D_METHOD("get_motion_remainder"), &PhysicsTestMotionResult2D::get_motion_remainder);
@@ -497,6 +478,9 @@ void PhysicsTestMotionResult2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collider_rid"), &PhysicsTestMotionResult2D::get_collider_rid);
ClassDB::bind_method(D_METHOD("get_collider"), &PhysicsTestMotionResult2D::get_collider);
ClassDB::bind_method(D_METHOD("get_collider_shape"), &PhysicsTestMotionResult2D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_depth"), &PhysicsTestMotionResult2D::get_collision_depth);
+ ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult2D::get_collision_safe_fraction);
+ ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult2D::get_collision_unsafe_fraction);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "", "get_motion");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_remainder"), "", "get_motion_remainder");
@@ -507,16 +491,23 @@ void PhysicsTestMotionResult2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_collider_rid");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_collision_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_safe_fraction"), "", "get_collision_safe_fraction");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_unsafe_fraction"), "", "get_collision_unsafe_fraction");
}
///////////////////////////////////////
-bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result) {
+bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result, bool p_exclude_raycast_shapes, const Vector<RID> &p_exclude) {
MotionResult *r = nullptr;
if (p_result.is_valid()) {
r = p_result->get_result_ptr();
}
- return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r);
+ Set<RID> exclude;
+ for (int i = 0; i < p_exclude.size(); i++) {
+ exclude.insert(p_exclude[i]);
+ }
+ return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r, p_exclude_raycast_shapes, exclude);
}
void PhysicsServer2D::_bind_methods() {
@@ -643,7 +634,7 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result", "exclude_raycast_shapes", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(true), DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer2D::body_get_direct_state);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index df39d6ae50..8542b54838 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -92,8 +92,6 @@ public:
PhysicsDirectBodyState2D();
};
-class PhysicsShapeQueryResult2D;
-
//used for script
class PhysicsShapeQueryParameters2D : public RefCounted {
GDCLASS(PhysicsShapeQueryParameters2D, RefCounted);
@@ -203,26 +201,6 @@ public:
PhysicsDirectSpaceState2D();
};
-class PhysicsShapeQueryResult2D : public RefCounted {
- GDCLASS(PhysicsShapeQueryResult2D, RefCounted);
-
- Vector<PhysicsDirectSpaceState2D::ShapeResult> result;
-
- friend class PhysicsDirectSpaceState2D;
-
-protected:
- static void _bind_methods();
-
-public:
- int get_result_count() const;
- RID get_result_rid(int p_idx) const;
- ObjectID get_result_object_id(int p_idx) const;
- Object *get_result_object(int p_idx) const;
- int get_result_object_shape(int p_idx) const;
-
- PhysicsShapeQueryResult2D();
-};
-
class PhysicsTestMotionResult2D;
class PhysicsServer2D : public Object {
@@ -230,7 +208,7 @@ class PhysicsServer2D : public Object {
static PhysicsServer2D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>());
+ virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>(), bool p_exclude_raycast_shapes = true, const Vector<RID> &p_exclude = Vector<RID>());
protected:
static void _bind_methods();
@@ -493,6 +471,9 @@ public:
Vector2 collision_point;
Vector2 collision_normal;
Vector2 collider_velocity;
+ real_t collision_depth = 0.0;
+ real_t collision_safe_fraction = 0.0;
+ real_t collision_unsafe_fraction = 0.0;
int collision_local_shape = 0;
ObjectID collider_id;
RID collider;
@@ -500,7 +481,7 @@ public:
Variant collider_metadata;
};
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) = 0;
struct SeparationResult {
real_t collision_depth;
@@ -514,7 +495,7 @@ public:
Variant collider_metadata;
};
- virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) = 0;
+ virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.08) = 0;
/* JOINT API */
@@ -583,7 +564,7 @@ public:
virtual bool is_flushing_queries() const = 0;
- virtual void set_collision_iterations(int iterations) = 0;
+ virtual void set_collision_iterations(int p_iterations) = 0;
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
@@ -619,6 +600,9 @@ public:
RID get_collider_rid() const;
Object *get_collider() const;
int get_collider_shape() const;
+ real_t get_collision_depth() const;
+ real_t get_collision_safe_fraction() const;
+ real_t get_collision_unsafe_fraction() const;
};
typedef PhysicsServer2D *(*CreatePhysicsServer2DCallback)();
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 1634169e8a..3ed8841119 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -365,39 +365,94 @@ void PhysicsDirectSpaceState3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState3D::_get_rest_info);
}
-int PhysicsShapeQueryResult3D::get_result_count() const {
- return result.size();
+///////////////////////////////
+
+Vector3 PhysicsTestMotionResult3D::get_motion() const {
+ return result.motion;
+}
+
+Vector3 PhysicsTestMotionResult3D::get_motion_remainder() const {
+ return result.remainder;
+}
+
+Vector3 PhysicsTestMotionResult3D::get_collision_point() const {
+ return result.collision_point;
}
-RID PhysicsShapeQueryResult3D::get_result_rid(int p_idx) const {
- return result[p_idx].rid;
+Vector3 PhysicsTestMotionResult3D::get_collision_normal() const {
+ return result.collision_normal;
}
-ObjectID PhysicsShapeQueryResult3D::get_result_object_id(int p_idx) const {
- return result[p_idx].collider_id;
+Vector3 PhysicsTestMotionResult3D::get_collider_velocity() const {
+ return result.collider_velocity;
}
-Object *PhysicsShapeQueryResult3D::get_result_object(int p_idx) const {
- return result[p_idx].collider;
+ObjectID PhysicsTestMotionResult3D::get_collider_id() const {
+ return result.collider_id;
}
-int PhysicsShapeQueryResult3D::get_result_object_shape(int p_idx) const {
- return result[p_idx].shape;
+RID PhysicsTestMotionResult3D::get_collider_rid() const {
+ return result.collider;
}
-PhysicsShapeQueryResult3D::PhysicsShapeQueryResult3D() {
+Object *PhysicsTestMotionResult3D::get_collider() const {
+ return ObjectDB::get_instance(result.collider_id);
}
-void PhysicsShapeQueryResult3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_result_count"), &PhysicsShapeQueryResult3D::get_result_count);
- ClassDB::bind_method(D_METHOD("get_result_rid", "idx"), &PhysicsShapeQueryResult3D::get_result_rid);
- ClassDB::bind_method(D_METHOD("get_result_object_id", "idx"), &PhysicsShapeQueryResult3D::get_result_object_id);
- ClassDB::bind_method(D_METHOD("get_result_object", "idx"), &PhysicsShapeQueryResult3D::get_result_object);
- ClassDB::bind_method(D_METHOD("get_result_object_shape", "idx"), &PhysicsShapeQueryResult3D::get_result_object_shape);
+int PhysicsTestMotionResult3D::get_collider_shape() const {
+ return result.collider_shape;
+}
+
+real_t PhysicsTestMotionResult3D::get_collision_depth() const {
+ return result.collision_depth;
+}
+
+real_t PhysicsTestMotionResult3D::get_collision_safe_fraction() const {
+ return result.collision_safe_fraction;
+}
+
+real_t PhysicsTestMotionResult3D::get_collision_unsafe_fraction() const {
+ return result.collision_unsafe_fraction;
+}
+
+void PhysicsTestMotionResult3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionResult3D::get_motion);
+ ClassDB::bind_method(D_METHOD("get_motion_remainder"), &PhysicsTestMotionResult3D::get_motion_remainder);
+ ClassDB::bind_method(D_METHOD("get_collision_point"), &PhysicsTestMotionResult3D::get_collision_point);
+ ClassDB::bind_method(D_METHOD("get_collision_normal"), &PhysicsTestMotionResult3D::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collider_velocity"), &PhysicsTestMotionResult3D::get_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collider_id"), &PhysicsTestMotionResult3D::get_collider_id);
+ ClassDB::bind_method(D_METHOD("get_collider_rid"), &PhysicsTestMotionResult3D::get_collider_rid);
+ ClassDB::bind_method(D_METHOD("get_collider"), &PhysicsTestMotionResult3D::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"), &PhysicsTestMotionResult3D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_depth"), &PhysicsTestMotionResult3D::get_collision_depth);
+ ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult3D::get_collision_safe_fraction);
+ ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult3D::get_collision_unsafe_fraction);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "", "get_motion");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion_remainder"), "", "get_motion_remainder");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_point"), "", "get_collision_point");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_normal"), "", "get_collision_normal");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_collider_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_collider_id");
+ ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_collider_rid");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_collision_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_safe_fraction"), "", "get_collision_safe_fraction");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_unsafe_fraction"), "", "get_collision_unsafe_fraction");
}
///////////////////////////////////////
+bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result) {
+ MotionResult *r = nullptr;
+ if (p_result.is_valid()) {
+ r = p_result->get_result_ptr();
+ }
+ return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r);
+}
+
RID PhysicsServer3D::shape_create(ShapeType p_shape) {
switch (p_shape) {
case SHAPE_PLANE:
@@ -551,6 +606,8 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()));
+
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state);
/* SOFT BODY API */
@@ -683,6 +740,8 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer3D::set_active);
+ ClassDB::bind_method(D_METHOD("set_collision_iterations", "iterations"), &PhysicsServer3D::set_collision_iterations);
+
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer3D::get_process_info);
BIND_ENUM_CONSTANT(SHAPE_PLANE);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index d9b805de87..17bae9a057 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -94,8 +94,6 @@ public:
PhysicsDirectBodyState3D();
};
-class PhysicsShapeQueryResult3D;
-
class PhysicsShapeQueryParameters3D : public RefCounted {
GDCLASS(PhysicsShapeQueryParameters3D, RefCounted);
friend class PhysicsDirectSpaceState3D;
@@ -196,26 +194,6 @@ public:
PhysicsDirectSpaceState3D();
};
-class PhysicsShapeQueryResult3D : public RefCounted {
- GDCLASS(PhysicsShapeQueryResult3D, RefCounted);
-
- Vector<PhysicsDirectSpaceState3D::ShapeResult> result;
-
- friend class PhysicsDirectSpaceState3D;
-
-protected:
- static void _bind_methods();
-
-public:
- int get_result_count() const;
- RID get_result_rid(int p_idx) const;
- ObjectID get_result_object_id(int p_idx) const;
- Object *get_result_object(int p_idx) const;
- int get_result_object_shape(int p_idx) const;
-
- PhysicsShapeQueryResult3D();
-};
-
class RenderingServerHandler {
public:
virtual void set_vertex(int p_vertex_id, const void *p_vector3) = 0;
@@ -225,11 +203,15 @@ public:
virtual ~RenderingServerHandler() {}
};
+class PhysicsTestMotionResult3D;
+
class PhysicsServer3D : public Object {
GDCLASS(PhysicsServer3D, Object);
static PhysicsServer3D *singleton;
+ virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>());
+
protected:
static void _bind_methods();
@@ -497,6 +479,9 @@ public:
Vector3 collision_point;
Vector3 collision_normal;
Vector3 collider_velocity;
+ real_t collision_depth = 0.0;
+ real_t collision_safe_fraction = 0.0;
+ real_t collision_unsafe_fraction = 0.0;
int collision_local_shape = 0;
ObjectID collider_id;
RID collider;
@@ -755,6 +740,8 @@ public:
virtual bool is_flushing_queries() const = 0;
+ virtual void set_collision_iterations(int p_iterations) = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
INFO_COLLISION_PAIRS,
@@ -767,6 +754,33 @@ public:
~PhysicsServer3D();
};
+class PhysicsTestMotionResult3D : public RefCounted {
+ GDCLASS(PhysicsTestMotionResult3D, RefCounted);
+
+ PhysicsServer3D::MotionResult result;
+ friend class PhysicsServer3D;
+
+protected:
+ static void _bind_methods();
+
+public:
+ PhysicsServer3D::MotionResult *get_result_ptr() const { return const_cast<PhysicsServer3D::MotionResult *>(&result); }
+
+ Vector3 get_motion() const;
+ Vector3 get_motion_remainder() const;
+
+ Vector3 get_collision_point() const;
+ Vector3 get_collision_normal() const;
+ Vector3 get_collider_velocity() const;
+ ObjectID get_collider_id() const;
+ RID get_collider_rid() const;
+ Object *get_collider() const;
+ int get_collider_shape() const;
+ real_t get_collision_depth() const;
+ real_t get_collision_safe_fraction() const;
+ real_t get_collision_unsafe_fraction() const;
+};
+
typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)();
class PhysicsServer3DManager {
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index fd11186751..717b4e8d14 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -55,6 +55,7 @@
#include "audio_server.h"
#include "camera/camera_feed.h"
#include "camera_server.h"
+#include "core/extension/native_extension_manager.h"
#include "display_server.h"
#include "navigation_server_2d.h"
#include "navigation_server_3d.h"
@@ -119,106 +120,106 @@ void preregister_server_types() {
void register_server_types() {
OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback);
- ClassDB::register_virtual_class<DisplayServer>();
- ClassDB::register_virtual_class<RenderingServer>();
- ClassDB::register_class<AudioServer>();
+ GDREGISTER_VIRTUAL_CLASS(DisplayServer);
+ GDREGISTER_VIRTUAL_CLASS(RenderingServer);
+ GDREGISTER_CLASS(AudioServer);
- ClassDB::register_class<TextServerManager>();
- ClassDB::register_virtual_class<TextServer>();
+ GDREGISTER_CLASS(TextServerManager);
+ GDREGISTER_VIRTUAL_CLASS(TextServer);
TextServer::initialize_hex_code_box_fonts();
- ClassDB::register_virtual_class<PhysicsServer2D>();
- ClassDB::register_virtual_class<PhysicsServer3D>();
- ClassDB::register_virtual_class<NavigationServer2D>();
- ClassDB::register_virtual_class<NavigationServer3D>();
- ClassDB::register_class<XRServer>();
- ClassDB::register_class<CameraServer>();
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer2D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer3D);
+ GDREGISTER_VIRTUAL_CLASS(NavigationServer2D);
+ GDREGISTER_VIRTUAL_CLASS(NavigationServer3D);
+ GDREGISTER_CLASS(XRServer);
+ GDREGISTER_CLASS(CameraServer);
- ClassDB::register_virtual_class<RenderingDevice>();
+ GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
- ClassDB::register_virtual_class<XRInterface>();
- ClassDB::register_class<XRPositionalTracker>();
+ GDREGISTER_VIRTUAL_CLASS(XRInterface);
+ GDREGISTER_CLASS(XRPositionalTracker);
- ClassDB::register_virtual_class<AudioStream>();
- ClassDB::register_virtual_class<AudioStreamPlayback>();
- ClassDB::register_virtual_class<AudioStreamPlaybackResampled>();
- ClassDB::register_class<AudioStreamMicrophone>();
- ClassDB::register_class<AudioStreamRandomPitch>();
- ClassDB::register_virtual_class<AudioEffect>();
- ClassDB::register_virtual_class<AudioEffectInstance>();
- ClassDB::register_class<AudioEffectEQ>();
- ClassDB::register_class<AudioEffectFilter>();
- ClassDB::register_class<AudioBusLayout>();
+ GDREGISTER_VIRTUAL_CLASS(AudioStream);
+ GDREGISTER_VIRTUAL_CLASS(AudioStreamPlayback);
+ GDREGISTER_VIRTUAL_CLASS(AudioStreamPlaybackResampled);
+ GDREGISTER_CLASS(AudioStreamMicrophone);
+ GDREGISTER_CLASS(AudioStreamRandomPitch);
+ GDREGISTER_VIRTUAL_CLASS(AudioEffect);
+ GDREGISTER_VIRTUAL_CLASS(AudioEffectInstance);
+ GDREGISTER_CLASS(AudioEffectEQ);
+ GDREGISTER_CLASS(AudioEffectFilter);
+ GDREGISTER_CLASS(AudioBusLayout);
- ClassDB::register_class<AudioStreamGenerator>();
- ClassDB::register_virtual_class<AudioStreamGeneratorPlayback>();
+ GDREGISTER_CLASS(AudioStreamGenerator);
+ GDREGISTER_VIRTUAL_CLASS(AudioStreamGeneratorPlayback);
{
//audio effects
- ClassDB::register_class<AudioEffectAmplify>();
+ GDREGISTER_CLASS(AudioEffectAmplify);
- ClassDB::register_class<AudioEffectReverb>();
+ GDREGISTER_CLASS(AudioEffectReverb);
- ClassDB::register_class<AudioEffectLowPassFilter>();
- ClassDB::register_class<AudioEffectHighPassFilter>();
- ClassDB::register_class<AudioEffectBandPassFilter>();
- ClassDB::register_class<AudioEffectNotchFilter>();
- ClassDB::register_class<AudioEffectBandLimitFilter>();
- ClassDB::register_class<AudioEffectLowShelfFilter>();
- ClassDB::register_class<AudioEffectHighShelfFilter>();
+ GDREGISTER_CLASS(AudioEffectLowPassFilter);
+ GDREGISTER_CLASS(AudioEffectHighPassFilter);
+ GDREGISTER_CLASS(AudioEffectBandPassFilter);
+ GDREGISTER_CLASS(AudioEffectNotchFilter);
+ GDREGISTER_CLASS(AudioEffectBandLimitFilter);
+ GDREGISTER_CLASS(AudioEffectLowShelfFilter);
+ GDREGISTER_CLASS(AudioEffectHighShelfFilter);
- ClassDB::register_class<AudioEffectEQ6>();
- ClassDB::register_class<AudioEffectEQ10>();
- ClassDB::register_class<AudioEffectEQ21>();
+ GDREGISTER_CLASS(AudioEffectEQ6);
+ GDREGISTER_CLASS(AudioEffectEQ10);
+ GDREGISTER_CLASS(AudioEffectEQ21);
- ClassDB::register_class<AudioEffectDistortion>();
+ GDREGISTER_CLASS(AudioEffectDistortion);
- ClassDB::register_class<AudioEffectStereoEnhance>();
+ GDREGISTER_CLASS(AudioEffectStereoEnhance);
- ClassDB::register_class<AudioEffectPanner>();
- ClassDB::register_class<AudioEffectChorus>();
- ClassDB::register_class<AudioEffectDelay>();
- ClassDB::register_class<AudioEffectCompressor>();
- ClassDB::register_class<AudioEffectLimiter>();
- ClassDB::register_class<AudioEffectPitchShift>();
- ClassDB::register_class<AudioEffectPhaser>();
+ GDREGISTER_CLASS(AudioEffectPanner);
+ GDREGISTER_CLASS(AudioEffectChorus);
+ GDREGISTER_CLASS(AudioEffectDelay);
+ GDREGISTER_CLASS(AudioEffectCompressor);
+ GDREGISTER_CLASS(AudioEffectLimiter);
+ GDREGISTER_CLASS(AudioEffectPitchShift);
+ GDREGISTER_CLASS(AudioEffectPhaser);
- ClassDB::register_class<AudioEffectRecord>();
- ClassDB::register_class<AudioEffectSpectrumAnalyzer>();
- ClassDB::register_virtual_class<AudioEffectSpectrumAnalyzerInstance>();
+ GDREGISTER_CLASS(AudioEffectRecord);
+ GDREGISTER_CLASS(AudioEffectSpectrumAnalyzer);
+ GDREGISTER_VIRTUAL_CLASS(AudioEffectSpectrumAnalyzerInstance);
- ClassDB::register_class<AudioEffectCapture>();
+ GDREGISTER_CLASS(AudioEffectCapture);
}
- ClassDB::register_virtual_class<RenderingDevice>();
- ClassDB::register_class<RDTextureFormat>();
- ClassDB::register_class<RDTextureView>();
- ClassDB::register_class<RDAttachmentFormat>();
- ClassDB::register_class<RDFramebufferPass>();
- ClassDB::register_class<RDSamplerState>();
- ClassDB::register_class<RDVertexAttribute>();
- ClassDB::register_class<RDUniform>();
- ClassDB::register_class<RDPipelineRasterizationState>();
- ClassDB::register_class<RDPipelineMultisampleState>();
- ClassDB::register_class<RDPipelineDepthStencilState>();
- ClassDB::register_class<RDPipelineColorBlendStateAttachment>();
- ClassDB::register_class<RDPipelineColorBlendState>();
- ClassDB::register_class<RDShaderSource>();
- ClassDB::register_class<RDShaderBytecode>();
- ClassDB::register_class<RDShaderFile>();
-
- ClassDB::register_class<CameraFeed>();
-
- ClassDB::register_virtual_class<PhysicsDirectBodyState2D>();
- ClassDB::register_virtual_class<PhysicsDirectSpaceState2D>();
- ClassDB::register_virtual_class<PhysicsShapeQueryResult2D>();
- ClassDB::register_class<PhysicsTestMotionResult2D>();
- ClassDB::register_class<PhysicsShapeQueryParameters2D>();
-
- ClassDB::register_class<PhysicsShapeQueryParameters3D>();
- ClassDB::register_virtual_class<PhysicsDirectBodyState3D>();
- ClassDB::register_virtual_class<PhysicsDirectSpaceState3D>();
- ClassDB::register_virtual_class<PhysicsShapeQueryResult3D>();
+ GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
+ GDREGISTER_CLASS(RDTextureFormat);
+ GDREGISTER_CLASS(RDTextureView);
+ GDREGISTER_CLASS(RDAttachmentFormat);
+ GDREGISTER_CLASS(RDFramebufferPass);
+ GDREGISTER_CLASS(RDSamplerState);
+ GDREGISTER_CLASS(RDVertexAttribute);
+ GDREGISTER_CLASS(RDUniform);
+ GDREGISTER_CLASS(RDPipelineRasterizationState);
+ GDREGISTER_CLASS(RDPipelineMultisampleState);
+ GDREGISTER_CLASS(RDPipelineDepthStencilState);
+ GDREGISTER_CLASS(RDPipelineColorBlendStateAttachment);
+ GDREGISTER_CLASS(RDPipelineColorBlendState);
+ GDREGISTER_CLASS(RDShaderSource);
+ GDREGISTER_CLASS(RDShaderBytecode);
+ GDREGISTER_CLASS(RDShaderFile);
+ GDREGISTER_CLASS(RDPipelineSpecializationConstant);
+
+ GDREGISTER_CLASS(CameraFeed);
+
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D);
+ GDREGISTER_CLASS(PhysicsTestMotionResult2D);
+ GDREGISTER_CLASS(PhysicsShapeQueryParameters2D);
+
+ GDREGISTER_CLASS(PhysicsShapeQueryParameters3D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D);
+ GDREGISTER_CLASS(PhysicsTestMotionResult3D);
// Physics 2D
GLOBAL_DEF(PhysicsServer2DManager::setting_property_name, "DEFAULT");
@@ -233,22 +234,26 @@ void register_server_types() {
PhysicsServer3DManager::register_server("GodotPhysics3D", &_createGodotPhysics3DCallback);
PhysicsServer3DManager::set_default_server("GodotPhysics3D");
+
+ NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
}
void unregister_server_types() {
+ NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
+
memdelete(shader_types);
TextServer::finish_hex_code_box_fonts();
}
void register_server_singletons() {
- Engine::get_singleton()->add_singleton(Engine::Singleton("DisplayServer", DisplayServer::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("RenderingServer", RenderingServer::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2D", PhysicsServer2D::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton_mut()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("DisplayServer", DisplayServer::get_singleton(), "DisplayServer"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("RenderingServer", RenderingServer::get_singleton(), "RenderingServer"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton(), "AudioServer"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2D", PhysicsServer2D::get_singleton(), "PhysicsServer2D"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton(), "PhysicsServer3D"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut(), "NavigationServer2D"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton_mut(), "NavigationServer3D"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton(), "XRServer"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer"));
}
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index d4c25b6253..b7cf0983af 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -36,6 +36,7 @@
#include "core/templates/self_list.h"
#include "scene/resources/mesh.h"
#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
class RasterizerSceneDummy : public RendererSceneRender {
@@ -60,6 +61,7 @@ public:
void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
+ void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
@@ -175,7 +177,7 @@ public:
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
- void 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, 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_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 = nullptr) override {}
+ void 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, 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_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 = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
@@ -199,6 +201,9 @@ public:
void update() override {}
void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
+ virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
+
RasterizerSceneDummy() {}
~RasterizerSceneDummy() {}
};
@@ -225,7 +230,6 @@ public:
}
void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
- void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
@@ -324,7 +328,9 @@ public:
void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
- void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
@@ -365,23 +371,6 @@ public:
void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
- /* IMMEDIATE API */
-
- RID immediate_allocate() override { return RID(); }
- void immediate_initialize(RID p_rid) override {}
- void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) override {}
- void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) override {}
- void immediate_normal(RID p_immediate, const Vector3 &p_normal) override {}
- void immediate_tangent(RID p_immediate, const Plane &p_tangent) override {}
- void immediate_color(RID p_immediate, const Color &p_color) override {}
- void immediate_uv(RID p_immediate, const Vector2 &tex_uv) override {}
- void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) override {}
- void immediate_end(RID p_immediate) override {}
- void immediate_clear(RID p_immediate) override {}
- void immediate_set_material(RID p_immediate, RID p_material) override {}
- RID immediate_get_material(RID p_immediate) const override { return RID(); }
- AABB immediate_get_aabb(RID p_immediate) const override { return AABB(); }
-
/* SKELETON API */
RID skeleton_allocate() override { return RID(); }
@@ -421,15 +410,14 @@ public:
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_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) override {}
void light_directional_set_sky_only(RID p_light, bool p_sky_only) override {}
bool light_directional_is_sky_only(RID p_light) const override { return false; }
- RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
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(); }
@@ -506,12 +494,6 @@ public:
void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {}
float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; }
- void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) override {}
- float voxel_gi_get_ao(RID p_voxel_gi) const override { return 0; }
-
- void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) override {}
- float voxel_gi_get_ao_size(RID p_voxel_gi) const override { return 0; }
-
void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {}
float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; }
@@ -686,17 +668,15 @@ public:
return true;
}
+ virtual void update_memory_info() override {}
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
+
bool has_os_feature(const String &p_feature) const override { return false; }
void update_dirty_resources() override {}
void set_debug_generate_wireframes(bool p_generate) override {}
- void render_info_begin_capture() override {}
- void render_info_end_capture() override {}
- int get_captured_render_info(RS::RenderInfo p_info) override { return 0; }
-
- uint64_t get_render_info(RS::RenderInfo p_info) override { return 0; }
String get_video_adapter_name() const override { return String(); }
String get_video_adapter_vendor() const override { return String(); }
@@ -734,8 +714,6 @@ public:
void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
void set_shadow_texture_size(int p_size) override {}
- void draw_window_margins(int *p_margins, RID *p_margin_textures) override {}
-
bool free(RID p_rid) override { return true; }
void update() override {}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 016a172f25..ec0a8347f8 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -97,7 +97,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
}
}
-void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<RendererCanvasCull::Item, true> &canvas_item_owner) {
+void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_Owner<RendererCanvasCull::Item, true> &canvas_item_owner) {
do {
ysort_owner->ysort_children_count = -1;
ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : nullptr;
@@ -392,8 +392,7 @@ RID RendererCanvasCull::canvas_allocate() {
return canvas_owner.allocate_rid();
}
void RendererCanvasCull::canvas_initialize(RID p_rid) {
- Canvas *canvas = memnew(Canvas);
- canvas_owner.initialize_rid(p_rid, canvas);
+ canvas_owner.initialize_rid(p_rid);
}
void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) {
@@ -429,8 +428,7 @@ RID RendererCanvasCull::canvas_item_allocate() {
return canvas_item_owner.allocate_rid();
}
void RendererCanvasCull::canvas_item_initialize(RID p_rid) {
- Item *canvas_item = memnew(Item);
- canvas_item_owner.initialize_rid(p_rid, canvas_item);
+ canvas_item_owner.initialize_rid(p_rid);
}
void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
@@ -1171,9 +1169,9 @@ RID RendererCanvasCull::canvas_light_allocate() {
return canvas_light_owner.allocate_rid();
}
void RendererCanvasCull::canvas_light_initialize(RID p_rid) {
- RendererCanvasRender::Light *clight = memnew(RendererCanvasRender::Light);
+ canvas_light_owner.initialize_rid(p_rid);
+ RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_rid);
clight->light_internal = RSG::canvas_render->light_create();
- return canvas_light_owner.initialize_rid(p_rid, clight);
}
void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
@@ -1367,9 +1365,7 @@ RID RendererCanvasCull::canvas_light_occluder_allocate() {
return canvas_light_occluder_owner.allocate_rid();
}
void RendererCanvasCull::canvas_light_occluder_initialize(RID p_rid) {
- RendererCanvasRender::LightOccluderInstance *occluder = memnew(RendererCanvasRender::LightOccluderInstance);
-
- return canvas_light_occluder_owner.initialize_rid(p_rid, occluder);
+ return canvas_light_occluder_owner.initialize_rid(p_rid);
}
void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
@@ -1451,9 +1447,9 @@ RID RendererCanvasCull::canvas_occluder_polygon_allocate() {
return canvas_light_occluder_polygon_owner.allocate_rid();
}
void RendererCanvasCull::canvas_occluder_polygon_initialize(RID p_rid) {
- LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon);
+ canvas_light_occluder_polygon_owner.initialize_rid(p_rid);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid);
occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create();
- return canvas_light_occluder_polygon_owner.initialize_rid(p_rid, occluder_poly);
}
void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
@@ -1596,8 +1592,6 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_owner.free(p_rid);
- memdelete(canvas);
-
} else if (canvas_item_owner.owns(p_rid)) {
Item *canvas_item = canvas_item_owner.getornull(p_rid);
ERR_FAIL_COND_V(!canvas_item, true);
@@ -1632,8 +1626,6 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_item_owner.free(p_rid);
- memdelete(canvas_item);
-
} else if (canvas_light_owner.owns(p_rid)) {
RendererCanvasRender::Light *canvas_light = canvas_light_owner.getornull(p_rid);
ERR_FAIL_COND_V(!canvas_light, true);
@@ -1648,7 +1640,6 @@ bool RendererCanvasCull::free(RID p_rid) {
RSG::canvas_render->free(canvas_light->light_internal);
canvas_light_owner.free(p_rid);
- memdelete(canvas_light);
} else if (canvas_light_occluder_owner.owns(p_rid)) {
RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid);
@@ -1667,7 +1658,6 @@ bool RendererCanvasCull::free(RID p_rid) {
}
canvas_light_occluder_owner.free(p_rid);
- memdelete(occluder);
} else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid);
@@ -1680,7 +1670,6 @@ bool RendererCanvasCull::free(RID p_rid) {
}
canvas_light_occluder_polygon_owner.free(p_rid);
- memdelete(occluder_poly);
} else {
return false;
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index a51b419613..79b5450d14 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -116,9 +116,9 @@ public:
}
};
- RID_PtrOwner<LightOccluderPolygon, true> canvas_light_occluder_polygon_owner;
+ RID_Owner<LightOccluderPolygon, true> canvas_light_occluder_polygon_owner;
- RID_PtrOwner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner;
+ RID_Owner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner;
struct Canvas : public RendererViewport::CanvasBase {
Set<RID> viewports;
@@ -163,9 +163,9 @@ public:
}
};
- mutable RID_PtrOwner<Canvas, true> canvas_owner;
- RID_PtrOwner<Item, true> canvas_item_owner;
- RID_PtrOwner<RendererCanvasRender::Light, true> canvas_light_owner;
+ mutable RID_Owner<Canvas, true> canvas_owner;
+ RID_Owner<Item, true> canvas_item_owner;
+ RID_Owner<RendererCanvasRender::Light, true> canvas_light_owner;
bool disable_scale;
bool sdf_used = false;
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index c10b9db035..8afe9ef410 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -608,8 +608,6 @@ public:
virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0;
virtual void set_shadow_texture_size(int p_size) = 0;
- virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0;
-
virtual bool free(RID p_rid) = 0;
virtual void update() = 0;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index eabdebf4b3..5fe9cdffba 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -36,10 +36,9 @@
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_scene.h"
-#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
-
+class RendererSceneRender;
struct BlitToScreen {
RID render_target;
Rect2i rect;
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 4fd5520e56..5cf8895c8e 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -37,21 +37,6 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "thirdparty/misc/cubemap_coeffs.h"
-static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) {
- p_array[0] = p_basis.elements[0][0];
- p_array[1] = p_basis.elements[1][0];
- p_array[2] = p_basis.elements[2][0];
- p_array[3] = 0;
- p_array[4] = p_basis.elements[0][1];
- p_array[5] = p_basis.elements[1][1];
- p_array[6] = p_basis.elements[2][1];
- p_array[7] = 0;
- p_array[8] = p_basis.elements[0][2];
- p_array[9] = p_basis.elements[1][2];
- p_array[10] = p_basis.elements[2][2];
- p_array[11] = 0;
-}
-
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
@@ -518,11 +503,10 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R
if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_metallic, p_normal_roughness), 3);
} else {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3);
}
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
@@ -1371,45 +1355,6 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
- SkyPushConstant sky_push_constant;
-
- memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
-
- for (uint32_t v = 0; v < p_view_count; v++) {
- // We only need key components of our projection matrix
- sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0];
- sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0];
- sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1];
- sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1];
- }
- sky_push_constant.position[0] = p_position.x;
- sky_push_constant.position[1] = p_position.y;
- sky_push_constant.position[2] = p_position.z;
- sky_push_constant.multiplier = p_multiplier;
- sky_push_constant.time = p_time;
- store_transform_3x3(p_orientation, sky_push_constant.orientation);
-
- RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
-
- RD::DrawListID draw_list = p_list;
-
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0);
- if (p_uniform_set.is_valid()) { //material may not have uniform set
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
- }
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_fog, 3);
-
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
-}
-
void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
ResolvePushConstant push_constant;
push_constant.screen_size[0] = p_screen_size.x;
@@ -1432,6 +1377,24 @@ void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RI
RD::get_singleton()->compute_list_end(p_barrier);
}
+void EffectsRD::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
+ ResolvePushConstant push_constant;
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.samples = p_samples;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[RESOLVE_MODE_DEPTH]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_depth), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_depth), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1);
+
+ RD::get_singleton()->compute_list_end(p_barrier);
+}
+
void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
Sort::PushConstant push_constant;
push_constant.total_elements = p_size;
@@ -1934,6 +1897,7 @@ EffectsRD::EffectsRD() {
Vector<String> resolve_modes;
resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n");
resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n");
+ resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n");
resolve.shader.initialize(resolve_modes);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 8b31ffbbd0..33d32f0c57 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -456,15 +456,6 @@ class EffectsRD {
} filter;
- struct SkyPushConstant {
- float orientation[12]; // 48 - 48
- float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 64, if we ever need more then 3 we should consider adding this to a set.
- float position[3]; // 12 - 92
- float multiplier; // 4 - 96
- float time; // 4 - 100
- float pad[3]; // 12 - 112
- };
-
enum SpecularMergeMode {
SPECULAR_MERGE_ADD,
SPECULAR_MERGE_SSR,
@@ -590,6 +581,7 @@ class EffectsRD {
enum ResolveMode {
RESOLVE_MODE_GI,
RESOLVE_MODE_GI_VOXEL_GI,
+ RESOLVE_MODE_DEPTH,
RESOLVE_MODE_MAX
};
@@ -749,13 +741,13 @@ public:
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
- void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
void sort_buffer(RID p_uniform_set, int p_size);
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 1653453c5c..ac20515c28 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -318,11 +318,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID prev_pipeline_rd;
RID prev_xforms_uniform_set;
- bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP);
+ bool shadow_pass = (p_pass_mode == PASS_MODE_SHADOW) || (p_pass_mode == PASS_MODE_SHADOW_DP);
SceneState::PushConstant push_constant;
- if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
+ if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) {
push_constant.uv_offset = Math::make_half_float(p_params->uv_offset.y) << 16;
push_constant.uv_offset |= Math::make_half_float(p_params->uv_offset.x);
} else {
@@ -339,14 +339,26 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
SceneShaderForwardClustered::ShaderData *shader;
void *mesh_surface;
- if (shadow_pass || p_params->pass_mode == PASS_MODE_DEPTH) { //regular depth pass can use these too
+ if (shadow_pass || p_pass_mode == PASS_MODE_DEPTH) { //regular depth pass can use these too
material_uniform_set = surf->material_uniform_set_shadow;
shader = surf->shader_shadow;
mesh_surface = surf->surface_shadow;
} else {
- material_uniform_set = surf->material_uniform_set;
- shader = surf->shader;
+#ifdef DEBUG_ENABLED
+ if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) {
+ material_uniform_set = scene_shader.default_material_uniform_set;
+ shader = scene_shader.default_material_shader_ptr;
+ } else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW)) {
+ material_uniform_set = scene_shader.overdraw_material_uniform_set;
+ shader = scene_shader.overdraw_material_shader_ptr;
+ } else {
+#endif
+ material_uniform_set = surf->material_uniform_set;
+ shader = surf->shader;
+#ifdef DEBUG_ENABLED
+ }
+#endif
mesh_surface = surf->surface;
}
@@ -357,7 +369,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
//find cull variant
SceneShaderForwardClustered::ShaderData::CullVariant cull_variant;
- if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL || p_params->pass_mode == PASS_MODE_SDF || ((p_params->pass_mode == PASS_MODE_SHADOW || p_params->pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
+ if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
cull_variant = SceneShaderForwardClustered::ShaderData::CULL_VARIANT_DOUBLE_SIDED;
} else {
bool mirror = surf->owner->mirror;
@@ -372,14 +384,30 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
SceneShaderForwardClustered::ShaderVersion shader_version = SceneShaderForwardClustered::SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
- switch (p_params->pass_mode) {
+ uint32_t pipeline_specialization = 0;
+
+ if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) {
+ if (element_info.uses_softshadow) {
+ pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS;
+ }
+ if (element_info.uses_projector) {
+ pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_PROJECTOR;
+ }
+
+ if (p_params->use_directional_soft_shadow) {
+ pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS;
+ }
+ }
+
+ switch (p_pass_mode) {
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
if (element_info.uses_lightmap) {
shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
- } else if (element_info.uses_forward_gi) {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI;
} else {
+ if (element_info.uses_forward_gi) {
+ pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
+ }
shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS;
}
} break;
@@ -440,7 +468,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
prev_index_array_rd = index_array_rd;
}
- RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe);
+ RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, 0, pipeline_specialization);
if (pipeline_rd != prev_pipeline_rd) {
// checking with prev shader does not make so much sense, as
@@ -561,11 +589,6 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
- scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get();
- scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get();
- scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get();
- scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get();
-
Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y;
@@ -801,13 +824,16 @@ void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_rende
RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr(), RD::BARRIER_MASK_RASTER);
}
}
-void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) {
+void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, int *p_render_info, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) {
RenderList *rl = &render_list[p_render_list];
uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size();
scene_state.instance_data[p_render_list].resize(p_offset + element_total);
rl->element_info.resize(p_offset + element_total);
+ if (p_render_info) {
+ p_render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] += element_total;
+ }
uint32_t repeats = 0;
GeometryInstanceSurfaceDataCache *prev_surface = nullptr;
for (uint32_t i = 0; i < element_total; i++) {
@@ -833,7 +859,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, u
bool cant_repeat = instance_data.flags & INSTANCE_DATA_FLAG_MULTIMESH || inst->mesh_instance.is_valid();
- if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2) {
+ if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && repeats < RenderElementInfo::MAX_REPEATS) {
//this element is the same as the previous one, count repeats to draw it using instancing
repeats++;
} else {
@@ -843,6 +869,9 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, u
}
}
repeats = 1;
+ if (p_render_info) {
+ p_render_info[RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME]++;
+ }
}
RenderElementInfo &element_info = rl->element_info[p_offset + i];
@@ -850,6 +879,8 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, u
element_info.lod_index = surface->sort.lod_index;
element_info.uses_forward_gi = surface->sort.uses_forward_gi;
element_info.uses_lightmap = surface->sort.uses_lightmap;
+ element_info.uses_softshadow = surface->sort.uses_softshadow;
+ element_info.uses_projector = surface->sort.uses_projector;
if (cant_repeat) {
prev_surface = nullptr;
@@ -869,6 +900,11 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, u
}
}
+_FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) {
+ static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 };
+ static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 };
+ return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
+}
void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) {
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
@@ -903,6 +939,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
uint32_t flags = inst->base_flags; //fill flags if appropriate
+ if (inst->non_uniform_scale) {
+ flags |= INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE;
+ }
bool uses_lightmap = false;
bool uses_gi = false;
@@ -1008,17 +1047,41 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
distance = -distance_max;
}
- surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ uint32_t indices;
+ surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, &indices);
+ if (p_render_data->render_info) {
+ indices = _indices_to_primitives(surf->primitive, indices);
+ if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += indices;
+ } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += indices;
+ }
+ }
} else {
surf->sort.lod_index = 0;
+ if (p_render_data->render_info) {
+ uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ to_draw = _indices_to_primitives(surf->primitive, to_draw);
+ to_draw *= inst->instance_count;
+ if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ }
+ }
}
// ADD Element
if (p_pass_mode == PASS_MODE_COLOR) {
- if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+#ifdef DEBUG_ENABLED
+ bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW);
+#else
+ bool force_alpha = false;
+#endif
+ if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
rl->add_element(surf);
}
- if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA) {
+ if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) {
render_list[RENDER_LIST_ALPHA].add_element(surf);
if (uses_gi) {
surf->sort.uses_forward_gi = 1;
@@ -1100,6 +1163,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
}
RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
+ static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 };
//first of all, make a new render pass
//fill up ubo
@@ -1209,8 +1273,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_voxelgi);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
- render_list[RENDER_LIST_ALPHA].sort_by_depth();
- _fill_instance_data(RENDER_LIST_OPAQUE);
+ render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority();
+ _fill_instance_data(RENDER_LIST_OPAQUE, p_render_data->render_info ? p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE] : (int *)nullptr);
_fill_instance_data(RENDER_LIST_ALPHA);
RD::get_singleton()->draw_command_end_label();
@@ -1324,7 +1388,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1340,10 +1404,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (needs_pre_resolve) {
RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE);
}
- static int texture_samples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 };
- storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_voxelgi ? render_buffer->voxelgi_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_voxelgi ? render_buffer->voxelgi_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]);
+ storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_voxelgi ? render_buffer->voxelgi_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_voxelgi ? render_buffer->voxelgi_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
} else if (finish_depth) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth);
+ storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
}
RD::get_singleton()->draw_command_end_label();
}
@@ -1382,7 +1445,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
_render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
@@ -1447,7 +1510,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth);
+ storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
}
if (using_separate_specular) {
@@ -1479,7 +1542,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -1503,7 +1566,7 @@ void RenderForwardClustered::_render_shadow_begin() {
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -1518,6 +1581,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
render_data.instances = &p_instances;
render_data.lod_camera_plane = p_camera_plane;
render_data.lod_distance_multiplier = p_lod_distance_multiplier;
+ render_data.render_info = p_render_info;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
@@ -1535,7 +1599,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, false, false, true);
uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from;
render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size);
- _fill_instance_data(RENDER_LIST_SECONDARY, render_list_from, render_list_size, false);
+ _fill_instance_data(RENDER_LIST_SECONDARY, p_render_info ? p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW] : (int *)nullptr, render_list_from, render_list_size, false);
{
//regular forward for now
@@ -1580,7 +1644,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1621,7 +1685,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
{
//regular forward for now
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set);
_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
}
RD::get_singleton()->draw_command_end_label();
@@ -1656,7 +1720,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RENDER_TIMESTAMP("Render Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -1699,7 +1763,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RENDER_TIMESTAMP("Render Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set, true);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -1817,7 +1881,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set, false);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, false);
_render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
@@ -1873,13 +1937,67 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ 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);
+ } 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);
+ } break;
+ case RS::DECAL_FILTER_LINEAR: {
+ sampler = 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);
+ } 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);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ 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);
+ } 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);
+ } 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);
+ } 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);
+ } 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);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 4;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_spot_light_buffer());
uniforms.push_back(u);
@@ -1887,35 +2005,35 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
{
RD::Uniform u;
- u.binding = 5;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_reflection_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_capture_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 9;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture();
u.ids.push_back(decal_atlas);
@@ -1923,7 +2041,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
u.ids.push_back(decal_atlas);
@@ -1931,7 +2049,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_decal_buffer());
uniforms.push_back(u);
@@ -1940,7 +2058,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 12;
+ u.binding = 14;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1948,7 +2066,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 13;
+ u.binding = 15;
u.ids.push_back(sdfgi_get_ubo());
uniforms.push_back(u);
}
@@ -2460,12 +2578,14 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->sort.sort_key2 = 0;
sdcache->sort.surface_index = p_surface;
- sdcache->sort.material_id_low = p_material_id & 0x3FFF;
- sdcache->sort.material_id_hi = p_material_id >> 14;
+ sdcache->sort.material_id_low = p_material_id & 0xFFFF;
+ sdcache->sort.material_id_hi = p_material_id >> 16;
sdcache->sort.shader_id = p_shader_id;
sdcache->sort.geometry_id = p_mesh.get_local_index(); //only meshes can repeat anyway
sdcache->sort.uses_forward_gi = ginstance->can_sdfgi;
sdcache->sort.priority = p_material->priority;
+ sdcache->sort.uses_projector = ginstance->using_projectors;
+ sdcache->sort.uses_softshadow = ginstance->using_softshadows;
}
void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
@@ -2594,6 +2714,8 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
//Fill push constant
+ ginstance->base_flags = 0;
+
bool store_transform = true;
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
@@ -2737,6 +2859,7 @@ void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p
float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
+
ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
ginstance->lod_model_scale = max_scale;
@@ -2857,6 +2980,56 @@ void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryI
}
}
+void RenderForwardClustered::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->using_projectors = p_projector;
+ ginstance->using_softshadows = p_softshadow;
+ _geometry_instance_mark_dirty(ginstance);
+}
+
+void RenderForwardClustered::_update_shader_quality_settings() {
+ Vector<RD::PipelineSpecializationConstant> spec_constants;
+
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+
+ sc.constant_id = SPEC_CONSTANT_SOFT_SHADOW_SAMPLES;
+ sc.int_value = soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES;
+ sc.int_value = directional_soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = directional_penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ scene_shader.set_default_specialization_constants(spec_constants);
+
+ _base_uniforms_changed(); //also need this
+}
+
RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
RendererSceneRenderRD(p_storage) {
singleton = this;
@@ -2894,6 +3067,8 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
}
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
+
+ _update_shader_quality_settings();
}
RenderForwardClustered::~RenderForwardClustered() {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 579c8de05e..6682c5e9b0 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -51,6 +51,15 @@ class RenderForwardClustered : public RendererSceneRenderRD {
};
enum {
+ SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 6,
+ SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 7,
+ SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 8,
+ SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9,
+ SPEC_CONSTANT_DECAL_FILTER = 10,
+ SPEC_CONSTANT_PROJECTOR_FILTER = 11,
+ };
+
+ enum {
SDFGI_MAX_CASCADES = 8,
MAX_VOXEL_GI_INSTANCESS = 8,
MAX_LIGHTMAPS = 8,
@@ -108,7 +117,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
~RenderBufferDataForwardClustered();
};
- virtual RenderBufferData *_create_render_buffer_data();
+ virtual RenderBufferData *_create_render_buffer_data() override;
void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
RID render_base_uniform_set;
@@ -117,8 +126,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
- virtual void _base_uniforms_changed();
- virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
+ virtual void _base_uniforms_changed() override;
+ virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
@@ -156,8 +165,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
uint32_t barrier = RD::BARRIER_MASK_ALL;
+ bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -172,6 +182,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
screen_lod_threshold = p_screen_lod_threshold;
element_offset = p_element_offset;
barrier = p_barrier;
+ use_directional_soft_shadow = p_use_directional_soft_shadows;
}
};
@@ -184,6 +195,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
};
enum {
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
@@ -196,7 +208,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 24,
};
struct SceneState {
@@ -220,11 +231,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float penumbra_shadow_kernel[128];
float soft_shadow_kernel[128];
- uint32_t directional_penumbra_shadow_samples;
- uint32_t directional_soft_shadow_samples;
- uint32_t penumbra_shadow_samples;
- uint32_t soft_shadow_samples;
-
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
@@ -353,7 +359,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
struct RenderElementInfo {
- uint32_t repeat : 22;
+ enum { MAX_REPEATS = (1 << 20) - 1 };
+ uint32_t repeat : 20;
+ uint32_t uses_projector : 1;
+ uint32_t uses_softshadow : 1;
uint32_t uses_lightmap : 1;
uint32_t uses_forward_gi : 1;
uint32_t lod_index : 8;
@@ -371,7 +380,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t render_list_thread_threshold = 500;
void _update_instance_data_buffer(RenderListType p_render_list);
- void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
+ void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false);
Map<Size2i, RID> sdfgi_framebuffer_size_cache;
@@ -402,12 +411,14 @@ class RenderForwardClustered : public RendererSceneRenderRD {
union {
struct {
uint64_t lod_index : 8;
- uint64_t surface_index : 10;
+ uint64_t surface_index : 8;
uint64_t geometry_id : 32;
- uint64_t material_id_low : 14;
+ uint64_t material_id_low : 16;
- uint64_t material_id_hi : 18;
+ uint64_t material_id_hi : 16;
uint64_t shader_id : 32;
+ uint64_t uses_softshadow : 1;
+ uint64_t uses_projector : 1;
uint64_t uses_forward_gi : 1;
uint64_t uses_lightmap : 1;
uint64_t depth_layer : 4;
@@ -455,6 +466,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t trail_steps = 1;
RID mesh_instance;
bool can_sdfgi = false;
+ bool using_projectors = false;
+ bool using_softshadows = false;
//used during setup
uint32_t base_flags = 0;
Transform3D transform;
@@ -551,7 +564,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
}
};
- void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
+ void sort_by_reverse_depth_and_priority() { //used for alpha
SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;
sorter.sort(elements.ptr(), elements.size());
@@ -564,47 +577,51 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RenderList render_list[RENDER_LIST_MAX];
+ virtual void _update_shader_quality_settings() override;
+
protected:
- virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color);
+ virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
- virtual void _render_shadow_begin();
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
- virtual void _render_shadow_process();
- virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ virtual void _render_shadow_begin() override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_process() override;
+ virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
public:
- virtual GeometryInstance *geometry_instance_create(RID p_base);
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance);
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
-
- virtual uint32_t geometry_instance_get_pair_mask();
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count);
-
- virtual bool free(RID p_rid);
+ virtual GeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
+ virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
+ virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
+ virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
+ virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
+ virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
+ virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
+ virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
+
+ virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
+
+ virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+
+ virtual uint32_t geometry_instance_get_pair_mask() override;
+ virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
+ virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
+ virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
+ virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
+
+ virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
+
+ virtual bool free(RID p_rid) override;
RenderForwardClustered(RendererStorageRD *p_storage);
~RenderForwardClustered();
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 f125931df8..333e87bdbd 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
@@ -287,7 +287,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
multisample_state.enable_alpha_to_one = true;
}
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
blend_state = blend_state_blend;
if (depth_draw == DEPTH_DRAW_OPAQUE) {
depth_stencil.enable_depth_write = false; //alpha does not draw depth
@@ -305,7 +305,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
continue; // do not use this version (will error if using it is attempted)
}
} else {
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
blend_state = blend_state_opaque;
} else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
//none, leave empty
@@ -320,13 +320,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
} else {
//specular write
blend_state = blend_state_opaque_specular;
- depth_stencil.enable_depth_test = false;
- depth_stencil.enable_depth_write = false;
}
}
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
}
}
@@ -410,7 +408,8 @@ RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_s
return shader_singleton->shader.version_get_native_source_code(version);
}
-SceneShaderForwardClustered::ShaderData::ShaderData() {
+SceneShaderForwardClustered::ShaderData::ShaderData() :
+ shader_list_element(this) {
valid = false;
uses_screen_texture = false;
}
@@ -426,6 +425,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
+ singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
}
@@ -437,94 +437,14 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) {
next_pass = p_pass;
}
-void SceneShaderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool SceneShaderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
- if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(shader_data->ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER);
- }
-
- uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
- }
-
- if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (shader_data->ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (uint32_t i = 0; i < tex_uniform_count; i++) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + i;
- u.ids.push_back(textures[i]);
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET);
+ 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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER);
}
SceneShaderForwardClustered::MaterialData::~MaterialData() {
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
+ free_parameters_uniform_set(uniform_set);
}
RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
@@ -546,11 +466,9 @@ SceneShaderForwardClustered::~SceneShaderForwardClustered() {
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(wireframe_material_shader);
storage->free(overdraw_material_shader);
storage->free(default_shader);
- storage->free(wireframe_material);
storage->free(overdraw_material);
storage->free(default_material);
}
@@ -567,7 +485,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
- shader_versions.push_back("\n#define USE_FORWARD_GI\n"); // SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI
shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
@@ -633,7 +550,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["SSS_STRENGTH"] = "sss_strength";
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
- actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve";
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
actions.renames["BACKLIGHT"] = "backlight";
actions.renames["AO"] = "ao";
@@ -767,7 +683,19 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
//default material and shader
default_shader = storage->shader_allocate();
storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n");
+ storage->shader_set_code(default_shader, R"(
+shader_type spatial;
+
+void vertex() {
+ ROUGHNESS = 0.8;
+}
+
+void fragment() {
+ ALBEDO = vec3(0.6);
+ ROUGHNESS = 0.8;
+ METALLIC = 0.2;
+}
+)");
default_material = storage->material_allocate();
storage->material_initialize(default_material);
storage->material_set_shader(default_material, default_shader);
@@ -775,22 +703,32 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
+
+ default_material_shader_ptr = md->shader_data;
+ default_material_uniform_set = md->uniform_set;
}
{
overdraw_material_shader = storage->shader_allocate();
storage->shader_initialize(overdraw_material_shader);
- storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
+ // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
+ storage->shader_set_code(overdraw_material_shader, R"(
+shader_type spatial;
+
+render_mode blend_add, unshaded;
+
+void fragment() {
+ ALBEDO = vec3(0.4, 0.8, 0.8);
+ ALPHA = 0.1;
+}
+)");
overdraw_material = storage->material_allocate();
storage->material_initialize(overdraw_material);
storage->material_set_shader(overdraw_material, overdraw_material_shader);
- wireframe_material_shader = storage->shader_allocate();
- storage->shader_initialize(wireframe_material_shader);
- storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }");
- wireframe_material = storage->material_allocate();
- storage->material_initialize(wireframe_material);
- storage->material_set_shader(wireframe_material, wireframe_material_shader);
+ MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ overdraw_material_shader_ptr = md->shader_data;
+ overdraw_material_uniform_set = md->uniform_set;
}
{
@@ -813,3 +751,16 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
}
+
+void SceneShaderForwardClustered::set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants) {
+ default_specialization_constants = p_constants;
+ for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
+ for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) {
+ for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
+ for (int k = 0; k < SHADER_VERSION_MAX; k++) {
+ E->self()->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 8add9f8095..8d75f30a20 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
@@ -52,7 +52,6 @@ public:
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI,
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
@@ -60,6 +59,13 @@ public:
SHADER_VERSION_MAX
};
+ enum ShaderSpecializations {
+ SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
+ SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
+ SHADER_SPECIALIZATION_SOFT_SHADOWS = 1 << 2,
+ SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
+ };
+
struct ShaderData : public RendererStorageRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
@@ -154,10 +160,13 @@ public:
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ SelfList<ShaderData> shader_list_element;
ShaderData();
virtual ~ShaderData();
};
+ SelfList<ShaderData>::List shader_list;
+
RendererStorageRD::ShaderData *_create_shader_func();
static RendererStorageRD::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func();
@@ -166,17 +175,14 @@ public:
struct MaterialData : public RendererStorageRD::MaterialData {
uint64_t last_frame;
ShaderData *shader_data;
- RID uniform_buffer;
RID uniform_set;
- Vector<RID> texture_cache;
- Vector<uint8_t> ubo_data;
uint64_t last_pass = 0;
uint32_t index = 0;
RID next_pass;
uint8_t priority;
virtual void set_render_priority(int p_priority);
virtual void set_next_pass(RID p_pass);
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~MaterialData();
};
@@ -192,8 +198,6 @@ public:
RID default_material;
RID overdraw_material_shader;
RID overdraw_material;
- RID wireframe_material_shader;
- RID wireframe_material;
RID default_shader_rd;
RID default_shader_sdfgi_rd;
@@ -202,10 +206,18 @@ public:
RID shadow_sampler;
+ RID default_material_uniform_set;
+ ShaderData *default_material_shader_ptr = nullptr;
+
+ RID overdraw_material_uniform_set;
+ ShaderData *overdraw_material_shader_ptr = nullptr;
+
+ Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
void init(RendererStorageRD *p_storage, const String p_defines);
+ void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
};
} // namespace RendererSceneRenderImplementation
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 ae09d215ff..438bbff53c 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -35,6 +35,34 @@
using namespace RendererSceneRenderImplementation;
+RenderForwardMobile::ForwardID RenderForwardMobile::_allocate_forward_id(ForwardIDType p_type) {
+ int32_t index = -1;
+ for (uint32_t i = 0; i < forward_id_allocators[p_type].allocations.size(); i++) {
+ if (forward_id_allocators[p_type].allocations[i] == false) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index == -1) {
+ index = forward_id_allocators[p_type].allocations.size();
+ forward_id_allocators[p_type].allocations.push_back(true);
+ forward_id_allocators[p_type].map.push_back(0xFF);
+ } else {
+ forward_id_allocators[p_type].allocations[index] = true;
+ }
+
+ return index;
+}
+void RenderForwardMobile::_free_forward_id(ForwardIDType p_type, ForwardID p_id) {
+ ERR_FAIL_INDEX(p_id, (ForwardID)forward_id_allocators[p_type].allocations.size());
+ forward_id_allocators[p_type].allocations[p_id] = false;
+}
+
+void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) {
+ forward_id_allocators[p_type].map[p_id] = p_index;
+}
+
/* Render buffer */
void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
@@ -65,9 +93,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
color = p_color_buffer;
depth = p_depth_buffer;
- // re-introduce setting up msaa? For now we ignore this...
+ RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
+ if (color_format == RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32) {
+ // @TODO add a second color buffer for alpha as this format is RGB only
+ }
+
Vector<RID> fb;
fb.push_back(p_color_buffer);
fb.push_back(depth);
@@ -80,7 +112,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
} else {
tf.texture_type = RD::TEXTURE_TYPE_2D;
}
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.format = color_format;
tf.width = p_width;
tf.height = p_height;
tf.array_layers = view_count; // create a layer for every view
@@ -131,6 +163,20 @@ bool RenderForwardMobile::free(RID p_rid) {
/* Render functions */
+RD::DataFormat RenderForwardMobile::_render_buffers_get_color_format() {
+ // Using 32bit buffers enables AFBC on mobile devices which should have a definate performance improvement (MALI G710 and newer support this on 64bit RTs)
+ // NO ALPHA and unsigned float.
+ // @TODO No alpha is an issue, recommendation here is to add a second RT for alpha
+ return RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+}
+
+bool RenderForwardMobile::_render_buffers_can_be_storage() {
+ // Using 32bit buffers enables AFBC on mobile devices which should have a definate performance improvement (MALI G710 and newer support this on 64bit RTs)
+ // NO ALPHA and unsigned float.
+ // @TODO No alpha is an issue, recommendation here is to add a second RT for alpha
+ return false;
+}
+
RID RenderForwardMobile::_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) {
//there should always be enough uniform buffers for render passes, otherwise bugs
ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
@@ -335,6 +381,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
bool using_ssr = false;
bool using_sss = false;
+ if (p_render_data->render_info) {
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = p_render_data->instances->size();
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
+ }
+
if (render_buffer) {
// setup rendering to render buffer
screen_size.x = render_buffer->width;
@@ -369,7 +420,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
- render_list[RENDER_LIST_ALPHA].sort_by_depth();
+ render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority();
// we no longer use this...
_fill_instance_data(RENDER_LIST_OPAQUE);
@@ -555,11 +606,15 @@ void RenderForwardMobile::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
+void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
+ if (p_render_info) {
+ p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = p_instances.size();
+ p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_instances.size();
+ }
RenderDataRD render_data;
render_data.cam_projection = p_projection;
render_data.cam_transform = p_transform;
@@ -567,6 +622,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
render_data.z_near = 0.0;
render_data.z_far = p_zfar;
render_data.instances = &p_instances;
+ render_data.render_info = p_render_info;
render_data.lod_camera_plane = p_camera_plane;
render_data.lod_distance_multiplier = p_lod_distance_multiplier;
@@ -843,13 +899,67 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ 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);
+ } 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);
+ } break;
+ case RS::DECAL_FILTER_LINEAR: {
+ sampler = 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);
+ } 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);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ 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);
+ } 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);
+ } 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);
+ } 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);
+ } 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);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 4;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_spot_light_buffer());
uniforms.push_back(u);
@@ -857,35 +967,35 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
{
RD::Uniform u;
- u.binding = 5;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_reflection_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_capture_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 9;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture();
u.ids.push_back(decal_atlas);
@@ -893,7 +1003,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
u.ids.push_back(decal_atlas);
@@ -901,7 +1011,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_decal_buffer());
uniforms.push_back(u);
@@ -910,7 +1020,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 12;
+ u.binding = 14;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -927,6 +1037,12 @@ RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers
return RID();
}
+_FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) {
+ static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 };
+ static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 };
+ return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
+}
+
void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append) {
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
@@ -963,6 +1079,10 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
uint32_t flags = inst->base_flags; //fill flags if appropriate
+ if (inst->non_uniform_scale) {
+ flags |= INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE;
+ }
+
bool uses_lightmap = false;
// bool uses_gi = false;
@@ -1032,21 +1152,42 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
distance = -distance_max;
}
- surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ uint32_t indices;
+ surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, &indices);
+ if (p_render_data->render_info) {
+ indices = _indices_to_primitives(surf->primitive, indices);
+ if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += indices;
+ } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += indices;
+ }
+ }
} else {
surf->lod_index = 0;
+ if (p_render_data->render_info) {
+ uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ to_draw = _indices_to_primitives(surf->primitive, to_draw);
+ to_draw *= inst->instance_count;
+ if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ }
+ }
}
// ADD Element
if (p_pass_mode == PASS_MODE_COLOR) {
- if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+#ifdef DEBUG_ENABLED
+ bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW);
+#else
+ bool force_alpha = false;
+#endif
+ if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
rl->add_element(surf);
}
- if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA) {
+ if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) {
render_list[RENDER_LIST_ALPHA].add_element(surf);
- // if (uses_gi) {
- // surf->sort.uses_forward_gi = 1;
- // }
}
if (uses_lightmap) {
@@ -1116,11 +1257,6 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
- scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get();
- scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get();
- scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get();
- scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get();
-
Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y;
@@ -1351,6 +1487,44 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para
}
}
+void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, const GeometryInstanceForwardMobile *p_instance) {
+ // first zero out our indices
+
+ p_push_constant->omni_lights[0] = 0xFFFF;
+ p_push_constant->omni_lights[1] = 0xFFFF;
+
+ p_push_constant->spot_lights[0] = 0xFFFF;
+ p_push_constant->spot_lights[1] = 0xFFFF;
+
+ p_push_constant->decals[0] = 0xFFFF;
+ p_push_constant->decals[1] = 0xFFFF;
+
+ p_push_constant->reflection_probes[0] = 0xFFFF;
+ p_push_constant->reflection_probes[1] = 0xFFFF;
+
+ for (uint32_t i = 0; i < MAX_RDL_CULL; i++) {
+ uint32_t ofs = i < 4 ? 0 : 1;
+ uint32_t shift = (i & 0x3) << 3;
+ uint32_t mask = ~(0xFF << shift);
+ if (i < p_instance->omni_light_count) {
+ p_push_constant->omni_lights[ofs] &= mask;
+ p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift;
+ }
+ if (i < p_instance->spot_light_count) {
+ p_push_constant->spot_lights[ofs] &= mask;
+ p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift;
+ }
+ if (i < p_instance->decals_count) {
+ p_push_constant->decals[ofs] &= mask;
+ p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift;
+ }
+ if (i < p_instance->reflection_probe_count) {
+ p_push_constant->reflection_probes[ofs] &= mask;
+ p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift;
+ }
+ }
+}
+
template <RenderForwardMobile::PassMode p_pass_mode>
void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
RD::DrawListID draw_list = p_draw_list;
@@ -1400,8 +1574,6 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
push_constant.lightmap_uv_scale[3] = inst->lightmap_uv_scale.size.y;
};
- _fill_instance_indices(inst->omni_lights, inst->omni_light_count, push_constant.omni_lights, inst->spot_lights, inst->spot_light_count, push_constant.spot_lights, inst->reflection_probes, inst->reflection_probe_count, push_constant.reflection_probes, inst->decals, inst->decals_count, push_constant.decals, push_constant.layer_mask);
-
RID material_uniform_set;
SceneShaderForwardMobile::ShaderData *shader;
void *mesh_surface;
@@ -1412,8 +1584,22 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
mesh_surface = surf->surface_shadow;
} else {
- material_uniform_set = surf->material_uniform_set;
- shader = surf->shader;
+ _fill_push_constant_instance_indices(&push_constant, inst);
+
+#ifdef DEBUG_ENABLED
+ if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) {
+ material_uniform_set = scene_shader.default_material_uniform_set;
+ shader = scene_shader.default_material_shader_ptr;
+ } else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW)) {
+ material_uniform_set = scene_shader.overdraw_material_uniform_set;
+ shader = scene_shader.overdraw_material_shader_ptr;
+ } else {
+#endif
+ material_uniform_set = surf->material_uniform_set;
+ shader = surf->shader;
+#ifdef DEBUG_ENABLED
+ }
+#endif
mesh_surface = surf->surface;
}
@@ -1708,13 +1894,13 @@ void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstanc
switch (type) {
case RS::LIGHT_OMNI: {
if (ginstance->omni_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->omni_lights[ginstance->omni_light_count] = p_light_instances[i];
+ ginstance->omni_lights[ginstance->omni_light_count] = light_instance_get_forward_id(p_light_instances[i]);
ginstance->omni_light_count++;
}
} break;
case RS::LIGHT_SPOT: {
if (ginstance->spot_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->spot_lights[ginstance->spot_light_count] = p_light_instances[i];
+ ginstance->spot_lights[ginstance->spot_light_count] = light_instance_get_forward_id(p_light_instances[i]);
ginstance->spot_light_count++;
}
} break;
@@ -1730,7 +1916,7 @@ void RenderForwardMobile::geometry_instance_pair_reflection_probe_instances(Geom
ginstance->reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL;
for (uint32_t i = 0; i < ginstance->reflection_probe_count; i++) {
- ginstance->reflection_probes[i] = p_reflection_probe_instances[i];
+ ginstance->reflection_probes[i] = reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]);
}
}
@@ -1740,7 +1926,7 @@ void RenderForwardMobile::geometry_instance_pair_decal_instances(GeometryInstanc
ginstance->decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL;
for (uint32_t i = 0; i < ginstance->decals_count; i++) {
- ginstance->decals[i] = p_decal_instances[i];
+ ginstance->decals[i] = decal_instance_get_forward_id(p_decal_instances[i]);
}
}
@@ -1748,6 +1934,9 @@ void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInst
// We do not have this here!
}
+void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
+}
+
void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
if (ginstance->dirty_list_element.in_list()) {
@@ -1995,6 +2184,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
//Fill push constant
bool store_transform = true;
+ ginstance->base_flags = 0;
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -2096,6 +2286,48 @@ uint32_t RenderForwardMobile::get_max_elements() const {
RenderForwardMobile *RenderForwardMobile::singleton = nullptr;
+void RenderForwardMobile::_update_shader_quality_settings() {
+ Vector<RD::PipelineSpecializationConstant> spec_constants;
+
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+
+ sc.constant_id = SPEC_CONSTANT_SOFT_SHADOW_SAMPLES;
+ sc.int_value = soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES;
+ sc.int_value = directional_soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = directional_penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ scene_shader.set_default_specialization_constants(spec_constants);
+
+ _base_uniforms_changed(); //also need this
+}
+
RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
RendererSceneRenderRD(p_storage) {
singleton = this;
@@ -2131,6 +2363,8 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
// !BAS! maybe we need a mobile version of this setting?
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
+
+ _update_shader_quality_settings();
}
RenderForwardMobile::~RenderForwardMobile() {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 99cbd45b10..973925d562 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -42,6 +42,18 @@ namespace RendererSceneRenderImplementation {
class RenderForwardMobile : public RendererSceneRenderRD {
friend SceneShaderForwardMobile;
+ struct ForwardIDAllocator {
+ LocalVector<bool> allocations;
+ LocalVector<uint8_t> map;
+ };
+
+ ForwardIDAllocator forward_id_allocators[FORWARD_ID_MAX];
+
+ virtual ForwardID _allocate_forward_id(ForwardIDType p_type) override;
+ virtual void _free_forward_id(ForwardIDType p_type, ForwardID p_id) override;
+ virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) override;
+ virtual bool _uses_forward_ids() const override { return true; }
+
protected:
/* Scene Shader */
@@ -53,6 +65,15 @@ protected:
};
enum {
+ SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 6,
+ SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 7,
+ SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 8,
+ SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9,
+ SPEC_CONSTANT_DECAL_FILTER = 10,
+ SPEC_CONSTANT_PROJECTOR_FILTER = 11,
+ };
+
+ enum {
MAX_LIGHTMAPS = 8,
MAX_RDL_CULL = 8, // maximum number of reflection probes, decals or lights we can cull per geometry instance
INSTANCE_DATA_BUFFER_MIN_SIZE = 4096
@@ -93,7 +114,7 @@ protected:
~RenderBufferDataForwardMobile();
};
- virtual RenderBufferData *_create_render_buffer_data();
+ virtual RenderBufferData *_create_render_buffer_data() override;
/* Rendering */
@@ -151,24 +172,27 @@ protected:
}
};
+ virtual RD::DataFormat _render_buffers_get_color_format() override;
+ virtual bool _render_buffers_can_be_storage() override;
+
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
- virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color);
+ virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
- virtual void _render_shadow_begin();
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
- virtual void _render_shadow_process();
- virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ virtual void _render_shadow_begin() override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_process() override;
+ virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
- virtual void _base_uniforms_changed();
+ virtual void _base_uniforms_changed() override;
void _update_render_base_uniform_set();
- virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
+ virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
@@ -213,11 +237,6 @@ protected:
float penumbra_shadow_kernel[128];
float soft_shadow_kernel[128];
- uint32_t directional_penumbra_shadow_samples;
- uint32_t directional_soft_shadow_samples;
- uint32_t penumbra_shadow_samples;
- uint32_t soft_shadow_samples;
-
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
@@ -356,7 +375,7 @@ protected:
}
};
- void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
+ void sort_by_reverse_depth_and_priority() { //used for alpha
SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;
sorter.sort(elements.ptr(), elements.size());
@@ -390,6 +409,7 @@ protected:
// check which ones of these apply, probably all except GI and SDFGI
enum {
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
@@ -402,7 +422,6 @@ protected:
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 24,
};
struct GeometryInstanceLightmapSH {
@@ -513,14 +532,14 @@ protected:
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
// culled light info
- uint32_t reflection_probe_count;
- RID reflection_probes[MAX_RDL_CULL];
- uint32_t omni_light_count;
- RID omni_lights[MAX_RDL_CULL];
- uint32_t spot_light_count;
- RID spot_lights[MAX_RDL_CULL];
- uint32_t decals_count;
- RID decals[MAX_RDL_CULL];
+ uint32_t reflection_probe_count = 0;
+ ForwardID reflection_probes[MAX_RDL_CULL];
+ uint32_t omni_light_count = 0;
+ ForwardID omni_lights[MAX_RDL_CULL];
+ uint32_t spot_light_count = 0;
+ ForwardID spot_lights[MAX_RDL_CULL];
+ uint32_t decals_count = 0;
+ ForwardID decals[MAX_RDL_CULL];
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
@@ -552,6 +571,10 @@ protected:
dirty_list_element(this) {}
};
+ _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, const GeometryInstanceForwardMobile *p_instance);
+
+ void _update_shader_quality_settings() override;
+
public:
static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
@@ -568,38 +591,40 @@ public:
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
- virtual GeometryInstance *geometry_instance_create(RID p_base);
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance);
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
-
- virtual uint32_t geometry_instance_get_pair_mask();
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count);
-
- virtual bool free(RID p_rid);
-
- virtual bool is_dynamic_gi_supported() const;
- virtual bool is_clustered_enabled() const;
- virtual bool is_volumetric_supported() const;
- virtual uint32_t get_max_elements() const;
+ virtual GeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
+ virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
+ virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
+ virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
+ virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
+ virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
+ virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
+ virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
+
+ virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
+
+ virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+
+ virtual uint32_t geometry_instance_get_pair_mask() override;
+ virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
+ virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
+ virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
+ virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
+
+ virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
+
+ virtual bool free(RID p_rid) override;
+
+ virtual bool is_dynamic_gi_supported() const override;
+ virtual bool is_clustered_enabled() const override;
+ virtual bool is_volumetric_supported() const override;
+ virtual uint32_t get_max_elements() const override;
RenderForwardMobile(RendererStorageRD *p_storage);
~RenderForwardMobile();
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index b5fb9fbc62..bcdcb05653 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -318,7 +318,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
}
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
}
}
@@ -402,7 +402,8 @@ RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_sour
return shader_singleton->shader.version_get_native_source_code(version);
}
-SceneShaderForwardMobile::ShaderData::ShaderData() {
+SceneShaderForwardMobile::ShaderData::ShaderData() :
+ shader_list_element(this) {
valid = false;
uses_screen_texture = false;
}
@@ -418,6 +419,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
+ singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
}
@@ -429,94 +431,14 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
next_pass = p_pass;
}
-void SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
- if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(shader_data->ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER);
- }
-
- uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
- }
-
- if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (shader_data->ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (uint32_t i = 0; i < tex_uniform_count; i++) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + i;
- u.ids.push_back(textures[i]);
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET);
+ 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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER);
}
SceneShaderForwardMobile::MaterialData::~MaterialData() {
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
+ free_parameters_uniform_set(uniform_set);
}
RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
@@ -621,7 +543,6 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["SSS_STRENGTH"] = "sss_strength";
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
- actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve";
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
actions.renames["BACKLIGHT"] = "backlight";
actions.renames["AO"] = "ao";
@@ -752,29 +673,51 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
//default material and shader
default_shader = storage->shader_allocate();
storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n");
+ storage->shader_set_code(default_shader, R"(
+shader_type spatial;
+
+void vertex() {
+ ROUGHNESS = 0.8;
+}
+
+void fragment() {
+ ALBEDO = vec3(0.6);
+ ROUGHNESS = 0.8;
+ METALLIC = 0.2;
+}
+)");
default_material = storage->material_allocate();
storage->material_initialize(default_material);
storage->material_set_shader(default_material, default_shader);
MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
+
+ default_material_shader_ptr = md->shader_data;
+ default_material_uniform_set = md->uniform_set;
}
{
overdraw_material_shader = storage->shader_allocate();
storage->shader_initialize(overdraw_material_shader);
- storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
+ // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
+ storage->shader_set_code(overdraw_material_shader, R"(
+shader_type spatial;
+
+render_mode blend_add, unshaded;
+
+void fragment() {
+ ALBEDO = vec3(0.4, 0.8, 0.8);
+ ALPHA = 0.1;
+}
+)");
overdraw_material = storage->material_allocate();
storage->material_initialize(overdraw_material);
storage->material_set_shader(overdraw_material, overdraw_material_shader);
- wireframe_material_shader = storage->shader_allocate();
- storage->shader_initialize(wireframe_material_shader);
- storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }");
- wireframe_material = storage->material_allocate();
- storage->material_initialize(wireframe_material);
- storage->material_set_shader(wireframe_material, wireframe_material_shader);
+ MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ overdraw_material_shader_ptr = md->shader_data;
+ overdraw_material_uniform_set = md->uniform_set;
}
{
@@ -798,15 +741,26 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
}
}
+void SceneShaderForwardMobile::set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants) {
+ default_specialization_constants = p_constants;
+ for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
+ for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) {
+ for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
+ for (int k = 0; k < SHADER_VERSION_MAX; k++) {
+ E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
+ }
+ }
+ }
+ }
+}
+
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(wireframe_material_shader);
storage->free(overdraw_material_shader);
storage->free(default_shader);
- storage->free(wireframe_material);
storage->free(overdraw_material);
storage->free(default_material);
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index f4f6ceeb1d..e1c10f0206 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -151,6 +151,8 @@ public:
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ SelfList<ShaderData> shader_list_element;
+
ShaderData();
virtual ~ShaderData();
};
@@ -163,20 +165,19 @@ public:
struct MaterialData : public RendererStorageRD::MaterialData {
uint64_t last_frame;
ShaderData *shader_data;
- RID uniform_buffer;
RID uniform_set;
- Vector<RID> texture_cache;
- Vector<uint8_t> ubo_data;
uint64_t last_pass = 0;
uint32_t index = 0;
RID next_pass;
uint8_t priority;
virtual void set_render_priority(int p_priority);
virtual void set_next_pass(RID p_pass);
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~MaterialData();
};
+ SelfList<ShaderData>::List shader_list;
+
RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
@@ -189,8 +190,6 @@ public:
RID default_material;
RID overdraw_material_shader;
RID overdraw_material;
- RID wireframe_material_shader;
- RID wireframe_material;
RID default_shader_rd;
RID default_vec4_xform_buffer;
@@ -198,10 +197,19 @@ public:
RID shadow_sampler;
+ RID default_material_uniform_set;
+ ShaderData *default_material_shader_ptr = nullptr;
+
+ RID overdraw_material_uniform_set;
+ ShaderData *overdraw_material_shader_ptr = nullptr;
+
SceneShaderForwardMobile();
~SceneShaderForwardMobile();
+ Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
+
void init(RendererStorageRD *p_storage, const String p_defines);
+ void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
};
} // namespace RendererSceneRenderImplementation
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index 22888ddbe5..aefe926cb0 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -31,14 +31,30 @@
#include "pipeline_cache_rd.h"
#include "core/os/memory.h"
-RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass) {
+RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations) {
RD::PipelineMultisampleState multisample_state_version = multisample_state;
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id, p_render_pass);
RD::PipelineRasterizationState raster_state_version = rasterization_state;
raster_state_version.wireframe = p_wireframe;
- RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass);
+ Vector<RD::PipelineSpecializationConstant> specialization_constants = base_specialization_constants;
+
+ uint32_t bool_index = 0;
+ uint32_t bool_specializations = p_bool_specializations;
+ while (bool_specializations) {
+ if (bool_specializations & (1 << bool_index)) {
+ RD::PipelineSpecializationConstant sc;
+ sc.bool_value = true;
+ sc.constant_id = bool_index;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ specialization_constants.push_back(sc);
+ bool_specializations &= ~(1 << bool_index);
+ }
+ bool_index++;
+ }
+
+ RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass, specialization_constants);
ERR_FAIL_COND_V(pipeline.is_null(), RID());
versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
versions[version_count].framebuffer_id = p_framebuffer_format_id;
@@ -46,11 +62,15 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
versions[version_count].wireframe = p_wireframe;
versions[version_count].pipeline = pipeline;
versions[version_count].render_pass = p_render_pass;
+ versions[version_count].bool_specializations = p_bool_specializations;
version_count++;
return pipeline;
}
void PipelineCacheRD::_clear() {
+#ifndef _MSC_VER
+#warning Clear should probably recompile all the variants already compiled instead to avoid stalls? needs discussion
+#endif
if (versions) {
for (uint32_t i = 0; i < version_count; i++) {
//shader may be gone, so this may not be valid
@@ -64,7 +84,7 @@ void PipelineCacheRD::_clear() {
}
}
-void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) {
+void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, const Vector<RD::PipelineSpecializationConstant> &p_base_specialization_constants) {
ERR_FAIL_COND(p_shader.is_null());
_clear();
shader = p_shader;
@@ -75,6 +95,11 @@ void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const
depth_stencil_state = p_depth_stencil_state;
blend_state = p_blend_state;
dynamic_state_flags = p_dynamic_state_flags;
+ base_specialization_constants = p_base_specialization_constants;
+}
+void PipelineCacheRD::update_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_base_specialization_constants) {
+ base_specialization_constants = p_base_specialization_constants;
+ _clear();
}
void PipelineCacheRD::update_shader(RID p_shader) {
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 387a8a038f..e52f47fa47 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -46,27 +46,30 @@ class PipelineCacheRD {
RD::PipelineDepthStencilState depth_stencil_state;
RD::PipelineColorBlendState blend_state;
int dynamic_state_flags;
+ Vector<RD::PipelineSpecializationConstant> base_specialization_constants;
struct Version {
RD::VertexFormatID vertex_id;
RD::FramebufferFormatID framebuffer_id;
uint32_t render_pass;
bool wireframe;
+ uint32_t bool_specializations;
RID pipeline;
};
Version *versions;
uint32_t version_count;
- RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass);
+ RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations = 0);
void _clear();
public:
- void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0);
+ void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, const Vector<RD::PipelineSpecializationConstant> &p_base_specialization_constants = Vector<RD::PipelineSpecializationConstant>());
+ void update_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_base_specialization_constants);
void update_shader(RID p_shader);
- _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false, uint32_t p_render_pass = 0) {
+ _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false, uint32_t p_render_pass = 0, uint32_t p_bool_specializations = 0) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
"Attempted to use an unused shader variant (shader is null),");
@@ -75,13 +78,13 @@ public:
spin_lock.lock();
RID result;
for (uint32_t i = 0; i < version_count; i++) {
- if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe && versions[i].render_pass == p_render_pass) {
+ if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe && versions[i].render_pass == p_render_pass && versions[i].bool_specializations == p_bool_specializations) {
result = versions[i].pipeline;
spin_lock.unlock();
return result;
}
}
- result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe, p_render_pass);
+ result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe, p_render_pass, p_bool_specializations);
spin_lock.unlock();
return result;
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 026969c09f..6a66e9fa01 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -2201,94 +2201,14 @@ RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
return shader_data;
}
-void RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
- if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(shader_data->ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
- }
-
- uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false);
- }
-
- if (shader_data->ubo_size == 0) {
- // This material does not require an uniform set, so don't create it.
- return;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (shader_data->ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (uint32_t i = 0; i < tex_uniform_count; i++) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + i;
- u.ids.push_back(textures[i]);
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
+ 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, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
}
RendererCanvasRenderRD::MaterialData::~MaterialData() {
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
+ free_parameters_uniform_set(uniform_set);
}
RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) {
@@ -2650,8 +2570,19 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
default_canvas_group_shader = storage->shader_allocate();
storage->shader_initialize(default_canvas_group_shader);
- storage->shader_set_code(default_canvas_group_shader, "shader_type canvas_item; \nvoid fragment() {\n\tvec4 c = textureLod(SCREEN_TEXTURE,SCREEN_UV,0.0); if (c.a > 0.0001) c.rgb/=c.a; COLOR *= c; \n}\n");
+ storage->shader_set_code(default_canvas_group_shader, R"(
+shader_type canvas_item;
+
+void fragment() {
+ vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
+ if (c.a > 0.0001) {
+ c.rgb /= c.a;
+ }
+
+ COLOR *= c;
+}
+)");
default_canvas_group_material = storage->material_allocate();
storage->material_initialize(default_canvas_group_material);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 8c1376e2dc..7c4f62832c 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -201,14 +201,11 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
struct MaterialData : public RendererStorageRD::MaterialData {
uint64_t last_frame;
ShaderData *shader_data;
- RID uniform_buffer;
RID uniform_set;
- Vector<RID> texture_cache;
- Vector<uint8_t> ubo_data;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~MaterialData();
};
@@ -457,8 +454,6 @@ public:
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {}
- void draw_window_margins(int *p_margins, RID *p_margin_textures) {}
-
virtual void set_shadow_texture_size(int p_size);
void set_time(double p_time);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index f9ac7c8fa3..e6ae66d56f 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -60,8 +60,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
}
Size2 screen_size(RD::get_singleton()->screen_get_width(p_screen), RD::get_singleton()->screen_get_height(p_screen));
- BlitMode mode = p_render_targets[i].lens_distortion.apply ? BLIT_MODE_LENS : p_render_targets[i].multi_view.use_layer ? BLIT_MODE_USE_LAYER :
- BLIT_MODE_NORMAL;
+ BlitMode mode = p_render_targets[i].lens_distortion.apply ? BLIT_MODE_LENS : (p_render_targets[i].multi_view.use_layer ? BLIT_MODE_USE_LAYER : BLIT_MODE_NORMAL);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blit.pipelines[mode]);
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
@@ -111,13 +110,14 @@ void RendererCompositorRD::initialize() {
blit_modes.push_back("\n");
blit_modes.push_back("\n#define USE_LAYER\n");
blit_modes.push_back("\n#define USE_LAYER\n#define APPLY_LENS_DISTORTION\n");
+ blit_modes.push_back("\n");
blit.shader.initialize(blit_modes);
blit.shader_version = blit.shader.version_create();
for (int i = 0; i < BLIT_MODE_MAX; i++) {
- blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
+ blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), i == BLIT_MODE_NORMAL_ALPHA ? RenderingDevice::PipelineColorBlendState::create_blend() : RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
}
//create index array for copy shader
@@ -153,6 +153,78 @@ void RendererCompositorRD::finalize() {
RD::get_singleton()->free(blit.sampler);
}
+void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
+ RD::get_singleton()->prepare_screen_for_drawing();
+
+ RID texture = storage->texture_allocate();
+ storage->texture_2d_initialize(texture, p_image);
+ RID rd_texture = storage->texture_get_rd_texture(texture);
+
+ RID uset;
+ {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(blit.sampler);
+ u.ids.push_back(rd_texture);
+ uniforms.push_back(u);
+ uset = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0);
+ }
+
+ Size2 window_size = DisplayServer::get_singleton()->window_get_size();
+
+ Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
+ Rect2 screenrect;
+ if (p_scale) {
+ if (window_size.width > window_size.height) {
+ //scale horizontally
+ screenrect.size.y = window_size.height;
+ screenrect.size.x = imgrect.size.x * window_size.height / imgrect.size.y;
+ screenrect.position.x = (window_size.width - screenrect.size.x) / 2;
+
+ } else {
+ //scale vertically
+ screenrect.size.x = window_size.width;
+ screenrect.size.y = imgrect.size.y * window_size.width / imgrect.size.x;
+ screenrect.position.y = (window_size.height - screenrect.size.y) / 2;
+ }
+ } else {
+ screenrect = imgrect;
+ screenrect.position += ((Size2(window_size.width, window_size.height) - screenrect.size) / 2.0).floor();
+ }
+
+ screenrect.position /= window_size;
+ screenrect.size /= window_size;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(DisplayServer::MAIN_WINDOW_ID, p_color);
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blit.pipelines[BLIT_MODE_NORMAL_ALPHA]);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0);
+
+ blit.push_constant.rect[0] = screenrect.position.x;
+ blit.push_constant.rect[1] = screenrect.position.y;
+ blit.push_constant.rect[2] = screenrect.size.width;
+ blit.push_constant.rect[3] = screenrect.size.height;
+ blit.push_constant.layer = 0;
+ blit.push_constant.eye_center[0] = 0;
+ blit.push_constant.eye_center[1] = 0;
+ blit.push_constant.k1 = 0;
+ blit.push_constant.k2 = 0;
+ blit.push_constant.upscale = 1.0;
+ blit.push_constant.aspect_ratio = 1.0;
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+
+ RD::get_singleton()->draw_list_end();
+
+ RD::get_singleton()->swap_buffers();
+
+ RD::get_singleton()->free(texture);
+}
+
RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 7a78322051..15b3b77ed9 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -50,6 +50,7 @@ protected:
BLIT_MODE_NORMAL,
BLIT_MODE_USE_LAYER,
BLIT_MODE_LENS,
+ BLIT_MODE_NORMAL_ALPHA,
BLIT_MODE_MAX
};
@@ -88,7 +89,7 @@ public:
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) {}
+ void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter);
void initialize();
void begin_frame(double frame_step);
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index be1642998c..98d08f68e8 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -3029,8 +3029,6 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers);
- RD::get_singleton()->draw_command_begin_label("VoxelGIs Setup");
-
VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES];
bool voxel_gi_instances_changed = false;
@@ -3078,9 +3076,6 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
gipd.bias = storage->voxel_gi_get_bias(base_probe);
gipd.normal_bias = storage->voxel_gi_get_normal_bias(base_probe);
gipd.blend_ambient = !storage->voxel_gi_is_interior(base_probe);
- gipd.anisotropy_strength = 0;
- gipd.ao = storage->voxel_gi_get_ao(base_probe);
- gipd.ao_size = Math::pow(storage->voxel_gi_get_ao_size(base_probe), 4.0f);
gipd.mipmaps = gipi->mipmaps.size();
}
@@ -3113,10 +3108,12 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
}
if (p_voxel_gi_instances.size() > 0) {
+ RD::get_singleton()->draw_command_begin_label("VoxelGIs Setup");
+
RD::get_singleton()->buffer_update(voxel_gi_buffer, 0, sizeof(VoxelGIData) * MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()), voxel_gi_data, RD::BARRIER_MASK_COMPUTE);
- }
- RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_end_label();
+ }
}
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) {
@@ -3349,6 +3346,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
} else {
mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
}
+
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi.uniform_set, 0);
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index 45fc7b3951..128bf09063 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -611,9 +611,9 @@ public:
uint32_t blend_ambient;
uint32_t texture_slot;
- float anisotropy_strength;
- float ao;
- float ao_size;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
uint32_t mipmaps;
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 089651cbfb..4870f5f397 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -567,6 +567,8 @@ int RendererSceneRenderRD::reflection_atlas_get_size(RID p_ref_atlas) const {
RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) {
ReflectionProbeInstance rpi;
rpi.probe = p_probe;
+ rpi.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE);
+
return reflection_probe_instance_owner.make_rid(rpi);
}
@@ -654,12 +656,12 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
//reflection atlas was unused, create:
RD::TextureFormat tf;
tf.array_layers = 6 * atlas->count;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.format = _render_buffers_get_color_format();
tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
tf.mipmaps = mipmaps;
tf.width = atlas->size;
tf.height = atlas->size;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
@@ -709,6 +711,10 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
}
}
+ if (rpi->atlas_index != -1) { // should we fail if this is still -1 ?
+ atlas->reflections.write[rpi->atlas_index].owner = p_instance;
+ }
+
rpi->atlas = p_reflection_atlas;
rpi->rendering = true;
rpi->dirty = false;
@@ -1229,6 +1235,9 @@ 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);
+ 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);
+ }
return li;
}
@@ -1302,6 +1311,7 @@ RendererSceneRenderRD::ShadowCubemap *RendererSceneRenderRD::_get_shadow_cubemap
RID RendererSceneRenderRD::decal_instance_create(RID p_decal) {
DecalInstance di;
di.decal = p_decal;
+ di.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_DECAL);
return decal_instance_owner.make_rid(di);
}
@@ -2114,6 +2124,14 @@ float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID
return rb->volumetric_fog->spread;
}
+RD::DataFormat RendererSceneRenderRD::_render_buffers_get_color_format() {
+ return RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+}
+
+bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
+ return true;
+}
+
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have atleast 1 view");
@@ -2140,13 +2158,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
if (rb->view_count > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.format = _render_buffers_get_color_format();
tf.width = rb->width;
tf.height = rb->height;
tf.array_layers = rb->view_count; // create a layer for every view
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
} else {
tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
@@ -2241,6 +2259,8 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
get_vogel_disk(penumbra_shadow_kernel, penumbra_shadow_samples);
get_vogel_disk(soft_shadow_kernel, soft_shadow_samples);
}
+
+ _update_shader_quality_settings();
}
void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) {
@@ -2281,6 +2301,23 @@ void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_q
get_vogel_disk(directional_penumbra_shadow_kernel, directional_penumbra_shadow_samples);
get_vogel_disk(directional_soft_shadow_kernel, directional_soft_shadow_samples);
}
+
+ _update_shader_quality_settings();
+}
+
+void RendererSceneRenderRD::decals_set_filter(RenderingServer::DecalFilter p_filter) {
+ if (decals_filter == p_filter) {
+ return;
+ }
+ decals_filter = p_filter;
+ _update_shader_quality_settings();
+}
+void RendererSceneRenderRD::light_projectors_set_filter(RenderingServer::LightProjectorFilter p_filter) {
+ if (light_projectors_filter == p_filter) {
+ return;
+ }
+ light_projectors_filter = p_filter;
+ _update_shader_quality_settings();
}
int RendererSceneRenderRD::get_roughness_layers() const {
@@ -2320,10 +2357,13 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
sort_array.sort(cluster.reflection_sort, cluster.reflection_count);
}
+ bool using_forward_ids = _uses_forward_ids();
for (uint32_t i = 0; i < cluster.reflection_count; i++) {
ReflectionProbeInstance *rpi = cluster.reflection_sort[i].instance;
- rpi->render_index = i;
+ if (using_forward_ids) {
+ _map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i);
+ }
RID base_probe = rpi->probe;
@@ -2373,7 +2413,7 @@ 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) {
+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) {
Transform3D inverse_transform = p_camera_transform.affine_inverse();
r_directional_light_count = 0;
@@ -2385,6 +2425,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
cluster.omni_light_count = 0;
cluster.spot_light_count = 0;
+ r_directional_light_soft_shadows = false;
+
for (int i = 0; i < (int)p_lights.size(); i++) {
LightInstance *li = light_instance_owner.getornull(p_lights[i]);
if (!li) {
@@ -2423,6 +2465,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// 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)) {
+ r_directional_light_soft_shadows = true;
+ }
} else {
angular_diameter = 0.0;
}
@@ -2615,6 +2660,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
}
+ bool using_forward_ids = _uses_forward_ids();
+
for (uint32_t i = 0; i < (cluster.omni_light_count + cluster.spot_light_count); i++) {
uint32_t index = (i < cluster.omni_light_count) ? i : i - (cluster.omni_light_count);
Cluster::LightData &light_data = (i < cluster.omni_light_count) ? cluster.omni_lights[index] : cluster.spot_lights[index];
@@ -2622,6 +2669,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
LightInstance *li = (i < cluster.omni_light_count) ? cluster.omni_light_sort[index].instance : cluster.spot_light_sort[index].instance;
RID base = li->light;
+ if (using_forward_ids) {
+ _map_forward_id(type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, li->forward_id, index);
+ }
+
Transform3D light_transform = li->transform;
float sign = storage->light_is_negative(base) ? -1 : 1;
@@ -2754,7 +2805,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.shadow_enabled = false;
}
- li->light_index = index;
li->cull_mask = storage->light_get_cull_mask(base);
if (current_cluster_builder != nullptr) {
@@ -2823,11 +2873,15 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
sort_array.sort(cluster.decal_sort, cluster.decal_count);
}
+ bool using_forward_ids = _uses_forward_ids();
for (uint32_t i = 0; i < cluster.decal_count; i++) {
DecalInstance *di = cluster.decal_sort[i].instance;
RID decal = di->decal;
- di->render_index = i;
+ if (using_forward_ids) {
+ _map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i);
+ }
+
di->cull_mask = storage->decal_get_cull_mask(decal);
Transform3D xform = di->transform;
@@ -2944,116 +2998,6 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
}
}
-void RendererSceneRenderRD::_fill_instance_indices(const RID *p_omni_light_instances, uint32_t p_omni_light_instance_count, uint32_t *p_omni_light_indices, const RID *p_spot_light_instances, uint32_t p_spot_light_instance_count, uint32_t *p_spot_light_indices, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count, uint32_t *p_reflection_probe_indices, const RID *p_decal_instances, uint32_t p_decal_instance_count, uint32_t *p_decal_instance_indices, uint32_t p_layer_mask, uint32_t p_max_dst_words) {
- // first zero out our indices
- for (uint32_t i = 0; i < p_max_dst_words; i++) {
- p_omni_light_indices[i] = 0;
- p_spot_light_indices[i] = 0;
- p_reflection_probe_indices[i] = 0;
- p_decal_instance_indices[i] = 0;
- }
-
- {
- // process omni lights
- uint32_t dword = 0;
- uint32_t shift = 0;
-
- for (uint32_t i = 0; i < p_omni_light_instance_count && dword < p_max_dst_words; i++) {
- LightInstance *li = light_instance_owner.getornull(p_omni_light_instances[i]);
-
- if ((li->cull_mask & p_layer_mask) && (li->light_index < 255)) {
- p_omni_light_indices[dword] += li->light_index << shift;
- if (shift == 24) {
- dword++;
- shift = 0;
- } else {
- shift += 8;
- }
- }
- }
-
- if (dword < 2) {
- // put in ending mark
- p_omni_light_indices[dword] += 0xFF << shift;
- }
- }
-
- {
- // process spot lights
- uint32_t dword = 0;
- uint32_t shift = 0;
-
- for (uint32_t i = 0; i < p_spot_light_instance_count && dword < p_max_dst_words; i++) {
- LightInstance *li = light_instance_owner.getornull(p_spot_light_instances[i]);
-
- if ((li->cull_mask & p_layer_mask) && (li->light_index < 255)) {
- p_spot_light_indices[dword] += li->light_index << shift;
- if (shift == 24) {
- dword++;
- shift = 0;
- } else {
- shift += 8;
- }
- }
- }
-
- if (dword < 2) {
- // put in ending mark
- p_spot_light_indices[dword] += 0xFF << shift;
- }
- }
-
- {
- // process reflection probes
- uint32_t dword = 0;
- uint32_t shift = 0;
-
- for (uint32_t i = 0; i < p_reflection_probe_instance_count && dword < p_max_dst_words; i++) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe_instances[i]);
-
- if ((rpi->cull_mask & p_layer_mask) && (rpi->render_index < 255)) {
- p_reflection_probe_indices[dword] += rpi->render_index << shift;
- if (shift == 24) {
- dword++;
- shift = 0;
- } else {
- shift += 8;
- }
- }
- }
-
- if (dword < 2) {
- // put in ending mark
- p_reflection_probe_indices[dword] += 0xFF << shift;
- }
- }
-
- {
- // process decals
- uint32_t dword = 0;
- uint32_t shift = 0;
-
- for (uint32_t i = 0; i < p_decal_instance_count && dword < p_max_dst_words; i++) {
- DecalInstance *decal = decal_instance_owner.getornull(p_decal_instances[i]);
-
- if ((decal->cull_mask & p_layer_mask) && (decal->render_index < 255)) {
- p_decal_instance_indices[dword] += decal->render_index << shift;
- if (shift == 24) {
- dword++;
- shift = 0;
- } else {
- shift += 8;
- }
- }
- }
-
- if (dword < 2) {
- // put in ending mark
- p_decal_instance_indices[dword] += 0xFF << shift;
- }
- }
-}
-
void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->volumetric_fog);
@@ -3522,7 +3466,6 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
Plane camera_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier();
-
{
for (int i = 0; i < render_state.render_shadow_count; i++) {
LightInstance *li = light_instance_owner.getornull(render_state.render_shadows[i].light);
@@ -3538,7 +3481,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
//cube shadows are rendered in their own way
for (uint32_t i = 0; i < render_state.cube_shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, true, true, true);
+ _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, true, true, true, p_render_data->render_info);
}
if (render_state.directional_shadows.size()) {
@@ -3568,11 +3511,11 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
//render directional shadows
for (uint32_t i = 0; i < render_state.directional_shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false);
+ _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false, p_render_data->render_info);
}
//render positional shadows
for (uint32_t i = 0; i < render_state.shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true);
+ _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true, p_render_data->render_info);
}
_render_shadow_process();
@@ -3618,7 +3561,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
- _setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count);
+ _setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
_setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse());
p_render_data->directional_light_count = directional_light_count;
@@ -3641,7 +3584,7 @@ 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, 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_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) {
+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, 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_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) {
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -3696,6 +3639,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_state.render_sdfgi_regions = p_render_sdfgi_regions;
render_state.render_sdfgi_region_count = p_render_sdfgi_region_count;
render_state.sdfgi_update_data = p_sdfgi_update_data;
+ render_data.render_info = r_render_info;
}
PagedArray<RID> empty;
@@ -3759,9 +3703,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
rb->sdfgi->update_light();
}
- if (p_voxel_gi_instances.size()) {
- gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
- }
+ gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
}
render_state.depth_prepass_used = false;
@@ -3808,7 +3750,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
}
}
-void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region) {
+void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
@@ -3954,7 +3896,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
if (render_cubemap) {
//rendering to cubemap
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, Rect2(), false, true, true, true);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, Rect2(), false, true, true, true, p_render_info);
if (finalize_cubemap) {
_render_shadow_process();
_render_shadow_end();
@@ -3975,7 +3917,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
} else {
//render shadow
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info);
}
}
@@ -4031,11 +3973,13 @@ bool RendererSceneRenderRD::free(RID p_rid) {
}
reflection_atlas_owner.free(p_rid);
} else if (reflection_probe_instance_owner.owns(p_rid)) {
- //not much to delete, just free it
- //ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
+ _free_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
} else if (decal_instance_owner.owns(p_rid)) {
+ DecalInstance *di = decal_instance_owner.getornull(p_rid);
+ _free_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id);
decal_instance_owner.free(p_rid);
} else if (lightmap_instance_owner.owns(p_rid)) {
lightmap_instance_owner.free(p_rid);
@@ -4070,6 +4014,9 @@ bool RendererSceneRenderRD::free(RID p_rid) {
shadow_atlas->shadow_owners.erase(p_rid);
}
+ if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
+ _free_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id);
+ }
light_instance_owner.free(p_rid);
} else if (shadow_atlas_owner.owns(p_rid)) {
@@ -4359,6 +4306,9 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"));
+ decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
+ light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
+
cull_argument.set_page_pool(&cull_argument_pool);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 9a793e42c5..5e0281002d 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -40,6 +40,7 @@
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
+#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -79,6 +80,9 @@ struct RenderDataRD {
uint32_t cluster_max_elements = 0;
uint32_t directional_light_count = 0;
+ bool directional_light_soft_shadows = false;
+
+ RendererScene::RenderInfo *render_info = nullptr;
};
class RendererSceneRenderRD : public RendererSceneRender {
@@ -96,14 +100,14 @@ protected:
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
- void _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);
+ void _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);
void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
virtual void _render_shadow_begin() = 0;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true) = 0;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
@@ -144,6 +148,25 @@ protected:
}
}
+ //used for mobile renderer mostly
+
+ typedef int32_t ForwardID;
+
+ enum ForwardIDType {
+ FORWARD_ID_TYPE_OMNI_LIGHT,
+ FORWARD_ID_TYPE_SPOT_LIGHT,
+ FORWARD_ID_TYPE_REFLECTION_PROBE,
+ FORWARD_ID_TYPE_DECAL,
+ FORWARD_ID_MAX,
+ };
+
+ virtual ForwardID _allocate_forward_id(ForwardIDType p_type) { return -1; }
+ virtual void _free_forward_id(ForwardIDType p_type, ForwardID p_id) {}
+ virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) {}
+ virtual bool _uses_forward_ids() const { return false; }
+
+ virtual void _update_shader_quality_settings() {}
+
private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
static RendererSceneRenderRD *singleton;
@@ -185,9 +208,10 @@ private:
uint32_t render_step = 0;
uint64_t last_pass = 0;
- uint32_t render_index = 0;
uint32_t cull_mask = 0;
+ ForwardID forward_id = -1;
+
Transform3D transform;
};
@@ -198,8 +222,8 @@ private:
struct DecalInstance {
RID decal;
Transform3D transform;
- uint32_t render_index;
uint32_t cull_mask;
+ ForwardID forward_id = -1;
};
mutable RID_Owner<DecalInstance> decal_instance_owner;
@@ -283,6 +307,8 @@ private:
int directional_soft_shadow_samples = 0;
int penumbra_shadow_samples = 0;
int soft_shadow_samples = 0;
+ RS::DecalFilter decals_filter = RS::DECAL_FILTER_LINEAR_MIPMAPS;
+ RS::LightProjectorFilter light_projectors_filter = RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS;
/* DIRECTIONAL SHADOW */
@@ -343,7 +369,6 @@ private:
uint64_t last_scene_pass = 0;
uint64_t last_scene_shadow_pass = 0;
uint64_t last_pass = 0;
- uint32_t light_index = 0;
uint32_t cull_mask = 0;
uint32_t light_directional_index = 0;
@@ -355,6 +380,8 @@ private:
Set<RID> shadow_atlases; //shadow atlases where this light is registered
+ ForwardID forward_id = -1;
+
LightInstance() {}
};
@@ -746,7 +773,7 @@ private:
uint32_t max_cluster_elements = 512;
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true);
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
public:
virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
@@ -754,10 +781,10 @@ public:
/* SHADOW ATLAS API */
- RID shadow_atlas_create();
- void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false);
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
+ virtual RID shadow_atlas_create() override;
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) override;
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
+ virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND_V(!atlas, false);
@@ -776,9 +803,9 @@ public:
return Size2(atlas->size, atlas->size);
}
- void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false);
- int get_directional_light_shadow_size(RID p_light_intance);
- void set_directional_shadow_count(int p_count);
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) override;
+ virtual int get_directional_light_shadow_size(RID p_light_intance) override;
+ virtual void set_directional_shadow_count(int p_count) override;
_FORCE_INLINE_ RID directional_shadow_get_texture() {
return directional_shadow.depth;
@@ -790,43 +817,43 @@ public:
/* SDFGI UPDATE */
- virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position);
- virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const;
- virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const;
- virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const;
+ virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
+ virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const override;
+ virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override;
+ virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override;
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
/* SKY API */
- virtual RID sky_allocate();
- virtual void sky_initialize(RID p_rid);
+ virtual RID sky_allocate() override;
+ virtual void sky_initialize(RID p_rid) override;
- void sky_set_radiance_size(RID p_sky, int p_radiance_size);
- void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
- void sky_set_material(RID p_sky, RID p_material);
- Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
+ virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) override;
+ virtual void sky_set_mode(RID p_sky, RS::SkyMode p_mode) override;
+ virtual void sky_set_material(RID p_sky, RID p_material) override;
+ virtual Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override;
/* ENVIRONMENT API */
- virtual RID environment_allocate();
- virtual void environment_initialize(RID p_rid);
+ virtual RID environment_allocate() override;
+ virtual void environment_initialize(RID p_rid) override;
- void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
- void environment_set_sky(RID p_env, RID p_sky);
- void environment_set_sky_custom_fov(RID p_env, float p_scale);
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
- void environment_set_bg_color(RID p_env, const Color &p_color);
- void environment_set_bg_energy(RID p_env, float p_energy);
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
- void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color());
+ virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override;
+ virtual void environment_set_sky(RID p_env, RID p_sky) override;
+ virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) override;
+ virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override;
+ virtual void environment_set_bg_color(RID p_env, const Color &p_color) override;
+ virtual void environment_set_bg_energy(RID p_env, float p_energy) override;
+ virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override;
+ virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) override;
- RS::EnvironmentBG environment_get_background(RID p_env) const;
+ virtual RS::EnvironmentBG environment_get_background(RID p_env) const override;
RID environment_get_sky(RID p_env) const;
float environment_get_sky_custom_fov(RID p_env) const;
Basis environment_get_sky_orientation(RID p_env) const;
Color environment_get_bg_color(RID p_env) const;
float environment_get_bg_energy(RID p_env) const;
- int environment_get_canvas_max_layer(RID p_env) const;
+ virtual int environment_get_canvas_max_layer(RID p_env) const override;
Color environment_get_ambient_light_color(RID p_env) const;
RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
float environment_get_ambient_light_energy(RID p_env) const;
@@ -834,13 +861,13 @@ public:
RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
Color environment_get_ao_color(RID p_env) const;
- bool is_environment(RID p_env) const;
+ virtual bool is_environment(RID p_env) const override;
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
- void environment_glow_set_use_bicubic_upscale(bool p_enable);
- void environment_glow_set_use_high_quality(bool p_enable);
+ virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override;
+ virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
+ virtual void environment_glow_set_use_high_quality(bool p_enable) override;
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective);
+ virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override;
bool environment_is_fog_enabled(RID p_env) const;
Color environment_get_fog_light_color(RID p_env) const;
float environment_get_fog_light_energy(RID p_env) const;
@@ -850,47 +877,47 @@ public:
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount);
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override;
- virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth);
- virtual void environment_set_volumetric_fog_filter_active(bool p_enable);
+ virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override;
+ virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override;
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
- void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
- void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
+ virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override;
+ virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override;
+ virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
bool environment_is_ssao_enabled(RID p_env) const;
float environment_get_ssao_ao_affect(RID p_env) const;
float environment_get_ssao_light_affect(RID p_env) const;
bool environment_is_ssr_enabled(RID p_env) const;
bool environment_is_sdfgi_enabled(RID p_env) const;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
- virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count);
- virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames);
- virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update);
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override;
+ virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override;
+ virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override;
+ virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override;
- void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
+ virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
- void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
+ virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override;
+ virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override;
- virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size);
+ virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
- virtual RID camera_effects_allocate();
- virtual void camera_effects_initialize(RID p_rid);
+ virtual RID camera_effects_allocate() override;
+ virtual void camera_effects_initialize(RID p_rid) override;
- virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter);
- virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape);
+ virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override;
+ virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override;
- virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount);
- virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure);
+ virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
+ virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
- RID light_instance_create(RID p_light);
- void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform);
- void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb);
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2());
- void light_instance_mark_visible(RID p_light_instance);
+ virtual RID light_instance_create(RID p_light) override;
+ virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
+ virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
+ virtual void light_instance_mark_visible(RID p_light_instance) override;
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
@@ -1002,14 +1029,9 @@ public:
return li->last_pass;
}
- _FORCE_INLINE_ void light_instance_set_index(RID p_light_instance, uint32_t p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
- li->light_index = p_index;
- }
-
- _FORCE_INLINE_ uint32_t light_instance_get_index(RID p_light_instance) {
+ _FORCE_INLINE_ ForwardID light_instance_get_forward_id(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
- return li->light_index;
+ return li->forward_id;
}
_FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
@@ -1017,9 +1039,9 @@ public:
return li->light_type;
}
- virtual RID reflection_atlas_create();
- virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count);
- virtual int reflection_atlas_get_size(RID p_ref_atlas) const;
+ virtual RID reflection_atlas_create() override;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
+ virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
_FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas);
@@ -1027,13 +1049,13 @@ public:
return atlas->reflection;
}
- virtual RID reflection_probe_instance_create(RID p_probe);
- virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform);
- virtual void reflection_probe_release_atlas_index(RID p_instance);
- virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
- virtual bool reflection_probe_instance_has_reflection(RID p_instance);
- virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas);
- virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
+ virtual RID reflection_probe_instance_create(RID p_probe) override;
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
+ virtual void reflection_probe_release_atlas_index(RID p_instance) override;
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
@@ -1046,17 +1068,11 @@ public:
return rpi->probe;
}
- _FORCE_INLINE_ void reflection_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND(!rpi);
- rpi->render_index = p_render_index;
- }
-
- _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_index(RID p_instance) {
+ _FORCE_INLINE_ ForwardID reflection_probe_instance_get_forward_id(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, 0);
- return rpi->render_index;
+ return rpi->forward_id;
}
_FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
@@ -1086,21 +1102,26 @@ public:
return rpi->atlas_index;
}
- virtual RID decal_instance_create(RID p_decal);
- virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform);
+ virtual RID decal_instance_create(RID p_decal) override;
+ virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const {
DecalInstance *decal = decal_instance_owner.getornull(p_decal);
return decal->decal;
}
+ _FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal) const {
+ DecalInstance *decal = decal_instance_owner.getornull(p_decal);
+ return decal->forward_id;
+ }
+
_FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal) const {
DecalInstance *decal = decal_instance_owner.getornull(p_decal);
return decal->transform;
}
- virtual RID lightmap_instance_create(RID p_lightmap);
- virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform);
+ virtual RID lightmap_instance_create(RID p_lightmap) override;
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
_FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr;
}
@@ -1114,21 +1135,21 @@ public:
return li->transform;
}
- void _fill_instance_indices(const RID *p_omni_light_instances, uint32_t p_omni_light_instance_count, uint32_t *p_omni_light_indices, const RID *p_spot_light_instances, uint32_t p_spot_light_instance_count, uint32_t *p_spot_light_indices, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count, uint32_t *p_reflection_probe_indices, const RID *p_decal_instances, uint32_t p_decal_instance_count, uint32_t *p_decal_instance_indices, uint32_t p_layer_mask, uint32_t p_max_dst_words = 2);
-
/* gi light probes */
- RID voxel_gi_instance_create(RID p_base);
- void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
- bool voxel_gi_needs_update(RID p_probe) const;
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
- void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) { gi.voxel_gi_quality = p_quality; }
+ virtual RID voxel_gi_instance_create(RID p_base) override;
+ virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override;
+ virtual bool voxel_gi_needs_update(RID p_probe) const override;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override;
+ virtual void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) override { gi.voxel_gi_quality = p_quality; }
/* render buffers */
- RID render_buffers_create();
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count);
- void gi_set_use_half_resolution(bool p_enable);
+ virtual RD::DataFormat _render_buffers_get_color_format();
+ virtual bool _render_buffers_can_be_storage();
+ virtual RID render_buffers_create() override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
@@ -1156,30 +1177,34 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- void 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, 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_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 = nullptr);
+ virtual void 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, 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_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 = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
- void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override;
- virtual void set_scene_pass(uint64_t p_pass) {
+ virtual void set_scene_pass(uint64_t p_pass) override {
scene_pass = p_pass;
}
_FORCE_INLINE_ uint64_t get_scene_pass() {
return scene_pass;
}
- virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit);
- virtual bool screen_space_roughness_limiter_is_active() const;
+ virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) override;
+ virtual bool screen_space_roughness_limiter_is_active() const override;
virtual float screen_space_roughness_limiter_get_amount() const;
virtual float screen_space_roughness_limiter_get_limit() const;
- virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality);
+ virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override;
RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
- virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale);
+ virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override;
+
+ virtual void shadows_quality_set(RS::ShadowQuality p_quality) override;
+ virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override;
+
+ virtual void decals_set_filter(RS::DecalFilter p_filter) override;
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
- virtual void shadows_quality_set(RS::ShadowQuality p_quality);
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality);
_FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; }
_FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; }
_FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; }
@@ -1195,21 +1220,24 @@ public:
_FORCE_INLINE_ int penumbra_shadow_samples_get() const { return penumbra_shadow_samples; }
_FORCE_INLINE_ int soft_shadow_samples_get() const { return soft_shadow_samples; }
+ _FORCE_INLINE_ RS::LightProjectorFilter light_projectors_get_filter() const { return light_projectors_filter; }
+ _FORCE_INLINE_ RS::DecalFilter decals_get_filter() const { return decals_filter; }
+
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
- virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size);
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override;
- virtual bool free(RID p_rid);
+ virtual bool free(RID p_rid) override;
- virtual void update();
+ virtual void update() override;
- virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw);
+ virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override;
_FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const {
return debug_draw;
}
- void set_time(double p_time, double p_step);
+ virtual void set_time(double p_time, double p_step) override;
RID get_reflection_probe_buffer();
RID get_omni_light_buffer();
@@ -1218,7 +1246,7 @@ public:
RID get_decal_buffer();
int get_max_directional_lights() const;
- void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
+ virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
virtual bool is_dynamic_gi_supported() const;
virtual bool is_clustered_enabled() const;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 2082ac9150..bc1603a219 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -230,96 +230,73 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
////////////////////////////////////////////////////////////////////////////////
// Sky material
-void RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
uniform_set_updated = true;
- if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(shader_data->ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
- }
+ 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, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
+}
- uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
+RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
- if ((uint32_t)texture_cache.size() != tex_uniform_count) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
+////////////////////////////////////////////////////////////////////////////////
+// Render sky
+
+static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) {
+ p_array[0] = p_basis.elements[0][0];
+ p_array[1] = p_basis.elements[1][0];
+ p_array[2] = p_basis.elements[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_basis.elements[0][1];
+ p_array[5] = p_basis.elements[1][1];
+ p_array[6] = p_basis.elements[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_basis.elements[0][2];
+ p_array[9] = p_basis.elements[1][2];
+ p_array[10] = p_basis.elements[2][2];
+ p_array[11] = 0;
+}
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
+void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
+ SkyPushConstant sky_push_constant;
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
- }
+ memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
- if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return;
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ // We only need key components of our projection matrix
+ sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0];
+ sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0];
+ sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1];
+ sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1];
}
+ sky_push_constant.position[0] = p_position.x;
+ sky_push_constant.position[1] = p_position.y;
+ sky_push_constant.position[2] = p_position.z;
+ sky_push_constant.multiplier = p_multiplier;
+ sky_push_constant.time = p_time;
+ store_transform_3x3(p_orientation, sky_push_constant.orientation);
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return;
- }
+ RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
- Vector<RD::Uniform> uniforms;
+ RD::DrawListID draw_list = p_list;
- {
- if (shader_data->ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(uniform_buffer);
- uniforms.push_back(u);
- }
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
- const RID *textures = texture_cache.ptrw();
- for (uint32_t i = 0; i < tex_uniform_count; i++) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + i;
- u.ids.push_back(textures[i]);
- uniforms.push_back(u);
- }
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0);
+ if (p_uniform_set.is_valid()) { //material may not have uniform set
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
}
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
-}
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- }
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant));
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
+ RD::get_singleton()->draw_list_draw(draw_list, true);
}
////////////////////////////////////////////////////////////////////////////////
@@ -780,7 +757,13 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
sky_shader.default_shader = storage->shader_allocate();
storage->shader_initialize(sky_shader.default_shader);
- storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void sky() { COLOR = vec3(0.0); } \n");
+ storage->shader_set_code(sky_shader.default_shader, R"(
+shader_type sky;
+
+void sky() {
+ COLOR = vec3(0.0);
+}
+)");
sky_shader.default_material = storage->material_allocate();
storage->material_initialize(sky_shader.default_material);
@@ -861,7 +844,15 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
sky_scene_state.fog_shader = storage->shader_allocate();
storage->shader_initialize(sky_scene_state.fog_shader);
- storage->shader_set_code(sky_scene_state.fog_shader, "shader_type sky; uniform vec4 clear_color; void sky() { COLOR = clear_color.rgb; } \n");
+ storage->shader_set_code(sky_scene_state.fog_shader, R"(
+shader_type sky;
+
+uniform vec4 clear_color;
+
+void sky() {
+ COLOR = clear_color.rgb;
+}
+)");
sky_scene_state.fog_material = storage->material_allocate();
storage->material_initialize(sky_scene_state.fog_material);
@@ -892,6 +883,41 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
sky_scene_state.fog_only_texture_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);
}
+
+ { //create index array for copy shaders
+ Vector<uint8_t> pv;
+ pv.resize(6 * 4);
+ {
+ uint8_t *w = pv.ptrw();
+ int *p32 = (int *)w;
+ p32[0] = 0;
+ p32[1] = 1;
+ p32[2] = 2;
+ p32[3] = 0;
+ p32[4] = 2;
+ p32[5] = 3;
+ }
+ index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
+ index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6);
+ }
+}
+
+RendererSceneSkyRD::~RendererSceneSkyRD() {
+ // TODO cleanup anything created in init...
+
+ if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.uniform_set);
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.default_fog_uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.default_fog_uniform_set);
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.fog_only_texture_uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.fog_only_texture_uniform_set);
+ }
+
+ RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
@@ -1156,7 +1182,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
}
@@ -1174,7 +1200,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
}
@@ -1188,7 +1214,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
@@ -1305,7 +1331,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- storage->get_effects()->render_sky(draw_list, p_time, sky->quarter_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
@@ -1318,7 +1344,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- storage->get_effects()->render_sky(draw_list, p_time, sky->half_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
@@ -1332,7 +1358,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- storage->get_effects()->render_sky(draw_list, p_time, p_fb, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 200902bff2..4f852e55a7 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -43,9 +43,6 @@
class RendererSceneRenderRD;
class RendererSceneSkyRD {
-private:
- RendererStorageRD *storage;
-
public:
enum SkySet {
SKY_SET_UNIFORMS,
@@ -55,6 +52,22 @@ public:
SKY_SET_MAX
};
+ // Skys need less info from Directional Lights than the normal shaders
+ struct SkyDirectionalLightData {
+ float direction[3];
+ float energy;
+ float color[3];
+ float size;
+ uint32_t enabled;
+ uint32_t pad[3];
+ };
+
+private:
+ RendererStorageRD *storage;
+
+ RID index_buffer;
+ RID index_array;
+
enum SkyTextureSetVersion {
SKY_TEXTURE_SET_BACKGROUND,
SKY_TEXTURE_SET_HALF_RES,
@@ -80,16 +93,53 @@ public:
SKY_VERSION_MAX
};
- // Skys need less info from Directional Lights than the normal shaders
- struct SkyDirectionalLightData {
- float direction[3];
- float energy;
- float color[3];
- float size;
- uint32_t enabled;
- uint32_t pad[3];
+ struct SkyPushConstant {
+ float orientation[12]; // 48 - 48
+ float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80
+ float position[3]; // 12 - 92
+ float multiplier; // 4 - 96
+ float time; // 4 - 100
+ float pad[3]; // 12 - 112 // Using pad to align on 16 bytes
+ // 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
+ struct SkyShaderData : public RendererStorageRD::ShaderData {
+ bool valid;
+ RID version;
+
+ PipelineCacheRD pipelines[SKY_VERSION_MAX];
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ Map<StringName, RID> default_texture_params;
+
+ bool uses_time;
+ bool uses_position;
+ bool uses_half_res;
+ bool uses_quarter_res;
+ bool uses_light;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererStorage::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;
+ SkyShaderData();
+ virtual ~SkyShaderData();
+ };
+
+ void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
+
+public:
struct SkySceneState {
struct UBO {
uint32_t volumetric_fog_enabled;
@@ -160,40 +210,6 @@ public:
void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end);
};
- struct SkyShaderData : public RendererStorageRD::ShaderData {
- bool valid;
- RID version;
-
- PipelineCacheRD pipelines[SKY_VERSION_MAX];
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
-
- String path;
- String code;
- Map<StringName, RID> default_texture_params;
-
- bool uses_time;
- bool uses_position;
- bool uses_half_res;
- bool uses_quarter_res;
- bool uses_light;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::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;
- SkyShaderData();
- virtual ~SkyShaderData();
- };
-
/* Sky shader */
struct SkyShader {
@@ -208,15 +224,12 @@ public:
struct SkyMaterialData : public RendererStorageRD::MaterialData {
uint64_t last_frame;
SkyShaderData *shader_data;
- RID uniform_buffer;
RID uniform_set;
- Vector<RID> texture_cache;
- Vector<uint8_t> ubo_data;
bool uniform_set_updated;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~SkyMaterialData();
};
@@ -270,8 +283,8 @@ public:
static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader);
RendererSceneSkyRD();
-
void init(RendererStorageRD *p_storage);
+ ~RendererSceneSkyRD();
void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index b95647b8b7..2657fa3ae8 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -35,6 +35,7 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
bool RendererStorageRD::can_create_resources_async() const {
@@ -883,10 +884,6 @@ void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_im
RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data());
}
-void RendererStorageRD::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) {
- _texture_2d_update(p_texture, p_image, p_layer, true);
-}
-
void RendererStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
_texture_2d_update(p_texture, p_image, p_layer, false);
}
@@ -1234,7 +1231,7 @@ RID RendererStorageRD::canvas_texture_allocate() {
return canvas_texture_owner.allocate_rid();
}
void RendererStorageRD::canvas_texture_initialize(RID p_rid) {
- canvas_texture_owner.initialize_rid(p_rid, memnew(CanvasTexture));
+ canvas_texture_owner.initialize_rid(p_rid);
}
void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
@@ -1529,27 +1526,18 @@ RID RendererStorageRD::material_allocate() {
return material_owner.allocate_rid();
}
void RendererStorageRD::material_initialize(RID p_rid) {
- Material material;
- material.data = nullptr;
- material.shader = nullptr;
- material.shader_type = SHADER_TYPE_MAX;
- material.update_next = nullptr;
- material.update_requested = false;
- material.uniform_dirty = false;
- material.texture_dirty = false;
- material.priority = 0;
- material.self = p_rid;
- material_owner.initialize_rid(p_rid, material);
+ material_owner.initialize_rid(p_rid);
+ Material *material = material_owner.getornull(p_rid);
+ material->self = p_rid;
}
void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
- if (material->update_requested) {
+ if (material->update_element.in_list()) {
return;
}
- material->update_next = material_update_list;
- material_update_list = material;
- material->update_requested = true;
+ material_update_list.add(&material->update_element);
+
material->uniform_dirty = material->uniform_dirty || p_uniform;
material->texture_dirty = material->texture_dirty || p_texture;
}
@@ -1604,6 +1592,7 @@ void RendererStorageRD::material_set_param(RID p_material, const StringName &p_p
if (p_value.get_type() == Variant::NIL) {
material->params.erase(p_param);
} else {
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
material->params[p_param] = p_value;
}
@@ -2235,6 +2224,10 @@ RendererStorageRD::MaterialData::~MaterialData() {
//unregister material from those using global textures
rs->global_variables.materials_using_texture.erase(global_texture_E);
}
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ }
}
void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
@@ -2384,6 +2377,105 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
}
}
+void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
+ if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(p_uniform_set);
+ }
+}
+
+bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+ if ((uint32_t)ubo_data.size() != p_ubo_size) {
+ p_uniform_dirty = true;
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ uniform_buffer = RID();
+ }
+
+ ubo_data.resize(p_ubo_size);
+ if (ubo_data.size()) {
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+ }
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ //check whether buffer changed
+ if (p_uniform_dirty && ubo_data.size()) {
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
+ }
+
+ uint32_t tex_uniform_count = p_texture_uniforms.size();
+
+ if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
+ texture_cache.resize(tex_uniform_count);
+ p_textures_dirty = true;
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ if (p_textures_dirty && tex_uniform_count) {
+ update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
+ }
+
+ if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+ // This material does not require an uniform set, so don't create it.
+ return false;
+ }
+
+ if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //no reason to update uniform set, only UBO (or nothing) was needed to update
+ return false;
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ if (p_ubo_size) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ const RID *textures = texture_cache.ptrw();
+ for (uint32_t i = 0; i < tex_uniform_count; i++) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1 + i;
+ u.ids.push_back(textures[i]);
+ uniforms.push_back(u);
+ }
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
+
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, _material_uniform_set_erased, &self);
+
+ return true;
+}
+
+void RendererStorageRD::_material_uniform_set_erased(const RID &p_set, void *p_material) {
+ RID rid = *(RID *)p_material;
+ Material *material = base_singleton->material_owner.getornull(rid);
+ if (material) {
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
+ }
+}
+
void RendererStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
Material *material = material_owner.getornull(p_material);
if (material->shader_type != p_shader_type) {
@@ -2395,20 +2487,23 @@ void RendererStorageRD::material_force_update_textures(RID p_material, ShaderTyp
}
void RendererStorageRD::_update_queued_materials() {
- Material *material = material_update_list;
- while (material) {
- Material *next = material->update_next;
+ while (material_update_list.first()) {
+ Material *material = material_update_list.first()->self();
+ bool uniforms_changed = false;
if (material->data) {
- material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
+ uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
}
- material->update_requested = false;
material->texture_dirty = false;
material->uniform_dirty = false;
- material->update_next = nullptr;
- material = next;
+
+ material_update_list.remove(&material->update_element);
+
+ if (uniforms_changed) {
+ //some implementations such as 3D renderer cache the matreial uniform set, so update is required
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
+ }
}
- material_update_list = nullptr;
}
/* MESH API */
@@ -2436,6 +2531,8 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
+ ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
+
#ifdef DEBUG_ENABLED
//do a validation, to catch errors first
{
@@ -2463,7 +2560,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
} break;
case RS::ARRAY_COLOR: {
- attrib_stride += sizeof(int16_t) * 4;
+ attrib_stride += sizeof(uint32_t);
} break;
case RS::ARRAY_TEX_UV: {
attrib_stride += sizeof(float) * 2;
@@ -2551,6 +2648,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
s->lods[i].edge_length = p_surface.lods[i].edge_length;
+ s->lods[i].index_count = indices;
}
}
}
@@ -2655,7 +2753,7 @@ RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) cons
return mesh->blend_shape_mode;
}
-void RendererStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
@@ -2666,6 +2764,30 @@ void RendererStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, in
RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
}
+void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
+}
+
+void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
+}
+
void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
@@ -2934,7 +3056,8 @@ RID RendererStorageRD::mesh_instance_create(RID p_base) {
Mesh *mesh = mesh_owner.getornull(p_base);
ERR_FAIL_COND_V(!mesh, RID());
- MeshInstance *mi = memnew(MeshInstance);
+ RID rid = mesh_instance_owner.make_rid();
+ MeshInstance *mi = mesh_instance_owner.getornull(rid);
mi->mesh = mesh;
@@ -2946,7 +3069,7 @@ RID RendererStorageRD::mesh_instance_create(RID p_base) {
mi->dirty = true;
- return mesh_instance_owner.make_rid(mi);
+ return rid;
}
void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance);
@@ -3233,8 +3356,8 @@ void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surf
case RS::ARRAY_COLOR: {
vd.offset = attribute_stride;
- vd.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- attribute_stride += sizeof(int16_t) * 4;
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ attribute_stride += sizeof(int8_t) * 4;
buffer = s->attribute_buffer;
} break;
case RS::ARRAY_TEX_UV: {
@@ -3896,6 +4019,7 @@ void RendererStorageRD::particles_set_emitting(RID p_particles, bool 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.getornull(p_particles);
ERR_FAIL_COND_V(!particles, false);
@@ -4218,6 +4342,10 @@ void RendererStorageRD::particles_request_process(RID p_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.getornull(p_particles);
ERR_FAIL_COND_V(!particles, AABB());
@@ -5102,6 +5230,7 @@ void RendererStorageRD::update_particles() {
}
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.getornull(p_particles);
ERR_FAIL_COND_V(!particles, false);
return !particles->emitting && particles->inactive;
@@ -5252,94 +5381,14 @@ RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func(
return shader_data;
}
-void RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
uniform_set_updated = true;
- if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(shader_data->ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
- }
-
- uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
- }
-
- if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (shader_data->ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (uint32_t i = 0; i < tex_uniform_count; i++) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + i;
- u.ids.push_back(textures[i]);
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
+ 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() {
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
+ free_parameters_uniform_set(uniform_set);
}
RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
@@ -5839,6 +5888,10 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
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:
@@ -5852,6 +5905,12 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
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: {
}
}
@@ -5888,8 +5947,11 @@ void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
light->projector = p_texture;
- if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
- texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ if (light->type != RS::LIGHT_DIRECTIONAL) {
+ if (light->projector.is_valid()) {
+ texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ }
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
}
}
@@ -6003,20 +6065,6 @@ RS::LightDirectionalShadowMode RendererStorageRD::light_directional_get_shadow_m
return light->directional_shadow_mode;
}
-void RendererStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) {
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_range_mode = p_range_mode;
-}
-
-RS::LightDirectionalShadowDepthRangeMode RendererStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
-
- return light->directional_range_mode;
-}
-
uint32_t RendererStorageRD::light_get_max_sdfgi_cascade(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
@@ -6610,32 +6658,6 @@ float RendererStorageRD::voxel_gi_get_energy(RID p_voxel_gi) const {
return voxel_gi->energy;
}
-void RendererStorageRD::voxel_gi_set_ao(RID p_voxel_gi, float p_ao) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->ao = p_ao;
-}
-
-float RendererStorageRD::voxel_gi_get_ao(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->ao;
-}
-
-void RendererStorageRD::voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->ao_size = p_strength;
-}
-
-float RendererStorageRD::voxel_gi_get_ao_size(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->ao_size;
-}
-
void RendererStorageRD::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
@@ -8333,6 +8355,9 @@ void RendererStorageRD::global_variable_set_override(const StringName &p_name, c
if (!global_variables.variables.has(p_name)) {
return; //variable may not exist
}
+
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
+
GlobalVariables::Variable &gv = global_variables.variables[p_name];
gv.override = p_value;
@@ -8657,8 +8682,6 @@ bool RendererStorageRD::free(RID p_rid) {
texture_owner.free(p_rid);
} else if (canvas_texture_owner.owns(p_rid)) {
- CanvasTexture *ct = canvas_texture_owner.getornull(p_rid);
- memdelete(ct);
canvas_texture_owner.free(p_rid);
} else if (shader_owner.owns(p_rid)) {
Shader *shader = shader_owner.getornull(p_rid);
@@ -8674,9 +8697,6 @@ bool RendererStorageRD::free(RID p_rid) {
} else if (material_owner.owns(p_rid)) {
Material *material = material_owner.getornull(p_rid);
- if (material->update_requested) {
- _update_queued_materials();
- }
material_set_shader(p_rid, RID()); //clean up shader
material->dependency.deleted_notify(p_rid);
@@ -8704,7 +8724,6 @@ bool RendererStorageRD::free(RID p_rid) {
mi->I = nullptr;
mesh_instance_owner.free(p_rid);
- memdelete(mi);
} else if (multimesh_owner.owns(p_rid)) {
_update_dirty_multimeshes();
@@ -8820,6 +8839,29 @@ String RendererStorageRD::get_captured_timestamp_name(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_name(p_index);
}
+void RendererStorageRD::update_memory_info() {
+ texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES);
+ buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS);
+ total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL);
+}
+uint64_t RendererStorageRD::get_rendering_info(RS::RenderingInfo p_info) {
+ if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) {
+ return texture_mem_cache;
+ } else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) {
+ return buffer_mem_cache;
+ } else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) {
+ return total_mem_cache;
+ }
+ return 0;
+}
+
+String RendererStorageRD::get_video_adapter_name() const {
+ return RenderingDevice::get_singleton()->get_device_name();
+}
+String RendererStorageRD::get_video_adapter_vendor() const {
+ return RenderingDevice::get_singleton()->get_device_vendor_name();
+}
+
RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
RendererStorageRD::RendererStorageRD() {
@@ -8840,7 +8882,6 @@ RendererStorageRD::RendererStorageRD() {
memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- material_update_list = nullptr;
{ //create default textures
RD::TextureFormat tformat;
@@ -9347,7 +9388,13 @@ RendererStorageRD::RendererStorageRD() {
// default material and shader for particles shader
particles_shader.default_shader = shader_allocate();
shader_initialize(particles_shader.default_shader);
- shader_set_code(particles_shader.default_shader, "shader_type particles; void process() { COLOR = vec4(1.0); } \n");
+ shader_set_code(particles_shader.default_shader, R"(
+shader_type particles;
+
+void process() {
+ COLOR = vec4(1.0);
+}
+)");
particles_shader.default_material = material_allocate();
material_initialize(particles_shader.default_material);
material_set_shader(particles_shader.default_material, particles_shader.default_shader);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index ab470cb3a6..f471874c8e 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -155,9 +155,13 @@ public:
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
virtual ~MaterialData();
+ //to be used internally by update_parameters, in the most common configuration of material parameters
+ bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void free_parameters_uniform_set(RID p_uniform_set);
+
private:
friend class RendererStorageRD;
RID self;
@@ -165,8 +169,14 @@ public:
List<RID>::Element *global_texture_E = nullptr;
uint64_t global_textures_pass = 0;
Map<StringName, uint64_t> used_global_textures;
+
+ //internally by update_parameters_uniform_set
+ Vector<uint8_t> ubo_data;
+ RID uniform_buffer;
+ Vector<RID> texture_cache;
};
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
+ static void _material_uniform_set_erased(const RID &p_set, void *p_material);
enum DefaultRDTexture {
DEFAULT_RD_TEXTURE_WHITE,
@@ -221,7 +231,7 @@ private:
~CanvasTexture();
};
- RID_PtrOwner<CanvasTexture, true> canvas_texture_owner;
+ RID_Owner<CanvasTexture, true> canvas_texture_owner;
/* TEXTURE API */
struct Texture {
@@ -373,25 +383,28 @@ private:
struct Material {
RID self;
- MaterialData *data;
- Shader *shader;
+ MaterialData *data = nullptr;
+ Shader *shader = nullptr;
//shortcut to shader data and type
- ShaderType shader_type;
+ ShaderType shader_type = SHADER_TYPE_MAX;
uint32_t shader_id = 0;
- bool update_requested;
- bool uniform_dirty;
- bool texture_dirty;
- Material *update_next;
+ bool uniform_dirty = false;
+ bool texture_dirty = false;
Map<StringName, Variant> params;
- int32_t priority;
+ int32_t priority = 0;
RID next_pass;
+ SelfList<Material> update_element;
+
Dependency dependency;
+
+ Material() :
+ update_element(this) {}
};
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Material, true> material_owner;
- Material *material_update_list;
+ SelfList<Material>::List material_update_list;
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
void _update_queued_materials();
@@ -434,6 +447,7 @@ private:
struct LOD {
float edge_length = 0.0;
+ uint32_t index_count = 0;
RID index_buffer;
RID index_array;
};
@@ -513,7 +527,7 @@ private:
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
- mutable RID_PtrOwner<MeshInstance> mesh_instance_owner;
+ mutable RID_Owner<MeshInstance> mesh_instance_owner;
SelfList<MeshInstance>::List dirty_mesh_instance_weights;
SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
@@ -894,17 +908,14 @@ private:
}
struct ParticlesMaterialData : public MaterialData {
- uint64_t last_frame;
- ParticlesShaderData *shader_data;
- RID uniform_buffer;
+ uint64_t last_frame = 0;
+ ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
- Vector<RID> texture_cache;
- Vector<uint8_t> ubo_data;
- bool uniform_set_updated;
+ bool uniform_set_updated = false;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~ParticlesMaterialData();
};
@@ -1002,7 +1013,6 @@ private:
uint32_t cull_mask = 0xFFFFFFFF;
RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
- RS::LightDirectionalShadowDepthRangeMode directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
bool directional_blend_splits = false;
bool directional_sky_only = false;
uint64_t version = 0;
@@ -1076,8 +1086,6 @@ private:
float dynamic_range = 4.0;
float energy = 1.0;
- float ao = 0.0;
- float ao_size = 0.5;
float bias = 1.4;
float normal_bias = 0.0;
float propagation = 0.7;
@@ -1298,7 +1306,6 @@ public:
virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate);
- virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); //mostly used for video and streaming
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data);
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to);
@@ -1457,7 +1464,9 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode);
virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
- virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
@@ -1526,10 +1535,18 @@ public:
return s->lod_count > 0;
}
- _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_lod_threshold) const {
+ _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return s->index_count ? s->index_count : s->vertex_count;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_lod_threshold, uint32_t *r_index_count = nullptr) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
int32_t current_lod = -1;
+ if (r_index_count) {
+ *r_index_count = s->index_count;
+ }
for (uint32_t i = 0; i < s->lod_count; i++) {
float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
if (screen_size > p_lod_threshold) {
@@ -1540,6 +1557,9 @@ public:
if (current_lod == -1) {
return 0;
} else {
+ if (r_index_count) {
+ *r_index_count = s->lods[current_lod].index_count;
+ }
return current_lod + 1;
}
}
@@ -1746,24 +1766,6 @@ public:
return multimesh->uniform_set_2d;
}
- /* IMMEDIATE API */
-
- RID immediate_allocate() { return RID(); }
- void immediate_initialize(RID p_immediate) {}
-
- virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {}
- virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {}
- virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) {}
- virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) {}
- virtual void immediate_color(RID p_immediate, const Color &p_color) {}
- virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {}
- virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {}
- virtual void immediate_end(RID p_immediate) {}
- virtual void immediate_clear(RID p_immediate) {}
- virtual void immediate_set_material(RID p_immediate, RID p_material) {}
- virtual RID immediate_get_material(RID p_immediate) const { return RID(); }
- virtual AABB immediate_get_aabb(RID p_immediate) const { return AABB(); }
-
/* SKELETON API */
RID skeleton_allocate();
@@ -1832,8 +1834,6 @@ public:
bool light_directional_get_blend_splits(RID p_light) const;
void light_directional_set_sky_only(RID p_light, bool p_sky_only);
bool light_directional_is_sky_only(RID p_light) const;
- void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode);
- RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_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);
@@ -1888,6 +1888,13 @@ public:
return light->shadow;
}
+ _FORCE_INLINE_ bool light_has_projector(RID p_light) const {
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return texture_owner.owns(light->projector);
+ }
+
_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
@@ -2056,12 +2063,6 @@ public:
void voxel_gi_set_energy(RID p_voxel_gi, float p_energy);
float voxel_gi_get_energy(RID p_voxel_gi) const;
- void voxel_gi_set_ao(RID p_voxel_gi, float p_ao);
- float voxel_gi_get_ao(RID p_voxel_gi) const;
-
- void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength);
- float voxel_gi_get_ao_size(RID p_voxel_gi) const;
-
void voxel_gi_set_bias(RID p_voxel_gi, float p_bias);
float voxel_gi_get_bias(RID p_voxel_gi) const;
@@ -2350,13 +2351,16 @@ public:
void set_debug_generate_wireframes(bool p_generate) {}
- void render_info_begin_capture() {}
- void render_info_end_capture() {}
- int get_captured_render_info(RS::RenderInfo p_info) { return 0; }
+ //keep cached since it can be called form any thread
+ uint64_t texture_mem_cache = 0;
+ uint64_t buffer_mem_cache = 0;
+ uint64_t total_mem_cache = 0;
+
+ virtual void update_memory_info();
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info);
- uint64_t get_render_info(RS::RenderInfo p_info) { return 0; }
- String get_video_adapter_name() const { return String(); }
- String get_video_adapter_vendor() const { return String(); }
+ String get_video_adapter_name() const;
+ String get_video_adapter_vendor() const;
virtual void capture_timestamps_begin();
virtual void capture_timestamp(const String &p_name);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index b347197289..1dde92d8ff 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -1351,7 +1351,13 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
if (err != OK) {
Vector<String> shader = p_code.split("\n");
for (int i = 0; i < shader.size(); i++) {
- print_line(itos(i + 1) + " " + shader[i]);
+ if (i + 1 == parser.get_error_line()) {
+ // Mark the error line to be visible without having to look at
+ // the trace at the end.
+ print_line(vformat("E%4d-> %s", i + 1, shader[i]));
+ } else {
+ print_line(vformat("%5d | %s", i + 1, shader[i]));
+ }
}
_err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER);
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index 3977f4efa0..60c881881d 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -77,9 +77,9 @@ struct VoxelGIData {
bool blend_ambient;
uint texture_slot;
- float anisotropy_strength;
- float ambient_occlusion;
- float ambient_occlusion_size;
+ uint pad0;
+ uint pad1;
+ uint pad2;
uint mipmaps;
};
@@ -551,27 +551,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
}
}
- if (voxel_gi_instances.data[index].ambient_occlusion > 0.001) {
- float size = 1.0 + voxel_gi_instances.data[index].ambient_occlusion_size * 7.0;
-
- float taps, blend;
- blend = modf(size, taps);
- float ao = 0.0;
- for (float i = 1.0; i <= taps; i++) {
- vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size;
- ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i;
- }
-
- if (blend > 0.001) {
- vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size;
- ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend;
- }
-
- ao = 1.0 - min(1.0, ao);
-
- light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, voxel_gi_instances.data[index].ambient_occlusion));
- }
-
light.rgb *= voxel_gi_instances.data[index].dynamic_range;
if (!voxel_gi_instances.data[index].blend_ambient) {
light.a = 1.0;
diff --git a/servers/rendering/renderer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/resolve.glsl
index a4610e081c..fecf812a8c 100644
--- a/servers/rendering/renderer_rd/shaders/resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/resolve.glsl
@@ -6,6 +6,11 @@
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+#ifdef MODE_RESOLVE_DEPTH
+layout(set = 0, binding = 0) uniform sampler2DMS source_depth;
+layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_depth;
+#endif
+
#ifdef MODE_RESOLVE_GI
layout(set = 0, binding = 0) uniform sampler2DMS source_depth;
layout(set = 0, binding = 1) uniform sampler2DMS source_normal_roughness;
@@ -34,6 +39,17 @@ void main() {
return;
}
+#ifdef MODE_RESOLVE_DEPTH
+
+ float depth_avg = 0.0;
+ for (int i = 0; i < params.sample_count; i++) {
+ depth_avg += texelFetch(source_depth, pos, i).r;
+ }
+ depth_avg /= float(params.sample_count);
+ imageStore(dest_depth, pos, vec4(depth_avg));
+
+#endif
+
#ifdef MODE_RESOLVE_GI
float best_depth = 1e20;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 8538030263..ef1c9bacfb 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -356,6 +356,24 @@ void main() {
#VERSION_DEFINES
+/* Specialization Constants (Toggles) */
+
+layout(constant_id = 0) const bool sc_use_forward_gi = false;
+layout(constant_id = 1) const bool sc_use_light_projector = false;
+layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
+layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false;
+
+/* Specialization Constants (Values) */
+
+layout(constant_id = 6) const uint sc_soft_shadow_samples = 4;
+layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4;
+
+layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4;
+layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
+
+layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
+layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
+
#include "scene_forward_clustered_inc.glsl"
/* Varyings */
@@ -450,12 +468,8 @@ layout(location = 0) out vec4 frag_color;
#include "scene_forward_lights_inc.glsl"
-#ifdef USE_FORWARD_GI
-
#include "scene_forward_gi_inc.glsl"
-#endif //USE_FORWARD_GI
-
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
#ifndef MODE_RENDER_DEPTH
@@ -547,9 +561,8 @@ void main() {
vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
- vec4 transmittance_color = vec4(0.0);
+ vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0);
float transmittance_depth = 0.0;
- float transmittance_curve = 1.0;
float transmittance_boost = 0.0;
float metallic = 0.0;
float specular = 0.5;
@@ -634,12 +647,8 @@ void main() {
}
#ifdef LIGHT_TRANSMITTANCE_USED
-#ifdef SSS_MODE_SKIN
- transmittance_color.a = sss_strength;
-#else
transmittance_color.a *= sss_strength;
#endif
-#endif
#ifndef USE_SHADOW_TO_OPACITY
@@ -798,25 +807,35 @@ void main() {
continue; //out of decal
}
- //we need ddx/ddy for mipmaps, so simulate them
- vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
- vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
-
float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
if (decals.data[decal_index].normal_fade > 0.0) {
fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
}
+ //we need ddx/ddy for mipmaps, so simulate them
+ vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
+ vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
+
if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
//has albedo
- vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ vec4 decal_albedo;
+ if (sc_decal_use_mipmaps) {
+ decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ } else {
+ decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
+ }
decal_albedo *= decals.data[decal_index].modulate;
decal_albedo.a *= fade;
albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
if (decals.data[decal_index].normal_rect != vec4(0.0)) {
- vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
+ vec3 decal_normal;
+ if (sc_decal_use_mipmaps) {
+ decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
+ } else {
+ decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
+ }
decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
//convert to view space, use xzy because y is up
@@ -826,7 +845,12 @@ void main() {
}
if (decals.data[decal_index].orm_rect != vec4(0.0)) {
- vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
+ vec3 decal_orm;
+ if (sc_decal_use_mipmaps) {
+ decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
+ } else {
+ decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
+ }
ao = mix(ao, decal_orm.r, decal_albedo.a);
roughness = mix(roughness, decal_orm.g, decal_albedo.a);
metallic = mix(metallic, decal_orm.b, decal_albedo.a);
@@ -835,7 +859,11 @@ void main() {
if (decals.data[decal_index].emission_rect != vec4(0.0)) {
//emission is additive, so its independent from albedo
- emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ if (sc_decal_use_mipmaps) {
+ emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ } else {
+ emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+ }
}
}
}
@@ -968,9 +996,9 @@ void main() {
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
}
}
-#elif defined(USE_FORWARD_GI)
+#else
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
+ if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
//make vertex orientation the world one, but still align to camera
vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
@@ -1042,7 +1070,7 @@ void main() {
}
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
+ if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
@@ -1073,9 +1101,8 @@ void main() {
specular_light = spec_accum.rgb;
ambient_light = amb_accum.rgb;
}
-#else
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
+ if (!sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
vec2 coord;
@@ -1106,7 +1133,7 @@ void main() {
ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a);
specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a);
}
-#endif
+#endif // !USE_LIGHTMAP
if (scene_data.ssao_enabled) {
float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
@@ -1233,14 +1260,13 @@ void main() {
float shadow = 1.0;
-#ifdef USE_SOFT_SHADOWS
//version with soft shadows, more expensive
if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -vertex.z;
+ if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) {
+ float depth_z = -vertex.z;
- vec4 pssm_coord;
- vec3 shadow_color = vec3(0.0);
- vec3 light_dir = directional_lights.data[i].direction;
+ vec3 shadow_color = vec3(0.0);
+ vec3 light_dir = directional_lights.data[i].direction;
#define BIAS_FUNC(m_var, m_idx) \
m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
@@ -1248,168 +1274,105 @@ void main() {
normal_bias -= light_dir * dot(light_dir, normal_bias); \
m_var.xyz += normal_bias;
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- vec4 v = vec4(vertex, 1.0);
+ uint blend_index = 0;
- BIAS_FUNC(v, 0)
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ vec4 v = vec4(vertex, 1.0);
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- pssm_coord /= pssm_coord.w;
+ BIAS_FUNC(v, 0)
+
+ vec4 pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
float range_begin = directional_lights.data[i].shadow_range_begin.x;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius;
shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ blend_index++;
}
- shadow_color = directional_lights.data[i].shadow_color1.rgb;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- vec4 v = vec4(vertex, 1.0);
+ if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 1)
+ BIAS_FUNC(v, 1)
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
+ vec4 pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
float range_begin = directional_lights.data[i].shadow_range_begin.y;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+
+ if (blend_index == 0) {
+ shadow = s;
+ } else {
+ //blend
+ float blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+ shadow = mix(shadow, s, blend);
+ }
+
+ blend_index++;
}
- shadow_color = directional_lights.data[i].shadow_color2.rgb;
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- vec4 v = vec4(vertex, 1.0);
+ if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 2)
+ BIAS_FUNC(v, 2)
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
+ vec4 pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
float range_begin = directional_lights.data[i].shadow_range_begin.z;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
+ float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- shadow_color = directional_lights.data[i].shadow_color3.rgb;
-
- } else {
- vec4 v = vec4(vertex, 1.0);
-
- BIAS_FUNC(v, 3)
-
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
+ if (blend_index == 0) {
+ shadow = s;
+ } else {
+ //blend
+ float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+ shadow = mix(shadow, s, blend);
+ }
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.w;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ blend_index++;
}
- shadow_color = directional_lights.data[i].shadow_color4.rgb;
- }
-
- if (directional_lights.data[i].blend_splits) {
- vec3 shadow_color_blend = vec3(0.0);
- float pssm_blend;
- float shadow2;
-
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ if (blend_index < 2) {
vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 1)
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.y;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
+ BIAS_FUNC(v, 3)
- pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
- shadow_color_blend = directional_lights.data[i].shadow_color2.rgb;
- } 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);
+ vec4 pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.z;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
-
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.w;
+ float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
+ vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
+ float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
- } 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_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.w;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+ if (blend_index == 0) {
+ shadow = s;
} else {
- shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ //blend
+ float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+ shadow = mix(shadow, s, blend);
}
-
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
- shadow_color_blend = directional_lights.data[i].shadow_color4.rgb;
- } else {
- pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
}
- pssm_blend = sqrt(pssm_blend);
-
- shadow = mix(shadow, shadow2, pssm_blend);
- shadow_color = mix(shadow_color, shadow_color_blend, pssm_blend);
- }
-
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
-
#undef BIAS_FUNC
- }
-#else
- // Soft shadow disabled version
+ } else { //no soft shadows
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -vertex.z;
+ float depth_z = -vertex.z;
- vec4 pssm_coord;
- 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))));
+ vec4 pssm_coord;
+ 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))));
#define BIAS_FUNC(m_var, m_idx) \
m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
@@ -1417,122 +1380,70 @@ void main() {
normal_bias -= light_dir * dot(light_dir, normal_bias); \
m_var.xyz += normal_bias;
- 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);
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
-
- transmittance_z = z - shadow_z;
- }
-#endif
- } 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);
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
-
- transmittance_z = z - shadow_z;
- }
-#endif
- } 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);
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
-
- transmittance_z = z - shadow_z;
- }
-#endif
-
- } else {
- vec4 v = vec4(vertex, 1.0);
-
- BIAS_FUNC(v, 3)
-
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
-
- transmittance_z = z - shadow_z;
- }
-#endif
- }
-
- 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);
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ vec4 v = vec4(vertex, 1.0);
- if (directional_lights.data[i].blend_splits) {
- float pssm_blend;
+ BIAS_FUNC(v, 0)
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ } 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);
- pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
- } else if (depth_z < 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);
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
- } else if (depth_z < 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);
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
- } else {
- pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
}
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);
- shadow = mix(shadow, shadow2, pssm_blend);
- }
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+
+ if (directional_lights.data[i].blend_splits) {
+ float pssm_blend;
+
+ 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);
+ } 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);
+ } 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);
+ } else {
+ pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
+ }
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
+ 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);
+ shadow = mix(shadow, shadow2, pssm_blend);
+ }
+
+ shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
#undef BIAS_FUNC
- }
-#endif
+ }
+ } // shadows
if (i < 4) {
shadow0 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << (i * 8);
@@ -1562,8 +1473,8 @@ void main() {
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
+ shadow_z *= directional_lights.data[i].shadow_z_range.x;
+ float z = trans_coord.z * directional_lights.data[i].shadow_z_range.x;
transmittance_z = z - shadow_z;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
@@ -1572,8 +1483,8 @@ void main() {
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
+ shadow_z *= directional_lights.data[i].shadow_z_range.y;
+ float z = trans_coord.z * directional_lights.data[i].shadow_z_range.y;
transmittance_z = z - shadow_z;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
@@ -1582,8 +1493,8 @@ void main() {
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
+ shadow_z *= directional_lights.data[i].shadow_z_range.z;
+ float z = trans_coord.z * directional_lights.data[i].shadow_z_range.z;
transmittance_z = z - shadow_z;
@@ -1593,221 +1504,218 @@ void main() {
trans_coord /= trans_coord.w;
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
- float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
+ shadow_z *= directional_lights.data[i].shadow_z_range.w;
+ float z = trans_coord.z * directional_lights.data[i].shadow_z_range.w;
transmittance_z = z - shadow_z;
}
+ }
#endif
- float shadow = 1.0;
+ float shadow = 1.0;
- if (i < 4) {
- shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
- } else {
- shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
- }
+ if (i < 4) {
+ shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
+ } else {
+ shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
+ }
+
+ blur_shadow(shadow);
- blur_shadow(shadow);
+ float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0;
- light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_curve,
- transmittance_boost,
- transmittance_z,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
+ rim, rim_tint, albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
+ clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
- binormal, tangent, anisotropy,
-#endif
-#ifdef USE_SOFT_SHADOW
- directional_lights.data[i].size,
+ binormal, tangent, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
- alpha,
+ alpha,
#endif
- diffuse_light,
- specular_light);
- }
+ diffuse_light,
+ specular_light);
}
+ }
- { //omni lights
+ { //omni lights
- uint cluster_omni_offset = cluster_offset;
+ uint cluster_omni_offset = cluster_offset;
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
- cluster_get_item_range(cluster_omni_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+ cluster_get_item_range(cluster_omni_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
#ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
#endif
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_omni_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_omni_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
#ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
#else
uint merged_mask = mask;
#endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
#endif
- uint light_index = 32 * i + bit;
+ uint light_index = 32 * i + bit;
- if (!bool(omni_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
+ if (!bool(omni_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
+ continue; //not masked
+ }
- if (omni_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
- continue; // Statically baked light and object uses lightmap, skip
- }
+ if (omni_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
+ continue; // Statically baked light and object uses lightmap, skip
+ }
- float shadow = light_process_omni_shadow(light_index, vertex, view);
+ float shadow = light_process_omni_shadow(light_index, vertex, view);
- shadow = blur_shadow(shadow);
+ shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_curve,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
- albedo,
+ rim,
+ rim_tint,
+ albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
+ clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent, binormal, anisotropy,
+ tangent, binormal, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
- alpha,
+ alpha,
#endif
- diffuse_light, specular_light);
- }
+ diffuse_light, specular_light);
}
}
+ }
- { //spot lights
+ { //spot lights
- uint cluster_spot_offset = cluster_offset + scene_data.cluster_type_size;
+ uint cluster_spot_offset = cluster_offset + scene_data.cluster_type_size;
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
- cluster_get_item_range(cluster_spot_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+ cluster_get_item_range(cluster_spot_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
#ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
#endif
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_spot_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_spot_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
#ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
#else
uint merged_mask = mask;
#endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
#endif
- uint light_index = 32 * i + bit;
+ uint light_index = 32 * i + bit;
- if (!bool(spot_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
+ if (!bool(spot_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
+ continue; //not masked
+ }
- if (spot_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
- continue; // Statically baked light and object uses lightmap, skip
- }
+ if (spot_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
+ continue; // Statically baked light and object uses lightmap, skip
+ }
- float shadow = light_process_spot_shadow(light_index, vertex, view);
+ float shadow = light_process_spot_shadow(light_index, vertex, view);
- shadow = blur_shadow(shadow);
+ shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_curve,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
- albedo,
+ rim,
+ rim_tint,
+ albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
+ clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent, binormal, anisotropy,
+ tangent, binormal, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
- alpha,
+ alpha,
#endif
- diffuse_light, specular_light);
- }
+ diffuse_light, specular_light);
}
}
+ }
#ifdef USE_SHADOW_TO_OPACITY
- alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
+ alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
#if defined(ALPHA_SCISSOR_USED)
- if (alpha < alpha_scissor) {
- discard;
- }
+ if (alpha < alpha_scissor) {
+ discard;
+ }
#endif // ALPHA_SCISSOR_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
- discard;
- }
+ if (alpha < opaque_prepass_threshold) {
+ discard;
+ }
#endif // USE_OPAQUE_PREPASS
@@ -1819,126 +1727,126 @@ void main() {
#ifdef MODE_RENDER_SDF
- {
- vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
- ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size));
-
- uint albedo16 = 0x1; //solid flag
- albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11;
- albedo16 |= clamp(uint(albedo.g * 31.0), 0, 31) << 6;
- albedo16 |= clamp(uint(albedo.b * 31.0), 0, 31) << 1;
-
- imageStore(albedo_volume_grid, grid_pos, uvec4(albedo16));
-
- uint facing_bits = 0;
- const vec3 aniso_dir[6] = vec3[](
- vec3(1, 0, 0),
- vec3(0, 1, 0),
- vec3(0, 0, 1),
- vec3(-1, 0, 0),
- vec3(0, -1, 0),
- vec3(0, 0, -1));
-
- vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp);
-
- float closest_dist = -1e20;
-
- for (uint i = 0; i < 6; i++) {
- float d = dot(cam_normal, aniso_dir[i]);
- if (d > closest_dist) {
- closest_dist = d;
- facing_bits = (1 << i);
- }
+ {
+ vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
+ ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size));
+
+ uint albedo16 = 0x1; //solid flag
+ albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11;
+ albedo16 |= clamp(uint(albedo.g * 31.0), 0, 31) << 6;
+ albedo16 |= clamp(uint(albedo.b * 31.0), 0, 31) << 1;
+
+ imageStore(albedo_volume_grid, grid_pos, uvec4(albedo16));
+
+ uint facing_bits = 0;
+ const vec3 aniso_dir[6] = vec3[](
+ vec3(1, 0, 0),
+ vec3(0, 1, 0),
+ vec3(0, 0, 1),
+ vec3(-1, 0, 0),
+ vec3(0, -1, 0),
+ vec3(0, 0, -1));
+
+ vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp);
+
+ float closest_dist = -1e20;
+
+ for (uint i = 0; i < 6; i++) {
+ float d = dot(cam_normal, aniso_dir[i]);
+ if (d > closest_dist) {
+ closest_dist = d;
+ facing_bits = (1 << i);
}
+ }
- imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
+ imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
- if (length(emission) > 0.001) {
- float lumas[6];
- vec3 light_total = vec3(0);
+ if (length(emission) > 0.001) {
+ float lumas[6];
+ vec3 light_total = vec3(0);
- for (int i = 0; i < 6; i++) {
- float strength = max(0.0, dot(cam_normal, aniso_dir[i]));
- vec3 light = emission * strength;
- light_total += light;
- lumas[i] = max(light.r, max(light.g, light.b));
- }
+ for (int i = 0; i < 6; i++) {
+ float strength = max(0.0, dot(cam_normal, aniso_dir[i]));
+ vec3 light = emission * strength;
+ light_total += light;
+ lumas[i] = max(light.r, max(light.g, light.b));
+ }
- float luma_total = max(light_total.r, max(light_total.g, light_total.b));
+ float luma_total = max(light_total.r, max(light_total.g, light_total.b));
- uint light_aniso = 0;
+ uint light_aniso = 0;
- for (int i = 0; i < 6; i++) {
- light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5);
- }
+ for (int i = 0; i < 6; i++) {
+ light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5);
+ }
- //compress to RGBE9995 to save space
+ //compress to RGBE9995 to save space
- const float pow2to9 = 512.0f;
- const float B = 15.0f;
- const float N = 9.0f;
- const float LN2 = 0.6931471805599453094172321215;
+ const float pow2to9 = 512.0f;
+ const float B = 15.0f;
+ const float N = 9.0f;
+ const float LN2 = 0.6931471805599453094172321215;
- float cRed = clamp(light_total.r, 0.0, 65408.0);
- float cGreen = clamp(light_total.g, 0.0, 65408.0);
- float cBlue = clamp(light_total.b, 0.0, 65408.0);
+ float cRed = clamp(light_total.r, 0.0, 65408.0);
+ float cGreen = clamp(light_total.g, 0.0, 65408.0);
+ float cBlue = clamp(light_total.b, 0.0, 65408.0);
- float cMax = max(cRed, max(cGreen, cBlue));
+ float cMax = max(cRed, max(cGreen, cBlue));
- float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
+ float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
- float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
+ float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
- float exps = expp + 1.0f;
+ float exps = expp + 1.0f;
- if (0.0 <= sMax && sMax < pow2to9) {
- exps = expp;
- }
+ if (0.0 <= sMax && sMax < pow2to9) {
+ exps = expp;
+ }
- float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
- float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
- float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
- //store as 8985 to have 2 extra neighbour bits
- uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
+ float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
+ float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
+ float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
+ //store as 8985 to have 2 extra neighbour bits
+ uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
- imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
- imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso));
- }
+ imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
+ imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso));
}
+ }
#endif
#ifdef MODE_RENDER_MATERIAL
- albedo_output_buffer.rgb = albedo;
- albedo_output_buffer.a = alpha;
+ albedo_output_buffer.rgb = albedo;
+ albedo_output_buffer.a = alpha;
- normal_output_buffer.rgb = normal * 0.5 + 0.5;
- normal_output_buffer.a = 0.0;
- depth_output_buffer.r = -vertex.z;
+ normal_output_buffer.rgb = normal * 0.5 + 0.5;
+ normal_output_buffer.a = 0.0;
+ depth_output_buffer.r = -vertex.z;
- orm_output_buffer.r = ao;
- orm_output_buffer.g = roughness;
- orm_output_buffer.b = metallic;
- orm_output_buffer.a = sss_strength;
+ orm_output_buffer.r = ao;
+ orm_output_buffer.g = roughness;
+ orm_output_buffer.b = metallic;
+ orm_output_buffer.a = sss_strength;
- emission_output_buffer.rgb = emission;
- emission_output_buffer.a = 0.0;
+ emission_output_buffer.rgb = emission;
+ emission_output_buffer.a = 0.0;
#endif
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
- normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
+ normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
#ifdef MODE_RENDER_VOXEL_GI
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- uint index2 = instances.data[instance_index].gi_offset >> 16;
- voxel_gi_buffer.x = index1 & 0xFF;
- voxel_gi_buffer.y = index2 & 0xFF;
- } else {
- voxel_gi_buffer.x = 0xFF;
- voxel_gi_buffer.y = 0xFF;
- }
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
+ uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
+ uint index2 = instances.data[instance_index].gi_offset >> 16;
+ voxel_gi_buffer.x = index1 & 0xFF;
+ voxel_gi_buffer.y = index2 & 0xFF;
+ } else {
+ voxel_gi_buffer.x = 0xFF;
+ voxel_gi_buffer.y = 0xFF;
+ }
#endif
#endif //MODE_RENDER_NORMAL_ROUGHNESS
@@ -1996,4 +1904,4 @@ void main() {
#endif //MODE_MULTIPLE_RENDER_TARGETS
#endif //MODE_RENDER_DEPTH
- }
+}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index e64e52623e..3a05275652 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -52,6 +52,11 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
+layout(set = 0, binding = 3) uniform sampler decal_sampler;
+
+layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
+
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
@@ -66,24 +71,22 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
-#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 24)
-
-layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
+layout(set = 0, binding = 5, std430) restrict readonly buffer OmniLights {
LightData data[];
}
omni_lights;
-layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
+layout(set = 0, binding = 6, std430) restrict readonly buffer SpotLights {
LightData data[];
}
spot_lights;
-layout(set = 0, binding = 5, std430) restrict readonly buffer ReflectionProbeData {
+layout(set = 0, binding = 7, std430) restrict readonly buffer ReflectionProbeData {
ReflectionData data[];
}
reflections;
-layout(set = 0, binding = 6, std140) uniform DirectionalLights {
+layout(set = 0, binding = 8, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
@@ -95,7 +98,7 @@ struct Lightmap {
mat3 normal_xform;
};
-layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
+layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
Lightmap data[];
}
lightmaps;
@@ -104,20 +107,20 @@ struct LightmapCapture {
vec4 sh[9];
};
-layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
lightmap_captures;
-layout(set = 0, binding = 9) uniform texture2D decal_atlas;
-layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 11) uniform texture2D decal_atlas;
+layout(set = 0, binding = 12) uniform texture2D decal_atlas_srgb;
-layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
DecalData data[];
}
decals;
-layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
@@ -129,7 +132,7 @@ struct SDFVoxelGICascadeData {
float to_cell; // 1/bounds * grid_size
};
-layout(set = 0, binding = 13, std140) uniform SDFGI {
+layout(set = 0, binding = 15, std140) uniform SDFGI {
vec3 grid_size;
uint max_cascades;
@@ -180,11 +183,6 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
vec4 penumbra_shadow_kernel[32];
vec4 soft_shadow_kernel[32];
- uint directional_penumbra_shadow_samples;
- uint directional_soft_shadow_samples;
- uint penumbra_shadow_samples;
- uint soft_shadow_samples;
-
vec4 ambient_light_color_energy;
float ambient_color_sky_mix;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 709ea45b88..7039ea2942 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -73,14 +73,13 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
+void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
vec4 transmittance_color,
float transmittance_depth,
- float transmittance_curve,
float transmittance_boost,
float transmittance_z,
#endif
@@ -93,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
#ifdef LIGHT_ANISOTROPY_USED
vec3 B, vec3 T, float anisotropy,
#endif
-#ifdef USE_SOFT_SHADOWS
- float A,
-#endif
#ifdef USE_SHADOW_TO_OPACITY
inout float alpha,
#endif
@@ -112,11 +108,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
#else
-#ifdef USE_SOFT_SHADOWS
float NdotL = min(A + dot(N, L), 1.0);
-#else
- float NdotL = dot(N, L);
-#endif
float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V);
float cNdotV = max(NdotV, 0.0);
@@ -126,19 +118,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
#endif
#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
-#ifdef USE_SOFT_SHADOWS
float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
-#else
- float cNdotH = clamp(dot(N, H), 0.0, 1.0);
-#endif
#endif
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
-#ifdef USE_SOFT_SHADOWS
float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
-#else
- float cLdotH = clamp(dot(L, H), 0.0, 1.0);
-#endif
#endif
float metallic = unpackUnorm4x8(orms).z;
@@ -189,9 +173,8 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
#ifdef LIGHT_TRANSMITTANCE_USED
-#ifdef SSS_MODE_SKIN
-
{
+#ifdef SSS_MODE_SKIN
float scale = 8.25 / transmittance_depth;
float d = scale * abs(transmittance_z);
float dd = -d * d;
@@ -203,19 +186,15 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
- }
#else
- if (transmittance_depth > 0.0) {
- float fade = clamp(abs(transmittance_z / transmittance_depth), 0.0, 1.0);
-
- fade = pow(max(0.0, 1.0 - fade), transmittance_curve);
- fade *= clamp(transmittance_boost - NdotL, 0.0, 1.0);
-
- diffuse_light += transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade;
+ float scale = 8.25 / transmittance_depth;
+ float d = scale * abs(transmittance_z);
+ float dd = -d * d;
+ diffuse_light += exp(dd) * transmittance_color.rgb * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
+#endif
}
-
-#endif //SSS_MODE_SKIN
+#else
#endif //LIGHT_TRANSMITTANCE_USED
}
@@ -238,11 +217,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L, N));
-#ifdef USE_SOFT_SHADOWS
float cRdotV = clamp(A + dot(R, V), 0.0, 1.0);
-#else
- float cRdotV = clamp(dot(R, V), 0.0, 1.0);
-#endif
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
float phong = pow(cRdotV, shininess);
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
@@ -326,7 +301,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (scene_data.directional_soft_shadow_samples == 1) {
+ if (sc_directional_soft_shadow_samples == 1) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -340,11 +315,11 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float avg = 0.0;
- for (uint i = 0; i < scene_data.directional_soft_shadow_samples; i++) {
+ for (uint i = 0; i < sc_directional_soft_shadow_samples; i++) {
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
}
- return avg * (1.0 / float(scene_data.directional_soft_shadow_samples));
+ return avg * (1.0 / float(sc_directional_soft_shadow_samples));
}
float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
@@ -352,7 +327,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (scene_data.soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 1) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -366,11 +341,11 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
float avg = 0.0;
- for (uint i = 0; i < scene_data.soft_shadow_samples; i++) {
+ for (uint i = 0; i < sc_soft_shadow_samples; i++) {
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0));
}
- return avg * (1.0 / float(scene_data.soft_shadow_samples));
+ return avg * (1.0 / float(sc_soft_shadow_samples));
}
float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) {
@@ -386,7 +361,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
- for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) {
vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < pssm_coord.z) {
@@ -402,12 +377,12 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
tex_scale *= penumbra;
float s = 0.0;
- for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) {
vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
}
- return s / float(scene_data.directional_penumbra_shadow_samples);
+ return s / float(sc_directional_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -448,8 +423,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
float shadow;
-#ifdef USE_SOFT_SHADOWS
- if (omni_lights.data[idx].soft_shadow_size > 0.0) {
+ if (sc_use_light_soft_shadows && omni_lights.data[idx].soft_shadow_size > 0.0) {
//soft shadow
//find blocker
@@ -474,7 +448,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
tangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale;
bitangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale;
- for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
@@ -511,7 +485,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
z_norm -= omni_lights.data[idx].inv_radius * omni_lights.data[idx].shadow_bias;
shadow = 0.0;
- for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
@@ -532,14 +506,13 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
}
- shadow /= float(scene_data.penumbra_shadow_samples);
+ shadow /= float(sc_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
shadow = 1.0;
}
} else {
-#endif
splane.xyz = normalize(splane.xyz);
vec4 clamp_rect = omni_lights.data[idx].atlas_rect;
@@ -559,9 +532,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
splane.w = 1.0; //needed? i think it should be 1 already
shadow = sample_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
-#ifdef USE_SOFT_SHADOWS
}
-#endif
return shadow;
}
@@ -577,7 +548,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_TRANSMITTANCE_USED
vec4 transmittance_color,
float transmittance_depth,
- float transmittance_curve,
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
@@ -599,14 +569,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float light_attenuation = omni_attenuation;
vec3 color = omni_lights.data[idx].color;
-#ifdef USE_SOFT_SHADOWS
float size_A = 0.0;
- if (omni_lights.data[idx].size > 0.0) {
+ if (sc_use_light_soft_shadows && omni_lights.data[idx].size > 0.0) {
float t = omni_lights.data[idx].size / max(0.001, light_length);
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
}
-#endif
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth; //no transmittance by default
@@ -617,20 +585,22 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
//redo shadowmapping, but shrink the model a bit to avoid arctifacts
vec4 splane = (omni_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * omni_lights.data[idx].transmittance_bias, 1.0));
- shadow_len = length(splane.xyz);
- splane = normalize(splane.xyz);
+ float shadow_len = length(splane.xyz);
+ splane.xyz = normalize(splane.xyz);
if (splane.z >= 0.0) {
splane.z += 1.0;
-
+ clamp_rect.y += clamp_rect.w;
} else {
splane.z = 1.0 - splane.z;
}
splane.xy /= splane.z;
+
splane.xy = splane.xy * 0.5 + 0.5;
splane.z = shadow_len * omni_lights.data[idx].inv_radius;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ // splane.xy = clamp(splane.xy,clamp_rect.xy + scene_data.shadow_atlas_pixel_size,clamp_rect.xy + clamp_rect.zw - scene_data.shadow_atlas_pixel_size );
splane.w = 1.0; //needed? i think it should be 1 already
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
@@ -638,9 +608,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
}
#endif
-#if 0
-
- if (omni_lights.data[idx].projector_rect != vec4(0.0)) {
+ if (sc_use_light_projector && omni_lights.data[idx].projector_rect != vec4(0.0)) {
vec3 local_v = (omni_lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
local_v = normalize(local_v);
@@ -658,53 +626,56 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
local_v.xy = local_v.xy * 0.5 + 0.5;
vec2 proj_uv = local_v.xy * atlas_rect.zw;
- vec2 proj_uv_ddx;
- vec2 proj_uv_ddy;
- {
- vec3 local_v_ddx = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)).xyz;
- local_v_ddx = normalize(local_v_ddx);
+ if (sc_projector_use_mipmaps) {
+ vec2 proj_uv_ddx;
+ vec2 proj_uv_ddy;
+ {
+ vec3 local_v_ddx = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)).xyz;
+ local_v_ddx = normalize(local_v_ddx);
- if (local_v_ddx.z >= 0.0) {
- local_v_ddx.z += 1.0;
- } else {
- local_v_ddx.z = 1.0 - local_v_ddx.z;
- }
+ if (local_v_ddx.z >= 0.0) {
+ local_v_ddx.z += 1.0;
+ } else {
+ local_v_ddx.z = 1.0 - local_v_ddx.z;
+ }
- local_v_ddx.xy /= local_v_ddx.z;
- local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5;
+ local_v_ddx.xy /= local_v_ddx.z;
+ local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5;
- proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv;
+ proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv;
- vec3 local_v_ddy = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
- local_v_ddy = normalize(local_v_ddy);
+ vec3 local_v_ddy = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
+ local_v_ddy = normalize(local_v_ddy);
- if (local_v_ddy.z >= 0.0) {
- local_v_ddy.z += 1.0;
- } else {
- local_v_ddy.z = 1.0 - local_v_ddy.z;
- }
+ if (local_v_ddy.z >= 0.0) {
+ local_v_ddy.z += 1.0;
+ } else {
+ local_v_ddy.z = 1.0 - local_v_ddy.z;
+ }
- local_v_ddy.xy /= local_v_ddy.z;
- local_v_ddy.xy = local_v_ddy.xy * 0.5 + 0.5;
+ local_v_ddy.xy /= local_v_ddy.z;
+ local_v_ddy.xy = local_v_ddy.xy * 0.5 + 0.5;
- proj_uv_ddy = local_v_ddy.xy * atlas_rect.zw - proj_uv;
- }
+ proj_uv_ddy = local_v_ddy.xy * atlas_rect.zw - proj_uv;
+ }
- vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy);
- no_shadow = mix(no_shadow, proj.rgb, proj.a);
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ color *= proj.rgb * proj.a;
+ } else {
+ vec4 proj = textureLod(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + atlas_rect.xy, 0.0);
+ color *= proj.rgb * proj.a;
+ }
}
-#endif
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
- transmittance_curve,
transmittance_boost,
transmittance_z,
#endif
@@ -717,9 +688,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SOFT_SHADOWS
- size_A,
-#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha,
#endif
@@ -753,8 +721,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
vec4 splane = (spot_lights.data[idx].shadow_matrix * v);
splane /= splane.w;
-#ifdef USE_SOFT_SHADOWS
- if (spot_lights.data[idx].soft_shadow_size > 0.0) {
+ if (sc_use_light_soft_shadows && spot_lights.data[idx].soft_shadow_size > 0.0) {
//soft shadow
//find blocker
@@ -774,11 +741,11 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
float uv_size = spot_lights.data[idx].soft_shadow_size * z_norm * spot_lights.data[idx].soft_shadow_scale;
vec2 clamp_max = spot_lights.data[idx].atlas_rect.xy + spot_lights.data[idx].atlas_rect.zw;
- for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
- if (d < z_norm) {
+ if (d < splane.z) {
blocker_average += d;
blocker_count += 1.0;
}
@@ -791,13 +758,13 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
uv_size *= penumbra;
shadow = 0.0;
- for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
- shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0));
+ shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0));
}
- shadow /= float(scene_data.penumbra_shadow_samples);
+ shadow /= float(sc_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -805,14 +772,11 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
}
} else {
-#endif
//hard shadow
vec4 shadow_uv = vec4(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z, 1.0);
shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv);
-#ifdef USE_SOFT_SHADOWS
}
-#endif
return shadow;
}
@@ -822,6 +786,18 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
return 1.0;
}
+vec2 normal_to_panorama(vec3 n) {
+ n = normalize(n);
+ vec2 panorama_coords = vec2(atan(n.x, n.z), acos(-n.y));
+
+ if (panorama_coords.x < 0.0) {
+ panorama_coords.x += M_PI * 2.0;
+ }
+
+ panorama_coords /= vec2(M_PI * 2.0, M_PI);
+ return panorama_coords;
+}
+
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
@@ -829,7 +805,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_TRANSMITTANCE_USED
vec4 transmittance_color,
float transmittance_depth,
- float transmittance_curve,
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
@@ -857,48 +832,66 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
vec3 color = spot_lights.data[idx].color;
float specular_amount = spot_lights.data[idx].specular_amount;
-#ifdef USE_SOFT_SHADOWS
float size_A = 0.0;
- if (spot_lights.data[idx].size > 0.0) {
+ if (sc_use_light_soft_shadows && spot_lights.data[idx].size > 0.0) {
float t = spot_lights.data[idx].size / max(0.001, light_length);
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
}
-#endif
-
- /*
- if (spot_lights.data[idx].atlas_rect!=vec4(0.0)) {
- //use projector texture
- }
- */
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth;
transmittance_color.a *= light_attenuation;
{
- splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * spot_lights.data[idx].transmittance_bias, 1.0));
+ vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * spot_lights.data[idx].transmittance_bias, 1.0));
splane /= splane.w;
splane.xy = splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy;
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
- //reconstruct depth
- shadow_z /= spot_lights.data[idx].inv_radius;
+
+ shadow_z = shadow_z * 2.0 - 1.0;
+ float z_far = 1.0 / spot_lights.data[idx].inv_radius;
+ float z_near = 0.01;
+ shadow_z = 2.0 * z_near * z_far / (z_far + z_near - shadow_z * (z_far - z_near));
+
//distance to light plane
float z = dot(spot_dir, -light_rel_vec);
transmittance_z = z - shadow_z;
}
#endif //LIGHT_TRANSMITTANCE_USED
+ if (sc_use_light_projector && spot_lights.data[idx].projector_rect != vec4(0.0)) {
+ vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+ splane /= splane.w;
+
+ vec2 proj_uv = normal_to_panorama(splane.xyz) * spot_lights.data[idx].projector_rect.zw;
+
+ if (sc_projector_use_mipmaps) {
+ //ensure we have proper mipmaps
+ vec4 splane_ddx = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0));
+ splane_ddx /= splane_ddx.w;
+ vec2 proj_uv_ddx = normal_to_panorama(splane_ddx.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
+
+ vec4 splane_ddy = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0));
+ splane_ddy /= splane_ddy.w;
+ vec2 proj_uv_ddy = normal_to_panorama(splane_ddy.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
+
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + spot_lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ color *= proj.rgb * proj.a;
+ } else {
+ vec4 proj = textureLod(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + spot_lights.data[idx].projector_rect.xy, 0.0);
+ color *= proj.rgb * proj.a;
+ }
+ }
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
- transmittance_curve,
transmittance_boost,
transmittance_z,
#endif
@@ -911,9 +904,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SOFT_SHADOW
- size_A,
-#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha,
#endif
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index aa8a0b96c5..7e72ece5dc 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -370,6 +370,26 @@ void main() {
#VERSION_DEFINES
+/* Specialization Constants */
+
+/* Specialization Constants (Toggles) */
+
+layout(constant_id = 0) const bool sc_use_forward_gi = false;
+layout(constant_id = 1) const bool sc_use_light_projector = false;
+layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
+layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false;
+
+/* Specialization Constants (Values) */
+
+layout(constant_id = 6) const uint sc_soft_shadow_samples = 4;
+layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4;
+
+layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4;
+layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
+
+layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
+layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
+
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
@@ -543,7 +563,6 @@ void main() {
vec3 backlight = vec3(0.0);
vec4 transmittance_color = vec4(0.0);
float transmittance_depth = 0.0;
- float transmittance_curve = 1.0;
float transmittance_boost = 0.0;
float metallic = 0.0;
float specular = 0.5;
@@ -1285,7 +1304,7 @@ void main() {
blur_shadow(shadow);
- light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1293,7 +1312,6 @@ void main() {
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
- transmittance_curve,
transmittance_boost,
transmittance_z,
#endif
@@ -1344,7 +1362,6 @@ void main() {
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
- transmittance_curve,
transmittance_boost,
#endif
*/
@@ -1393,7 +1410,6 @@ void main() {
#ifdef LIGHT_TRANSMITTANCE_USED
transmittance_color,
transmittance_depth,
- transmittance_curve,
transmittance_boost,
#endif
*/
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 7fcd84695d..1b8e21551c 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -51,6 +51,10 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
+layout(set = 0, binding = 3) uniform sampler decal_sampler;
+layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
+
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
@@ -65,24 +69,22 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
-#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 24)
-
-layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
+layout(set = 0, binding = 5, std430) restrict readonly buffer OmniLights {
LightData data[];
}
omni_lights;
-layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
+layout(set = 0, binding = 6, std430) restrict readonly buffer SpotLights {
LightData data[];
}
spot_lights;
-layout(set = 0, binding = 5, std430) restrict readonly buffer ReflectionProbeData {
+layout(set = 0, binding = 7, std430) restrict readonly buffer ReflectionProbeData {
ReflectionData data[];
}
reflections;
-layout(set = 0, binding = 6, std140) uniform DirectionalLights {
+layout(set = 0, binding = 8, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
@@ -94,7 +96,7 @@ struct Lightmap {
mat3 normal_xform;
};
-layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
+layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
Lightmap data[];
}
lightmaps;
@@ -103,20 +105,20 @@ struct LightmapCapture {
vec4 sh[9];
};
-layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
lightmap_captures;
-layout(set = 0, binding = 9) uniform texture2D decal_atlas;
-layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 11) uniform texture2D decal_atlas;
+layout(set = 0, binding = 12) uniform texture2D decal_atlas_srgb;
-layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
DecalData data[];
}
decals;
-layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
@@ -142,11 +144,6 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
vec4 penumbra_shadow_kernel[32];
vec4 soft_shadow_kernel[32];
- uint directional_penumbra_shadow_samples;
- uint directional_soft_shadow_samples;
- uint penumbra_shadow_samples;
- uint soft_shadow_samples;
-
vec4 ambient_light_color_energy;
float ambient_color_sky_mix;
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl
index 7e06516d90..2328effe7b 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl
+++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl
@@ -36,12 +36,12 @@ void main() {
float divisor = 0.0;
vec4 color;
float depth;
- vec3 normal;
+ vec4 normal;
if (params.filtered) {
color = vec4(0.0);
depth = 0.0;
- normal = vec3(0.0);
+ normal = vec4(0.0);
for (int i = 0; i < 4; i++) {
ivec2 ofs = ssC << 1;
@@ -53,7 +53,9 @@ void main() {
}
color += texelFetch(source_ssr, ofs, 0);
float d = texelFetch(source_depth, ofs, 0).r;
- normal += texelFetch(source_normal, ofs, 0).xyz * 2.0 - 1.0;
+ vec4 nr = texelFetch(source_normal, ofs, 0);
+ normal.xyz += nr.xyz * 2.0 - 1.0;
+ normal.w += nr.w;
d = d * 2.0 - 1.0;
if (params.orthogonal) {
@@ -66,11 +68,12 @@ void main() {
color /= 4.0;
depth /= 4.0;
- normal = normalize(normal / 4.0) * 0.5 + 0.5;
+ normal.xyz = normalize(normal.xyz / 4.0) * 0.5 + 0.5;
+ normal.w /= 4.0;
} else {
color = texelFetch(source_ssr, ssC << 1, 0);
depth = texelFetch(source_depth, ssC << 1, 0).r;
- normal = texelFetch(source_normal, ssC << 1, 0).xyz;
+ normal = texelFetch(source_normal, ssC << 1, 0);
depth = depth * 2.0 - 1.0;
if (params.orthogonal) {
@@ -83,5 +86,5 @@ void main() {
imageStore(dest_ssr, ssC, color);
imageStore(dest_depth, ssC, vec4(depth));
- imageStore(dest_normal, ssC, vec4(normal, 0.0));
+ imageStore(dest_normal, ssC, normal);
}
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index d71425f465..972637d183 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -56,7 +56,6 @@ public:
virtual RID scenario_allocate() = 0;
virtual void scenario_initialize(RID p_rid) = 0;
- virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) = 0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx) = 0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
@@ -81,7 +80,6 @@ public:
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0;
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;
- virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0;
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
@@ -203,12 +201,20 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
- virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface) = 0;
+
+ struct RenderInfo {
+ int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {};
+ };
+
+ virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
virtual void update() = 0;
virtual void render_probes() = 0;
virtual void update_visibility_notifiers() = 0;
+ virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
+
virtual bool free(RID p_rid) = 0;
RendererScene();
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index e0d0ce76be..3336623f21 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -43,7 +43,7 @@ RID RendererSceneCull::camera_allocate() {
return camera_owner.allocate_rid();
}
void RendererSceneCull::camera_initialize(RID p_rid) {
- camera_owner.initialize_rid(p_rid, memnew(Camera));
+ camera_owner.initialize_rid(p_rid);
}
void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -151,6 +151,22 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
}
+ if (light->uses_projector) {
+ geom->projector_count++;
+ if (geom->projector_count == 1) {
+ InstanceData &idata = A->scenario->instance_data[A->array_index];
+ idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
+ }
+ }
+
+ if (light->uses_softshadow) {
+ geom->softshadow_count++;
+ if (geom->softshadow_count == 1) {
+ InstanceData &idata = A->scenario->instance_data[A->array_index];
+ idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
+ }
+ }
+
} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -242,6 +258,32 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
}
+ if (light->uses_projector) {
+#ifdef DEBUG_ENABLED
+ if (geom->projector_count == 0) {
+ ERR_PRINT("geom->projector_count==0 - BUG!");
+ }
+#endif
+ geom->projector_count--;
+ if (geom->projector_count == 0) {
+ InstanceData &idata = A->scenario->instance_data[A->array_index];
+ idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
+ }
+ }
+
+ if (light->uses_softshadow) {
+#ifdef DEBUG_ENABLED
+ if (geom->softshadow_count == 0) {
+ ERR_PRINT("geom->softshadow_count==0 - BUG!");
+ }
+#endif
+ geom->softshadow_count--;
+ if (geom->softshadow_count == 0) {
+ InstanceData &idata = A->scenario->instance_data[A->array_index];
+ idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
+ }
+ }
+
} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -310,7 +352,9 @@ RID RendererSceneCull::scenario_allocate() {
return scenario_owner.allocate_rid();
}
void RendererSceneCull::scenario_initialize(RID p_rid) {
- Scenario *scenario = memnew(Scenario);
+ scenario_owner.initialize_rid(p_rid);
+
+ Scenario *scenario = scenario_owner.getornull(p_rid);
scenario->self = p_rid;
scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create();
@@ -326,14 +370,6 @@ void RendererSceneCull::scenario_initialize(RID p_rid) {
scenario->instance_visibility.set_page_pool(&instance_visibility_data_page_pool);
RendererSceneOcclusionCull::get_singleton()->add_scenario(p_rid);
-
- scenario_owner.initialize_rid(p_rid, scenario);
-}
-
-void RendererSceneCull::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
- ERR_FAIL_COND(!scenario);
- scenario->debug = p_debug_mode;
}
void RendererSceneCull::scenario_set_environment(RID p_scenario, RID p_environment) {
@@ -422,10 +458,9 @@ RID RendererSceneCull::instance_allocate() {
return instance_owner.allocate_rid();
}
void RendererSceneCull::instance_initialize(RID p_rid) {
- Instance *instance = memnew(Instance);
+ instance_owner.initialize_rid(p_rid);
+ Instance *instance = instance_owner.getornull(p_rid);
instance->self = p_rid;
-
- instance_owner.initialize_rid(p_rid, instance);
}
void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
@@ -479,7 +514,6 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
switch (instance->base_type) {
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
- case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
scene_render->geometry_instance_free(geom->geometry_instance);
@@ -591,7 +625,6 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
} break;
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
- case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
@@ -889,7 +922,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
}
inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
- return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE;
+ return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES;
}
void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
@@ -942,9 +975,6 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
}
}
-void RendererSceneCull::instance_set_exterior(RID p_instance, bool p_enabled) {
-}
-
void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@@ -1327,6 +1357,8 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
+
Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
if (!E) {
@@ -1530,7 +1562,6 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
switch (p_instance->base_type) {
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
- case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
idata.instance_geometry = geom->geometry_instance;
@@ -1543,7 +1574,11 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
}
} break;
case RS::INSTANCE_LIGHT: {
- idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance.get_id();
+ 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;
+
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance.get_id();
@@ -1749,14 +1784,6 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
}
} break;
- case RenderingServer::INSTANCE_IMMEDIATE: {
- if (p_instance->custom_aabb) {
- new_aabb = *p_instance->custom_aabb;
- } else {
- new_aabb = RSG::storage->immediate_get_aabb(p_instance->base);
- }
-
- } break;
case RenderingServer::INSTANCE_PARTICLES: {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
@@ -1898,8 +1925,6 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
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);
- RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
-
real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
real_t range = max_distance - min_distance;
@@ -2059,22 +2084,13 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
}
}
- x_max_cam = x_vec.dot(center) + radius + soft_shadow_expand;
- x_min_cam = x_vec.dot(center) - radius - soft_shadow_expand;
- y_max_cam = y_vec.dot(center) + radius + soft_shadow_expand;
- y_min_cam = y_vec.dot(center) - radius - soft_shadow_expand;
-
- if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
- //this trick here is what stabilizes the shadow (make potential jaggies to not move)
- //at the cost of some wasted resolution. Still the quality increase is very well worth it
-
- real_t unit = radius * 2.0 / texture_size;
-
- x_max_cam = Math::snapped(x_max_cam, unit);
- x_min_cam = Math::snapped(x_min_cam, unit);
- y_max_cam = Math::snapped(y_max_cam, unit);
- y_min_cam = Math::snapped(y_min_cam, unit);
- }
+ // This trick here is what stabilizes the shadow (make potential jaggies to not move)
+ // at the cost of some wasted resolution. Still, the quality increase is very well worth it.
+ const real_t unit = radius * 2.0 / texture_size;
+ x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);
+ x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);
+ y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);
+ y_min_cam = Math::snapped(y_vec.dot(center) - radius - soft_shadow_expand, unit);
}
//now that we know all ranges, we can proceed to make the light frustum planes, for culling octree
@@ -2404,7 +2420,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface) {
+void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
#ifndef _3D_DISABLED
Camera *camera = camera_owner.getornull(p_camera);
@@ -2486,7 +2502,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
// For now just cull on the first camera
RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool);
- _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
+ _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_lod_threshold, true, r_render_info);
#endif
}
@@ -2676,6 +2692,13 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
}
+ if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+
+ scene_render->geometry_instance_set_softshadow_projector_pairing(geom->geometry_instance, geom->softshadow_count > 0, geom->projector_count > 0);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY);
+ }
+
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
uint32_t idx = 0;
@@ -2792,7 +2815,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
-void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows) {
+void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
Instance *render_reflection_probe = instance_owner.getornull(p_reflection_probe); //if null, not rendering to it
Scenario *scenario = scenario_owner.getornull(p_scenario);
@@ -3137,7 +3160,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data);
+ scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
for (uint32_t i = 0; i < max_shadows_used; i++) {
render_shadow_data[i].instances.clear();
@@ -3174,7 +3197,6 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
#ifndef _3D_DISABLED
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
RID environment;
@@ -3682,25 +3704,6 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker);
}
- } else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) {
- RID mat = RSG::storage->immediate_get_material(p_instance->base);
-
- if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) {
- can_cast_shadows = false;
- }
-
- if (mat.is_valid() && RSG::storage->material_is_animated(mat)) {
- is_animated = true;
- }
-
- if (mat.is_valid()) {
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- }
-
- if (mat.is_valid()) {
- RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
- }
-
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
@@ -3818,10 +3821,7 @@ bool RendererSceneCull::free(RID p_rid) {
}
if (camera_owner.owns(p_rid)) {
- Camera *camera = camera_owner.getornull(p_rid);
-
camera_owner.free(p_rid);
- memdelete(camera);
} else if (scenario_owner.owns(p_rid)) {
Scenario *scenario = scenario_owner.getornull(p_rid);
@@ -3837,7 +3837,6 @@ bool RendererSceneCull::free(RID p_rid) {
scene_render->free(scenario->reflection_atlas);
scenario_owner.free(p_rid);
RendererSceneOcclusionCull::get_singleton()->remove_scenario(p_rid);
- memdelete(scenario);
} else if (RendererSceneOcclusionCull::get_singleton()->is_occluder(p_rid)) {
RendererSceneOcclusionCull::get_singleton()->free_occluder(p_rid);
@@ -3861,7 +3860,6 @@ bool RendererSceneCull::free(RID p_rid) {
update_dirty_instances(); //in case something changed this
instance_owner.free(p_rid);
- memdelete(instance);
} else {
return false;
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 652d322731..96fe6ce25c 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -97,7 +97,7 @@ public:
}
};
- mutable RID_PtrOwner<Camera, true> camera_owner;
+ mutable RID_Owner<Camera, true> camera_owner;
virtual RID camera_allocate();
virtual void camera_initialize(RID p_rid);
@@ -267,6 +267,7 @@ public:
FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK = (3 << 20), // 2 bits, overlaps with the other vis. dependency flags
FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE = (1 << 20),
FLAG_VISIBILITY_DEPENDENCY_HIDDEN = (1 << 21),
+ FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY = (1 << 22),
};
uint32_t flags = 0;
@@ -315,7 +316,6 @@ public:
DynamicBVH indexers[INDEXER_MAX];
- RS::ScenarioDebugMode debug;
RID self;
List<Instance *> directional_lights;
@@ -338,14 +338,13 @@ public:
Scenario() {
indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY);
indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES);
- debug = RS::SCENARIO_DEBUG_DISABLED;
used_viewport_visibility_bits = 0;
}
};
int indexer_update_iterations = 0;
- mutable RID_PtrOwner<Scenario, true> scenario_owner;
+ mutable RID_Owner<Scenario, true> scenario_owner;
static void _instance_pair(Instance *p_A, Instance *p_B);
static void _instance_unpair(Instance *p_A, Instance *p_B);
@@ -355,7 +354,6 @@ public:
virtual RID scenario_allocate();
virtual void scenario_initialize(RID p_rid);
- virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx);
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
@@ -492,6 +490,14 @@ public:
case RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES: {
//ignored
} break;
+ case RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
+ //requires repairing
+ if (instance->indexer_id.is_valid()) {
+ singleton->_unpair_instance(instance);
+ singleton->_instance_queue_update(instance, true, true);
+ }
+
+ } break;
}
}
@@ -570,6 +576,8 @@ public:
Set<Instance *> lights;
bool can_cast_shadows;
bool material_is_animated;
+ uint32_t projector_count = 0;
+ uint32_t softshadow_count = 0;
Set<Instance *> decals;
Set<Instance *> reflection_probes;
@@ -634,6 +642,8 @@ public:
List<Instance *>::Element *D; // directional light in scenario
bool shadow_dirty;
+ bool uses_projector = false;
+ bool uses_softshadow = false;
Set<Instance *> geometries;
@@ -895,7 +905,7 @@ public:
uint32_t thread_cull_threshold = 200;
- RID_PtrOwner<Instance, true> instance_owner;
+ RID_Owner<Instance, true> instance_owner;
uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecessary on clustered
@@ -914,7 +924,6 @@ public:
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton);
- virtual void instance_set_exterior(RID p_instance, bool p_enabled);
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin);
@@ -1023,10 +1032,10 @@ public:
void _scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
- void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true);
+ void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface);
+ void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
void update_dirty_instances();
void render_particle_colliders();
@@ -1134,6 +1143,9 @@ public:
PASS1(set_debug_draw_mode, RS::ViewportDebugDraw)
+ PASS1(decals_set_filter, RS::DecalFilter)
+ PASS1(light_projectors_set_filter, RS::LightProjectorFilter)
+
virtual void update();
bool free(RID p_rid);
diff --git a/servers/rendering/renderer_scene_occlusion_cull.cpp b/servers/rendering/renderer_scene_occlusion_cull.cpp
index 54795f32a7..1b8aea36d7 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.cpp
+++ b/servers/rendering/renderer_scene_occlusion_cull.cpp
@@ -185,7 +185,7 @@ RID RendererSceneOcclusionCull::HZBuffer::get_debug_texture() {
if (debug_texture.is_null()) {
debug_texture = RS::get_singleton()->texture_2d_create(debug_image);
} else {
- RenderingServer::get_singleton()->texture_2d_update_immediate(debug_texture, debug_image);
+ RenderingServer::get_singleton()->texture_2d_update(debug_texture, debug_image);
}
return debug_texture;
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 3682122dd3..2000afa0d3 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -33,6 +33,7 @@
#include "core/math/camera_matrix.h"
#include "core/templates/paged_array.h"
+#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_storage.h"
class RendererSceneRender {
@@ -68,6 +69,8 @@ public:
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
+ virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) = 0;
+
virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
/* SHADOW ATLAS API */
@@ -234,7 +237,7 @@ public:
void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect);
};
- virtual void 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, 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_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 = nullptr) = 0;
+ virtual void 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, 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_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 = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
@@ -259,6 +262,9 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
+ virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
+
virtual void update() = 0;
virtual ~RendererSceneRender() {}
};
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index f22c582f48..b9bc349f79 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -48,6 +48,7 @@ public:
DEPENDENCY_CHANGED_SKELETON_DATA,
DEPENDENCY_CHANGED_SKELETON_BONES,
DEPENDENCY_CHANGED_LIGHT,
+ DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR,
DEPENDENCY_CHANGED_REFLECTION_PROBE,
};
@@ -130,7 +131,6 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
- virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
@@ -230,7 +230,9 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0;
virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
- virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
@@ -288,24 +290,6 @@ public:
virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
- /* IMMEDIATE API */
-
- virtual RID immediate_allocate() = 0;
- virtual void immediate_initialize(RID p_rid) = 0;
-
- virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0;
- virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0;
- virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0;
- virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0;
- virtual void immediate_color(RID p_immediate, const Color &p_color) = 0;
- virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0;
- virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0;
- virtual void immediate_end(RID p_immediate) = 0;
- virtual void immediate_clear(RID p_immediate) = 0;
- virtual void immediate_set_material(RID p_immediate, RID p_material) = 0;
- virtual RID immediate_get_material(RID p_immediate) const = 0;
- virtual AABB immediate_get_aabb(RID p_immediate) const = 0;
-
/* SKELETON API */
virtual RID skeleton_allocate() = 0;
@@ -348,14 +332,14 @@ public:
virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0;
virtual bool light_directional_is_sky_only(RID p_light) const = 0;
- virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
- virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_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;
@@ -438,12 +422,6 @@ public:
virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
- virtual void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) = 0;
- virtual float voxel_gi_get_ao(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) = 0;
- virtual float voxel_gi_get_ao_size(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;
@@ -624,11 +602,9 @@ public:
virtual void set_debug_generate_wireframes(bool p_generate) = 0;
- virtual void render_info_begin_capture() = 0;
- virtual void render_info_end_capture() = 0;
- virtual int get_captured_render_info(RS::RenderInfo p_info) = 0;
+ virtual void update_memory_info() = 0;
- virtual uint64_t get_render_info(RS::RenderInfo p_info) = 0;
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 34bdb15c62..15ce1dbe63 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -95,7 +95,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
}
float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width);
- RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface);
+ RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
@@ -112,9 +112,15 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
int scenario_canvas_max_layer = 0;
+ for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_TYPE_MAX; i++) {
+ for (int j = 0; j < RS::VIEWPORT_RENDER_INFO_MAX; j++) {
+ p_viewport->render_info.info[i][j] = 0;
+ }
+ }
+
Color bgcolor = RSG::storage->get_default_clear_color();
- if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) {
+ if (!p_viewport->disable_2d && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) {
RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
if (RSG::scene->is_environment(environment)) {
scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS;
@@ -122,7 +128,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
}
}
- bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera);
+ bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera) && !p_viewport->disable_3d;
if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
if (p_viewport->transparent_bg) {
@@ -145,7 +151,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
_draw_3d(p_viewport);
}
- if (!p_viewport->hide_canvas) {
+ if (!p_viewport->disable_2d) {
int i = 0;
Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
@@ -522,6 +528,10 @@ void RendererViewport::draw_viewports() {
}
}
+ int vertices_drawn = 0;
+ int objects_drawn = 0;
+ int draw_calls_used = 0;
+
for (int i = 0; i < active_viewports.size(); i++) {
Viewport *vp = active_viewports[i];
@@ -544,19 +554,11 @@ void RendererViewport::draw_viewports() {
// render...
RSG::scene->set_debug_draw_mode(vp->debug_draw);
- RSG::storage->render_info_begin_capture();
// and draw viewport
_draw_viewport(vp, view_count);
// measure
- RSG::storage->render_info_end_capture();
- vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_VERTICES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_DRAW_CALLS_IN_FRAME);
// commit our eyes
Vector<BlitToScreen> blits = xr_interface->commit_views(vp->render_target, vp->viewport_to_screen_rect);
@@ -576,19 +578,10 @@ void RendererViewport::draw_viewports() {
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
RSG::scene->set_debug_draw_mode(vp->debug_draw);
- RSG::storage->render_info_begin_capture();
// render standard mono camera
_draw_viewport(vp, 1);
- RSG::storage->render_info_end_capture();
- vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_VERTICES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME);
- vp->render_info[RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_DRAW_CALLS_IN_FRAME);
-
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !RSG::rasterizer->is_low_end())) {
//copy to screen if set as such
BlitToScreen blit;
@@ -613,9 +606,17 @@ void RendererViewport::draw_viewports() {
}
RENDER_TIMESTAMP("<Rendering Viewport " + itos(i));
+
+ objects_drawn += vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] + vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME];
+ vertices_drawn += vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] + vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME];
+ draw_calls_used += vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] + vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME];
}
RSG::scene->set_debug_draw_mode(RS::VIEWPORT_DEBUG_DRAW_DISABLED);
+ total_objects_drawn = objects_drawn;
+ total_vertices_drawn = vertices_drawn;
+ total_draw_calls_used = draw_calls_used;
+
RENDER_TIMESTAMP("<Render Viewports");
//this needs to be called to make screen swapping more efficient
RSG::rasterizer->prepare_for_blitting_render_targets();
@@ -630,15 +631,12 @@ RID RendererViewport::viewport_allocate() {
}
void RendererViewport::viewport_initialize(RID p_rid) {
- Viewport *viewport = memnew(Viewport);
+ viewport_owner.initialize_rid(p_rid);
+ Viewport *viewport = viewport_owner.getornull(p_rid);
viewport->self = p_rid;
- viewport->hide_scenario = false;
- viewport->hide_canvas = false;
viewport->render_target = RSG::storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
-
- viewport_owner.initialize_rid(p_rid, viewport);
}
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
@@ -696,7 +694,7 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
ERR_FAIL_COND(!viewport);
if (p_active) {
- ERR_FAIL_COND(active_viewports.find(viewport) != -1); //already active
+ ERR_FAIL_COND_MSG(active_viewports.find(viewport) != -1, "Can't make active a Viewport that is already active.");
viewport->occlusion_buffer_dirty = true;
active_viewports.push_back(viewport);
} else {
@@ -792,25 +790,25 @@ RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const
return RID();
}
-void RendererViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) {
+void RendererViewport::viewport_set_disable_2d(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->hide_scenario = p_hide;
+ viewport->disable_2d = p_disable;
}
-void RendererViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) {
+void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->hide_canvas = p_hide;
+ viewport->disable_environment = p_disable;
}
-void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
+void RendererViewport::viewport_set_disable_3d(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->disable_environment = p_disable;
+ viewport->disable_3d = p_disable;
}
void RendererViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
@@ -990,7 +988,7 @@ void RendererViewport::viewport_set_lod_threshold(RID p_viewport, float p_pixels
viewport->lod_threshold = p_pixels;
}
-int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) {
+int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfoType p_type, RS::ViewportRenderInfo p_info) {
ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1);
Viewport *viewport = viewport_owner.getornull(p_viewport);
@@ -998,7 +996,7 @@ int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRende
return 0; //there should be a lock here..
}
- return viewport->render_info[p_info];
+ return viewport->render_info.info[p_type][p_info];
}
void RendererViewport::viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw) {
@@ -1085,7 +1083,6 @@ bool RendererViewport::free(RID p_rid) {
}
viewport_owner.free(p_rid);
- memdelete(viewport);
return true;
}
@@ -1119,9 +1116,19 @@ void RendererViewport::set_default_clear_color(const Color &p_color) {
RSG::storage->set_default_clear_color(p_color);
}
-//workaround for setting this on thread
-void RendererViewport::call_set_use_vsync(bool p_enable) {
- DisplayServer::get_singleton()->_set_use_vsync(p_enable);
+// Workaround for setting this on thread.
+void RendererViewport::call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window) {
+ DisplayServer::get_singleton()->window_set_vsync_mode(p_mode, p_window);
+}
+
+int RendererViewport::get_total_objects_drawn() const {
+ return total_objects_drawn;
+}
+int RendererViewport::get_total_vertices_drawn() const {
+ return total_vertices_drawn;
+}
+int RendererViewport::get_total_draw_calls_used() const {
+ return total_draw_calls_used;
}
RendererViewport::RendererViewport() {
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index ffda9ad8f0..ac7a35f97d 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -34,6 +34,7 @@
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_scene.h"
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
@@ -68,9 +69,9 @@ public:
Rect2 viewport_to_screen_rect;
bool viewport_render_direct_to_screen;
- bool hide_scenario;
- bool hide_canvas;
- bool disable_environment;
+ bool disable_2d = false;
+ bool disable_environment = false;
+ bool disable_3d = false;
bool measure_render_time;
bool snap_2d_transforms_to_pixel;
@@ -92,7 +93,6 @@ public:
uint64_t last_pass = 0;
- int render_info[RS::VIEWPORT_RENDER_INFO_MAX];
RS::ViewportDebugDraw debug_draw;
RS::ViewportClearMode clear_mode;
@@ -133,11 +133,13 @@ public:
Map<RID, CanvasData> canvas_map;
+ RendererScene::RenderInfo render_info;
+
Viewport() {
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
transparent_bg = false;
- disable_environment = false;
+
viewport_to_screen = DisplayServer::INVALID_WINDOW_ID;
shadow_atlas_size = 0;
measure_render_time = false;
@@ -152,9 +154,6 @@ public:
snap_2d_transforms_to_pixel = false;
snap_2d_vertices_to_pixel = false;
- for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) {
- render_info[i] = 0;
- }
use_xr = false;
sdf_active = false;
@@ -172,7 +171,7 @@ public:
uint64_t draw_viewports_pass = 0;
- mutable RID_PtrOwner<Viewport, true> viewport_owner;
+ mutable RID_Owner<Viewport, true> viewport_owner;
struct ViewportSort {
_FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
@@ -188,6 +187,10 @@ public:
Vector<Viewport *> active_viewports;
+ int total_objects_drawn = 0;
+ int total_vertices_drawn = 0;
+ int total_draw_calls_used = 0;
+
private:
void _draw_3d(Viewport *p_viewport);
void _draw_viewport(Viewport *p_viewport, uint32_t p_view_count = 1);
@@ -217,9 +220,9 @@ public:
RID viewport_get_texture(RID p_viewport) const;
RID viewport_get_occluder_debug_texture(RID p_viewport) const;
- void viewport_set_hide_scenario(RID p_viewport, bool p_hide);
- void viewport_set_hide_canvas(RID p_viewport, bool p_hide);
+ void viewport_set_disable_2d(RID p_viewport, bool p_disable);
void viewport_set_disable_environment(RID p_viewport, bool p_disable);
+ void viewport_set_disable_3d(RID p_viewport, bool p_disable);
void viewport_attach_camera(RID p_viewport, RID p_camera);
void viewport_set_scenario(RID p_viewport, RID p_scenario);
@@ -242,7 +245,7 @@ public:
void viewport_set_occlusion_culling_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality);
void viewport_set_lod_threshold(RID p_viewport, float p_pixels);
- virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info);
+ virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfoType p_type, RS::ViewportRenderInfo p_info);
virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw);
void viewport_set_measure_render_time(RID p_viewport, bool p_enable);
@@ -264,8 +267,12 @@ public:
bool free(RID p_rid);
- //workaround for setting this on thread
- void call_set_use_vsync(bool p_enable);
+ int get_total_objects_drawn() const;
+ int get_total_vertices_drawn() const;
+ int get_total_draw_calls_used() const;
+
+ // Workaround for setting this on thread.
+ void call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window);
RendererViewport();
virtual ~RendererViewport() {}
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index c52d97a3de..3594939362 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -221,7 +221,36 @@ Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier);
}
-RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass) {
+static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constants(const TypedArray<RDPipelineSpecializationConstant> &p_constants) {
+ Vector<RenderingDevice::PipelineSpecializationConstant> ret;
+ ret.resize(p_constants.size());
+ for (int i = 0; i < p_constants.size(); i++) {
+ Ref<RDPipelineSpecializationConstant> c = p_constants[i];
+ ERR_CONTINUE(c.is_null());
+ RenderingDevice::PipelineSpecializationConstant &sc = ret.write[i];
+ Variant value = c->get_value();
+ switch (value.get_type()) {
+ case Variant::BOOL: {
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.bool_value = value;
+ } break;
+ case Variant::INT: {
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+ sc.int_value = value;
+ } break;
+ case Variant::FLOAT: {
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
+ sc.float_value = value;
+ } break;
+ default: {
+ }
+ }
+
+ sc.constant_id = c->get_constant_id();
+ }
+ return ret;
+}
+RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) {
PipelineRasterizationState rasterization_state;
if (p_rasterization_state.is_valid()) {
rasterization_state = p_rasterization_state->base;
@@ -252,7 +281,11 @@ RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p
}
}
- return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags, p_for_render_pass);
+ return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags, p_for_render_pass, _get_spec_constants(p_specialization_constants));
+}
+
+RID RenderingDevice::_compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants = TypedArray<RDPipelineSpecializationConstant>()) {
+ return compute_pipeline_create(p_shader, _get_spec_constants(p_specialization_constants));
}
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
@@ -348,10 +381,10 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL));
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
- ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass", "specialization_constants"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0), DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid);
- ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader"), &RenderingDevice::compute_pipeline_create);
+ ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader", "specialization_constants"), &RenderingDevice::_compute_pipeline_create, DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
ClassDB::bind_method(D_METHOD("compute_pipeline_is_valid", "compute_pieline"), &RenderingDevice::compute_pipeline_is_valid);
ClassDB::bind_method(D_METHOD("screen_get_width", "screen"), &RenderingDevice::screen_get_width, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
@@ -416,6 +449,8 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_device_name"), &RenderingDevice::get_device_name);
ClassDB::bind_method(D_METHOD("get_device_pipeline_cache_uuid"), &RenderingDevice::get_device_pipeline_cache_uuid);
+ ClassDB::bind_method(D_METHOD("get_memory_usage"), &RenderingDevice::get_memory_usage);
+
BIND_CONSTANT(BARRIER_MASK_RASTER);
BIND_CONSTANT(BARRIER_MASK_COMPUTE);
BIND_CONSTANT(BARRIER_MASK_TRANSFER);
@@ -851,6 +886,10 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_GLSL);
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_HLSL);
+ BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL);
+ BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT);
+ BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT);
+
BIND_ENUM_CONSTANT(LIMIT_MAX_BOUND_UNIFORM_SETS);
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS);
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURES_PER_UNIFORM_SET);
@@ -887,6 +926,10 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y);
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z);
+ BIND_ENUM_CONSTANT(MEMORY_TEXTURES);
+ BIND_ENUM_CONSTANT(MEMORY_BUFFERS);
+ BIND_ENUM_CONSTANT(MEMORY_TOTAL);
+
BIND_CONSTANT(INVALID_ID);
BIND_CONSTANT(INVALID_FORMAT_ID);
}
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index be7e127491..9a154ef7e9 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -48,6 +48,7 @@ class RDPipelineMultisampleState;
class RDPipelineDepthStencilState;
class RDPipelineColorBlendState;
class RDFramebufferPass;
+class RDPipelineSpecializationConstant;
class RenderingDevice : public Object {
GDCLASS(RenderingDevice, Object)
@@ -715,11 +716,39 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0;
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
+ typedef void (*UniformSetInvalidatedCallback)(const RID &, void *);
+ virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Vector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving
+ /******************************************/
+ /**** PIPELINE SPECIALIZATION CONSTANT ****/
+ /******************************************/
+
+ enum PipelineSpecializationConstantType {
+ PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL,
+ PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT,
+ PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT,
+ };
+
+ struct PipelineSpecializationConstant {
+ PipelineSpecializationConstantType type;
+ uint32_t constant_id;
+ union {
+ uint32_t int_value;
+ float float_value;
+ bool bool_value;
+ };
+
+ PipelineSpecializationConstant() {
+ type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ constant_id = 0;
+ int_value = 0;
+ }
+ };
+
/*************************/
/**** RENDER PIPELINE ****/
/*************************/
@@ -976,13 +1005,13 @@ public:
};
virtual bool render_pipeline_is_valid(RID p_pipeline) = 0;
- virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0) = 0;
+ virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0;
/**************************/
/**** COMPUTE PIPELINE ****/
/**************************/
- virtual RID compute_pipeline_create(RID p_shader) = 0;
+ virtual RID compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0;
virtual bool compute_pipeline_is_valid(RID p_pipeline) = 0;
/****************/
@@ -1128,7 +1157,13 @@ public:
virtual void submit() = 0;
virtual void sync() = 0;
- virtual uint64_t get_memory_usage() const = 0;
+ enum MemoryType {
+ MEMORY_TEXTURES,
+ MEMORY_BUFFERS,
+ MEMORY_TOTAL
+ };
+
+ virtual uint64_t get_memory_usage(MemoryType p_type) const = 0;
virtual RenderingDevice *create_local_device() = 0;
@@ -1165,7 +1200,8 @@ protected:
Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
- RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0);
+ RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);
+ RID _compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());
void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
@@ -1197,9 +1233,11 @@ VARIANT_ENUM_CAST(RenderingDevice::LogicOperation)
VARIANT_ENUM_CAST(RenderingDevice::BlendFactor)
VARIANT_ENUM_CAST(RenderingDevice::BlendOperation)
VARIANT_ENUM_CAST(RenderingDevice::PipelineDynamicStateFlags)
+VARIANT_ENUM_CAST(RenderingDevice::PipelineSpecializationConstantType)
VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
VARIANT_ENUM_CAST(RenderingDevice::Limit)
+VARIANT_ENUM_CAST(RenderingDevice::MemoryType)
typedef RenderingDevice RD;
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index dc59568ce9..4c31880faf 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -452,6 +452,41 @@ protected:
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_ids", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_ids", "get_ids");
}
};
+
+class RDPipelineSpecializationConstant : public RefCounted {
+ GDCLASS(RDPipelineSpecializationConstant, RefCounted)
+ friend class RenderingDevice;
+
+ Variant value = false;
+ uint32_t constant_id = 0;
+
+public:
+ void set_value(const Variant &p_value) {
+ ERR_FAIL_COND(p_value.get_type() != Variant::BOOL && p_value.get_type() != Variant::INT && p_value.get_type() != Variant::FLOAT);
+ value = p_value;
+ }
+ Variant get_value() const { return value; }
+
+ void set_constant_id(uint32_t p_id) {
+ constant_id = p_id;
+ }
+ uint32_t get_constant_id() const {
+ return constant_id;
+ }
+
+protected:
+ static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_value", "value"), &RDPipelineSpecializationConstant::set_value);
+ ClassDB::bind_method(D_METHOD("get_value"), &RDPipelineSpecializationConstant::get_value);
+
+ ClassDB::bind_method(D_METHOD("set_constant_id", "constant_id"), &RDPipelineSpecializationConstant::set_constant_id);
+ ClassDB::bind_method(D_METHOD("get_constant_id"), &RDPipelineSpecializationConstant::get_constant_id);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_value", "get_value");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "constant_id", PROPERTY_HINT_RANGE, "0,65535,0"), "set_constant_id", "get_constant_id");
+ }
+};
+
class RDPipelineRasterizationState : public RefCounted {
GDCLASS(RDPipelineRasterizationState, RefCounted)
friend class RenderingDevice;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 629d212b69..c79dfb1649 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -42,26 +42,6 @@
int RenderingServerDefault::changes = 0;
-/* BLACK BARS */
-
-void RenderingServerDefault::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
- black_margin[SIDE_LEFT] = p_left;
- black_margin[SIDE_TOP] = p_top;
- black_margin[SIDE_RIGHT] = p_right;
- black_margin[SIDE_BOTTOM] = p_bottom;
-}
-
-void RenderingServerDefault::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) {
- black_image[SIDE_LEFT] = p_left;
- black_image[SIDE_TOP] = p_top;
- black_image[SIDE_RIGHT] = p_right;
- black_image[SIDE_BOTTOM] = p_bottom;
-}
-
-void RenderingServerDefault::_draw_margins() {
- RSG::canvas_render->draw_window_margins(black_margin, black_image);
-};
-
/* FREE */
void RenderingServerDefault::_free(RID p_rid) {
@@ -93,7 +73,7 @@ void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const
void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
//needs to be done before changes is reset to 0, to not force the editor to redraw
- RS::get_singleton()->emit_signal("frame_pre_draw");
+ RS::get_singleton()->emit_signal(SNAME("frame_pre_draw"));
changes = 0;
@@ -114,7 +94,6 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::viewport->draw_viewports();
RSG::canvas_render->update();
- _draw_margins();
RSG::rasterizer->end_frame(p_swap_buffers);
RSG::canvas->update_visibility_notifiers();
@@ -134,7 +113,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
frame_drawn_callbacks.pop_front();
}
- RS::get_singleton()->emit_signal("frame_post_draw");
+ RS::get_singleton()->emit_signal(SNAME("frame_post_draw"));
if (RSG::storage->get_captured_timestamps_count()) {
Vector<FrameProfileArea> new_profile;
@@ -210,6 +189,8 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
print_frame_profile_frame_count = 0;
}
}
+
+ RSG::storage->update_memory_info();
}
float RenderingServerDefault::get_frame_setup_time_cpu() const {
@@ -260,8 +241,15 @@ void RenderingServerDefault::finish() {
/* STATUS INFORMATION */
-uint64_t RenderingServerDefault::get_render_info(RenderInfo p_info) {
- return RSG::storage->get_render_info(p_info);
+uint64_t RenderingServerDefault::get_rendering_info(RenderingInfo p_info) {
+ if (p_info == RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME) {
+ return RSG::viewport->get_total_objects_drawn();
+ } else if (p_info == RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME) {
+ return RSG::viewport->get_total_vertices_drawn();
+ } else if (p_info == RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME) {
+ return RSG::viewport->get_total_draw_calls_used();
+ }
+ return RSG::storage->get_rendering_info(p_info);
}
String RenderingServerDefault::get_video_adapter_name() const {
@@ -410,11 +398,6 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
sr->set_scene_render(RSG::rasterizer->get_scene());
frame_profile_frame = 0;
-
- for (int i = 0; i < 4; i++) {
- black_margin[i] = 0;
- black_image[i] = RID();
- }
}
RenderingServerDefault::~RenderingServerDefault() {
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 16e9f1fc77..282b0564da 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -58,9 +58,6 @@ class RenderingServerDefault : public RenderingServer {
static int changes;
RID test_cube;
- int black_margin[4];
- RID black_image[4];
-
struct FrameDrawnCallbacks {
ObjectID object;
StringName method;
@@ -69,7 +66,6 @@ class RenderingServerDefault : public RenderingServer {
List<FrameDrawnCallbacks> frame_drawn_callbacks;
- void _draw_margins();
static void _changes_changed() {}
uint64_t frame_profile_frame;
@@ -192,8 +188,6 @@ public:
FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
FUNCRIDTEX1(texture_proxy, RID)
- //goes pass-through
- FUNC3(texture_2d_update_immediate, RID, const Ref<Image> &, int)
//these go through command queue if they are in another thread
FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)
@@ -290,7 +284,9 @@ public:
FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
- FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
+ FUNC4(mesh_surface_update_vertex_region, RID, int, int, const Vector<uint8_t> &)
+ FUNC4(mesh_surface_update_attribute_region, RID, int, int, const Vector<uint8_t> &)
+ FUNC4(mesh_surface_update_skin_region, RID, int, int, const Vector<uint8_t> &)
FUNC3(mesh_surface_set_material, RID, int, RID)
FUNC2RC(RID, mesh_surface_get_material, RID, int)
@@ -333,21 +329,6 @@ public:
FUNC2(multimesh_set_visible_instances, RID, int)
FUNC1RC(int, multimesh_get_visible_instances, RID)
- /* IMMEDIATE API */
-
- FUNCRIDSPLIT(immediate)
- FUNC3(immediate_begin, RID, PrimitiveType, RID)
- FUNC2(immediate_vertex, RID, const Vector3 &)
- FUNC2(immediate_normal, RID, const Vector3 &)
- FUNC2(immediate_tangent, RID, const Plane &)
- FUNC2(immediate_color, RID, const Color &)
- FUNC2(immediate_uv, RID, const Vector2 &)
- FUNC2(immediate_uv2, RID, const Vector2 &)
- FUNC1(immediate_end, RID)
- FUNC1(immediate_clear, RID)
- FUNC2(immediate_set_material, RID, RID)
- FUNC1RC(RID, immediate_get_material, RID)
-
/* SKELETON API */
FUNCRIDSPLIT(skeleton)
@@ -381,7 +362,6 @@ public:
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
FUNC2(light_directional_set_blend_splits, RID, bool)
FUNC2(light_directional_set_sky_only, RID, bool)
- FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* PROBE API */
@@ -431,34 +411,12 @@ public:
FUNC1RC(Transform3D, voxel_gi_get_to_cell_xform, RID)
FUNC2(voxel_gi_set_dynamic_range, RID, float)
- FUNC1RC(float, voxel_gi_get_dynamic_range, RID)
-
FUNC2(voxel_gi_set_propagation, RID, float)
- FUNC1RC(float, voxel_gi_get_propagation, RID)
-
FUNC2(voxel_gi_set_energy, RID, float)
- FUNC1RC(float, voxel_gi_get_energy, RID)
-
- FUNC2(voxel_gi_set_ao, RID, float)
- FUNC1RC(float, voxel_gi_get_ao, RID)
-
- FUNC2(voxel_gi_set_ao_size, RID, float)
- FUNC1RC(float, voxel_gi_get_ao_size, RID)
-
FUNC2(voxel_gi_set_bias, RID, float)
- FUNC1RC(float, voxel_gi_get_bias, RID)
-
FUNC2(voxel_gi_set_normal_bias, RID, float)
- FUNC1RC(float, voxel_gi_get_normal_bias, RID)
-
FUNC2(voxel_gi_set_interior, RID, bool)
- FUNC1RC(bool, voxel_gi_is_interior, RID)
-
FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
- FUNC1RC(bool, voxel_gi_is_using_two_bounces, RID)
-
- FUNC2(voxel_gi_set_anisotropy_strength, RID, float)
- FUNC1RC(float, voxel_gi_get_anisotropy_strength, RID)
/* LIGHTMAP */
@@ -582,9 +540,9 @@ public:
FUNC1RC(RID, viewport_get_texture, RID)
- FUNC2(viewport_set_hide_scenario, RID, bool)
- FUNC2(viewport_set_hide_canvas, RID, bool)
+ FUNC2(viewport_set_disable_2d, RID, bool)
FUNC2(viewport_set_disable_environment, RID, bool)
+ FUNC2(viewport_set_disable_3d, RID, bool)
FUNC2(viewport_attach_camera, RID, RID)
FUNC2(viewport_set_scenario, RID, RID)
@@ -612,14 +570,14 @@ public:
FUNC1(viewport_set_occlusion_culling_build_quality, ViewportOcclusionCullingBuildQuality)
FUNC2(viewport_set_lod_threshold, RID, float)
- FUNC2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
+ FUNC3R(int, viewport_get_render_info, RID, ViewportRenderInfoType, ViewportRenderInfo)
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
FUNC2(viewport_set_measure_render_time, RID, bool)
FUNC1RC(float, viewport_get_measured_render_time_cpu, RID)
FUNC1RC(float, viewport_get_measured_render_time_gpu, RID)
- FUNC1(call_set_use_vsync, bool)
+ FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
/* ENVIRONMENT API */
@@ -698,6 +656,8 @@ public:
FUNC1(shadows_quality_set, ShadowQuality);
FUNC1(directional_shadow_quality_set, ShadowQuality);
+ FUNC1(decals_set_filter, RS::DecalFilter);
+ FUNC1(light_projectors_set_filter, RS::LightProjectorFilter);
/* SCENARIO API */
@@ -709,7 +669,6 @@ public:
FUNCRIDSPLIT(scenario)
- FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
FUNC2(scenario_set_environment, RID, RID)
FUNC2(scenario_set_camera_effects, RID, RID)
FUNC2(scenario_set_fallback_environment, RID, RID)
@@ -729,7 +688,6 @@ public:
FUNC2(instance_set_custom_aabb, RID, AABB)
FUNC2(instance_attach_skeleton, RID, RID)
- FUNC2(instance_set_exterior, RID, bool)
FUNC2(instance_set_extra_visibility_margin, RID, real_t)
FUNC2(instance_set_visibility_parent, RID, RID)
@@ -897,11 +855,6 @@ public:
#undef WRITE_ACTION
#undef SYNC_DEBUG
- /* BLACK BARS */
-
- virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) override;
- virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) override;
-
/* FREE */
virtual void free(RID p_rid) override {
@@ -925,7 +878,7 @@ public:
/* STATUS INFORMATION */
- virtual uint64_t get_render_info(RenderInfo p_info) override;
+ virtual uint64_t get_rendering_info(RenderingInfo p_info) override;
virtual String get_video_adapter_name() const override;
virtual String get_video_adapter_vendor() const override;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 9b2ba36358..f771d6d0ef 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -918,6 +918,7 @@ void ShaderLanguage::clear() {
used_uniforms.clear();
used_functions.clear();
used_structs.clear();
+ used_local_vars.clear();
warnings.clear();
#endif // DEBUG_ENABLED
@@ -936,7 +937,7 @@ void ShaderLanguage::clear() {
}
#ifdef DEBUG_ENABLED
-void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, IdentifierType p_type) {
+void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, IdentifierType p_type, const StringName &p_function) {
switch (p_type) {
case IdentifierType::IDENTIFIER_CONSTANT:
if (HAS_WARNING(ShaderWarning::UNUSED_CONSTANT_FLAG) && used_constants.has(p_identifier)) {
@@ -958,6 +959,11 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden
used_functions[p_identifier].used = true;
}
break;
+ case IdentifierType::IDENTIFIER_LOCAL_VAR:
+ if (HAS_WARNING(ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG) && used_local_vars.has(p_function) && used_local_vars[p_function].has(p_identifier)) {
+ used_local_vars[p_function][p_identifier].used = true;
+ }
+ break;
default:
break;
}
@@ -4171,7 +4177,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = func;
#ifdef DEBUG_ENABLED
if (check_warnings) {
- _parse_used_identifier(name, IdentifierType::IDENTIFIER_FUNCTION);
+ StringName func_name;
+
+ if (p_block && p_block->parent_function) {
+ func_name = p_block->parent_function->name;
+ }
+
+ _parse_used_identifier(name, IdentifierType::IDENTIFIER_FUNCTION, func_name);
}
#endif // DEBUG_ENABLED
}
@@ -4319,7 +4331,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
#ifdef DEBUG_ENABLED
if (check_warnings) {
- _parse_used_identifier(identifier, ident_type);
+ StringName func_name;
+
+ if (p_block && p_block->parent_function) {
+ func_name = p_block->parent_function->name;
+ }
+
+ _parse_used_identifier(identifier, ident_type, func_name);
}
#endif // DEBUG_ENABLED
}
@@ -5537,6 +5555,20 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG)) {
+ if (p_block && p_block->parent_function) {
+ StringName func_name = p_block->parent_function->name;
+
+ if (!used_local_vars.has(func_name)) {
+ used_local_vars.insert(func_name, Map<StringName, Usage>());
+ }
+
+ used_local_vars[func_name].insert(name, Usage(tk_line));
+ }
+ }
+#endif // DEBUG_ENABLED
+
BlockNode::Variable var;
var.type = type;
var.precision = precision;
@@ -7984,6 +8016,15 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
#ifdef DEBUG_ENABLED
void ShaderLanguage::_check_warning_accums() {
+ for (Map<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *>::Element *E = warnings_check_map2.front(); E; E = E->next()) {
+ for (Map<StringName, Map<StringName, Usage>>::Element *T = (*E->get()).front(); T; T = T->next()) {
+ for (const Map<StringName, Usage>::Element *U = T->get().front(); U; U = U->next()) {
+ if (!U->get().used) {
+ _add_warning(E->key(), U->get().decl_line, U->key());
+ }
+ }
+ }
+ }
for (Map<ShaderWarning::Code, Map<StringName, Usage> *>::Element *E = warnings_check_map.front(); E; E = E->next()) {
for (const Map<StringName, Usage>::Element *U = (*E->get()).front(); U; U = U->next()) {
if (!U->get().used) {
@@ -8456,6 +8497,8 @@ ShaderLanguage::ShaderLanguage() {
warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs);
warnings_check_map.insert(ShaderWarning::UNUSED_UNIFORM, &used_uniforms);
warnings_check_map.insert(ShaderWarning::UNUSED_VARYING, &used_varyings);
+
+ warnings_check_map2.insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, &used_local_vars);
#endif // DEBUG_ENABLED
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 4120e04ee1..a91fa57a8e 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -848,6 +848,9 @@ private:
Map<StringName, Usage> used_structs;
Map<ShaderWarning::Code, Map<StringName, Usage> *> warnings_check_map;
+ Map<StringName, Map<StringName, Usage>> used_local_vars;
+ Map<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> warnings_check_map2;
+
List<ShaderWarning> warnings;
bool check_warnings = false;
@@ -917,7 +920,7 @@ private:
bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr, ConstantNode::Value *r_constant_value = nullptr);
#ifdef DEBUG_ENABLED
- void _parse_used_identifier(const StringName &p_identifier, IdentifierType p_type);
+ void _parse_used_identifier(const StringName &p_identifier, IdentifierType p_type, const StringName &p_function);
#endif // DEBUG_ENABLED
bool _is_operator_assign(Operator p_op) const;
bool _validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message = nullptr);
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index c4e7511374..376d23ccb3 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -122,7 +122,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_CURVE"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_BOOST"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["BACKLIGHT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp
index aa11b4e397..0c1d6408c9 100644
--- a/servers/rendering/shader_warnings.cpp
+++ b/servers/rendering/shader_warnings.cpp
@@ -59,6 +59,8 @@ String ShaderWarning::get_message() const {
return vformat("The uniform '%s' is declared but never used.", subject);
case UNUSED_VARYING:
return vformat("The varying '%s' is declared but never used.", subject);
+ case UNUSED_LOCAL_VARIABLE:
+ return vformat("The local variable '%s' is declared but never used.", subject);
default:
break;
}
@@ -79,6 +81,7 @@ String ShaderWarning::get_name_from_code(Code p_code) {
"UNUSED_STRUCT",
"UNUSED_UNIFORM",
"UNUSED_VARYING",
+ "UNUSED_LOCAL_VARIABLE",
};
static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
@@ -106,6 +109,7 @@ static void init_code_to_flags_map() {
code_to_flags_map->insert(ShaderWarning::UNUSED_STRUCT, ShaderWarning::UNUSED_STRUCT_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG);
+ code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG);
}
ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index c40aeefa2d..db872d8fb1 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -46,6 +46,7 @@ public:
UNUSED_STRUCT,
UNUSED_UNIFORM,
UNUSED_VARYING,
+ UNUSED_LOCAL_VARIABLE,
WARNING_MAX,
};
@@ -57,6 +58,7 @@ public:
UNUSED_STRUCT_FLAG = 8U,
UNUSED_UNIFORM_FLAG = 16U,
UNUSED_VARYING_FLAG = 32U,
+ UNUSED_LOCAL_VARIABLE_FLAG = 64U,
};
private:
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index f25f255321..a39d0e89ee 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -31,7 +31,7 @@
#include "rendering_server.h"
#include "core/config/project_settings.h"
-
+#include "servers/rendering/rendering_server_globals.h"
RenderingServer *RenderingServer::singleton = nullptr;
RenderingServer *(*RenderingServer::create_func)() = nullptr;
@@ -67,12 +67,6 @@ Array RenderingServer::_texture_debug_usage_bind() {
return arr;
}
-Array RenderingServer::_shader_get_param_list_bind(RID p_shader) const {
- List<PropertyInfo> l;
- shader_get_param_list(p_shader, &l);
- return convert_property_list(&l);
-}
-
static Array to_array(const Vector<ObjectID> &ids) {
Array a;
a.resize(ids.size());
@@ -83,16 +77,25 @@ static Array to_array(const Vector<ObjectID> &ids) {
}
Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const {
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
+ }
Vector<ObjectID> ids = instances_cull_aabb(p_aabb, p_scenario);
return to_array(ids);
}
Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
+ }
Vector<ObjectID> ids = instances_cull_ray(p_from, p_to, p_scenario);
return to_array(ids);
}
Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const {
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
+ }
Vector<Plane> planes;
for (int i = 0; i < p_convex.size(); ++i) {
Variant v = p_convex[i];
@@ -347,7 +350,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
{
for (int i = 0; i < p_vertex_array_len; i++) {
- float vector[2] = { src[i].x, src[i].y };
+ float vector[2] = { (float)src[i].x, (float)src[i].y };
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(float) * 2);
@@ -372,7 +375,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
{
for (int i = 0; i < p_vertex_array_len; i++) {
- float vector[3] = { src[i].x, src[i].y, src[i].z };
+ float vector[3] = { (float)src[i].x, (float)src[i].y, (float)src[i].z };
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(float) * 3);
@@ -438,13 +441,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER);
const Color *src = array.ptr();
- uint16_t color16[4];
for (int i = 0; i < p_vertex_array_len; i++) {
- color16[0] = Math::make_half_float(src[i].r);
- color16[1] = Math::make_half_float(src[i].g);
- color16[2] = Math::make_half_float(src[i].b);
- color16[3] = Math::make_half_float(src[i].a);
- memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], color16, 8);
+ uint8_t color8[4] = {
+ uint8_t(CLAMP(src[i].r * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(src[i].g * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(src[i].b * 255.0, 0.0, 255.0)),
+ uint8_t(CLAMP(src[i].a * 255.0, 0.0, 255.0))
+ };
+ memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], color8, 4);
}
} break;
case RS::ARRAY_TEX_UV: {
@@ -457,7 +461,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const Vector2 *src = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- float uv[2] = { src[i].x, src[i].y };
+ float uv[2] = { (float)src[i].x, (float)src[i].y };
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 2 * 4);
}
@@ -474,7 +478,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const Vector2 *src = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- float uv[2] = { src[i].x, src[i].y };
+ float uv[2] = { (float)src[i].x, (float)src[i].y };
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 2 * 4);
}
} break;
@@ -761,7 +765,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
elem_size = 4;
} break;
case RS::ARRAY_COLOR: {
- elem_size = 8;
+ elem_size = 4;
} break;
case RS::ARRAY_TEX_UV: {
elem_size = 8;
@@ -1123,8 +1127,9 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
Color *w = arr.ptrw();
for (int32_t j = 0; j < p_vertex_len; j++) {
- const uint16_t *v = (const uint16_t *)&ar[j * attrib_elem_size + offsets[i]];
- w[j] = Color(Math::half_to_float(v[0]), Math::half_to_float(v[1]), Math::half_to_float(v[2]), Math::half_to_float(v[3]));
+ const uint8_t *v = (const uint8_t *)&ar[j * attrib_elem_size + offsets[i]];
+
+ w[j] = Color(v[0] / 255.0, v[1] / 255.0, v[2] / 255.0, v[3] / 255.0);
}
ret[i] = arr;
@@ -1441,29 +1446,247 @@ RenderingDevice *RenderingServer::create_local_rendering_device() const {
return RenderingDevice::get_singleton()->create_local_device();
}
+static Vector<Ref<Image>> _get_imgvec(const TypedArray<Image> &p_layers) {
+ Vector<Ref<Image>> images;
+ images.resize(p_layers.size());
+ for (int i = 0; i < p_layers.size(); i++) {
+ images.write[i] = p_layers[i];
+ }
+ return images;
+}
+RID RenderingServer::_texture_2d_layered_create(const TypedArray<Image> &p_layers, TextureLayeredType p_layered_type) {
+ return texture_2d_layered_create(_get_imgvec(p_layers), p_layered_type);
+}
+RID RenderingServer::_texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data) {
+ return texture_3d_create(p_format, p_width, p_height, p_depth, p_mipmaps, _get_imgvec(p_data));
+}
+
+void RenderingServer::_texture_3d_update(RID p_texture, const TypedArray<Image> &p_data) {
+ texture_3d_update(p_texture, _get_imgvec(p_data));
+}
+
+TypedArray<Image> RenderingServer::_texture_3d_get(RID p_texture) const {
+ Vector<Ref<Image>> images = texture_3d_get(p_texture);
+ TypedArray<Image> ret;
+ ret.resize(images.size());
+ for (int i = 0; i < images.size(); i++) {
+ ret[i] = images[i];
+ }
+ return ret;
+}
+
+TypedArray<Dictionary> RenderingServer::_shader_get_param_list(RID p_shader) const {
+ List<PropertyInfo> l;
+ shader_get_param_list(p_shader, &l);
+ return convert_property_list(&l);
+}
+
+static RS::SurfaceData _dict_to_surf(const Dictionary &p_dictionary) {
+ ERR_FAIL_COND_V(!p_dictionary.has("primitive"), RS::SurfaceData());
+ ERR_FAIL_COND_V(!p_dictionary.has("format"), RS::SurfaceData());
+ ERR_FAIL_COND_V(!p_dictionary.has("vertex_data"), RS::SurfaceData());
+ ERR_FAIL_COND_V(!p_dictionary.has("vertex_count"), RS::SurfaceData());
+ ERR_FAIL_COND_V(!p_dictionary.has("aabb"), RS::SurfaceData());
+
+ RS::SurfaceData sd;
+
+ sd.primitive = RS::PrimitiveType(int(p_dictionary["primitive"]));
+ sd.format = p_dictionary["format"];
+ sd.vertex_data = p_dictionary["vertex_data"];
+ if (p_dictionary.has("attribute_data")) {
+ sd.attribute_data = p_dictionary["attribute_data"];
+ }
+ if (p_dictionary.has("skin_data")) {
+ sd.skin_data = p_dictionary["skin_data"];
+ }
+
+ sd.vertex_count = p_dictionary["vertex_count"];
+
+ if (p_dictionary.has("index_data")) {
+ sd.index_data = p_dictionary["index_data"];
+ ERR_FAIL_COND_V(!p_dictionary.has("index_count"), RS::SurfaceData());
+ sd.index_count = p_dictionary["index_count"];
+ }
+
+ sd.aabb = p_dictionary["aabb"];
+
+ if (p_dictionary.has("lods")) {
+ Array lods = p_dictionary["lods"];
+ for (int i = 0; i < lods.size(); i++) {
+ Dictionary lod = lods[i];
+ ERR_CONTINUE(!lod.has("edge_length"));
+ ERR_CONTINUE(!lod.has("index_data"));
+ RS::SurfaceData::LOD l;
+ l.edge_length = lod["edge_length"];
+ l.index_data = lod["index_data"];
+ sd.lods.push_back(l);
+ }
+ }
+
+ if (p_dictionary.has("bone_aabbs")) {
+ Array aabbs = p_dictionary["bone_aabbs"];
+ for (int i = 0; i < aabbs.size(); i++) {
+ AABB aabb = aabbs[i];
+ sd.bone_aabbs.push_back(aabb);
+ }
+ }
+
+ if (p_dictionary.has("blend_shape_data")) {
+ sd.blend_shape_data = p_dictionary["blend_shape_data"];
+ }
+
+ if (p_dictionary.has("material")) {
+ sd.material = p_dictionary["material"];
+ }
+
+ return sd;
+}
+RID RenderingServer::_mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count) {
+ Vector<RS::SurfaceData> surfaces;
+ for (int i = 0; i < p_surfaces.size(); i++) {
+ surfaces.push_back(_dict_to_surf(p_surfaces[i]));
+ }
+ return mesh_create_from_surfaces(surfaces);
+}
+void RenderingServer::_mesh_add_surface(RID p_mesh, const Dictionary &p_surface) {
+ mesh_add_surface(p_mesh, _dict_to_surf(p_surface));
+}
+Dictionary RenderingServer::_mesh_get_surface(RID p_mesh, int p_idx) {
+ RS::SurfaceData sd = mesh_get_surface(p_mesh, p_idx);
+
+ Dictionary d;
+ d["primitive"] = sd.primitive;
+ d["format"] = sd.format;
+ d["vertex_data"] = sd.vertex_data;
+ if (sd.attribute_data.size()) {
+ d["attribute_data"] = sd.attribute_data;
+ }
+ if (sd.skin_data.size()) {
+ d["skin_data"] = sd.skin_data;
+ }
+ d["vertex_count"] = sd.vertex_count;
+ if (sd.index_count) {
+ d["index_data"] = sd.index_data;
+ d["index_count"] = sd.index_count;
+ }
+ d["aabb"] = sd.aabb;
+
+ if (sd.lods.size()) {
+ Array lods;
+ for (int i = 0; i < sd.lods.size(); i++) {
+ Dictionary ld;
+ ld["edge_length"] = sd.lods[i].edge_length;
+ ld["index_data"] = sd.lods[i].index_data;
+ lods.push_back(lods);
+ }
+ d["lods"] = lods;
+ }
+
+ if (sd.bone_aabbs.size()) {
+ Array aabbs;
+ for (int i = 0; i < sd.bone_aabbs.size(); i++) {
+ aabbs.push_back(sd.bone_aabbs[i]);
+ }
+ d["bone_aabbs"] = aabbs;
+ }
+
+ if (sd.blend_shape_data.size()) {
+ d["blend_shape_data"] = sd.blend_shape_data;
+ }
+
+ if (sd.material.is_valid()) {
+ d["material"] = sd.material;
+ }
+ return d;
+}
+
+Array RenderingServer::_instance_geometry_get_shader_parameter_list(RID p_instance) const {
+ List<PropertyInfo> params;
+ instance_geometry_get_shader_parameter_list(p_instance, &params);
+ return convert_property_list(&params);
+}
+
+TypedArray<Image> RenderingServer::_bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) {
+ Vector<RID> mat_overrides;
+ for (int i = 0; i < p_material_overrides.size(); i++) {
+ mat_overrides.push_back(p_material_overrides[i]);
+ }
+ return bake_render_uv2(p_base, mat_overrides, p_image_size);
+}
+
+void RenderingServer::_particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses) {
+ Vector<Transform3D> tbposes;
+ tbposes.resize(p_bind_poses.size());
+ for (int i = 0; i < p_bind_poses.size(); i++) {
+ tbposes.write[i] = p_bind_poses[i];
+ }
+ particles_set_trail_bind_poses(p_particles, tbposes);
+}
+
void RenderingServer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("force_sync"), &RenderingServer::sync);
- ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers", "frame_step"), &RenderingServer::draw, DEFVAL(true), DEFVAL(0.0));
- ClassDB::bind_method(D_METHOD("create_local_rendering_device"), &RenderingServer::create_local_rendering_device);
+ BIND_CONSTANT(NO_INDEX_ARRAY);
+ BIND_CONSTANT(ARRAY_WEIGHTS_SIZE);
+ BIND_CONSTANT(CANVAS_ITEM_Z_MIN);
+ BIND_CONSTANT(CANVAS_ITEM_Z_MAX);
+ BIND_CONSTANT(MAX_GLOW_LEVELS);
+ BIND_CONSTANT(MAX_CURSORS);
+ BIND_CONSTANT(MAX_2D_DIRECTIONAL_LIGHTS);
-#ifndef _MSC_VER
-#warning TODO all texture methods need re-binding
-#endif
+ /* TEXTURE */
ClassDB::bind_method(D_METHOD("texture_2d_create", "image"), &RenderingServer::texture_2d_create);
+ ClassDB::bind_method(D_METHOD("texture_2d_layered_create", "layers", "layered_type"), &RenderingServer::_texture_2d_layered_create);
+ ClassDB::bind_method(D_METHOD("texture_3d_create", "format", "width", "height", "depth", "mipmaps", "data"), &RenderingServer::_texture_3d_create);
+ ClassDB::bind_method(D_METHOD("texture_proxy_create", "base"), &RenderingServer::texture_proxy_create);
+
+ ClassDB::bind_method(D_METHOD("texture_2d_update", "texture", "image", "layer"), &RenderingServer::texture_2d_update);
+ ClassDB::bind_method(D_METHOD("texture_3d_update", "texture", "data"), &RenderingServer::_texture_3d_update);
+ ClassDB::bind_method(D_METHOD("texture_proxy_update", "texture", "proxy_to"), &RenderingServer::texture_proxy_update);
+
+ ClassDB::bind_method(D_METHOD("texture_2d_placeholder_create"), &RenderingServer::texture_2d_placeholder_create);
+ ClassDB::bind_method(D_METHOD("texture_2d_layered_placeholder_create", "layered_type"), &RenderingServer::texture_2d_layered_placeholder_create);
+ ClassDB::bind_method(D_METHOD("texture_3d_placeholder_create"), &RenderingServer::texture_3d_placeholder_create);
+
ClassDB::bind_method(D_METHOD("texture_2d_get", "texture"), &RenderingServer::texture_2d_get);
+ ClassDB::bind_method(D_METHOD("texture_2d_layer_get", "texture", "layer"), &RenderingServer::texture_2d_layer_get);
+ ClassDB::bind_method(D_METHOD("texture_3d_get", "texture"), &RenderingServer::_texture_3d_get);
+
+ ClassDB::bind_method(D_METHOD("texture_replace", "texture", "by_texture"), &RenderingServer::texture_replace);
+ ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height"), &RenderingServer::texture_set_size_override);
+
+ ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &RenderingServer::texture_set_path);
+ ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &RenderingServer::texture_get_path);
+
+ ClassDB::bind_method(D_METHOD("texture_set_force_redraw_if_visible", "texture", "enable"), &RenderingServer::texture_set_force_redraw_if_visible);
+
+ BIND_ENUM_CONSTANT(TEXTURE_LAYERED_2D_ARRAY);
+ BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP);
+ BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP_ARRAY);
+
+ BIND_ENUM_CONSTANT(CUBEMAP_LAYER_LEFT);
+ BIND_ENUM_CONSTANT(CUBEMAP_LAYER_RIGHT);
+ BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BOTTOM);
+ BIND_ENUM_CONSTANT(CUBEMAP_LAYER_TOP);
+ BIND_ENUM_CONSTANT(CUBEMAP_LAYER_FRONT);
+ BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BACK);
+
+ /* SHADER */
-#ifndef _3D_DISABLED
- ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
- ClassDB::bind_method(D_METHOD("sky_set_material", "sky", "material"), &RenderingServer::sky_set_material);
-#endif
ClassDB::bind_method(D_METHOD("shader_create"), &RenderingServer::shader_create);
- ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &RenderingServer::shader_set_code);
ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &RenderingServer::shader_get_code);
- ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list_bind);
- ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "name", "texture"), &RenderingServer::shader_set_default_texture_param);
- ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "name"), &RenderingServer::shader_get_default_texture_param);
- ClassDB::bind_method(D_METHOD("shader_get_param_default", "material", "parameter"), &RenderingServer::shader_get_param_default);
+ ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list);
+ ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default);
+
+ ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture"), &RenderingServer::shader_set_default_texture_param);
+ ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param"), &RenderingServer::shader_get_default_texture_param);
+
+ BIND_ENUM_CONSTANT(SHADER_SPATIAL);
+ BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM);
+ BIND_ENUM_CONSTANT(SHADER_PARTICLES);
+ BIND_ENUM_CONSTANT(SHADER_SKY);
+ BIND_ENUM_CONSTANT(SHADER_MAX);
+
+ /* MATERIAL */
ClassDB::bind_method(D_METHOD("material_create"), &RenderingServer::material_create);
ClassDB::bind_method(D_METHOD("material_set_shader", "shader_material", "shader"), &RenderingServer::material_set_shader);
@@ -1473,18 +1696,26 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("material_set_next_pass", "material", "next_material"), &RenderingServer::material_set_next_pass);
+ BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MIN);
+ BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MAX);
+
+ /* MESH API */
+
+ ClassDB::bind_method(D_METHOD("mesh_create_from_surfaces", "surfaces", "blend_shape_count"), &RenderingServer::_mesh_create_from_surfaces, DEFVAL(0));
ClassDB::bind_method(D_METHOD("mesh_create"), &RenderingServer::mesh_create);
ClassDB::bind_method(D_METHOD("mesh_surface_get_format_offset", "format", "vertex_count", "array_index"), &RenderingServer::mesh_surface_get_format_offset);
ClassDB::bind_method(D_METHOD("mesh_surface_get_format_vertex_stride", "format", "vertex_count"), &RenderingServer::mesh_surface_get_format_vertex_stride);
ClassDB::bind_method(D_METHOD("mesh_surface_get_format_attribute_stride", "format", "vertex_count"), &RenderingServer::mesh_surface_get_format_attribute_stride);
ClassDB::bind_method(D_METHOD("mesh_surface_get_format_skin_stride", "format", "vertex_count"), &RenderingServer::mesh_surface_get_format_skin_stride);
- //ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primitive", "arrays", "blend_shapes", "lods", "compress_format"), &RenderingServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("mesh_add_surface", "mesh", "surface"), &RenderingServer::_mesh_add_surface);
+ ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primitive", "arrays", "blend_shapes", "lods", "compress_format"), &RenderingServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &RenderingServer::mesh_get_blend_shape_count);
ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &RenderingServer::mesh_set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &RenderingServer::mesh_get_blend_shape_mode);
- ClassDB::bind_method(D_METHOD("mesh_surface_update_region", "mesh", "surface", "offset", "data"), &RenderingServer::mesh_surface_update_region);
+
ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &RenderingServer::mesh_surface_set_material);
ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &RenderingServer::mesh_surface_get_material);
+ ClassDB::bind_method(D_METHOD("mesh_get_surface", "mesh", "surface"), &RenderingServer::_mesh_get_surface);
ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &RenderingServer::mesh_surface_get_arrays);
ClassDB::bind_method(D_METHOD("mesh_surface_get_blend_shape_arrays", "mesh", "surface"), &RenderingServer::mesh_surface_get_blend_shape_arrays);
ClassDB::bind_method(D_METHOD("mesh_get_surface_count", "mesh"), &RenderingServer::mesh_get_surface_count);
@@ -1492,6 +1723,81 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &RenderingServer::mesh_get_custom_aabb);
ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &RenderingServer::mesh_clear);
+ ClassDB::bind_method(D_METHOD("mesh_surface_update_vertex_region", "mesh", "surface", "offset", "data"), &RenderingServer::mesh_surface_update_vertex_region);
+ ClassDB::bind_method(D_METHOD("mesh_surface_update_attribute_region", "mesh", "surface", "offset", "data"), &RenderingServer::mesh_surface_update_attribute_region);
+ ClassDB::bind_method(D_METHOD("mesh_surface_update_skin_region", "mesh", "surface", "offset", "data"), &RenderingServer::mesh_surface_update_skin_region);
+
+ ClassDB::bind_method(D_METHOD("mesh_set_shadow_mesh", "mesh", "shadow_mesh"), &RenderingServer::mesh_set_shadow_mesh);
+
+ BIND_ENUM_CONSTANT(ARRAY_VERTEX);
+ BIND_ENUM_CONSTANT(ARRAY_NORMAL);
+ BIND_ENUM_CONSTANT(ARRAY_TANGENT);
+ BIND_ENUM_CONSTANT(ARRAY_COLOR);
+ BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
+ BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM0);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM1);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM2);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM3);
+ BIND_ENUM_CONSTANT(ARRAY_BONES);
+ BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
+ BIND_ENUM_CONSTANT(ARRAY_INDEX);
+ BIND_ENUM_CONSTANT(ARRAY_MAX);
+
+ BIND_CONSTANT(ARRAY_CUSTOM_COUNT);
+
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_UNORM);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_SNORM);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_HALF);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_HALF);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_R_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGB_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_MAX);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BITS);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3_SHIFT);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_MASK);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_FLAGS_BASE);
+
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
+
+ BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
+ BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP);
+ BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP);
+ BIND_ENUM_CONSTANT(PRIMITIVE_MAX);
+
+ BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
+ BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
+
+ /* MULTIMESH API */
+
ClassDB::bind_method(D_METHOD("multimesh_create"), &RenderingServer::multimesh_create);
ClassDB::bind_method(D_METHOD("multimesh_allocate_data", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::multimesh_allocate_data, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &RenderingServer::multimesh_get_instance_count);
@@ -1510,21 +1816,11 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &RenderingServer::multimesh_get_visible_instances);
ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &RenderingServer::multimesh_set_buffer);
ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &RenderingServer::multimesh_get_buffer);
-#ifndef _3D_DISABLED
- ClassDB::bind_method(D_METHOD("immediate_create"), &RenderingServer::immediate_create);
- ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &RenderingServer::immediate_begin, DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("immediate_vertex", "immediate", "vertex"), &RenderingServer::immediate_vertex);
- ClassDB::bind_method(D_METHOD("immediate_vertex_2d", "immediate", "vertex"), &RenderingServer::immediate_vertex_2d);
- ClassDB::bind_method(D_METHOD("immediate_normal", "immediate", "normal"), &RenderingServer::immediate_normal);
- ClassDB::bind_method(D_METHOD("immediate_tangent", "immediate", "tangent"), &RenderingServer::immediate_tangent);
- ClassDB::bind_method(D_METHOD("immediate_color", "immediate", "color"), &RenderingServer::immediate_color);
- ClassDB::bind_method(D_METHOD("immediate_uv", "immediate", "tex_uv"), &RenderingServer::immediate_uv);
- ClassDB::bind_method(D_METHOD("immediate_uv2", "immediate", "tex_uv"), &RenderingServer::immediate_uv2);
- ClassDB::bind_method(D_METHOD("immediate_end", "immediate"), &RenderingServer::immediate_end);
- ClassDB::bind_method(D_METHOD("immediate_clear", "immediate"), &RenderingServer::immediate_clear);
- ClassDB::bind_method(D_METHOD("immediate_set_material", "immediate", "material"), &RenderingServer::immediate_set_material);
- ClassDB::bind_method(D_METHOD("immediate_get_material", "immediate"), &RenderingServer::immediate_get_material);
-#endif
+
+ BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_2D);
+ BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_3D);
+
+ /* SKELETON API */
ClassDB::bind_method(D_METHOD("skeleton_create"), &RenderingServer::skeleton_create);
ClassDB::bind_method(D_METHOD("skeleton_allocate_data", "skeleton", "bones", "is_2d_skeleton"), &RenderingServer::skeleton_allocate_data, DEFVAL(false));
@@ -1533,8 +1829,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform", "skeleton", "bone"), &RenderingServer::skeleton_bone_get_transform);
ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform_2d", "skeleton", "bone", "transform"), &RenderingServer::skeleton_bone_set_transform_2d);
ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform_2d", "skeleton", "bone"), &RenderingServer::skeleton_bone_get_transform_2d);
+ ClassDB::bind_method(D_METHOD("skeleton_set_base_transform_2d", "skeleton", "base_transform"), &RenderingServer::skeleton_set_base_transform_2d);
+
+ /* Light API */
-#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("directional_light_create"), &RenderingServer::directional_light_create);
ClassDB::bind_method(D_METHOD("omni_light_create"), &RenderingServer::omni_light_create);
ClassDB::bind_method(D_METHOD("spot_light_create"), &RenderingServer::spot_light_create);
@@ -1548,13 +1846,70 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask);
ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode);
ClassDB::bind_method(D_METHOD("light_set_bake_mode", "light", "bake_mode"), &RenderingServer::light_set_bake_mode);
+ ClassDB::bind_method(D_METHOD("light_set_max_sdfgi_cascade", "light", "cascade"), &RenderingServer::light_set_max_sdfgi_cascade);
ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &RenderingServer::light_omni_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &RenderingServer::light_directional_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &RenderingServer::light_directional_set_blend_splits);
ClassDB::bind_method(D_METHOD("light_directional_set_sky_only", "light", "enable"), &RenderingServer::light_directional_set_sky_only);
- ClassDB::bind_method(D_METHOD("light_directional_set_shadow_depth_range_mode", "light", "range_mode"), &RenderingServer::light_directional_set_shadow_depth_range_mode);
+
+ ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
+
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
+
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
+ BIND_ENUM_CONSTANT(LIGHT_OMNI);
+ BIND_ENUM_CONSTANT(LIGHT_SPOT);
+
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SIZE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
+
+ BIND_ENUM_CONSTANT(LIGHT_BAKE_DISABLED);
+ BIND_ENUM_CONSTANT(LIGHT_BAKE_DYNAMIC);
+ BIND_ENUM_CONSTANT(LIGHT_BAKE_STATIC);
+
+ BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID);
+ BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE);
+
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS);
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS);
+
+ ClassDB::bind_method(D_METHOD("shadows_quality_set", "quality"), &RenderingServer::shadows_quality_set);
+ ClassDB::bind_method(D_METHOD("directional_shadow_quality_set", "quality"), &RenderingServer::directional_shadow_quality_set);
+ ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size);
+
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_HARD);
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_LOW);
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_MEDIUM);
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_HIGH);
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_ULTRA);
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_MAX);
+
+ /* REFLECTION PROBE */
ClassDB::bind_method(D_METHOD("reflection_probe_create"), &RenderingServer::reflection_probe_create);
ClassDB::bind_method(D_METHOD("reflection_probe_set_update_mode", "probe", "mode"), &RenderingServer::reflection_probe_set_update_mode);
@@ -1569,54 +1924,85 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_box_projection", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_box_projection);
ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_shadows);
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask);
+ ClassDB::bind_method(D_METHOD("reflection_probe_set_resolution", "probe", "resolution"), &RenderingServer::reflection_probe_set_resolution);
+ ClassDB::bind_method(D_METHOD("reflection_probe_set_lod_threshold", "probe", "pixels"), &RenderingServer::reflection_probe_set_lod_threshold);
-#ifndef _MSC_VER
-#warning TODO all voxel_gi methods need re-binding
-#endif
-#if 0
- ClassDB::bind_method(D_METHOD("voxel_gi_create"), &RenderingServer::voxel_gi_create);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_bounds", "probe", "bounds"), &RenderingServer::voxel_gi_set_bounds);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_bounds", "probe"), &RenderingServer::voxel_gi_get_bounds);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_cell_size", "probe", "range"), &RenderingServer::voxel_gi_set_cell_size);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_cell_size", "probe"), &RenderingServer::voxel_gi_get_cell_size);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_to_cell_xform", "probe", "xform"), &RenderingServer::voxel_gi_set_to_cell_xform);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_to_cell_xform", "probe"), &RenderingServer::voxel_gi_get_to_cell_xform);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_data", "probe", "data"), &RenderingServer::voxel_gi_set_dynamic_data);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_dynamic_data", "probe"), &RenderingServer::voxel_gi_get_dynamic_data);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_range", "probe", "range"), &RenderingServer::voxel_gi_set_dynamic_range);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_dynamic_range", "probe"), &RenderingServer::voxel_gi_get_dynamic_range);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_energy", "probe", "energy"), &RenderingServer::voxel_gi_set_energy);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_energy", "probe"), &RenderingServer::voxel_gi_get_energy);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_bias", "probe", "bias"), &RenderingServer::voxel_gi_set_bias);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_bias", "probe"), &RenderingServer::voxel_gi_get_bias);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_normal_bias", "probe", "bias"), &RenderingServer::voxel_gi_set_normal_bias);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_normal_bias", "probe"), &RenderingServer::voxel_gi_get_normal_bias);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_propagation", "probe", "propagation"), &RenderingServer::voxel_gi_set_propagation);
- ClassDB::bind_method(D_METHOD("voxel_gi_get_propagation", "probe"), &RenderingServer::voxel_gi_get_propagation);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_interior", "probe", "enable"), &RenderingServer::voxel_gi_set_interior);
- ClassDB::bind_method(D_METHOD("voxel_gi_is_interior", "probe"), &RenderingServer::voxel_gi_is_interior);
- ClassDB::bind_method(D_METHOD("voxel_gi_set_compress", "probe", "enable"), &RenderingServer::voxel_gi_set_compress);
- ClassDB::bind_method(D_METHOD("voxel_gi_is_compressed", "probe"), &RenderingServer::voxel_gi_is_compressed);
-#endif
- /*
- ClassDB::bind_method(D_METHOD("lightmap_create()"), &RenderingServer::lightmap_capture_create);
- ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &RenderingServer::lightmap_capture_set_bounds);
- ClassDB::bind_method(D_METHOD("lightmap_capture_get_bounds", "capture"), &RenderingServer::lightmap_capture_get_bounds);
- ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree", "capture", "octree"), &RenderingServer::lightmap_capture_set_octree);
- ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_transform", "capture", "xform"), &RenderingServer::lightmap_capture_set_octree_cell_transform);
- ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_transform", "capture"), &RenderingServer::lightmap_capture_get_octree_cell_transform);
- ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_subdiv", "capture", "subdiv"), &RenderingServer::lightmap_capture_set_octree_cell_subdiv);
- ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_subdiv", "capture"), &RenderingServer::lightmap_capture_get_octree_cell_subdiv);
- ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree", "capture"), &RenderingServer::lightmap_capture_get_octree);
- ClassDB::bind_method(D_METHOD("lightmap_capture_set_energy", "capture", "energy"), &RenderingServer::lightmap_capture_set_energy);
- ClassDB::bind_method(D_METHOD("lightmap_capture_get_energy", "capture"), &RenderingServer::lightmap_capture_get_energy);
-*/
+ BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE);
+ BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS);
- ClassDB::bind_method(D_METHOD("occluder_create"), &RenderingServer::occluder_create);
- ClassDB::bind_method(D_METHOD("occluder_set_mesh"), &RenderingServer::occluder_set_mesh);
+ BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_DISABLED);
+ BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_ENVIRONMENT);
+ BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_COLOR);
+
+ /* DECAL */
+
+ ClassDB::bind_method(D_METHOD("decal_create"), &RenderingServer::decal_create);
+ ClassDB::bind_method(D_METHOD("decal_set_extents", "decal", "extents"), &RenderingServer::decal_set_extents);
+ ClassDB::bind_method(D_METHOD("decal_set_texture", "decal", "type", "texture"), &RenderingServer::decal_set_texture);
+ ClassDB::bind_method(D_METHOD("decal_set_emission_energy", "decal", "energy"), &RenderingServer::decal_set_emission_energy);
+ ClassDB::bind_method(D_METHOD("decal_set_albedo_mix", "decal", "albedo_mix"), &RenderingServer::decal_set_albedo_mix);
+ ClassDB::bind_method(D_METHOD("decal_set_modulate", "decal", "color"), &RenderingServer::decal_set_modulate);
+ ClassDB::bind_method(D_METHOD("decal_set_cull_mask", "decal", "mask"), &RenderingServer::decal_set_cull_mask);
+ ClassDB::bind_method(D_METHOD("decal_set_distance_fade", "decal", "enabled", "begin", "length"), &RenderingServer::decal_set_distance_fade);
+ ClassDB::bind_method(D_METHOD("decal_set_fade", "decal", "above", "below"), &RenderingServer::decal_set_fade);
+ ClassDB::bind_method(D_METHOD("decal_set_normal_fade", "decal", "fade"), &RenderingServer::decal_set_normal_fade);
+
+ ClassDB::bind_method(D_METHOD("decals_set_filter", "filter"), &RenderingServer::decals_set_filter);
+
+ BIND_ENUM_CONSTANT(DECAL_TEXTURE_ALBEDO);
+ BIND_ENUM_CONSTANT(DECAL_TEXTURE_NORMAL);
+ BIND_ENUM_CONSTANT(DECAL_TEXTURE_ORM);
+ BIND_ENUM_CONSTANT(DECAL_TEXTURE_EMISSION);
+ BIND_ENUM_CONSTANT(DECAL_TEXTURE_MAX);
+
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
+
+ /* VOXEL GI API */
+
+ ClassDB::bind_method(D_METHOD("voxel_gi_create"), &RenderingServer::voxel_gi_create);
+ ClassDB::bind_method(D_METHOD("voxel_gi_allocate_data", "voxel_gi", "to_cell_xform", "aabb", "octree_size", "octree_cells", "data_cells", "distance_field", "level_counts"), &RenderingServer::voxel_gi_allocate_data);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_octree_size", "voxel_gi"), &RenderingServer::voxel_gi_get_octree_size);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_octree_cells", "voxel_gi"), &RenderingServer::voxel_gi_get_octree_cells);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_data_cells", "voxel_gi"), &RenderingServer::voxel_gi_get_data_cells);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_distance_field", "voxel_gi"), &RenderingServer::voxel_gi_get_distance_field);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_level_counts", "voxel_gi"), &RenderingServer::voxel_gi_get_level_counts);
+ ClassDB::bind_method(D_METHOD("voxel_gi_get_to_cell_xform", "voxel_gi"), &RenderingServer::voxel_gi_get_to_cell_xform);
+
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_range", "voxel_gi", "range"), &RenderingServer::voxel_gi_set_dynamic_range);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_propagation", "voxel_gi", "amount"), &RenderingServer::voxel_gi_set_propagation);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_energy", "voxel_gi", "energy"), &RenderingServer::voxel_gi_set_energy);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_bias", "voxel_gi", "bias"), &RenderingServer::voxel_gi_set_bias);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_normal_bias", "voxel_gi", "bias"), &RenderingServer::voxel_gi_set_normal_bias);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_interior", "voxel_gi", "enable"), &RenderingServer::voxel_gi_set_interior);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_use_two_bounces", "voxel_gi", "enable"), &RenderingServer::voxel_gi_set_use_two_bounces);
+
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_quality", "quality"), &RenderingServer::voxel_gi_set_quality);
+
+ BIND_ENUM_CONSTANT(VOXEL_GI_QUALITY_LOW);
+ BIND_ENUM_CONSTANT(VOXEL_GI_QUALITY_HIGH);
+
+ /* LIGHTMAP */
+
+ ClassDB::bind_method(D_METHOD("lightmap_create"), &RenderingServer::lightmap_create);
+ ClassDB::bind_method(D_METHOD("lightmap_set_textures", "lightmap", "light", "uses_sh"), &RenderingServer::lightmap_set_textures);
+ ClassDB::bind_method(D_METHOD("lightmap_set_probe_bounds", "lightmap", "bounds"), &RenderingServer::lightmap_set_probe_bounds);
+ ClassDB::bind_method(D_METHOD("lightmap_set_probe_interior", "lightmap", "interior"), &RenderingServer::lightmap_set_probe_interior);
+ ClassDB::bind_method(D_METHOD("lightmap_set_probe_capture_data", "lightmap", "points", "point_sh", "tetrahedra", "bsp_tree"), &RenderingServer::lightmap_set_probe_capture_data);
+ ClassDB::bind_method(D_METHOD("lightmap_get_probe_capture_points", "lightmap"), &RenderingServer::lightmap_get_probe_capture_points);
+ ClassDB::bind_method(D_METHOD("lightmap_get_probe_capture_sh", "lightmap"), &RenderingServer::lightmap_get_probe_capture_sh);
+ ClassDB::bind_method(D_METHOD("lightmap_get_probe_capture_tetrahedra", "lightmap"), &RenderingServer::lightmap_get_probe_capture_tetrahedra);
+ ClassDB::bind_method(D_METHOD("lightmap_get_probe_capture_bsp_tree", "lightmap"), &RenderingServer::lightmap_get_probe_capture_bsp_tree);
+
+ ClassDB::bind_method(D_METHOD("lightmap_set_probe_capture_update_speed", "speed"), &RenderingServer::lightmap_set_probe_capture_update_speed);
+
+ /* PARTICLES API */
-#endif
ClassDB::bind_method(D_METHOD("particles_create"), &RenderingServer::particles_create);
+ ClassDB::bind_method(D_METHOD("particles_set_mode", "particles", "mode"), &RenderingServer::particles_set_mode);
ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &RenderingServer::particles_set_emitting);
ClassDB::bind_method(D_METHOD("particles_get_emitting", "particles"), &RenderingServer::particles_get_emitting);
ClassDB::bind_method(D_METHOD("particles_set_amount", "particles", "amount"), &RenderingServer::particles_set_amount);
@@ -1630,16 +2016,89 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("particles_set_use_local_coordinates", "particles", "enable"), &RenderingServer::particles_set_use_local_coordinates);
ClassDB::bind_method(D_METHOD("particles_set_process_material", "particles", "material"), &RenderingServer::particles_set_process_material);
ClassDB::bind_method(D_METHOD("particles_set_fixed_fps", "particles", "fps"), &RenderingServer::particles_set_fixed_fps);
+ ClassDB::bind_method(D_METHOD("particles_set_interpolate", "particles", "enable"), &RenderingServer::particles_set_interpolate);
ClassDB::bind_method(D_METHOD("particles_set_fractional_delta", "particles", "enable"), &RenderingServer::particles_set_fractional_delta);
+ ClassDB::bind_method(D_METHOD("particles_set_collision_base_size", "particles", "size"), &RenderingServer::particles_set_collision_base_size);
+ ClassDB::bind_method(D_METHOD("particles_set_transform_align", "particles", "align"), &RenderingServer::particles_set_transform_align);
+ ClassDB::bind_method(D_METHOD("particles_set_trails", "particles", "enable", "length_sec"), &RenderingServer::particles_set_trails);
+ ClassDB::bind_method(D_METHOD("particles_set_trail_bind_poses", "particles", "bind_poses"), &RenderingServer::_particles_set_trail_bind_poses);
+
ClassDB::bind_method(D_METHOD("particles_is_inactive", "particles"), &RenderingServer::particles_is_inactive);
ClassDB::bind_method(D_METHOD("particles_request_process", "particles"), &RenderingServer::particles_request_process);
ClassDB::bind_method(D_METHOD("particles_restart", "particles"), &RenderingServer::particles_restart);
+
+ ClassDB::bind_method(D_METHOD("particles_set_subemitter", "particles", "subemitter_particles"), &RenderingServer::particles_set_subemitter);
+ ClassDB::bind_method(D_METHOD("particles_emit", "particles", "transform", "velocity", "color", "custom", "emit_flags"), &RenderingServer::particles_emit);
+
ClassDB::bind_method(D_METHOD("particles_set_draw_order", "particles", "order"), &RenderingServer::particles_set_draw_order);
ClassDB::bind_method(D_METHOD("particles_set_draw_passes", "particles", "count"), &RenderingServer::particles_set_draw_passes);
ClassDB::bind_method(D_METHOD("particles_set_draw_pass_mesh", "particles", "pass", "mesh"), &RenderingServer::particles_set_draw_pass_mesh);
ClassDB::bind_method(D_METHOD("particles_get_current_aabb", "particles"), &RenderingServer::particles_get_current_aabb);
ClassDB::bind_method(D_METHOD("particles_set_emission_transform", "particles", "transform"), &RenderingServer::particles_set_emission_transform);
+ BIND_ENUM_CONSTANT(PARTICLES_MODE_2D);
+ BIND_ENUM_CONSTANT(PARTICLES_MODE_3D);
+
+ BIND_ENUM_CONSTANT(PARTICLES_TRANSFORM_ALIGN_DISABLED);
+ BIND_ENUM_CONSTANT(PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD);
+ BIND_ENUM_CONSTANT(PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY);
+ BIND_ENUM_CONSTANT(PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY);
+
+ BIND_CONSTANT(PARTICLES_EMIT_FLAG_POSITION);
+ BIND_CONSTANT(PARTICLES_EMIT_FLAG_ROTATION_SCALE);
+ BIND_CONSTANT(PARTICLES_EMIT_FLAG_VELOCITY);
+ BIND_CONSTANT(PARTICLES_EMIT_FLAG_COLOR);
+ BIND_CONSTANT(PARTICLES_EMIT_FLAG_CUSTOM);
+
+ BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_INDEX);
+ BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_LIFETIME);
+ BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+ BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_VIEW_DEPTH);
+
+ /* PARTICLES COLLISION */
+
+ ClassDB::bind_method(D_METHOD("particles_collision_create"), &RenderingServer::particles_collision_create);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_collision_type", "particles_collision", "type"), &RenderingServer::particles_collision_set_collision_type);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_cull_mask", "particles_collision", "mask"), &RenderingServer::particles_collision_set_cull_mask);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_sphere_radius", "particles_collision", "radius"), &RenderingServer::particles_collision_set_sphere_radius);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_box_extents", "particles_collision", "extents"), &RenderingServer::particles_collision_set_box_extents);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_attractor_strength", "particles_collision", "setrngth"), &RenderingServer::particles_collision_set_attractor_strength);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_attractor_directionality", "particles_collision", "amount"), &RenderingServer::particles_collision_set_attractor_directionality);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_attractor_attenuation", "particles_collision", "curve"), &RenderingServer::particles_collision_set_attractor_attenuation);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_field_texture", "particles_collision", "texture"), &RenderingServer::particles_collision_set_field_texture);
+
+ ClassDB::bind_method(D_METHOD("particles_collision_height_field_update", "particles_collision"), &RenderingServer::particles_collision_height_field_update);
+ ClassDB::bind_method(D_METHOD("particles_collision_set_height_field_resolution", "particles_collision", "resolution"), &RenderingServer::particles_collision_set_height_field_resolution);
+
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_TYPE_BOX_ATTRACT);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_TYPE_BOX_COLLIDE);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_TYPE_SDF_COLLIDE);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE);
+
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_256);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_512);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_2048);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_4096);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_8192);
+ BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
+
+ /* VISIBILITY NOTIFIER */
+
+ ClassDB::bind_method(D_METHOD("visibility_notifier_create"), &RenderingServer::visibility_notifier_create);
+ ClassDB::bind_method(D_METHOD("visibility_notifier_set_aabb", "notifier", "aabb"), &RenderingServer::visibility_notifier_set_aabb);
+ ClassDB::bind_method(D_METHOD("visibility_notifier_set_callbacks", "notifier", "enter_callable", "exit_callable"), &RenderingServer::visibility_notifier_set_callbacks);
+
+ /* OCCLUDER */
+
+ ClassDB::bind_method(D_METHOD("occluder_create"), &RenderingServer::occluder_create);
+ ClassDB::bind_method(D_METHOD("occluder_set_mesh", "occluder", "vertices", "indices"), &RenderingServer::occluder_set_mesh);
+
+ /* CAMERA */
+
ClassDB::bind_method(D_METHOD("camera_create"), &RenderingServer::camera_create);
ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &RenderingServer::camera_set_perspective);
ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &RenderingServer::camera_set_orthogonal);
@@ -1647,8 +2106,11 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &RenderingServer::camera_set_transform);
ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &RenderingServer::camera_set_cull_mask);
ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &RenderingServer::camera_set_environment);
+ ClassDB::bind_method(D_METHOD("camera_set_camera_effects", "camera", "effects"), &RenderingServer::camera_set_camera_effects);
ClassDB::bind_method(D_METHOD("camera_set_use_vertical_aspect", "camera", "enable"), &RenderingServer::camera_set_use_vertical_aspect);
+ /* VIEWPORT */
+
ClassDB::bind_method(D_METHOD("viewport_create"), &RenderingServer::viewport_create);
ClassDB::bind_method(D_METHOD("viewport_set_use_xr", "viewport", "use_xr"), &RenderingServer::viewport_set_use_xr);
ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::viewport_set_size);
@@ -1660,338 +2122,47 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode);
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture);
- ClassDB::bind_method(D_METHOD("viewport_set_hide_scenario", "viewport", "hidden"), &RenderingServer::viewport_set_hide_scenario);
- ClassDB::bind_method(D_METHOD("viewport_set_hide_canvas", "viewport", "hidden"), &RenderingServer::viewport_set_hide_canvas);
+ ClassDB::bind_method(D_METHOD("viewport_set_disable_3d", "viewport", "disable"), &RenderingServer::viewport_set_disable_3d);
+ ClassDB::bind_method(D_METHOD("viewport_set_disable_2d", "viewport", "disable"), &RenderingServer::viewport_set_disable_2d);
ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &RenderingServer::viewport_set_disable_environment);
ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &RenderingServer::viewport_attach_camera);
ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &RenderingServer::viewport_set_scenario);
ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &RenderingServer::viewport_attach_canvas);
ClassDB::bind_method(D_METHOD("viewport_remove_canvas", "viewport", "canvas"), &RenderingServer::viewport_remove_canvas);
+ ClassDB::bind_method(D_METHOD("viewport_set_snap_2d_transforms_to_pixel", "viewport", "enabled"), &RenderingServer::viewport_set_snap_2d_transforms_to_pixel);
+ ClassDB::bind_method(D_METHOD("viewport_set_snap_2d_vertices_to_pixel", "viewport", "enabled"), &RenderingServer::viewport_set_snap_2d_vertices_to_pixel);
+
+ ClassDB::bind_method(D_METHOD("viewport_set_default_canvas_item_texture_filter", "viewport", "filter"), &RenderingServer::viewport_set_default_canvas_item_texture_filter);
+ ClassDB::bind_method(D_METHOD("viewport_set_default_canvas_item_texture_repeat", "viewport", "repeat"), &RenderingServer::viewport_set_default_canvas_item_texture_repeat);
+
ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &RenderingServer::viewport_set_canvas_transform);
+ ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &RenderingServer::viewport_set_canvas_stacking);
+
ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &RenderingServer::viewport_set_transparent_background);
ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &RenderingServer::viewport_set_global_canvas_transform);
- ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &RenderingServer::viewport_set_canvas_stacking);
+
+ ClassDB::bind_method(D_METHOD("viewport_set_sdf_oversize_and_scale", "viewport", "oversize", "scale"), &RenderingServer::viewport_set_sdf_oversize_and_scale);
+
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_shadow_atlas_size, DEFVAL(false));
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision);
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa);
+ ClassDB::bind_method(D_METHOD("viewport_set_screen_space_aa", "viewport", "mode"), &RenderingServer::viewport_set_screen_space_aa);
ClassDB::bind_method(D_METHOD("viewport_set_use_debanding", "viewport", "enable"), &RenderingServer::viewport_set_use_debanding);
ClassDB::bind_method(D_METHOD("viewport_set_use_occlusion_culling", "viewport", "enable"), &RenderingServer::viewport_set_use_occlusion_culling);
ClassDB::bind_method(D_METHOD("viewport_set_occlusion_rays_per_thread", "rays_per_thread"), &RenderingServer::viewport_set_occlusion_rays_per_thread);
ClassDB::bind_method(D_METHOD("viewport_set_occlusion_culling_build_quality", "quality"), &RenderingServer::viewport_set_occlusion_culling_build_quality);
- ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &RenderingServer::viewport_get_render_info);
+ ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "type", "info"), &RenderingServer::viewport_get_render_info);
ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &RenderingServer::viewport_set_debug_draw);
ClassDB::bind_method(D_METHOD("viewport_set_measure_render_time", "viewport", "enable"), &RenderingServer::viewport_set_measure_render_time);
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_cpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_cpu);
- ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
-
- ClassDB::bind_method(D_METHOD("environment_create"), &RenderingServer::environment_create);
- ClassDB::bind_method(D_METHOD("environment_set_background", "env", "bg"), &RenderingServer::environment_set_background);
- ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &RenderingServer::environment_set_sky);
- ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &RenderingServer::environment_set_sky_custom_fov);
- ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &RenderingServer::environment_set_sky_orientation);
- ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &RenderingServer::environment_set_bg_color);
- ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &RenderingServer::environment_set_bg_energy);
- ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &RenderingServer::environment_set_canvas_max_layer);
- ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source", "ao_color"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color()));
- ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow);
- ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap);
- ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment);
- ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr);
- ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao);
- ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective"), &RenderingServer::environment_set_fog);
-
- ClassDB::bind_method(D_METHOD("scenario_create"), &RenderingServer::scenario_create);
- ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &RenderingServer::scenario_set_debug);
- ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &RenderingServer::scenario_set_environment);
- ClassDB::bind_method(D_METHOD("scenario_set_camera_effects", "scenario", "effects"), &RenderingServer::scenario_set_camera_effects);
- ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &RenderingServer::scenario_set_fallback_environment);
-
-#ifndef _3D_DISABLED
-
- ClassDB::bind_method(D_METHOD("instance_create2", "base", "scenario"), &RenderingServer::instance_create2);
- ClassDB::bind_method(D_METHOD("instance_create"), &RenderingServer::instance_create);
- ClassDB::bind_method(D_METHOD("instance_set_base", "instance", "base"), &RenderingServer::instance_set_base);
- ClassDB::bind_method(D_METHOD("instance_set_scenario", "instance", "scenario"), &RenderingServer::instance_set_scenario);
- ClassDB::bind_method(D_METHOD("instance_set_layer_mask", "instance", "mask"), &RenderingServer::instance_set_layer_mask);
- ClassDB::bind_method(D_METHOD("instance_set_transform", "instance", "transform"), &RenderingServer::instance_set_transform);
- ClassDB::bind_method(D_METHOD("instance_attach_object_instance_id", "instance", "id"), &RenderingServer::instance_attach_object_instance_id);
- ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight);
- ClassDB::bind_method(D_METHOD("instance_set_surface_override_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_override_material);
- ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible);
- // ClassDB::bind_method(D_METHOD("instance_set_use_lightmap", "instance", "lightmap_instance", "lightmap"), &RenderingServer::instance_set_use_lightmap);
- ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb);
- ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton);
- ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior);
- ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &RenderingServer::instance_set_extra_visibility_margin);
- ClassDB::bind_method(D_METHOD("instance_set_visibility_parent", "instance", "parent"), &RenderingServer::instance_set_visibility_parent);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &RenderingServer::instance_geometry_set_cast_shadows_setting);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_visibility_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_visibility_range);
-
- ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("instances_cull_convex", "convex", "scenario"), &RenderingServer::_instances_cull_convex_bind, DEFVAL(RID()));
-#endif
- ClassDB::bind_method(D_METHOD("canvas_create"), &RenderingServer::canvas_create);
- ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &RenderingServer::canvas_set_item_mirroring);
- ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &RenderingServer::canvas_set_modulate);
-#ifndef _MSC_VER
-#warning TODO method bindings need to be fixed
-#endif
-#if 0
-
- ClassDB::bind_method(D_METHOD("canvas_item_create"), &RenderingServer::canvas_item_create);
- ClassDB::bind_method(D_METHOD("canvas_item_set_parent", "item", "parent"), &RenderingServer::canvas_item_set_parent);
- ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &RenderingServer::canvas_item_set_visible);
- ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &RenderingServer::canvas_item_set_light_mask);
- ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &RenderingServer::canvas_item_set_transform);
- ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &RenderingServer::canvas_item_set_clip);
- ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &RenderingServer::canvas_item_set_distance_field_mode);
- ClassDB::bind_method(D_METHOD("canvas_item_set_custom_rect", "item", "use_custom_rect", "rect"), &RenderingServer::canvas_item_set_custom_rect, DEFVAL(Rect2()));
- ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &RenderingServer::canvas_item_set_modulate);
- ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &RenderingServer::canvas_item_set_self_modulate);
- ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &RenderingServer::canvas_item_set_draw_behind_parent);
- 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);
- ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose", "normal_map"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &RenderingServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map", "antialiased"), &RenderingServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture", "normal_map"), &RenderingServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()), DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &RenderingServer::canvas_item_add_multimesh, DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map"), &RenderingServer::canvas_item_add_particles);
- ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &RenderingServer::canvas_item_add_set_transform);
- ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &RenderingServer::canvas_item_add_clip_ignore);
- ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &RenderingServer::canvas_item_set_sort_children_by_y);
-#endif
- ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &RenderingServer::canvas_item_set_z_index);
- ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &RenderingServer::canvas_item_set_z_as_relative_to_parent);
- ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &RenderingServer::canvas_item_set_copy_to_backbuffer);
- ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &RenderingServer::canvas_item_clear);
- ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &RenderingServer::canvas_item_set_draw_index);
- ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &RenderingServer::canvas_item_set_material);
- ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &RenderingServer::canvas_item_set_use_parent_material);
- ClassDB::bind_method(D_METHOD("canvas_light_create"), &RenderingServer::canvas_light_create);
- ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &RenderingServer::canvas_light_attach_to_canvas);
- ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_enabled);
- ClassDB::bind_method(D_METHOD("canvas_light_set_texture_scale", "light", "scale"), &RenderingServer::canvas_light_set_texture_scale);
- ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &RenderingServer::canvas_light_set_transform);
- ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &RenderingServer::canvas_light_set_texture);
- ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &RenderingServer::canvas_light_set_texture_offset);
- ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &RenderingServer::canvas_light_set_color);
- ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &RenderingServer::canvas_light_set_height);
- ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &RenderingServer::canvas_light_set_energy);
- ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &RenderingServer::canvas_light_set_z_range);
- ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &RenderingServer::canvas_light_set_layer_range);
- ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_cull_mask);
- ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_shadow_cull_mask);
- ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &RenderingServer::canvas_light_set_mode);
- ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_shadow_enabled);
- ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &RenderingServer::canvas_light_set_shadow_filter);
- ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &RenderingServer::canvas_light_set_shadow_color);
- ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &RenderingServer::canvas_light_set_shadow_smooth);
-
- ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &RenderingServer::canvas_light_occluder_create);
- ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &RenderingServer::canvas_light_occluder_attach_to_canvas);
- ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &RenderingServer::canvas_light_occluder_set_enabled);
- ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &RenderingServer::canvas_light_occluder_set_polygon);
- ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &RenderingServer::canvas_light_occluder_set_transform);
- ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &RenderingServer::canvas_light_occluder_set_light_mask);
- ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &RenderingServer::canvas_occluder_polygon_create);
- ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &RenderingServer::canvas_occluder_polygon_set_shape);
- ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode);
-
- ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add);
- ClassDB::bind_method(D_METHOD("global_variable_remove", "name"), &RenderingServer::global_variable_remove);
- ClassDB::bind_method(D_METHOD("global_variable_get_list"), &RenderingServer::global_variable_get_list);
- ClassDB::bind_method(D_METHOD("global_variable_set", "name", "value"), &RenderingServer::global_variable_set);
- ClassDB::bind_method(D_METHOD("global_variable_get", "name"), &RenderingServer::global_variable_get);
- ClassDB::bind_method(D_METHOD("global_variable_get_type", "name"), &RenderingServer::global_variable_get_type);
-
- ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_margins);
- ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_images);
-
- ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // shouldn't conflict with Object::free()
-
- ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &RenderingServer::request_frame_drawn_callback);
- ClassDB::bind_method(D_METHOD("has_changed"), &RenderingServer::has_changed);
- ClassDB::bind_method(D_METHOD("init"), &RenderingServer::init);
- ClassDB::bind_method(D_METHOD("finish"), &RenderingServer::finish);
- ClassDB::bind_method(D_METHOD("get_render_info", "info"), &RenderingServer::get_render_info);
- ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &RenderingServer::get_video_adapter_name);
- ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &RenderingServer::get_video_adapter_vendor);
-#ifndef _3D_DISABLED
-
- ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &RenderingServer::make_sphere_mesh);
- ClassDB::bind_method(D_METHOD("get_test_cube"), &RenderingServer::get_test_cube);
-#endif
- ClassDB::bind_method(D_METHOD("get_test_texture"), &RenderingServer::get_test_texture);
- ClassDB::bind_method(D_METHOD("get_white_texture"), &RenderingServer::get_white_texture);
-
- ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale", "use_filter"), &RenderingServer::set_boot_image, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &RenderingServer::set_default_clear_color);
-
- ClassDB::bind_method(D_METHOD("has_feature", "feature"), &RenderingServer::has_feature);
- ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &RenderingServer::has_os_feature);
- ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &RenderingServer::set_debug_generate_wireframes);
-
- ClassDB::bind_method(D_METHOD("is_render_loop_enabled"), &RenderingServer::is_render_loop_enabled);
- ClassDB::bind_method(D_METHOD("set_render_loop_enabled", "enabled"), &RenderingServer::set_render_loop_enabled);
-
- ClassDB::bind_method(D_METHOD("get_frame_setup_time_cpu"), &RenderingServer::get_frame_setup_time_cpu);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_loop_enabled"), "set_render_loop_enabled", "is_render_loop_enabled");
-
- BIND_CONSTANT(NO_INDEX_ARRAY);
- BIND_CONSTANT(ARRAY_WEIGHTS_SIZE);
- BIND_CONSTANT(CANVAS_ITEM_Z_MIN);
- BIND_CONSTANT(CANVAS_ITEM_Z_MAX);
- BIND_CONSTANT(MAX_GLOW_LEVELS);
- BIND_CONSTANT(MAX_CURSORS);
-
- BIND_ENUM_CONSTANT(TEXTURE_LAYERED_2D_ARRAY);
- BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP);
- BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP_ARRAY);
-
- BIND_ENUM_CONSTANT(CUBEMAP_LAYER_LEFT);
- BIND_ENUM_CONSTANT(CUBEMAP_LAYER_RIGHT);
- BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BOTTOM);
- BIND_ENUM_CONSTANT(CUBEMAP_LAYER_TOP);
- BIND_ENUM_CONSTANT(CUBEMAP_LAYER_FRONT);
- BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BACK);
-
- BIND_ENUM_CONSTANT(SHADER_SPATIAL);
- BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM);
- BIND_ENUM_CONSTANT(SHADER_PARTICLES);
- BIND_ENUM_CONSTANT(SHADER_SKY);
- BIND_ENUM_CONSTANT(SHADER_MAX);
-
- BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MIN);
- BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MAX);
-
- BIND_ENUM_CONSTANT(ARRAY_VERTEX);
- BIND_ENUM_CONSTANT(ARRAY_NORMAL);
- BIND_ENUM_CONSTANT(ARRAY_TANGENT);
- BIND_ENUM_CONSTANT(ARRAY_COLOR);
- BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
- BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
- BIND_ENUM_CONSTANT(ARRAY_CUSTOM0);
- BIND_ENUM_CONSTANT(ARRAY_CUSTOM1);
- BIND_ENUM_CONSTANT(ARRAY_CUSTOM2);
- BIND_ENUM_CONSTANT(ARRAY_CUSTOM3);
- BIND_ENUM_CONSTANT(ARRAY_BONES);
- BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
- BIND_ENUM_CONSTANT(ARRAY_INDEX);
- BIND_ENUM_CONSTANT(ARRAY_MAX);
-
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
-
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK);
-
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT);
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3_SHIFT);
-
- BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_MASK);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_FLAGS_BASE);
-
- BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
- BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
- BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
-
- BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
- BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
- BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP);
- BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES);
- BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP);
- BIND_ENUM_CONSTANT(PRIMITIVE_MAX);
-
- BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
- BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
-
- BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_2D);
- BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_3D);
-
- BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
- BIND_ENUM_CONSTANT(LIGHT_OMNI);
- BIND_ENUM_CONSTANT(LIGHT_SPOT);
-
- BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SIZE);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
-
- BIND_ENUM_CONSTANT(LIGHT_BAKE_DISABLED);
- BIND_ENUM_CONSTANT(LIGHT_BAKE_DYNAMIC);
- BIND_ENUM_CONSTANT(LIGHT_BAKE_STATIC);
-
- BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID);
- BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE);
-
- BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
- BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS);
- BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS);
-
- BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
- BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED);
-
- BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE);
- BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS);
-
- BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_DISABLED);
- BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_ENVIRONMENT);
- BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_COLOR);
-
- BIND_ENUM_CONSTANT(DECAL_TEXTURE_ALBEDO);
- BIND_ENUM_CONSTANT(DECAL_TEXTURE_NORMAL);
- BIND_ENUM_CONSTANT(DECAL_TEXTURE_ORM);
- BIND_ENUM_CONSTANT(DECAL_TEXTURE_EMISSION);
- BIND_ENUM_CONSTANT(DECAL_TEXTURE_MAX);
-
- BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_INDEX);
- BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_LIFETIME);
- BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_VIEW_DEPTH);
+ ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED);
- BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE);
- BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE);
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); //then goes to disabled); must be manually updated
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // default
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS);
@@ -1999,6 +2170,17 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER);
BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_100_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_120_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_150_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_200_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_MAX);
+
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_SCALE_100_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_SCALE_50_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_SCALE_25_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SDF_SCALE_MAX);
+
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_DISABLED);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_2X);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X);
@@ -2010,14 +2192,19 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_SCREEN_SPACE_AA_FXAA);
BIND_ENUM_CONSTANT(VIEWPORT_SCREEN_SPACE_AA_MAX);
+ BIND_ENUM_CONSTANT(VIEWPORT_OCCLUSION_BUILD_QUALITY_LOW);
+ BIND_ENUM_CONSTANT(VIEWPORT_OCCLUSION_BUILD_QUALITY_MEDIUM);
+ BIND_ENUM_CONSTANT(VIEWPORT_OCCLUSION_BUILD_QUALITY_HIGH);
+
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME);
- BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME);
- BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_TYPE_VISIBLE);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_TYPE_SHADOW);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_TYPE_MAX);
+
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_UNSHADED);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_LIGHTING);
@@ -2036,11 +2223,62 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SDFGI);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SDFGI_PROBES);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_BUFFER);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLE_LOD);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS);
+ /* SKY API */
+
+ ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
+ ClassDB::bind_method(D_METHOD("sky_set_radiance_size", "sky", "radiance_size"), &RenderingServer::sky_set_radiance_size);
+ ClassDB::bind_method(D_METHOD("sky_set_mode", "sky", "mode"), &RenderingServer::sky_set_mode);
+ ClassDB::bind_method(D_METHOD("sky_set_material", "sky", "material"), &RenderingServer::sky_set_material);
+ ClassDB::bind_method(D_METHOD("sky_bake_panorama", "sky", "energy", "bake_irradiance", "size"), &RenderingServer::sky_bake_panorama);
+
+ BIND_ENUM_CONSTANT(SKY_MODE_AUTOMATIC);
BIND_ENUM_CONSTANT(SKY_MODE_QUALITY);
+ BIND_ENUM_CONSTANT(SKY_MODE_INCREMENTAL);
BIND_ENUM_CONSTANT(SKY_MODE_REALTIME);
+ /* ENVIRONMENT */
+
+ ClassDB::bind_method(D_METHOD("environment_create"), &RenderingServer::environment_create);
+ ClassDB::bind_method(D_METHOD("environment_set_background", "env", "bg"), &RenderingServer::environment_set_background);
+ ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &RenderingServer::environment_set_sky);
+ ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &RenderingServer::environment_set_sky_custom_fov);
+ ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &RenderingServer::environment_set_sky_orientation);
+ ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &RenderingServer::environment_set_bg_color);
+ ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &RenderingServer::environment_set_bg_energy);
+ ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &RenderingServer::environment_set_canvas_max_layer);
+ ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source", "ao_color"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color()));
+ ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow);
+ ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap);
+ ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment);
+ ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr);
+ ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao);
+ ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective"), &RenderingServer::environment_set_fog);
+ ClassDB::bind_method(D_METHOD("environment_set_sdfgi", "env", "enable", "cascades", "min_cell_size", "y_scale", "use_occlusion", "bounce_feedback", "read_sky", "energy", "normal_bias", "probe_bias"), &RenderingServer::environment_set_sdfgi);
+ ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "light", "light_energy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount"), &RenderingServer::environment_set_volumetric_fog);
+
+ ClassDB::bind_method(D_METHOD("environment_glow_set_use_bicubic_upscale", "enable"), &RenderingServer::environment_glow_set_use_bicubic_upscale);
+ ClassDB::bind_method(D_METHOD("environment_glow_set_use_high_quality", "enable"), &RenderingServer::environment_glow_set_use_high_quality);
+ ClassDB::bind_method(D_METHOD("environment_set_ssr_roughness_quality", "quality"), &RenderingServer::environment_set_ssr_roughness_quality);
+ ClassDB::bind_method(D_METHOD("environment_set_ssao_quality", "quality", "half_size", "adaptive_target", "blur_passes", "fadeout_from", "fadeout_to"), &RenderingServer::environment_set_ssao_quality);
+ ClassDB::bind_method(D_METHOD("environment_set_sdfgi_ray_count", "ray_count"), &RenderingServer::environment_set_sdfgi_ray_count);
+ ClassDB::bind_method(D_METHOD("environment_set_sdfgi_frames_to_converge", "frames"), &RenderingServer::environment_set_sdfgi_frames_to_converge);
+ ClassDB::bind_method(D_METHOD("environment_set_sdfgi_frames_to_update_light", "frames"), &RenderingServer::environment_set_sdfgi_frames_to_update_light);
+ ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog_volume_size", "size", "depth"), &RenderingServer::environment_set_volumetric_fog_volume_size);
+ ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog_filter_active", "active"), &RenderingServer::environment_set_volumetric_fog_filter_active);
+
+ ClassDB::bind_method(D_METHOD("environment_bake_panorama", "environment", "bake_irradiance", "size"), &RenderingServer::environment_bake_panorama);
+
+ ClassDB::bind_method(D_METHOD("screen_space_roughness_limiter_set_active", "enable", "amount", "limit"), &RenderingServer::screen_space_roughness_limiter_set_active);
+ ClassDB::bind_method(D_METHOD("sub_surface_scattering_set_quality", "quality"), &RenderingServer::sub_surface_scattering_set_quality);
+ ClassDB::bind_method(D_METHOD("sub_surface_scattering_set_scale", "scale", "depth_scale"), &RenderingServer::sub_surface_scattering_set_scale);
+
BIND_ENUM_CONSTANT(ENV_BG_CLEAR_COLOR);
BIND_ENUM_CONSTANT(ENV_BG_COLOR);
BIND_ENUM_CONSTANT(ENV_BG_SKY);
@@ -2080,40 +2318,107 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_HIGH);
BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_ULTRA);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_4);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_6);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_8);
+
+ BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_DISABLED);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_75_PERCENT);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_50_PERCENT);
+
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_4);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_8);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_16);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_32);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_64);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_96);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_128);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_RAY_COUNT_MAX);
+
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CONVERGE_IN_5_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CONVERGE_IN_10_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CONVERGE_IN_15_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CONVERGE_IN_20_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CONVERGE_IN_25_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CONVERGE_IN_30_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_CONVERGE_MAX);
+
+ BIND_ENUM_CONSTANT(ENV_SDFGI_UPDATE_LIGHT_IN_1_FRAME);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_UPDATE_LIGHT_IN_2_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_UPDATE_LIGHT_IN_4_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_UPDATE_LIGHT_IN_8_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_UPDATE_LIGHT_IN_16_FRAMES);
+ BIND_ENUM_CONSTANT(ENV_SDFGI_UPDATE_LIGHT_MAX);
+
BIND_ENUM_CONSTANT(SUB_SURFACE_SCATTERING_QUALITY_DISABLED);
BIND_ENUM_CONSTANT(SUB_SURFACE_SCATTERING_QUALITY_LOW);
BIND_ENUM_CONSTANT(SUB_SURFACE_SCATTERING_QUALITY_MEDIUM);
BIND_ENUM_CONSTANT(SUB_SURFACE_SCATTERING_QUALITY_HIGH);
+ /* CAMERA EFFECTS */
+
+ ClassDB::bind_method(D_METHOD("camera_effects_create"), &RenderingServer::camera_effects_create);
+
+ ClassDB::bind_method(D_METHOD("camera_effects_set_dof_blur_quality", "quality", "use_jitter"), &RenderingServer::camera_effects_set_dof_blur_quality);
+ ClassDB::bind_method(D_METHOD("camera_effects_set_dof_blur_bokeh_shape", "shape"), &RenderingServer::camera_effects_set_dof_blur_bokeh_shape);
+
+ ClassDB::bind_method(D_METHOD("camera_effects_set_dof_blur", "camera_effects", "far_enable", "far_distance", "far_transition", "near_enable", "near_distance", "near_transition", "amount"), &RenderingServer::camera_effects_set_dof_blur);
+ ClassDB::bind_method(D_METHOD("camera_effects_set_custom_exposure", "camera_effects", "enable", "exposure"), &RenderingServer::camera_effects_set_custom_exposure);
+
+ BIND_ENUM_CONSTANT(DOF_BOKEH_BOX);
+ BIND_ENUM_CONSTANT(DOF_BOKEH_HEXAGON);
+ BIND_ENUM_CONSTANT(DOF_BOKEH_CIRCLE);
+
BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_VERY_LOW);
BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_LOW);
BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_MEDIUM);
BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_HIGH);
- BIND_ENUM_CONSTANT(DOF_BOKEH_BOX);
- BIND_ENUM_CONSTANT(DOF_BOKEH_HEXAGON);
- BIND_ENUM_CONSTANT(DOF_BOKEH_CIRCLE);
+ /* SCENARIO */
- BIND_ENUM_CONSTANT(SHADOW_QUALITY_HARD);
- BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_LOW);
- BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_MEDIUM);
- BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_HIGH);
- BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_ULTRA);
- BIND_ENUM_CONSTANT(SHADOW_QUALITY_MAX);
+ ClassDB::bind_method(D_METHOD("scenario_create"), &RenderingServer::scenario_create);
+ ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &RenderingServer::scenario_set_environment);
+ ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &RenderingServer::scenario_set_fallback_environment);
+ ClassDB::bind_method(D_METHOD("scenario_set_camera_effects", "scenario", "effects"), &RenderingServer::scenario_set_camera_effects);
- BIND_ENUM_CONSTANT(SCENARIO_DEBUG_DISABLED);
- BIND_ENUM_CONSTANT(SCENARIO_DEBUG_WIREFRAME);
- BIND_ENUM_CONSTANT(SCENARIO_DEBUG_OVERDRAW);
- BIND_ENUM_CONSTANT(SCENARIO_DEBUG_SHADELESS);
+ /* INSTANCE */
- BIND_ENUM_CONSTANT(VIEWPORT_OCCLUSION_BUILD_QUALITY_LOW);
- BIND_ENUM_CONSTANT(VIEWPORT_OCCLUSION_BUILD_QUALITY_MEDIUM);
- BIND_ENUM_CONSTANT(VIEWPORT_OCCLUSION_BUILD_QUALITY_HIGH);
+ ClassDB::bind_method(D_METHOD("instance_create2", "base", "scenario"), &RenderingServer::instance_create2);
+ ClassDB::bind_method(D_METHOD("instance_create"), &RenderingServer::instance_create);
+ ClassDB::bind_method(D_METHOD("instance_set_base", "instance", "base"), &RenderingServer::instance_set_base);
+ ClassDB::bind_method(D_METHOD("instance_set_scenario", "instance", "scenario"), &RenderingServer::instance_set_scenario);
+ ClassDB::bind_method(D_METHOD("instance_set_layer_mask", "instance", "mask"), &RenderingServer::instance_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("instance_set_transform", "instance", "transform"), &RenderingServer::instance_set_transform);
+ ClassDB::bind_method(D_METHOD("instance_attach_object_instance_id", "instance", "id"), &RenderingServer::instance_attach_object_instance_id);
+ ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight);
+ ClassDB::bind_method(D_METHOD("instance_set_surface_override_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_override_material);
+ ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible);
+
+ ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb);
+
+ ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton);
+ ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &RenderingServer::instance_set_extra_visibility_margin);
+ ClassDB::bind_method(D_METHOD("instance_set_visibility_parent", "instance", "parent"), &RenderingServer::instance_set_visibility_parent);
+
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &RenderingServer::instance_geometry_set_cast_shadows_setting);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_visibility_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_visibility_range);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_lightmap", "instance", "lightmap", "lightmap_uv_scale", "lightmap_slice"), &RenderingServer::instance_geometry_set_lightmap);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_lod_bias", "instance", "lod_bias"), &RenderingServer::instance_geometry_set_lod_bias);
+
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_parameter", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_parameter);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter_default_value);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_list", "instance"), &RenderingServer::_instance_geometry_get_shader_parameter_list);
+
+ ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("instances_cull_convex", "convex", "scenario"), &RenderingServer::_instances_cull_convex_bind, DEFVAL(RID()));
BIND_ENUM_CONSTANT(INSTANCE_NONE);
BIND_ENUM_CONSTANT(INSTANCE_MESH);
BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH);
- BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE);
BIND_ENUM_CONSTANT(INSTANCE_PARTICLES);
BIND_ENUM_CONSTANT(INSTANCE_PARTICLES_COLLISION);
BIND_ENUM_CONSTANT(INSTANCE_LIGHT);
@@ -2122,7 +2427,9 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(INSTANCE_VOXEL_GI);
BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP);
BIND_ENUM_CONSTANT(INSTANCE_OCCLUDER);
+ BIND_ENUM_CONSTANT(INSTANCE_VISIBLITY_NOTIFIER);
BIND_ENUM_CONSTANT(INSTANCE_MAX);
+
BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);
BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_BAKED_LIGHT);
@@ -2136,6 +2443,80 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
+ /* Bake 3D Object */
+
+ ClassDB::bind_method(D_METHOD("bake_render_uv2", "base", "material_overrides", "image_size"), &RenderingServer::bake_render_uv2);
+
+ BIND_ENUM_CONSTANT(BAKE_CHANNEL_ALBEDO_ALPHA);
+ BIND_ENUM_CONSTANT(BAKE_CHANNEL_NORMAL);
+ BIND_ENUM_CONSTANT(BAKE_CHANNEL_ORM);
+ BIND_ENUM_CONSTANT(BAKE_CHANNEL_EMISSION);
+
+ /* CANVAS (2D) */
+
+ ClassDB::bind_method(D_METHOD("canvas_create"), &RenderingServer::canvas_create);
+ ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &RenderingServer::canvas_set_item_mirroring);
+ ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &RenderingServer::canvas_set_modulate);
+ ClassDB::bind_method(D_METHOD("canvas_set_disable_scale", "disable"), &RenderingServer::canvas_set_disable_scale);
+
+ /* CANVAS TEXTURE */
+
+ ClassDB::bind_method(D_METHOD("canvas_texture_create"), &RenderingServer::canvas_texture_create);
+ ClassDB::bind_method(D_METHOD("canvas_texture_set_channel", "canvas_texture", "channel", "texture"), &RenderingServer::canvas_texture_set_channel);
+ ClassDB::bind_method(D_METHOD("canvas_texture_set_shading_parameters", "canvas_texture", "base_color", "shininess"), &RenderingServer::canvas_texture_set_shading_parameters);
+
+ ClassDB::bind_method(D_METHOD("canvas_texture_set_texture_filter", "canvas_texture", "filter"), &RenderingServer::canvas_texture_set_texture_filter);
+ ClassDB::bind_method(D_METHOD("canvas_texture_set_texture_repeat", "canvas_texture", "repeat"), &RenderingServer::canvas_texture_set_texture_repeat);
+
+ BIND_ENUM_CONSTANT(CANVAS_TEXTURE_CHANNEL_DIFFUSE);
+ BIND_ENUM_CONSTANT(CANVAS_TEXTURE_CHANNEL_NORMAL);
+ BIND_ENUM_CONSTANT(CANVAS_TEXTURE_CHANNEL_SPECULAR);
+
+ /* CANVAS ITEM */
+
+ ClassDB::bind_method(D_METHOD("canvas_item_create"), &RenderingServer::canvas_item_create);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_parent", "item", "parent"), &RenderingServer::canvas_item_set_parent);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_default_texture_filter", "item", "filter"), &RenderingServer::canvas_item_set_default_texture_filter);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_default_texture_repeat", "item", "repeat"), &RenderingServer::canvas_item_set_default_texture_repeat);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &RenderingServer::canvas_item_set_visible);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &RenderingServer::canvas_item_set_light_mask);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &RenderingServer::canvas_item_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &RenderingServer::canvas_item_set_clip);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &RenderingServer::canvas_item_set_distance_field_mode);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_custom_rect", "item", "use_custom_rect", "rect"), &RenderingServer::canvas_item_set_custom_rect, DEFVAL(Rect2()));
+ ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &RenderingServer::canvas_item_set_modulate);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &RenderingServer::canvas_item_set_self_modulate);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &RenderingServer::canvas_item_set_draw_behind_parent);
+ //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_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);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture"), &RenderingServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count"), &RenderingServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture"), &RenderingServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture"), &RenderingServer::canvas_item_add_multimesh, DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture"), &RenderingServer::canvas_item_add_particles);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &RenderingServer::canvas_item_add_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &RenderingServer::canvas_item_add_clip_ignore);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &RenderingServer::canvas_item_set_sort_children_by_y);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &RenderingServer::canvas_item_set_z_index);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &RenderingServer::canvas_item_set_z_as_relative_to_parent);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &RenderingServer::canvas_item_set_copy_to_backbuffer);
+
+ ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &RenderingServer::canvas_item_clear);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &RenderingServer::canvas_item_set_draw_index);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &RenderingServer::canvas_item_set_material);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &RenderingServer::canvas_item_set_use_parent_material);
+
+ ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_notifier", "item", "enable", "area", "enter_callable", "exit_callable"), &RenderingServer::canvas_item_set_visibility_notifier);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_canvas_group_mode", "item", "mode", "clear_margin", "fit_empty", "fit_margin", "blur_mipmaps"), &RenderingServer::canvas_item_set_canvas_group_mode, DEFVAL(5.0), DEFVAL(false), DEFVAL(0.0), DEFVAL(false));
+
BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH);
BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);
@@ -2159,6 +2540,28 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_OPAQUE);
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_TRANSPARENT);
+ /* CANVAS LIGHT */
+
+ ClassDB::bind_method(D_METHOD("canvas_light_create"), &RenderingServer::canvas_light_create);
+ ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &RenderingServer::canvas_light_attach_to_canvas);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_enabled);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_texture_scale", "light", "scale"), &RenderingServer::canvas_light_set_texture_scale);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &RenderingServer::canvas_light_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &RenderingServer::canvas_light_set_texture);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &RenderingServer::canvas_light_set_texture_offset);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &RenderingServer::canvas_light_set_color);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &RenderingServer::canvas_light_set_height);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &RenderingServer::canvas_light_set_energy);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &RenderingServer::canvas_light_set_z_range);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &RenderingServer::canvas_light_set_layer_range);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_cull_mask);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_shadow_cull_mask);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &RenderingServer::canvas_light_set_mode);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_shadow_enabled);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &RenderingServer::canvas_light_set_shadow_filter);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &RenderingServer::canvas_light_set_shadow_color);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &RenderingServer::canvas_light_set_shadow_smooth);
+
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_POINT);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_DIRECTIONAL);
@@ -2171,10 +2574,38 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_MAX);
+ /* CANVAS OCCLUDER */
+
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &RenderingServer::canvas_light_occluder_create);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &RenderingServer::canvas_light_occluder_attach_to_canvas);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &RenderingServer::canvas_light_occluder_set_enabled);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &RenderingServer::canvas_light_occluder_set_polygon);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_as_sdf_collision", "occluder", "enable"), &RenderingServer::canvas_light_occluder_set_as_sdf_collision);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &RenderingServer::canvas_light_occluder_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &RenderingServer::canvas_light_occluder_set_light_mask);
+
+ /* CANVAS LIGHT OCCLUDER POLYGON */
+
+ ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &RenderingServer::canvas_occluder_polygon_create);
+ ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &RenderingServer::canvas_occluder_polygon_set_shape);
+ ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode);
+
+ ClassDB::bind_method(D_METHOD("canvas_set_shadow_texture_size", "size"), &RenderingServer::canvas_set_shadow_texture_size);
+
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
+ /* GLOBAL VARIABLES */
+
+ ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add);
+ ClassDB::bind_method(D_METHOD("global_variable_remove", "name"), &RenderingServer::global_variable_remove);
+ ClassDB::bind_method(D_METHOD("global_variable_get_list"), &RenderingServer::global_variable_get_list);
+ ClassDB::bind_method(D_METHOD("global_variable_set", "name", "value"), &RenderingServer::global_variable_set);
+ ClassDB::bind_method(D_METHOD("global_variable_set_override", "name", "value"), &RenderingServer::global_variable_set_override);
+ ClassDB::bind_method(D_METHOD("global_variable_get", "name"), &RenderingServer::global_variable_get);
+ ClassDB::bind_method(D_METHOD("global_variable_get_type", "name"), &RenderingServer::global_variable_get_type);
+
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BOOL);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC2);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC3);
@@ -2205,22 +2636,53 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLERCUBE);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAX);
- BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME);
- BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME);
- BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME);
- BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL);
- BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED);
- BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED);
- BIND_ENUM_CONSTANT(INFO_VERTEX_MEM_USED);
+ /* Free */
+ ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // shouldn't conflict with Object::free()
+
+ /* Misc */
+
+ ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &RenderingServer::request_frame_drawn_callback);
+ ClassDB::bind_method(D_METHOD("has_changed"), &RenderingServer::has_changed);
+ ClassDB::bind_method(D_METHOD("get_rendering_info", "info"), &RenderingServer::get_rendering_info);
+ ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &RenderingServer::get_video_adapter_name);
+ ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &RenderingServer::get_video_adapter_vendor);
+
+ ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &RenderingServer::make_sphere_mesh);
+ ClassDB::bind_method(D_METHOD("get_test_cube"), &RenderingServer::get_test_cube);
+
+ ClassDB::bind_method(D_METHOD("get_test_texture"), &RenderingServer::get_test_texture);
+ ClassDB::bind_method(D_METHOD("get_white_texture"), &RenderingServer::get_white_texture);
+
+ ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale", "use_filter"), &RenderingServer::set_boot_image, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &RenderingServer::set_default_clear_color);
+
+ ClassDB::bind_method(D_METHOD("has_feature", "feature"), &RenderingServer::has_feature);
+ ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &RenderingServer::has_os_feature);
+ ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &RenderingServer::set_debug_generate_wireframes);
+
+ ClassDB::bind_method(D_METHOD("is_render_loop_enabled"), &RenderingServer::is_render_loop_enabled);
+ ClassDB::bind_method(D_METHOD("set_render_loop_enabled", "enabled"), &RenderingServer::set_render_loop_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_frame_setup_time_cpu"), &RenderingServer::get_frame_setup_time_cpu);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_loop_enabled"), "set_render_loop_enabled", "is_render_loop_enabled");
+
+ BIND_ENUM_CONSTANT(RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDERING_INFO_TEXTURE_MEM_USED);
+ BIND_ENUM_CONSTANT(RENDERING_INFO_BUFFER_MEM_USED);
+ BIND_ENUM_CONSTANT(RENDERING_INFO_VIDEO_MEM_USED);
BIND_ENUM_CONSTANT(FEATURE_SHADERS);
BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED);
ADD_SIGNAL(MethodInfo("frame_pre_draw"));
ADD_SIGNAL(MethodInfo("frame_post_draw"));
+
+ ClassDB::bind_method(D_METHOD("force_sync"), &RenderingServer::sync);
+ ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers", "frame_step"), &RenderingServer::draw, DEFVAL(true), DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("create_local_rendering_device"), &RenderingServer::create_local_rendering_device);
}
void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data) {
@@ -2253,10 +2715,6 @@ void RenderingServer::mesh_add_surface_from_planes(RID p_mesh, const Vector<Plan
mesh_add_surface_from_mesh_data(p_mesh, mdata);
}
-void RenderingServer::immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex) {
- immediate_vertex(p_immediate, Vector3(p_vertex.x, p_vertex.y, 0));
-}
-
RID RenderingServer::instance_create2(RID p_base, RID p_scenario) {
RID instance = instance_create();
instance_set_base(instance, p_base);
@@ -2330,7 +2788,6 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false);
- GLOBAL_DEF("rendering/global_illumination/voxel_gi/anisotropic", false);
GLOBAL_DEF("rendering/global_illumination/voxel_gi/quality", 1);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/voxel_gi/quality", PropertyInfo(Variant::INT, "rendering/global_illumination/voxel_gi/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)"));
@@ -2373,6 +2830,11 @@ RenderingServer::RenderingServer() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/amount", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/limit", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
+ GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+
GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512);
GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/occlusion_culling/bvh_build_quality", PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"));
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 594e2d885c..28aee1b575 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -78,7 +78,8 @@ public:
CANVAS_ITEM_Z_MAX = 4096,
MAX_GLOW_LEVELS = 7,
MAX_CURSORS = 8,
- MAX_2D_DIRECTIONAL_LIGHTS = 8
+ MAX_2D_DIRECTIONAL_LIGHTS = 8,
+ MAX_MESH_SURFACES = 256
};
/* TEXTURE API */
@@ -103,7 +104,6 @@ public:
virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; //all slices, then all the mipmaps, must be coherent
virtual RID texture_proxy_create(RID p_base) = 0;
- virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0;
@@ -119,10 +119,6 @@ public:
virtual void texture_replace(RID p_texture, RID p_by_texture) = 0;
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0;
-#endif
virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
virtual String texture_get_path(RID p_texture) const = 0;
@@ -173,7 +169,6 @@ public:
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
- Array _shader_get_param_list_bind(RID p_shader) const;
virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
@@ -214,9 +209,9 @@ public:
enum ArrayType {
ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit)
- ARRAY_NORMAL = 1, // A2B10G10R10
+ ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored
ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal
- ARRAY_COLOR = 3, // RGBA16F
+ ARRAY_COLOR = 3, // RGBA8
ARRAY_TEX_UV = 4, // RG32F
ARRAY_TEX_UV2 = 5, // RG32F
ARRAY_CUSTOM0 = 6, // depends on ArrayCustomFormat
@@ -342,7 +337,9 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, BlendShapeMode p_mode) = 0;
virtual BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
- virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
@@ -390,22 +387,6 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
- /* IMMEDIATE API */
-
- virtual RID immediate_create() = 0;
- virtual void immediate_begin(RID p_immediate, PrimitiveType p_rimitive, RID p_texture = RID()) = 0;
- virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0;
- virtual void immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex);
- virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0;
- virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0;
- virtual void immediate_color(RID p_immediate, const Color &p_color) = 0;
- virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0;
- virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0;
- virtual void immediate_end(RID p_immediate) = 0;
- virtual void immediate_clear(RID p_immediate) = 0;
- virtual void immediate_set_material(RID p_immediate, RID p_material) = 0;
- virtual RID immediate_get_material(RID p_immediate) const = 0;
-
/* SKELETON API */
virtual RID skeleton_create() = 0;
@@ -489,12 +470,29 @@ public:
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0;
- enum LightDirectionalShadowDepthRangeMode {
- LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE,
- LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED,
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) = 0;
+
+ enum ShadowQuality {
+ SHADOW_QUALITY_HARD,
+ SHADOW_QUALITY_SOFT_LOW,
+ SHADOW_QUALITY_SOFT_MEDIUM,
+ SHADOW_QUALITY_SOFT_HIGH,
+ SHADOW_QUALITY_SOFT_ULTRA,
+ SHADOW_QUALITY_MAX
};
- virtual void light_directional_set_shadow_depth_range_mode(RID p_light, LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
+ virtual void shadows_quality_set(ShadowQuality p_quality) = 0;
+ virtual void directional_shadow_quality_set(ShadowQuality p_quality) = 0;
+
+ enum LightProjectorFilter {
+ LIGHT_PROJECTOR_FILTER_NEAREST,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
+ LIGHT_PROJECTOR_FILTER_LINEAR,
+ LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS,
+ LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
+ };
+
+ virtual void light_projectors_set_filter(LightProjectorFilter p_filter) = 0;
/* PROBE API */
@@ -548,6 +546,16 @@ public:
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;
+ enum DecalFilter {
+ DECAL_FILTER_NEAREST,
+ DECAL_FILTER_NEAREST_MIPMAPS,
+ DECAL_FILTER_LINEAR,
+ DECAL_FILTER_LINEAR_MIPMAPS,
+ DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
+ };
+
+ virtual void decals_set_filter(DecalFilter p_quality) = 0;
+
/* VOXEL GI API */
virtual RID voxel_gi_create() = 0;
@@ -563,34 +571,12 @@ public:
virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const = 0;
virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0;
- virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0;
- virtual float voxel_gi_get_propagation(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
- virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) = 0;
- virtual float voxel_gi_get_ao(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) = 0;
- virtual float voxel_gi_get_ao_size(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
- virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0;
- virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0;
- virtual bool voxel_gi_is_interior(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0;
- virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) = 0;
- virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const = 0;
enum VoxelGIQuality {
VOXEL_GI_QUALITY_LOW,
@@ -745,7 +731,7 @@ public:
virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0;
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
- /* VIEWPORT TARGET API */
+ /* VIEWPORT API */
enum CanvasItemTextureFilter {
CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item
@@ -796,9 +782,9 @@ public:
virtual RID viewport_get_texture(RID p_viewport) const = 0;
- virtual void viewport_set_hide_scenario(RID p_viewport, bool p_hide) = 0;
- virtual void viewport_set_hide_canvas(RID p_viewport, bool p_hide) = 0;
virtual void viewport_set_disable_environment(RID p_viewport, bool p_disable) = 0;
+ virtual void viewport_set_disable_3d(RID p_viewport, bool p_disable) = 0;
+ virtual void viewport_set_disable_2d(RID p_viewport, bool p_disable) = 0;
virtual void viewport_attach_camera(RID p_viewport, RID p_camera) = 0;
virtual void viewport_set_scenario(RID p_viewport, RID p_scenario) = 0;
@@ -871,15 +857,18 @@ public:
enum ViewportRenderInfo {
VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME,
- VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME,
- VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME,
- VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME,
- VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME,
+ VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME,
VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME,
VIEWPORT_RENDER_INFO_MAX,
};
- virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) = 0;
+ enum ViewportRenderInfoType {
+ VIEWPORT_RENDER_INFO_TYPE_VISIBLE,
+ VIEWPORT_RENDER_INFO_TYPE_SHADOW,
+ VIEWPORT_RENDER_INFO_TYPE_MAX
+ };
+
+ virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfoType p_type, ViewportRenderInfo p_info) = 0;
enum ViewportDebugDraw {
VIEWPORT_DEBUG_DRAW_DISABLED,
@@ -914,8 +903,6 @@ public:
virtual float viewport_get_measured_render_time_cpu(RID p_viewport) const = 0;
virtual float viewport_get_measured_render_time_gpu(RID p_viewport) const = 0;
- virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) = 0;
-
/* SKY API */
enum SkyMode {
@@ -966,10 +953,6 @@ public:
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0;
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
-#endif
enum EnvironmentGlowBlendMode {
ENV_GLOW_BLEND_MODE_ADDITIVE,
@@ -1111,30 +1094,10 @@ public:
virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
- enum ShadowQuality {
- SHADOW_QUALITY_HARD,
- SHADOW_QUALITY_SOFT_LOW,
- SHADOW_QUALITY_SOFT_MEDIUM,
- SHADOW_QUALITY_SOFT_HIGH,
- SHADOW_QUALITY_SOFT_ULTRA,
- SHADOW_QUALITY_MAX
- };
-
- virtual void shadows_quality_set(ShadowQuality p_quality) = 0;
- virtual void directional_shadow_quality_set(ShadowQuality p_quality) = 0;
-
/* SCENARIO API */
virtual RID scenario_create() = 0;
- enum ScenarioDebugMode {
- SCENARIO_DEBUG_DISABLED,
- SCENARIO_DEBUG_WIREFRAME,
- SCENARIO_DEBUG_OVERDRAW,
- SCENARIO_DEBUG_SHADELESS,
- };
-
- virtual void scenario_set_debug(RID p_scenario, ScenarioDebugMode p_debug_mode) = 0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) = 0;
@@ -1145,7 +1108,6 @@ public:
INSTANCE_NONE,
INSTANCE_MESH,
INSTANCE_MULTIMESH,
- INSTANCE_IMMEDIATE,
INSTANCE_PARTICLES,
INSTANCE_PARTICLES_COLLISION,
INSTANCE_LIGHT,
@@ -1157,7 +1119,7 @@ public:
INSTANCE_VISIBLITY_NOTIFIER,
INSTANCE_MAX,
- INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES)
+ INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_PARTICLES)
};
virtual RID instance_create2(RID p_base, RID p_scenario);
@@ -1176,7 +1138,6 @@ public:
virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0;
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;
- virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0;
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
@@ -1208,7 +1169,6 @@ public:
virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0;
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0;
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
-
virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
@@ -1238,6 +1198,7 @@ public:
virtual void canvas_set_disable_scale(bool p_disable) = 0;
+ /* CANVAS TEXTURE */
virtual RID canvas_texture_create() = 0;
enum CanvasTextureChannel {
@@ -1252,6 +1213,8 @@ public:
virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, CanvasItemTextureFilter p_filter) = 0;
virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, CanvasItemTextureRepeat p_repeat) = 0;
+ /* CANVAS ITEM */
+
virtual RID canvas_item_create() = 0;
virtual void canvas_item_set_parent(RID p_item, RID p_parent) = 0;
@@ -1295,6 +1258,7 @@ public:
virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0;
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0;
virtual void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) = 0;
+
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0;
virtual void canvas_item_set_z_index(RID p_item, int p_z) = 0;
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0;
@@ -1319,6 +1283,7 @@ public:
virtual void canvas_item_set_canvas_group_mode(RID p_item, CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false) = 0;
+ /* CANVAS LIGHT */
virtual RID canvas_light_create() = 0;
enum CanvasLightMode {
@@ -1365,6 +1330,8 @@ public:
virtual void canvas_light_set_shadow_color(RID p_light, const Color &p_color) = 0;
virtual void canvas_light_set_shadow_smooth(RID p_light, float p_smooth) = 0;
+ /* CANVAS LIGHT OCCLUDER */
+
virtual RID canvas_light_occluder_create() = 0;
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) = 0;
virtual void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) = 0;
@@ -1373,6 +1340,8 @@ public:
virtual void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) = 0;
virtual void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) = 0;
+ /* CANVAS LIGHT OCCLUDER POLYGON */
+
virtual RID canvas_occluder_polygon_create() = 0;
virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) = 0;
@@ -1435,11 +1404,6 @@ public:
static ShaderLanguage::DataType global_variable_type_get_shader_datatype(GlobalVariableType p_type);
- /* BLACK BARS */
-
- virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0;
- virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) = 0;
-
/* FREE */
virtual void free(RID p_rid) = 0; ///< free RIDs associated with the visual server
@@ -1456,20 +1420,17 @@ public:
/* STATUS INFORMATION */
- enum RenderInfo {
- INFO_OBJECTS_IN_FRAME,
- INFO_VERTICES_IN_FRAME,
- INFO_MATERIAL_CHANGES_IN_FRAME,
- INFO_SHADER_CHANGES_IN_FRAME,
- INFO_SURFACE_CHANGES_IN_FRAME,
- INFO_DRAW_CALLS_IN_FRAME,
- INFO_USAGE_VIDEO_MEM_TOTAL,
- INFO_VIDEO_MEM_USED,
- INFO_TEXTURE_MEM_USED,
- INFO_VERTEX_MEM_USED,
+ enum RenderingInfo {
+ RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME,
+ RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME,
+ RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME,
+ RENDERING_INFO_TEXTURE_MEM_USED,
+ RENDERING_INFO_BUFFER_MEM_USED,
+ RENDERING_INFO_VIDEO_MEM_USED,
+ RENDERING_INFO_MAX
};
- virtual uint64_t get_render_info(RenderInfo p_info) = 0;
+ virtual uint64_t get_rendering_info(RenderingInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
@@ -1515,7 +1476,7 @@ public:
virtual void set_debug_generate_wireframes(bool p_generate) = 0;
- virtual void call_set_use_vsync(bool p_enable) = 0;
+ virtual void call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window) = 0;
virtual bool is_low_end() const = 0;
@@ -1528,6 +1489,20 @@ public:
RenderingServer();
virtual ~RenderingServer();
+
+private:
+ //binder helpers
+ RID _texture_2d_layered_create(const TypedArray<Image> &p_layers, TextureLayeredType p_layered_type);
+ RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data);
+ void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data);
+ TypedArray<Image> _texture_3d_get(RID p_texture) const;
+ TypedArray<Dictionary> _shader_get_param_list(RID p_shader) const;
+ RID _mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count);
+ void _mesh_add_surface(RID p_mesh, const Dictionary &p_surface);
+ Dictionary _mesh_get_surface(RID p_mesh, int p_idx);
+ Array _instance_geometry_get_shader_parameter_list(RID p_instance) const;
+ TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size);
+ void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses);
};
// make variant understand the enums
@@ -1536,6 +1511,7 @@ VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer);
VARIANT_ENUM_CAST(RenderingServer::ShaderMode);
VARIANT_ENUM_CAST(RenderingServer::ArrayType);
VARIANT_ENUM_CAST(RenderingServer::ArrayFormat);
+VARIANT_ENUM_CAST(RenderingServer::ArrayCustomFormat);
VARIANT_ENUM_CAST(RenderingServer::PrimitiveType);
VARIANT_ENUM_CAST(RenderingServer::BlendShapeMode);
VARIANT_ENUM_CAST(RenderingServer::MultimeshTransformFormat);
@@ -1544,18 +1520,28 @@ VARIANT_ENUM_CAST(RenderingServer::LightParam);
VARIANT_ENUM_CAST(RenderingServer::LightBakeMode);
VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode);
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode);
-VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowDepthRangeMode);
+VARIANT_ENUM_CAST(RenderingServer::LightProjectorFilter);
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeAmbientMode);
+VARIANT_ENUM_CAST(RenderingServer::VoxelGIQuality);
VARIANT_ENUM_CAST(RenderingServer::DecalTexture);
+VARIANT_ENUM_CAST(RenderingServer::DecalFilter);
+VARIANT_ENUM_CAST(RenderingServer::ParticlesMode);
+VARIANT_ENUM_CAST(RenderingServer::ParticlesTransformAlign);
VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder);
+VARIANT_ENUM_CAST(RenderingServer::ParticlesEmitFlags);
+VARIANT_ENUM_CAST(RenderingServer::ParticlesCollisionType);
+VARIANT_ENUM_CAST(RenderingServer::ParticlesCollisionHeightfieldResolution);
VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportMSAA);
VARIANT_ENUM_CAST(RenderingServer::ViewportScreenSpaceAA);
VARIANT_ENUM_CAST(RenderingServer::ViewportRenderInfo);
+VARIANT_ENUM_CAST(RenderingServer::ViewportRenderInfoType);
VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw);
VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
+VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
+VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);
@@ -1564,11 +1550,15 @@ VARIANT_ENUM_CAST(RenderingServer::EnvironmentGlowBlendMode);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentToneMapper);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSRRoughnessQuality);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSAOQuality);
+VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGICascades);
+VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIFramesToConverge);
+VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIRayCount);
+VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIFramesToUpdateLight);
+VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIYScale);
VARIANT_ENUM_CAST(RenderingServer::SubSurfaceScatteringQuality);
VARIANT_ENUM_CAST(RenderingServer::DOFBlurQuality);
VARIANT_ENUM_CAST(RenderingServer::DOFBokehShape);
VARIANT_ENUM_CAST(RenderingServer::ShadowQuality);
-VARIANT_ENUM_CAST(RenderingServer::ScenarioDebugMode);
VARIANT_ENUM_CAST(RenderingServer::InstanceType);
VARIANT_ENUM_CAST(RenderingServer::InstanceFlags);
VARIANT_ENUM_CAST(RenderingServer::ShadowCastingSetting);
@@ -1581,8 +1571,10 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasLightBlendMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter);
VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode);
VARIANT_ENUM_CAST(RenderingServer::GlobalVariableType);
-VARIANT_ENUM_CAST(RenderingServer::RenderInfo);
+VARIANT_ENUM_CAST(RenderingServer::RenderingInfo);
VARIANT_ENUM_CAST(RenderingServer::Features);
+VARIANT_ENUM_CAST(RenderingServer::CanvasTextureChannel);
+VARIANT_ENUM_CAST(RenderingServer::BakeChannels);
// Alias to make it easier to use.
#define RS RenderingServer
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 6f48148cab..1491368109 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -331,6 +331,9 @@ void TextServer::_bind_methods() {
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"), &TextServer::_shaped_text_get_word_breaks);
+
+ ClassDB::bind_method(D_METHOD("shaped_text_overrun_trim_to_width", "shaped", "width", "overrun_trim_flags"), &TextServer::shaped_text_overrun_trim_to_width, DEFVAL(0), DEFVAL(OVERRUN_NO_TRIMMING));
+
ClassDB::bind_method(D_METHOD("shaped_text_get_objects", "shaped"), &TextServer::shaped_text_get_objects);
ClassDB::bind_method(D_METHOD("shaped_text_get_object_rect", "shaped", "key"), &TextServer::shaped_text_get_object_rect);
@@ -381,6 +384,13 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(BREAK_WORD_BOUND);
BIND_ENUM_CONSTANT(BREAK_GRAPHEME_BOUND);
+ /* TextOverrunFlag */
+ BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ONLY);
+ BIND_ENUM_CONSTANT(OVERRUN_ADD_ELLIPSIS);
+ BIND_ENUM_CONSTANT(OVERRUN_ENFORCE_ELLIPSIS);
+
/* GraphemeFlag */
BIND_ENUM_CONSTANT(GRAPHEME_IS_RTL);
BIND_ENUM_CONSTANT(GRAPHEME_IS_VIRTUAL);
@@ -646,7 +656,7 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
float width = 0.f;
int line_start = MAX(p_start, range.x);
int last_safe_break = -1;
-
+ int word_count = 0;
int l_size = logical.size();
const Glyph *l_gl = logical.ptr();
@@ -655,12 +665,15 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
continue;
}
if (l_gl[i].count > 0) {
- if ((p_width > 0) && (width + l_gl[i].advance > p_width) && (last_safe_break >= 0)) {
+ //Ignore trailing spaces.
+ bool is_space = (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE;
+ if ((p_width > 0) && (width + (is_space ? 0 : l_gl[i].advance) > p_width) && (last_safe_break >= 0)) {
lines.push_back(Vector2i(line_start, l_gl[last_safe_break].end));
line_start = l_gl[last_safe_break].end;
i = last_safe_break;
last_safe_break = -1;
width = 0;
+ word_count = 0;
continue;
}
if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
@@ -675,8 +688,12 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_safe_break = i;
+ word_count++;
}
}
+ if (((p_break_flags & BREAK_WORD_BOUND_ADAPTIVE) == BREAK_WORD_BOUND_ADAPTIVE) && word_count == 0) {
+ last_safe_break = i;
+ }
if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) {
last_safe_break = i;
}
@@ -695,7 +712,7 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
return lines;
}
-Vector<Vector2i> TextServer::shaped_text_get_word_breaks(RID p_shaped) const {
+Vector<Vector2i> TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
Vector<Vector2i> words;
const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped);
@@ -709,7 +726,7 @@ Vector<Vector2i> TextServer::shaped_text_get_word_breaks(RID p_shaped) const {
for (int i = 0; i < l_size; i++) {
if (l_gl[i].count > 0) {
- if (((l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) || ((l_gl[i].flags & GRAPHEME_IS_PUNCTUATION) == GRAPHEME_IS_PUNCTUATION)) {
+ if ((l_gl[i].flags & p_grapheme_flags) != 0) {
words.push_back(Vector2i(word_start, l_gl[i].start));
word_start = l_gl[i].end;
}
diff --git a/servers/text_server.h b/servers/text_server.h
index 138ceb9356..4c2ada7fc9 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -66,8 +66,16 @@ public:
BREAK_NONE = 0,
BREAK_MANDATORY = 1 << 4,
BREAK_WORD_BOUND = 1 << 5,
- BREAK_GRAPHEME_BOUND = 1 << 6
- //RESERVED = 1 << 7
+ BREAK_GRAPHEME_BOUND = 1 << 6,
+ BREAK_WORD_BOUND_ADAPTIVE = 1 << 5 | 1 << 7
+ };
+
+ enum TextOverrunFlag {
+ OVERRUN_NO_TRIMMING = 0,
+ OVERRUN_TRIM = 1 << 0,
+ OVERRUN_TRIM_WORD_ONLY = 1 << 1,
+ OVERRUN_ADD_ELLIPSIS = 1 << 2,
+ OVERRUN_ENFORCE_ELLIPSIS = 1 << 3
};
enum GraphemeFlag {
@@ -79,7 +87,8 @@ public:
GRAPHEME_IS_BREAK_SOFT = 1 << 5, // Is line break (optional break, e.g. space).
GRAPHEME_IS_TAB = 1 << 6, // Is tab or vertical tab.
GRAPHEME_IS_ELONGATION = 1 << 7, // Elongation (e.g. kashida), glyph can be duplicated or truncated to fit line to width.
- GRAPHEME_IS_PUNCTUATION = 1 << 8 // Punctuation (can be used as word break, but not line break or justifiction).
+ GRAPHEME_IS_PUNCTUATION = 1 << 8, // Punctuation, except underscore (can be used as word break, but not line break or justifiction).
+ GRAPHEME_IS_UNDERSCORE = 1 << 9, // Underscore (can be used as word break).
};
enum Hinting {
@@ -138,7 +147,7 @@ public:
return true;
}
}
- return l.count > r.count; // Sort first glyoh with count & flags, order of the rest are irrelevant.
+ return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant.
} else {
return l.start < r.start;
}
@@ -346,7 +355,9 @@ public:
virtual Vector<Vector2i> shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<float> &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped) const;
+ virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
+
+ virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_clip_flags) = 0;
virtual Array shaped_text_get_objects(RID p_shaped) const = 0;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const = 0;
@@ -461,6 +472,7 @@ VARIANT_ENUM_CAST(TextServer::Direction);
VARIANT_ENUM_CAST(TextServer::Orientation);
VARIANT_ENUM_CAST(TextServer::JustificationFlag);
VARIANT_ENUM_CAST(TextServer::LineBreakFlag);
+VARIANT_ENUM_CAST(TextServer::TextOverrunFlag);
VARIANT_ENUM_CAST(TextServer::GraphemeFlag);
VARIANT_ENUM_CAST(TextServer::Hinting);
VARIANT_ENUM_CAST(TextServer::Feature);
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index b12fff319d..c27656047f 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -164,7 +164,7 @@ void XRServer::add_interface(const Ref<XRInterface> &p_interface) {
};
interfaces.push_back(p_interface);
- emit_signal("interface_added", p_interface->get_name());
+ emit_signal(SNAME("interface_added"), p_interface->get_name());
};
void XRServer::remove_interface(const Ref<XRInterface> &p_interface) {
@@ -182,7 +182,7 @@ void XRServer::remove_interface(const Ref<XRInterface> &p_interface) {
print_verbose("XR: Removed interface" + p_interface->get_name());
- emit_signal("interface_removed", p_interface->get_name());
+ emit_signal(SNAME("interface_removed"), p_interface->get_name());
interfaces.remove(idx);
};
@@ -269,7 +269,7 @@ void XRServer::add_tracker(Ref<XRPositionalTracker> p_tracker) {
ERR_FAIL_COND(p_tracker.is_null());
trackers.push_back(p_tracker);
- emit_signal("tracker_added", p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id());
+ emit_signal(SNAME("tracker_added"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id());
};
void XRServer::remove_tracker(Ref<XRPositionalTracker> p_tracker) {
@@ -285,7 +285,7 @@ void XRServer::remove_tracker(Ref<XRPositionalTracker> p_tracker) {
ERR_FAIL_COND(idx == -1);
- emit_signal("tracker_removed", p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id());
+ emit_signal(SNAME("tracker_removed"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id());
trackers.remove(idx);
};
diff --git a/tests/test_class_db.h b/tests/test_class_db.h
index 75785fa5ed..29edf5a4a0 100644
--- a/tests/test_class_db.h
+++ b/tests/test_class_db.h
@@ -754,6 +754,9 @@ void add_exposed_classes(Context &r_context) {
const List<StringName> &enum_constants = enum_map.get(*k);
for (const List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
const StringName &constant_name = E->get();
+ TEST_FAIL_COND(String(constant_name).find("::") != -1,
+ "Enum constant contains '::', check bindings to remove the scope: '",
+ String(class_name), ".", String(enum_.name), ".", String(constant_name), "'.");
int *value = class_info->constant_map.getptr(constant_name);
TEST_FAIL_COND(!value, "Missing enum constant value: '",
String(class_name), ".", String(enum_.name), ".", String(constant_name), "'.");
@@ -773,8 +776,11 @@ void add_exposed_classes(Context &r_context) {
for (const List<String>::Element *E = constants.front(); E; E = E->next()) {
const String &constant_name = E->get();
+ TEST_FAIL_COND(constant_name.find("::") != -1,
+ "Constant contains '::', check bindings to remove the scope: '",
+ String(class_name), ".", constant_name, "'.");
int *value = class_info->constant_map.getptr(StringName(E->get()));
- TEST_FAIL_COND(!value, "Missing enum constant value: '", String(class_name), ".", String(constant_name), "'.");
+ TEST_FAIL_COND(!value, "Missing constant value: '", String(class_name), ".", String(constant_name), "'.");
ConstantData constant;
constant.name = constant_name;
diff --git a/tests/test_gui.cpp b/tests/test_gui.cpp
index b83bd10af4..0ec8aa78c4 100644
--- a/tests/test_gui.cpp
+++ b/tests/test_gui.cpp
@@ -217,7 +217,7 @@ public:
richtext->add_text("faeries.\n");
richtext->pop();
richtext->add_text("In this new episode, we will attempt to ");
- richtext->push_font(richtext->get_theme_font("mono_font", "Fonts"));
+ richtext->push_font(richtext->get_theme_font(SNAME("mono_font"), SNAME("Fonts")));
richtext->push_color(Color(0.7, 0.5, 1.0));
richtext->add_text("deliver something nice");
richtext->pop();
diff --git a/tests/test_object.h b/tests/test_object.h
index b7eedc2670..36f9ef2a51 100644
--- a/tests/test_object.h
+++ b/tests/test_object.h
@@ -206,7 +206,7 @@ TEST_CASE("[Object] Script instance property getter") {
}
TEST_CASE("[Object] Built-in property setter") {
- ClassDB::register_class<_TestDerivedObject>();
+ GDREGISTER_CLASS(_TestDerivedObject);
_TestDerivedObject derived_object;
bool valid = false;
@@ -218,7 +218,7 @@ TEST_CASE("[Object] Built-in property setter") {
}
TEST_CASE("[Object] Built-in property getter") {
- ClassDB::register_class<_TestDerivedObject>();
+ GDREGISTER_CLASS(_TestDerivedObject);
_TestDerivedObject derived_object;
derived_object.set_property(100);
diff --git a/tests/test_text_server.h b/tests/test_text_server.h
index 3d700f8ec4..cac022e33f 100644
--- a/tests/test_text_server.h
+++ b/tests/test_text_server.h
@@ -55,7 +55,7 @@ TEST_SUITE("[[TextServer]") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err);
- RID font = ts->create_font_memory(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size, "ttf");
+ RID font = ts->create_font_memory(_font_NotoSans_Regular, _font_NotoSans_Regular_size, "ttf");
TEST_FAIL_COND(font == RID(), "Loading font failed.");
ts->free(font);
}
@@ -66,7 +66,7 @@ TEST_SUITE("[[TextServer]") {
TextServer *ts = TextServerManager::initialize(i, err);
Vector<RID> font;
- font.push_back(ts->create_font_memory(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size, "ttf"));
+ font.push_back(ts->create_font_memory(_font_NotoSans_Regular, _font_NotoSans_Regular_size, "ttf"));
font.push_back(ts->create_font_memory(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, "ttf"));
String test = U"คนอ้วน khon uan ר××”";
@@ -112,7 +112,7 @@ TEST_SUITE("[[TextServer]") {
}
Vector<RID> font;
- font.push_back(ts->create_font_memory(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size, "ttf"));
+ font.push_back(ts->create_font_memory(_font_NotoSans_Regular, _font_NotoSans_Regular_size, "ttf"));
font.push_back(ts->create_font_memory(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, "ttf"));
String test = U"Arabic (اَلْعَرَبÙيَّةÙ, al-Ê¿arabiyyah)";
@@ -156,7 +156,7 @@ TEST_SUITE("[[TextServer]") {
// 5^ 10^
Vector<RID> font;
- font.push_back(ts->create_font_memory(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size, "ttf"));
+ font.push_back(ts->create_font_memory(_font_NotoSans_Regular, _font_NotoSans_Regular_size, "ttf"));
font.push_back(ts->create_font_memory(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, "ttf"));
RID ctx = ts->create_shaped_text();
@@ -186,7 +186,7 @@ TEST_SUITE("[[TextServer]") {
TextServer *ts = TextServerManager::initialize(i, err);
Vector<RID> font;
- font.push_back(ts->create_font_memory(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size, "ttf"));
+ font.push_back(ts->create_font_memory(_font_NotoSans_Regular, _font_NotoSans_Regular_size, "ttf"));
font.push_back(ts->create_font_memory(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, "ttf"));
String test_1 = U"الحمد";
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 03a2ddf5e4..3f28838fac 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -123,9 +123,9 @@ Files extracted from upstream source:
## fonts
-- `NotoSans*.ttf`, `NotoNaskhArabicUI_Regular.ttf`:
- * Upstream: https://github.com/googlei18n/noto-fonts
- * Version: 1.06 (2017)
+- `NotoSans*.ttf`, `NotoNaskhArabicUI_*.ttf`:
+ * Upstream: https://github.com/googlefonts/noto-fonts
+ * Version: v2017-10-24-phase3-second-cleanup
* License: OFL-1.1
* Comment: Use UI font variant if available, because it has tight vertical metrics and
good for UI.
@@ -347,21 +347,21 @@ changes are marked with `// -- GODOT --` comments.
## mbedtls
- Upstream: https://tls.mbed.org/
-- Version: 2.16.10 (d61fa61bef06b64132e3490543c81b8ee40fbee3, 2021)
+- Version: 2.16.11 (aa1d4e097342af799ba80dfb13640efef498227c, 2021)
- License: Apache 2.0
File extracted from upstream release tarball:
-- All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/`
-- All `*.c` from `library/` to `thirdparty/mbedtls/library/`
-- LICENSE and apache-2.0.txt files
-- Applied the patch in `thirdparty/mbedtls/patches/1453.diff` (PR 1453).
- Soon to be merged upstream. Check it out at next update.
+- All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/`.
+- All `*.c` from `library/` to `thirdparty/mbedtls/library/`.
+- `LICENSE` and `apache-2.0.txt` files.
+- Applied the patch in `thirdparty/mbedtls/patches/1453.diff` (upstream PR:
+ https://github.com/ARMmbed/mbedtls/pull/1453).
- Applied the patch in `thirdparty/mbedtls/patches/padlock.diff`. This disables
VIA padlock support which defines a symbol `unsupported` which clashes with
a pre-defined symbol.
-- Added 2 files `godot_core_mbedtls_platform.{c,h}` providing configuration
- for light bundling with core.
+- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
+ providing configuration for light bundling with core.
## meshoptimizer
@@ -616,6 +616,11 @@ Files extracted from upstream source:
- `include` folder
- `LICENSE`
+Some downstream changes have been made and are identified by
+`// -- GODOT begin --` and `// -- GODOT end --` comments.
+They can be reapplied using the patch included in the `patches`
+folder.
+
## squish
diff --git a/thirdparty/fonts/NotoNaskhArabicUI_Bold.ttf b/thirdparty/fonts/NotoNaskhArabicUI_Bold.ttf
new file mode 100644
index 0000000000..5576af7fee
--- /dev/null
+++ b/thirdparty/fonts/NotoNaskhArabicUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoNaskhArabicUI_Regular.ttf b/thirdparty/fonts/NotoNaskhArabicUI_Regular.ttf
index 67713c697e..9b7a93d136 100644
--- a/thirdparty/fonts/NotoNaskhArabicUI_Regular.ttf
+++ b/thirdparty/fonts/NotoNaskhArabicUI_Regular.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansBengaliUI_Bold.ttf b/thirdparty/fonts/NotoSansBengaliUI_Bold.ttf
new file mode 100644
index 0000000000..dc61efefd5
--- /dev/null
+++ b/thirdparty/fonts/NotoSansBengaliUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansBengali_Regular.ttf b/thirdparty/fonts/NotoSansBengaliUI_Regular.ttf
index daeabcf817..d43c292ad6 100644
--- a/thirdparty/fonts/NotoSansBengali_Regular.ttf
+++ b/thirdparty/fonts/NotoSansBengaliUI_Regular.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansDevanagariUI_Bold.ttf b/thirdparty/fonts/NotoSansDevanagariUI_Bold.ttf
new file mode 100644
index 0000000000..74791aa469
--- /dev/null
+++ b/thirdparty/fonts/NotoSansDevanagariUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf b/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf
index 1f9fb2e857..e48dced0c9 100644
--- a/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf
+++ b/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansGeorgian_Bold.ttf b/thirdparty/fonts/NotoSansGeorgian_Bold.ttf
new file mode 100644
index 0000000000..5443d04cfa
--- /dev/null
+++ b/thirdparty/fonts/NotoSansGeorgian_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansHebrew_Bold.ttf b/thirdparty/fonts/NotoSansHebrew_Bold.ttf
new file mode 100644
index 0000000000..08ef5dc749
--- /dev/null
+++ b/thirdparty/fonts/NotoSansHebrew_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansHebrew_Regular.ttf b/thirdparty/fonts/NotoSansHebrew_Regular.ttf
index 5027f5c228..0a89e9d21f 100644
--- a/thirdparty/fonts/NotoSansHebrew_Regular.ttf
+++ b/thirdparty/fonts/NotoSansHebrew_Regular.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansMalayalamUI_Bold.ttf b/thirdparty/fonts/NotoSansMalayalamUI_Bold.ttf
new file mode 100644
index 0000000000..42e5d56f3f
--- /dev/null
+++ b/thirdparty/fonts/NotoSansMalayalamUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansOriyaUI_Bold.ttf b/thirdparty/fonts/NotoSansOriyaUI_Bold.ttf
new file mode 100644
index 0000000000..36323f79ef
--- /dev/null
+++ b/thirdparty/fonts/NotoSansOriyaUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansSinhalaUI_Bold.ttf b/thirdparty/fonts/NotoSansSinhalaUI_Bold.ttf
new file mode 100644
index 0000000000..ecfff97e05
--- /dev/null
+++ b/thirdparty/fonts/NotoSansSinhalaUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTamilUI_Bold.ttf b/thirdparty/fonts/NotoSansTamilUI_Bold.ttf
new file mode 100644
index 0000000000..16bcd57081
--- /dev/null
+++ b/thirdparty/fonts/NotoSansTamilUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTeluguUI_Bold.ttf b/thirdparty/fonts/NotoSansTeluguUI_Bold.ttf
new file mode 100644
index 0000000000..16ac368795
--- /dev/null
+++ b/thirdparty/fonts/NotoSansTeluguUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansThaiUI_Bold.ttf b/thirdparty/fonts/NotoSansThaiUI_Bold.ttf
new file mode 100644
index 0000000000..5d998f9215
--- /dev/null
+++ b/thirdparty/fonts/NotoSansThaiUI_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansThaiUI_Regular.ttf b/thirdparty/fonts/NotoSansThaiUI_Regular.ttf
index 9c50a1b8f5..8e317961d1 100644
--- a/thirdparty/fonts/NotoSansThaiUI_Regular.ttf
+++ b/thirdparty/fonts/NotoSansThaiUI_Regular.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSansUI_Bold.ttf b/thirdparty/fonts/NotoSansUI_Bold.ttf
deleted file mode 100644
index 810450aa81..0000000000
--- a/thirdparty/fonts/NotoSansUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansUI_Regular.ttf b/thirdparty/fonts/NotoSansUI_Regular.ttf
deleted file mode 100644
index 65b29fcff1..0000000000
--- a/thirdparty/fonts/NotoSansUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSans_Bold.ttf b/thirdparty/fonts/NotoSans_Bold.ttf
new file mode 100644
index 0000000000..1db7886e94
--- /dev/null
+++ b/thirdparty/fonts/NotoSans_Bold.ttf
Binary files differ
diff --git a/thirdparty/fonts/NotoSans_Regular.ttf b/thirdparty/fonts/NotoSans_Regular.ttf
new file mode 100644
index 0000000000..0a01a062f0
--- /dev/null
+++ b/thirdparty/fonts/NotoSans_Regular.ttf
Binary files differ
diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h
index 13763d4200..20f43f2256 100644
--- a/thirdparty/mbedtls/include/mbedtls/aria.h
+++ b/thirdparty/mbedtls/include/mbedtls/aria.h
@@ -88,14 +88,14 @@
/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */
-#if !defined(MBEDTLS_ARIA_ALT)
-// Regular implementation
-//
-
#ifdef __cplusplus
extern "C" {
#endif
+#if !defined(MBEDTLS_ARIA_ALT)
+// Regular implementation
+//
+
/**
* \brief The ARIA context-type definition.
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h
index 9615090f91..6f1201bf50 100644
--- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h
+++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h
@@ -71,6 +71,46 @@
#include "bignum.h"
+
+/*
+ * Conversion macros for embedded constants:
+ * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2
+ */
+#if defined(MBEDTLS_HAVE_INT32)
+
+#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \
+ ( (mbedtls_mpi_uint) (a) << 0 ) | \
+ ( (mbedtls_mpi_uint) (b) << 8 ) | \
+ ( (mbedtls_mpi_uint) (c) << 16 ) | \
+ ( (mbedtls_mpi_uint) (d) << 24 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \
+ MBEDTLS_BYTES_TO_T_UINT_4( a, b, 0, 0 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+ MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ), \
+ MBEDTLS_BYTES_TO_T_UINT_4( e, f, g, h )
+
+#else /* 64-bits */
+
+#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+ ( (mbedtls_mpi_uint) (a) << 0 ) | \
+ ( (mbedtls_mpi_uint) (b) << 8 ) | \
+ ( (mbedtls_mpi_uint) (c) << 16 ) | \
+ ( (mbedtls_mpi_uint) (d) << 24 ) | \
+ ( (mbedtls_mpi_uint) (e) << 32 ) | \
+ ( (mbedtls_mpi_uint) (f) << 40 ) | \
+ ( (mbedtls_mpi_uint) (g) << 48 ) | \
+ ( (mbedtls_mpi_uint) (h) << 56 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \
+ MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \
+ MBEDTLS_BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
+
+#endif /* bits in mbedtls_mpi_uint */
+
#if defined(MBEDTLS_HAVE_ASM)
#ifndef asm
diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h
index 610f5d1f50..d53b457630 100644
--- a/thirdparty/mbedtls/include/mbedtls/config.h
+++ b/thirdparty/mbedtls/include/mbedtls/config.h
@@ -453,7 +453,7 @@
* be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt
* must stay untouched.
*
- * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
+ * \note If you use the AES_xxx_ALT macros, then it is recommended to also set
* MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
* tables.
*
diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h
index bdc750eb24..e4a1ed81cf 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecp.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecp.h
@@ -154,6 +154,40 @@ typedef struct mbedtls_ecp_point
}
mbedtls_ecp_point;
+/* Determine the minimum safe value of MBEDTLS_ECP_MAX_BITS. */
+#if !defined(MBEDTLS_ECP_C)
+#define MBEDTLS_ECP_MAX_BITS_MIN 0
+/* Note: the curves must be listed in DECREASING size! */
+#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 521
+#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 512
+#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 448
+#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 384
+#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 384
+#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 256
+#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 256
+#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 256
+#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 255
+#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 225 // n is slightly above 2^224
+#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 224
+#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 192
+#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 192
+#else
+#error "MBEDTLS_ECP_C enabled, but no curve?"
+#endif
+
#if !defined(MBEDTLS_ECP_ALT)
/*
* default mbed TLS elliptic curve arithmetic implementation
@@ -228,7 +262,13 @@ mbedtls_ecp_group;
* \{
*/
-#if !defined(MBEDTLS_ECP_MAX_BITS)
+#if defined(MBEDTLS_ECP_MAX_BITS)
+
+#if MBEDTLS_ECP_MAX_BITS < MBEDTLS_ECP_MAX_BITS_MIN
+#error "MBEDTLS_ECP_MAX_BITS is smaller than the largest supported curve"
+#endif
+
+#else
/**
* The maximum size of the groups, that is, of \c N and \c P.
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/padlock.h b/thirdparty/mbedtls/include/mbedtls/padlock.h
index d8246e2cd0..0e4a6bbf69 100644
--- a/thirdparty/mbedtls/include/mbedtls/padlock.h
+++ b/thirdparty/mbedtls/include/mbedtls/padlock.h
@@ -98,7 +98,7 @@ extern "C" {
*
* \param feature The feature to detect
*
- * \return 1 if CPU has support for the feature, 0 otherwise
+ * \return non-zero if CPU has support for the feature, 0 otherwise
*/
int mbedtls_padlock_has_support( int feature );
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h
index fe33ac8d57..0abeb430e4 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl.h
@@ -2237,7 +2237,7 @@ void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf,
#if defined(MBEDTLS_ECP_C)
/**
* \brief Set the allowed curves in order of preference.
- * (Default: all defined curves.)
+ * (Default: all defined curves in order of decreasing size.)
*
* On server: this only affects selection of the ECDHE curve;
* the curves used for ECDH and ECDSA are determined by the
@@ -2269,7 +2269,9 @@ void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf,
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
/**
* \brief Set the allowed hashes for signatures during the handshake.
- * (Default: all available hashes except MD5.)
+ * (Default: all SHA-2 hashes, largest first. Also SHA-1 if
+ * the compile-time option
+ * `MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE` is enabled.)
*
* \note This only affects which hashes are offered and can be used
* for signatures during the handshake. Hashes for message
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
index a10a434138..a83f5e6662 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
@@ -124,7 +124,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx );
* Recommended value: 86400 (one day).
*
* \note It is highly recommended to select a cipher that is at
- * least as strong as the the strongest ciphersuite
+ * least as strong as the strongest ciphersuite
* supported. Usually that means a 256-bit key.
*
* \note The lifetime of the keys is twice the lifetime of tickets.
diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h
index bd5c730c1d..49cbeb003a 100644
--- a/thirdparty/mbedtls/include/mbedtls/version.h
+++ b/thirdparty/mbedtls/include/mbedtls/version.h
@@ -65,16 +65,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 16
-#define MBEDTLS_VERSION_PATCH 10
+#define MBEDTLS_VERSION_PATCH 11
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x02100A00
-#define MBEDTLS_VERSION_STRING "2.16.10"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.10"
+#define MBEDTLS_VERSION_NUMBER 0x02100B00
+#define MBEDTLS_VERSION_STRING "2.16.11"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.11"
#if defined(MBEDTLS_VERSION_C)
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
index c38e0c0556..30da1909b7 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
@@ -229,12 +229,21 @@ typedef void mbedtls_x509_crt_restart_ctx;
/**
* Default security profile. Should provide a good balance between security
* and compatibility with current deployments.
+ *
+ * This profile permits:
+ * - SHA2 hashes.
+ * - All supported elliptic curves.
+ * - RSA with 2048 bits and above.
+ *
+ * New minor versions of Mbed TLS may extend this profile, for example if
+ * new curves are added to the library. New minor versions of Mbed TLS will
+ * not reduce this profile unless serious security concerns require it.
*/
extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default;
/**
* Expected next default profile. Recommended for new deployments.
- * Currently targets a 128-bit security level, except for RSA-2048.
+ * Currently targets a 128-bit security level, except for allowing RSA-2048.
*/
extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next;
diff --git a/thirdparty/mbedtls/library/aria.c b/thirdparty/mbedtls/library/aria.c
index ef0392f658..50ccb91c70 100644
--- a/thirdparty/mbedtls/library/aria.c
+++ b/thirdparty/mbedtls/library/aria.c
@@ -952,7 +952,7 @@ static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext
{ \
if( verbose ) \
mbedtls_printf( "failed\n" ); \
- return( 1 ); \
+ goto exit; \
} else { \
if( verbose ) \
mbedtls_printf( "passed\n" ); \
@@ -966,6 +966,7 @@ int mbedtls_aria_self_test( int verbose )
int i;
uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE];
mbedtls_aria_context ctx;
+ int ret = 1;
#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR))
size_t j;
@@ -977,6 +978,8 @@ int mbedtls_aria_self_test( int verbose )
uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE];
#endif
+ mbedtls_aria_init( &ctx );
+
/*
* Test set 1
*/
@@ -1096,7 +1099,11 @@ int mbedtls_aria_self_test( int verbose )
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
- return( 0 );
+ ret = 0;
+
+exit:
+ mbedtls_aria_free( &ctx );
+ return( ret );
}
#endif /* MBEDTLS_SELF_TEST */
diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c
index f133f6c13c..540f7523b5 100644
--- a/thirdparty/mbedtls/library/bignum.c
+++ b/thirdparty/mbedtls/library/bignum.c
@@ -267,6 +267,36 @@ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
memcpy( Y, &T, sizeof( mbedtls_mpi ) );
}
+/**
+ * Select between two sign values in constant-time.
+ *
+ * This is functionally equivalent to second ? a : b but uses only bit
+ * operations in order to avoid branches.
+ *
+ * \param[in] a The first sign; must be either +1 or -1.
+ * \param[in] b The second sign; must be either +1 or -1.
+ * \param[in] second Must be either 1 (return b) or 0 (return a).
+ *
+ * \return The selected sign value.
+ */
+static int mpi_safe_cond_select_sign( int a, int b, unsigned char second )
+{
+ /* In order to avoid questions about what we can reasonnably assume about
+ * the representations of signed integers, move everything to unsigned
+ * by taking advantage of the fact that a and b are either +1 or -1. */
+ unsigned ua = a + 1;
+ unsigned ub = b + 1;
+
+ /* second was 0 or 1, mask is 0 or 2 as are ua and ub */
+ const unsigned mask = second << 1;
+
+ /* select ua or ub */
+ unsigned ur = ( ua & ~mask ) | ( ub & mask );
+
+ /* ur is now 0 or 2, convert back to -1 or +1 */
+ return( (int) ur - 1 );
+}
+
/*
* Conditionally assign dest = src, without leaking information
* about whether the assignment was made or not.
@@ -279,8 +309,23 @@ static void mpi_safe_cond_assign( size_t n,
unsigned char assign )
{
size_t i;
+
+ /* MSVC has a warning about unary minus on unsigned integer types,
+ * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+ /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
+ const mbedtls_mpi_uint mask = -assign;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
for( i = 0; i < n; i++ )
- dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
+ dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
}
/*
@@ -292,20 +337,34 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned
{
int ret = 0;
size_t i;
+ mbedtls_mpi_uint limb_mask;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
+ /* MSVC has a warning about unary minus on unsigned integer types,
+ * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
/* make sure assign is 0 or 1 in a time-constant manner */
- assign = (assign | (unsigned char)-assign) >> 7;
+ assign = (assign | (unsigned char)-assign) >> (sizeof( assign ) * 8 - 1);
+ /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
+ limb_mask = -assign;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
- X->s = X->s * ( 1 - assign ) + Y->s * assign;
+ X->s = mpi_safe_cond_select_sign( X->s, Y->s, assign );
mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
for( i = Y->n; i < X->n; i++ )
- X->p[i] *= ( 1 - assign );
+ X->p[i] &= ~limb_mask;
cleanup:
return( ret );
@@ -321,6 +380,7 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char sw
{
int ret, s;
size_t i;
+ mbedtls_mpi_uint limb_mask;
mbedtls_mpi_uint tmp;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
@@ -328,22 +388,35 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char sw
if( X == Y )
return( 0 );
+ /* MSVC has a warning about unary minus on unsigned integer types,
+ * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
/* make sure swap is 0 or 1 in a time-constant manner */
- swap = (swap | (unsigned char)-swap) >> 7;
+ swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
+ /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
+ limb_mask = -swap;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
s = X->s;
- X->s = X->s * ( 1 - swap ) + Y->s * swap;
- Y->s = Y->s * ( 1 - swap ) + s * swap;
+ X->s = mpi_safe_cond_select_sign( X->s, Y->s, swap );
+ Y->s = mpi_safe_cond_select_sign( Y->s, s, swap );
for( i = 0; i < X->n; i++ )
{
tmp = X->p[i];
- X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
- Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
+ X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
+ Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
}
cleanup:
@@ -500,6 +573,7 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
{
int ret;
size_t i, j, slen, n;
+ int sign = 1;
mbedtls_mpi_uint d;
mbedtls_mpi T;
MPI_VALIDATE_RET( X != NULL );
@@ -510,6 +584,12 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
mbedtls_mpi_init( &T );
+ if( s[0] == '-' )
+ {
+ ++s;
+ sign = -1;
+ }
+
slen = strlen( s );
if( radix == 16 )
@@ -524,12 +604,6 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
for( i = slen, j = 0; i > 0; i--, j++ )
{
- if( i == 1 && s[i - 1] == '-' )
- {
- X->s = -1;
- break;
- }
-
MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
}
@@ -540,26 +614,15 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
for( i = 0; i < slen; i++ )
{
- if( i == 0 && s[i] == '-' )
- {
- X->s = -1;
- continue;
- }
-
MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
-
- if( X->s == 1 )
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
- }
- else
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
- }
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
}
}
+ if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
+ X->s = -1;
+
cleanup:
mbedtls_mpi_free( &T );
@@ -1570,6 +1633,7 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
int ret;
size_t i, j;
mbedtls_mpi TA, TB;
+ int result_is_zero = 0;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
@@ -1582,10 +1646,14 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
for( i = A->n; i > 0; i-- )
if( A->p[i - 1] != 0 )
break;
+ if( i == 0 )
+ result_is_zero = 1;
for( j = B->n; j > 0; j-- )
if( B->p[j - 1] != 0 )
break;
+ if( j == 0 )
+ result_is_zero = 1;
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
@@ -1593,7 +1661,14 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
for( ; j > 0; j-- )
mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
- X->s = A->s * B->s;
+ /* If the result is 0, we don't shortcut the operation, which reduces
+ * but does not eliminate side channels leaking the zero-ness. We do
+ * need to take care to set the sign bit properly since the library does
+ * not fully support an MPI object with a value of 0 and s == -1. */
+ if( result_is_zero )
+ X->s = 1;
+ else
+ X->s = A->s * B->s;
cleanup:
@@ -2042,6 +2117,72 @@ static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
}
/*
+ * Constant-flow boolean "equal" comparison:
+ * return x == y
+ *
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations - it can be used in conjunction with
+ * mbedtls_ssl_cf_mask_from_bit().
+ *
+ * This function is implemented without using comparison operators, as those
+ * might be translated to branches by some compilers on some platforms.
+ */
+static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
+{
+ /* diff = 0 if x == y, non-zero otherwise */
+ const size_t diff = x ^ y;
+
+ /* MSVC has a warning about unary minus on unsigned integer types,
+ * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+ /* diff_msb's most significant bit is equal to x != y */
+ const size_t diff_msb = ( diff | (size_t) -diff );
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+ /* diff1 = (x != y) ? 1 : 0 */
+ const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
+
+ return( 1 ^ diff1 );
+}
+
+/**
+ * Select an MPI from a table without leaking the index.
+ *
+ * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
+ * reads the entire table in order to avoid leaking the value of idx to an
+ * attacker able to observe memory access patterns.
+ *
+ * \param[out] R Where to write the selected MPI.
+ * \param[in] T The table to read from.
+ * \param[in] T_size The number of elements in the table.
+ * \param[in] idx The index of the element to select;
+ * this must satisfy 0 <= idx < T_size.
+ *
+ * \return \c 0 on success, or a negative error code.
+ */
+static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
+{
+ int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+ size_t i;
+
+ for( i = 0; i < T_size; i++ )
+ {
+ MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
+ (unsigned char) mbedtls_mpi_cf_bool_eq( i, idx ) ) );
+ }
+
+cleanup:
+ return( ret );
+}
+
+/*
* Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
*/
int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
@@ -2053,7 +2194,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
size_t i, j, nblimbs;
size_t bufsize, nbits;
mbedtls_mpi_uint ei, mm, state;
- mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
+ mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
int neg;
MPI_VALIDATE_RET( X != NULL );
@@ -2077,6 +2218,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
mpi_montg_init( &mm, N );
mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
mbedtls_mpi_init( &Apos );
+ mbedtls_mpi_init( &WW );
memset( W, 0, sizeof( W ) );
i = mbedtls_mpi_bitlen( E );
@@ -2090,6 +2232,11 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
#endif
j = N->n + 1;
+ /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
+ * and mpi_montred() calls later. Here we ensure that W[1] and X are
+ * large enough, and later we'll grow other W[i] to the same length.
+ * They must not be shrunk midway through this function!
+ */
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
@@ -2127,6 +2274,10 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
else
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
+ /* Re-grow W[1] if necessary. This should be only necessary in one corner
+ * case: when A == 0 represented with A.n == 0, mbedtls_mpi_copy shrinks
+ * W[1] to 0 limbs. */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n +1 ) );
mpi_montmul( &W[1], &RR, N, mm, &T );
@@ -2217,7 +2368,8 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
/*
* X = X * W[wbits] R^-1 mod N
*/
- mpi_montmul( X, &W[wbits], N, mm, &T );
+ MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
+ mpi_montmul( X, &WW, N, mm, &T );
state--;
nbits = 0;
@@ -2255,6 +2407,7 @@ cleanup:
mbedtls_mpi_free( &W[i] );
mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
+ mbedtls_mpi_free( &WW );
if( _RR == NULL || _RR->p == NULL )
mbedtls_mpi_free( &RR );
@@ -2283,6 +2436,16 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
lz = mbedtls_mpi_lsb( &TA );
lzt = mbedtls_mpi_lsb( &TB );
+ /* The loop below gives the correct result when A==0 but not when B==0.
+ * So have a special case for B==0. Leverage the fact that we just
+ * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
+ * slightly more efficient than cmp_int(). */
+ if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
+ {
+ ret = mbedtls_mpi_copy( G, A );
+ goto cleanup;
+ }
+
if( lzt < lz )
lz = lzt;
@@ -2291,11 +2454,52 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
TA.s = TB.s = 1;
+ /* We mostly follow the procedure described in HAC 14.54, but with some
+ * minor differences:
+ * - Sequences of multiplications or divisions by 2 are grouped into a
+ * single shift operation.
+ * - The procedure in HAC assumes that 0 < TB <= TA.
+ * - The condition TB <= TA is not actually necessary for correctness.
+ * TA and TB have symmetric roles except for the loop termination
+ * condition, and the shifts at the beginning of the loop body
+ * remove any significance from the ordering of TA vs TB before
+ * the shifts.
+ * - If TA = 0, the loop goes through 0 iterations and the result is
+ * correctly TB.
+ * - The case TB = 0 was short-circuited above.
+ *
+ * For the correctness proof below, decompose the original values of
+ * A and B as
+ * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
+ * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
+ * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
+ * and gcd(A',B') is odd or 0.
+ *
+ * At the beginning, we have TA = |A|/2^a and TB = |B|/2^b.
+ * The code maintains the following invariant:
+ * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
+ */
+
+ /* Proof that the loop terminates:
+ * At each iteration, either the right-shift by 1 is made on a nonzero
+ * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
+ * by at least 1, or the right-shift by 1 is made on zero and then
+ * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
+ * since in that case TB is calculated from TB-TA with the condition TB>TA).
+ */
while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
{
+ /* Divisions by 2 preserve the invariant (I). */
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
+ /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
+ * TA-TB is even so the division by 2 has an integer result.
+ * Invariant (I) is preserved since any odd divisor of both TA and TB
+ * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
+ * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
+ * divides TA.
+ */
if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
@@ -2306,8 +2510,18 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
}
+ /* Note that one of TA or TB is still odd. */
}
+ /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
+ * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
+ * - If there was at least one loop iteration, then one of TA or TB is odd,
+ * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
+ * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
+ * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
+ * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
+ */
+
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
diff --git a/thirdparty/mbedtls/library/camellia.c b/thirdparty/mbedtls/library/camellia.c
index 40d62121bf..6cf265e578 100644
--- a/thirdparty/mbedtls/library/camellia.c
+++ b/thirdparty/mbedtls/library/camellia.c
@@ -973,9 +973,11 @@ int mbedtls_camellia_self_test( int verbose )
unsigned char nonce_counter[16];
unsigned char stream_block[16];
#endif
+ int ret = 1;
mbedtls_camellia_context ctx;
+ mbedtls_camellia_init( &ctx );
memset( key, 0, 32 );
for( j = 0; j < 6; j++ ) {
@@ -1005,8 +1007,7 @@ int mbedtls_camellia_self_test( int verbose )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
-
- return( 1 );
+ goto exit;
}
}
@@ -1058,8 +1059,7 @@ int mbedtls_camellia_self_test( int verbose )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
-
- return( 1 );
+ goto exit;
}
}
@@ -1102,8 +1102,7 @@ int mbedtls_camellia_self_test( int verbose )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
-
- return( 1 );
+ goto exit;
}
}
else
@@ -1118,8 +1117,7 @@ int mbedtls_camellia_self_test( int verbose )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
-
- return( 1 );
+ goto exit;
}
}
@@ -1131,7 +1129,11 @@ int mbedtls_camellia_self_test( int verbose )
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
- return( 0 );
+ ret = 0;
+
+exit:
+ mbedtls_camellia_free( &ctx );
+ return( ret );
}
#endif /* MBEDTLS_SELF_TEST */
diff --git a/thirdparty/mbedtls/library/debug.c b/thirdparty/mbedtls/library/debug.c
index 5f06d0da13..9caa361d44 100644
--- a/thirdparty/mbedtls/library/debug.c
+++ b/thirdparty/mbedtls/library/debug.c
@@ -261,8 +261,8 @@ void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
const char *text, const mbedtls_mpi *X )
{
char str[DEBUG_BUF_SIZE];
- int j, k, zeros = 1;
- size_t i, n, idx = 0;
+ size_t bitlen;
+ size_t idx = 0;
if( NULL == ssl ||
NULL == ssl->conf ||
@@ -273,55 +273,43 @@ void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
return;
}
- for( n = X->n - 1; n > 0; n-- )
- if( X->p[n] != 0 )
- break;
-
- for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
- if( ( ( X->p[n] >> j ) & 1 ) != 0 )
- break;
-
- mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
- text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
+ bitlen = mbedtls_mpi_bitlen( X );
+ mbedtls_snprintf( str, sizeof( str ), "value of '%s' (%u bits) is:\n",
+ text, (unsigned) bitlen );
debug_send_line( ssl, level, file, line, str );
- idx = 0;
- for( i = n + 1, j = 0; i > 0; i-- )
+ if( bitlen == 0 )
{
- if( zeros && X->p[i - 1] == 0 )
- continue;
-
- for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
+ str[0] = ' '; str[1] = '0'; str[2] = '0';
+ idx = 3;
+ }
+ else
+ {
+ int n;
+ for( n = (int) ( ( bitlen - 1 ) / 8 ); n >= 0; n-- )
{
- if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
- continue;
- else
- zeros = 0;
-
- if( j % 16 == 0 )
+ size_t limb_offset = n / sizeof( mbedtls_mpi_uint );
+ size_t offset_in_limb = n % sizeof( mbedtls_mpi_uint );
+ unsigned char octet =
+ ( X->p[limb_offset] >> ( offset_in_limb * 8 ) ) & 0xff;
+ mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", octet );
+ idx += 3;
+ /* Wrap lines after 16 octets that each take 3 columns */
+ if( idx >= 3 * 16 )
{
- if( j > 0 )
- {
- mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
- debug_send_line( ssl, level, file, line, str );
- idx = 0;
- }
+ mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
+ debug_send_line( ssl, level, file, line, str );
+ idx = 0;
}
-
- idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int)
- ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
-
- j++;
}
-
}
- if( zeros == 1 )
- idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" );
-
- mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
- debug_send_line( ssl, level, file, line, str );
+ if( idx != 0 )
+ {
+ mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
+ debug_send_line( ssl, level, file, line, str );
+ }
}
#endif /* MBEDTLS_BIGNUM_C */
diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c
index d652cf0ac9..535b698ce6 100644
--- a/thirdparty/mbedtls/library/dhm.c
+++ b/thirdparty/mbedtls/library/dhm.c
@@ -130,22 +130,21 @@ static int dhm_read_bignum( mbedtls_mpi *X,
*/
static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
{
- mbedtls_mpi L, U;
+ mbedtls_mpi U;
int ret = 0;
- mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
+ mbedtls_mpi_init( &U );
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
- if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
+ if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
{
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
cleanup:
- mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
+ mbedtls_mpi_free( &U );
return( ret );
}
@@ -181,38 +180,54 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
}
/*
- * Setup and write the ServerKeyExchange parameters
+ * Pick a random R in the range [2, M-2] for blinding or key generation.
*/
-int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
- unsigned char *output, size_t *olen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret, count = 0;
- size_t n1, n2, n3;
- unsigned char *p;
- DHM_VALIDATE_RET( ctx != NULL );
- DHM_VALIDATE_RET( output != NULL );
- DHM_VALIDATE_RET( olen != NULL );
- DHM_VALIDATE_RET( f_rng != NULL );
+ int ret, count;
+ size_t m_size = mbedtls_mpi_size( M );
+ size_t m_bitlen = mbedtls_mpi_bitlen( M );
+
+ count = 0;
+ do
+ {
+ if( count++ > 30 )
+ return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, m_size, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, ( m_size * 8 ) - m_bitlen ) );
+ }
+ while( dhm_check_range( R, M ) != 0 );
+
+cleanup:
+ return( ret );
+}
+
+static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret = 0;
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+ if( x_size < 0 )
+ return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
- /*
- * Generate X as large as possible ( < P )
- */
- do
+ if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
-
- if( count++ > 10 )
+ }
+ else
+ {
+ /* Generate X as large as possible ( <= P - 2 ) */
+ ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
+ if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
+ if( ret != 0 )
+ return( ret );
}
- while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
/*
* Calculate GX = G^X mod P
@@ -223,8 +238,33 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
return( ret );
+cleanup:
+ return( ret );
+}
+
+/*
+ * Setup and write the ServerKeyExchange parameters
+ */
+int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
+ unsigned char *output, size_t *olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ size_t n1, n2, n3;
+ unsigned char *p;
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( output != NULL );
+ DHM_VALIDATE_RET( olen != NULL );
+ DHM_VALIDATE_RET( f_rng != NULL );
+
+ ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
+ if( ret != 0 )
+ goto cleanup;
+
/*
- * export P, G, GX
+ * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
+ * not required". We omit leading zeros for compactness.
*/
#define DHM_MPI_EXPORT( X, n ) \
do { \
@@ -250,11 +290,9 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
ctx->len = n1;
cleanup:
-
- if( ret != 0 )
+ if( ret != 0 && ret > -128 )
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
-
- return( 0 );
+ return( ret );
}
/*
@@ -306,7 +344,7 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret, count = 0;
+ int ret;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( f_rng != NULL );
@@ -314,62 +352,18 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
if( olen < 1 || olen > ctx->len )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
- if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
- return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
-
- /*
- * generate X and calculate GX = G^X mod P
- */
- do
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
-
- if( count++ > 10 )
- return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
- }
- while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
-
- MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
- &ctx->P , &ctx->RP ) );
-
- if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
- return( ret );
+ ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
+ if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
+ return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
+ if( ret != 0 )
+ goto cleanup;
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
cleanup:
-
- if( ret != 0 )
+ if( ret != 0 && ret > -128 )
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
- return( 0 );
-}
-
-/*
- * Pick a random R in the range [2, M) for blinding purposes
- */
-static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
-{
- int ret, count;
-
- count = 0;
- do
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
-
- if( count++ > 10 )
- return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
- }
- while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
-
-cleanup:
return( ret );
}
@@ -420,7 +414,7 @@ static int dhm_update_blinding( mbedtls_dhm_context *ctx,
* We need to generate blinding values from scratch
*/
- /* Vi = random( 2, P-1 ) */
+ /* Vi = random( 2, P-2 ) */
MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
/* Vf = Vi^-X mod P
@@ -484,8 +478,9 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
}
+ /* Output the secret without any leading zero byte. This is mandatory
+ * for TLS per RFC 5246 §8.1.2. */
*olen = mbedtls_mpi_size( &ctx->K );
-
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
cleanup:
diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c
index fe41b4128a..a7486c198a 100644
--- a/thirdparty/mbedtls/library/ecp.c
+++ b/thirdparty/mbedtls/library/ecp.c
@@ -106,6 +106,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/threading.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/bn_mul.h"
#include <string.h>
@@ -1738,18 +1739,17 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
/* Generate l such that 1 < l < p */
do
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
-
- if( count++ > 10 )
+ if( count++ > 30 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
}
- while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
+ while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
+ ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
/* Z = l * Z */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z );
@@ -2505,7 +2505,7 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
if( mbedtls_internal_ecp_grp_capable( grp ) )
- return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
+ return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ) );
#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
p_size = ( grp->pbits + 7 ) / 8;
@@ -2514,18 +2514,17 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
/* Generate l such that 1 < l < p */
do
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
-
- if( count++ > 10 )
+ if( count++ > 30 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
}
- while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
+ while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
+ ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z );
@@ -2970,6 +2969,97 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
}
#if defined(ECP_MONTGOMERY)
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)}
+#define ECP_MPI_INIT_ARRAY(x) \
+ ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
+/*
+ * Constants for the two points other than 0, 1, -1 (mod p) in
+ * https://cr.yp.to/ecdh.html#validate
+ * See ecp_check_pubkey_x25519().
+ */
+static const mbedtls_mpi_uint x25519_bad_point_1[] = {
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 ),
+};
+static const mbedtls_mpi_uint x25519_bad_point_2[] = {
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 ),
+};
+static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY(
+ x25519_bad_point_1 );
+static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY(
+ x25519_bad_point_2 );
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+
+/*
+ * Check that the input point is not one of the low-order points.
+ * This is recommended by the "May the Fourth" paper:
+ * https://eprint.iacr.org/2017/806.pdf
+ * Those points are never sent by an honest peer.
+ */
+static int ecp_check_bad_points_mx( const mbedtls_mpi *X, const mbedtls_mpi *P,
+ const mbedtls_ecp_group_id grp_id )
+{
+ int ret;
+ mbedtls_mpi XmP;
+
+ mbedtls_mpi_init( &XmP );
+
+ /* Reduce X mod P so that we only need to check values less than P.
+ * We know X < 2^256 so we can proceed by subtraction. */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &XmP, X ) );
+ while( mbedtls_mpi_cmp_mpi( &XmP, P ) >= 0 )
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &XmP, &XmP, P ) );
+
+ /* Check against the known bad values that are less than P. For Curve448
+ * these are 0, 1 and -1. For Curve25519 we check the values less than P
+ * from the following list: https://cr.yp.to/ecdh.html#validate */
+ if( mbedtls_mpi_cmp_int( &XmP, 1 ) <= 0 ) /* takes care of 0 and 1 */
+ {
+ ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+ goto cleanup;
+ }
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+ if( grp_id == MBEDTLS_ECP_DP_CURVE25519 )
+ {
+ if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_1 ) == 0 )
+ {
+ ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+ goto cleanup;
+ }
+
+ if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_2 ) == 0 )
+ {
+ ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+ goto cleanup;
+ }
+ }
+#else
+ (void) grp_id;
+#endif
+
+ /* Final check: check if XmP + 1 is P (final because it changes XmP!) */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &XmP, &XmP, 1 ) );
+ if( mbedtls_mpi_cmp_mpi( &XmP, P ) == 0 )
+ {
+ ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ mbedtls_mpi_free( &XmP );
+
+ return( ret );
+}
+
/*
* Check validity of a public key for Montgomery curves with x-only schemes
*/
@@ -2981,7 +3071,13 @@ static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_
if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
return( MBEDTLS_ERR_ECP_INVALID_KEY );
- return( 0 );
+ /* Implicit in all standards (as they don't consider negative numbers):
+ * X must be non-negative. This is normally ensured by the way it's
+ * encoded for transmission, but let's be extra sure. */
+ if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 )
+ return( MBEDTLS_ERR_ECP_INVALID_KEY );
+
+ return( ecp_check_bad_points_mx( &pt->X, &grp->P, grp->id ) );
}
#endif /* ECP_MONTGOMERY */
@@ -3059,6 +3155,11 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
{
int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
size_t n_size;
+#if defined(ECP_SHORTWEIERSTRASS)
+ mbedtls_mpi one;
+
+ mbedtls_mpi_init( &one );
+#endif
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( d != NULL );
@@ -3099,7 +3200,10 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
{
/* SEC1 3.2.1: Generate d such that 1 <= n < N */
int count = 0;
- unsigned cmp = 0;
+ unsigned lt_lower = 1, lt_upper = 0;
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &one, grp->N.n ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
/*
* Match the procedure given in RFC 6979 (deterministic ECDSA):
@@ -3123,19 +3227,22 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
* such as secp224k1 are actually very close to the worst case.
*/
if( ++count > 30 )
- return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
-
- ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
- if( ret != 0 )
{
+ ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( d, &grp->N, &lt_upper ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( d, &one, &lt_lower ) );
}
- while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
+ while( lt_lower != 0 || lt_upper == 0 );
}
#endif /* ECP_SHORTWEIERSTRASS */
cleanup:
+#if defined(ECP_SHORTWEIERSTRASS)
+ mbedtls_mpi_free( &one );
+#endif
return( ret );
}
diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c
index b04596b561..afa3b6324e 100644
--- a/thirdparty/mbedtls/library/ecp_curves.c
+++ b/thirdparty/mbedtls/library/ecp_curves.c
@@ -54,6 +54,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/bn_mul.h"
#include <string.h>
@@ -70,44 +71,10 @@
#define inline __inline
#endif
-/*
- * Conversion macros for embedded constants:
- * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2
- */
-#if defined(MBEDTLS_HAVE_INT32)
-
-#define BYTES_TO_T_UINT_4( a, b, c, d ) \
- ( (mbedtls_mpi_uint) (a) << 0 ) | \
- ( (mbedtls_mpi_uint) (b) << 8 ) | \
- ( (mbedtls_mpi_uint) (c) << 16 ) | \
- ( (mbedtls_mpi_uint) (d) << 24 )
-
-#define BYTES_TO_T_UINT_2( a, b ) \
- BYTES_TO_T_UINT_4( a, b, 0, 0 )
-
-#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
- BYTES_TO_T_UINT_4( a, b, c, d ), \
- BYTES_TO_T_UINT_4( e, f, g, h )
-
-#else /* 64-bits */
-
-#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
- ( (mbedtls_mpi_uint) (a) << 0 ) | \
- ( (mbedtls_mpi_uint) (b) << 8 ) | \
- ( (mbedtls_mpi_uint) (c) << 16 ) | \
- ( (mbedtls_mpi_uint) (d) << 24 ) | \
- ( (mbedtls_mpi_uint) (e) << 32 ) | \
- ( (mbedtls_mpi_uint) (f) << 40 ) | \
- ( (mbedtls_mpi_uint) (g) << 48 ) | \
- ( (mbedtls_mpi_uint) (h) << 56 )
+#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)}
-#define BYTES_TO_T_UINT_4( a, b, c, d ) \
- BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
-
-#define BYTES_TO_T_UINT_2( a, b ) \
- BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
-
-#endif /* bits in mbedtls_mpi_uint */
+#define ECP_MPI_INIT_ARRAY(x) \
+ ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
/*
* Note: the constants are in little-endian order
@@ -119,29 +86,29 @@
*/
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
static const mbedtls_mpi_uint secp192r1_p[] = {
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
static const mbedtls_mpi_uint secp192r1_b[] = {
- BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ),
- BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ),
- BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ),
};
static const mbedtls_mpi_uint secp192r1_gx[] = {
- BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ),
- BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ),
- BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ),
};
static const mbedtls_mpi_uint secp192r1_gy[] = {
- BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ),
- BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ),
- BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ),
};
static const mbedtls_mpi_uint secp192r1_n[] = {
- BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ),
- BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
@@ -150,34 +117,34 @@ static const mbedtls_mpi_uint secp192r1_n[] = {
*/
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
static const mbedtls_mpi_uint secp224r1_p[] = {
- BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
- BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
};
static const mbedtls_mpi_uint secp224r1_b[] = {
- BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ),
- BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ),
- BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ),
- BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ),
+ MBEDTLS_BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ),
};
static const mbedtls_mpi_uint secp224r1_gx[] = {
- BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ),
- BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ),
- BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ),
- BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ),
+ MBEDTLS_BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ),
};
static const mbedtls_mpi_uint secp224r1_gy[] = {
- BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ),
- BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ),
- BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ),
- BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ),
+ MBEDTLS_BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ),
};
static const mbedtls_mpi_uint secp224r1_n[] = {
- BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ),
- BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
};
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
@@ -186,34 +153,34 @@ static const mbedtls_mpi_uint secp224r1_n[] = {
*/
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
static const mbedtls_mpi_uint secp256r1_p[] = {
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
- BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
- BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
};
static const mbedtls_mpi_uint secp256r1_b[] = {
- BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ),
- BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ),
- BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ),
- BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ),
};
static const mbedtls_mpi_uint secp256r1_gx[] = {
- BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
- BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
- BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
- BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
};
static const mbedtls_mpi_uint secp256r1_gy[] = {
- BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
- BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
- BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
- BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
};
static const mbedtls_mpi_uint secp256r1_n[] = {
- BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ),
- BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
};
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
@@ -222,44 +189,44 @@ static const mbedtls_mpi_uint secp256r1_n[] = {
*/
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
static const mbedtls_mpi_uint secp384r1_p[] = {
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
- BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
static const mbedtls_mpi_uint secp384r1_b[] = {
- BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ),
- BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ),
- BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ),
- BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ),
- BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ),
- BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ),
};
static const mbedtls_mpi_uint secp384r1_gx[] = {
- BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ),
- BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ),
- BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ),
- BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ),
- BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ),
- BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ),
};
static const mbedtls_mpi_uint secp384r1_gy[] = {
- BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ),
- BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ),
- BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ),
- BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ),
- BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ),
- BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ),
};
static const mbedtls_mpi_uint secp384r1_n[] = {
- BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ),
- BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ),
- BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
@@ -268,154 +235,154 @@ static const mbedtls_mpi_uint secp384r1_n[] = {
*/
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
static const mbedtls_mpi_uint secp521r1_p[] = {
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
};
static const mbedtls_mpi_uint secp521r1_b[] = {
- BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ),
- BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ),
- BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ),
- BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ),
- BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ),
- BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ),
- BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ),
- BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ),
- BYTES_TO_T_UINT_2( 0x51, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x51, 0x00 ),
};
static const mbedtls_mpi_uint secp521r1_gx[] = {
- BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ),
- BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ),
- BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ),
- BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ),
- BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ),
- BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ),
- BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ),
- BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ),
- BYTES_TO_T_UINT_2( 0xC6, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0xC6, 0x00 ),
};
static const mbedtls_mpi_uint secp521r1_gy[] = {
- BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ),
- BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ),
- BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ),
- BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ),
- BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ),
- BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ),
- BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ),
- BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ),
- BYTES_TO_T_UINT_2( 0x18, 0x01 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x18, 0x01 ),
};
static const mbedtls_mpi_uint secp521r1_n[] = {
- BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ),
- BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ),
- BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ),
- BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ),
- BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
};
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
static const mbedtls_mpi_uint secp192k1_p[] = {
- BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
static const mbedtls_mpi_uint secp192k1_a[] = {
- BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
};
static const mbedtls_mpi_uint secp192k1_b[] = {
- BYTES_TO_T_UINT_2( 0x03, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x03, 0x00 ),
};
static const mbedtls_mpi_uint secp192k1_gx[] = {
- BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ),
- BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ),
- BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ),
};
static const mbedtls_mpi_uint secp192k1_gy[] = {
- BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ),
- BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ),
- BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ),
};
static const mbedtls_mpi_uint secp192k1_n[] = {
- BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ),
- BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
static const mbedtls_mpi_uint secp224k1_p[] = {
- BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
};
static const mbedtls_mpi_uint secp224k1_a[] = {
- BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
};
static const mbedtls_mpi_uint secp224k1_b[] = {
- BYTES_TO_T_UINT_2( 0x05, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x05, 0x00 ),
};
static const mbedtls_mpi_uint secp224k1_gx[] = {
- BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ),
- BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ),
- BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ),
- BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ),
+ MBEDTLS_BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ),
};
static const mbedtls_mpi_uint secp224k1_gy[] = {
- BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ),
- BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ),
- BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ),
- BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ),
+ MBEDTLS_BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ),
};
static const mbedtls_mpi_uint secp224k1_n[] = {
- BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ),
- BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ),
- BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
- BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ),
};
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
static const mbedtls_mpi_uint secp256k1_p[] = {
- BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
static const mbedtls_mpi_uint secp256k1_a[] = {
- BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
};
static const mbedtls_mpi_uint secp256k1_b[] = {
- BYTES_TO_T_UINT_2( 0x07, 0x00 ),
+ MBEDTLS_BYTES_TO_T_UINT_2( 0x07, 0x00 ),
};
static const mbedtls_mpi_uint secp256k1_gx[] = {
- BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ),
- BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ),
- BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ),
- BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ),
};
static const mbedtls_mpi_uint secp256k1_gy[] = {
- BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ),
- BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ),
- BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ),
- BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ),
};
static const mbedtls_mpi_uint secp256k1_n[] = {
- BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ),
- BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ),
- BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
- BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
};
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
@@ -424,40 +391,40 @@ static const mbedtls_mpi_uint secp256k1_n[] = {
*/
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
static const mbedtls_mpi_uint brainpoolP256r1_p[] = {
- BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ),
- BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ),
- BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
- BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
};
static const mbedtls_mpi_uint brainpoolP256r1_a[] = {
- BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ),
- BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ),
- BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ),
- BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ),
};
static const mbedtls_mpi_uint brainpoolP256r1_b[] = {
- BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ),
- BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ),
- BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ),
- BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ),
};
static const mbedtls_mpi_uint brainpoolP256r1_gx[] = {
- BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ),
- BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ),
- BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ),
- BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ),
};
static const mbedtls_mpi_uint brainpoolP256r1_gy[] = {
- BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ),
- BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ),
- BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ),
- BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ),
};
static const mbedtls_mpi_uint brainpoolP256r1_n[] = {
- BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ),
- BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ),
- BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
- BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
};
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
@@ -466,52 +433,52 @@ static const mbedtls_mpi_uint brainpoolP256r1_n[] = {
*/
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
static const mbedtls_mpi_uint brainpoolP384r1_p[] = {
- BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ),
- BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ),
- BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ),
- BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
- BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
- BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
};
static const mbedtls_mpi_uint brainpoolP384r1_a[] = {
- BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
- BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ),
- BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ),
- BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ),
- BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ),
- BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ),
};
static const mbedtls_mpi_uint brainpoolP384r1_b[] = {
- BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ),
- BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ),
- BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ),
- BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ),
- BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ),
- BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
};
static const mbedtls_mpi_uint brainpoolP384r1_gx[] = {
- BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ),
- BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ),
- BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ),
- BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ),
- BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ),
- BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ),
};
static const mbedtls_mpi_uint brainpoolP384r1_gy[] = {
- BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ),
- BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ),
- BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ),
- BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ),
- BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ),
- BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ),
};
static const mbedtls_mpi_uint brainpoolP384r1_n[] = {
- BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ),
- BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ),
- BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ),
- BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
- BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
- BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
};
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
@@ -520,64 +487,64 @@ static const mbedtls_mpi_uint brainpoolP384r1_n[] = {
*/
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
static const mbedtls_mpi_uint brainpoolP512r1_p[] = {
- BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ),
- BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ),
- BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ),
- BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ),
- BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
- BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
- BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
- BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
};
static const mbedtls_mpi_uint brainpoolP512r1_a[] = {
- BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ),
- BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ),
- BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ),
- BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ),
- BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ),
- BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ),
- BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ),
- BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ),
};
static const mbedtls_mpi_uint brainpoolP512r1_b[] = {
- BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ),
- BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ),
- BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ),
- BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ),
- BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ),
- BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ),
- BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ),
- BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ),
};
static const mbedtls_mpi_uint brainpoolP512r1_gx[] = {
- BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ),
- BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ),
- BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ),
- BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ),
- BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ),
- BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ),
- BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ),
- BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ),
};
static const mbedtls_mpi_uint brainpoolP512r1_gy[] = {
- BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ),
- BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ),
- BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ),
- BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ),
- BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ),
- BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ),
- BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ),
- BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ),
};
static const mbedtls_mpi_uint brainpoolP512r1_n[] = {
- BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ),
- BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ),
- BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ),
- BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ),
- BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
- BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
- BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
- BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
};
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
@@ -689,6 +656,13 @@ static int ecp_mod_p256k1( mbedtls_mpi * );
G ## _n, sizeof( G ## _n ) )
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+/* Constants used by ecp_use_curve25519() */
+static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42;
+static const unsigned char curve25519_part_of_n[] = {
+ 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6,
+ 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED,
+};
+
/*
* Specialized function for creating the Curve25519 group
*/
@@ -697,7 +671,7 @@ static int ecp_use_curve25519( mbedtls_ecp_group *grp )
int ret;
/* Actually ( A + 2 ) / 4 */
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve25519_a24 ) );
/* P = 2^255 - 19 */
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) );
@@ -706,8 +680,8 @@ static int ecp_use_curve25519( mbedtls_ecp_group *grp )
grp->pbits = mbedtls_mpi_bitlen( &grp->P );
/* N = 2^252 + 27742317777372353535851937790883648493 */
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16,
- "14DEF9DEA2F79CD65812631A5CF5D3ED" ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &grp->N,
+ curve25519_part_of_n, sizeof( curve25519_part_of_n ) ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) );
/* Y intentionally not set, since we use x/z coordinates.
@@ -728,6 +702,15 @@ cleanup:
#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+/* Constants used by ecp_use_curve448() */
+static const mbedtls_mpi_sint curve448_a24 = 0x98AA;
+static const unsigned char curve448_part_of_n[] = {
+ 0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24,
+ 0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93,
+ 0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC,
+ 0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D,
+};
+
/*
* Specialized function for creating the Curve448 group
*/
@@ -739,7 +722,7 @@ static int ecp_use_curve448( mbedtls_ecp_group *grp )
mbedtls_mpi_init( &Ns );
/* Actually ( A + 2 ) / 4 */
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve448_a24 ) );
/* P = 2^448 - 2^224 - 1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) );
@@ -757,8 +740,8 @@ static int ecp_use_curve448( mbedtls_ecp_group *grp )
/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16,
- "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &Ns,
+ curve448_part_of_n, sizeof( curve448_part_of_n ) ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) );
/* Actually, the required msb for private keys */
@@ -1048,13 +1031,13 @@ static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
/*
* If the result is negative, we get it in the form
- * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
+ * c * 2^bits + N, with c negative and N positive shorter than 'bits'
*/
static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits )
{
int ret;
- /* C = - c * 2^(bits + 32) */
+ /* C = - c * 2^bits */
#if !defined(MBEDTLS_HAVE_INT64)
((void) bits);
#else
@@ -1452,9 +1435,11 @@ cleanup:
static int ecp_mod_p192k1( mbedtls_mpi *N )
{
static mbedtls_mpi_uint Rp[] = {
- BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00 ) };
- return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) );
+ return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
+ 0 ) );
}
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
@@ -1466,12 +1451,14 @@ static int ecp_mod_p192k1( mbedtls_mpi *N )
static int ecp_mod_p224k1( mbedtls_mpi *N )
{
static mbedtls_mpi_uint Rp[] = {
- BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+ MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00 ) };
#if defined(MBEDTLS_HAVE_INT64)
return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) );
#else
- return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) );
+ return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
+ 0 ) );
#endif
}
@@ -1485,8 +1472,10 @@ static int ecp_mod_p224k1( mbedtls_mpi *N )
static int ecp_mod_p256k1( mbedtls_mpi *N )
{
static mbedtls_mpi_uint Rp[] = {
- BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
- return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) );
+ MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00 ) };
+ return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
+ 0 ) );
}
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c
index c5f414a010..9f1a32bdc1 100644
--- a/thirdparty/mbedtls/library/entropy.c
+++ b/thirdparty/mbedtls/library/entropy.c
@@ -494,14 +494,20 @@ int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
{
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
- FILE *f;
+ FILE *f = NULL;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
- if( ( f = fopen( path, "wb" ) ) == NULL )
- return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
-
if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
+ {
+ ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ goto exit;
+ }
+
+ if( ( f = fopen( path, "wb" ) ) == NULL )
+ {
+ ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
goto exit;
+ }
if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
{
@@ -514,7 +520,9 @@ int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *p
exit:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
- fclose( f );
+ if( f != NULL )
+ fclose( f );
+
return( ret );
}
diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c
index 671115f15f..1e701a5000 100644
--- a/thirdparty/mbedtls/library/net_sockets.c
+++ b/thirdparty/mbedtls/library/net_sockets.c
@@ -47,11 +47,15 @@
/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
* be set before config.h, which pulls in glibc's features.h indirectly.
* Harmless on other platforms. */
+#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
+#endif
#if defined(__NetBSD__)
+#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600 /* sockaddr_storage */
#endif
+#endif
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
@@ -163,6 +167,31 @@ static int net_prepare( void )
}
/*
+ * Return 0 if the file descriptor is valid, an error otherwise.
+ * If for_select != 0, check whether the file descriptor is within the range
+ * allowed for fd_set used for the FD_xxx macros and the select() function.
+ */
+static int check_fd( int fd, int for_select )
+{
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+ !defined(EFI32)
+ (void) for_select;
+#else
+ /* A limitation of select() is that it only works with file descriptors
+ * that are strictly less than FD_SETSIZE. This is a limitation of the
+ * fd_set type. Error out early, because attempting to call FD_SET on a
+ * large file descriptor is a buffer overflow on typical platforms. */
+ if( for_select && fd >= FD_SETSIZE )
+ return( MBEDTLS_ERR_NET_POLL_FAILED );
+#endif
+
+ return( 0 );
+}
+
+/*
* Initialize a context
*/
void mbedtls_net_init( mbedtls_net_context *ctx )
@@ -493,15 +522,9 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
int fd = ctx->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
-
- /* A limitation of select() is that it only works with file descriptors
- * that are strictly less than FD_SETSIZE. This is a limitation of the
- * fd_set type. Error out early, because attempting to call FD_SET on a
- * large file descriptor is a buffer overflow on typical platforms. */
- if( fd >= FD_SETSIZE )
- return( MBEDTLS_ERR_NET_POLL_FAILED );
+ ret = check_fd( fd, 1 );
+ if( ret != 0 )
+ return( ret );
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
@@ -580,8 +603,9 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
int ret;
int fd = ((mbedtls_net_context *) ctx)->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+ ret = check_fd( fd, 0 );
+ if( ret != 0 )
+ return( ret );
ret = (int) read( fd, buf, len );
@@ -619,15 +643,9 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
fd_set read_fds;
int fd = ((mbedtls_net_context *) ctx)->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
-
- /* A limitation of select() is that it only works with file descriptors
- * that are strictly less than FD_SETSIZE. This is a limitation of the
- * fd_set type. Error out early, because attempting to call FD_SET on a
- * large file descriptor is a buffer overflow on typical platforms. */
- if( fd >= FD_SETSIZE )
- return( MBEDTLS_ERR_NET_POLL_FAILED );
+ ret = check_fd( fd, 1 );
+ if( ret != 0 )
+ return( ret );
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );
@@ -667,8 +685,9 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
int ret;
int fd = ((mbedtls_net_context *) ctx)->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+ ret = check_fd( fd, 0 );
+ if( ret != 0 )
+ return( ret );
ret = (int) write( fd, buf, len );
diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c
index 8341ff1303..278b7e91ab 100644
--- a/thirdparty/mbedtls/library/nist_kw.c
+++ b/thirdparty/mbedtls/library/nist_kw.c
@@ -219,8 +219,6 @@ int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
- unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
- unsigned char *A = output;
*out_len = 0;
/*
@@ -296,6 +294,9 @@ int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
}
else
{
+ unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
+ unsigned char *A = output;
+
/*
* Do the wrapping function W, as defined in RFC 3394 section 2.2.1
*/
@@ -359,7 +360,7 @@ static int unwrap( mbedtls_nist_kw_context *ctx,
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
- unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+ unsigned char *R = NULL;
*out_len = 0;
if( semiblocks < MIN_SEMIBLOCKS_COUNT )
@@ -369,6 +370,7 @@ static int unwrap( mbedtls_nist_kw_context *ctx,
memcpy( A, input, KW_SEMIBLOCK_LENGTH );
memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+ R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
/* Calculate intermediate values */
for( t = s; t >= 1; t-- )
diff --git a/thirdparty/mbedtls/library/pk.c b/thirdparty/mbedtls/library/pk.c
index 81cfdbfe80..8998271b97 100644
--- a/thirdparty/mbedtls/library/pk.c
+++ b/thirdparty/mbedtls/library/pk.c
@@ -225,12 +225,15 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len
{
const mbedtls_md_info_t *md_info;
- if( *hash_len != 0 )
+ if( *hash_len != 0 && md_alg == MBEDTLS_MD_NONE )
return( 0 );
if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
return( -1 );
+ if ( *hash_len != 0 && *hash_len < mbedtls_md_get_size( md_info ) )
+ return ( -1 );
+
*hash_len = mbedtls_md_get_size( md_info );
return( 0 );
}
diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c
index e410f3aae1..2622351a42 100644
--- a/thirdparty/mbedtls/library/pkparse.c
+++ b/thirdparty/mbedtls/library/pkparse.c
@@ -1070,7 +1070,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret );
if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
- return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+ return( ret );
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c
index 090040e9ab..01df17a5f3 100644
--- a/thirdparty/mbedtls/library/ssl_ciphersuites.c
+++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c
@@ -918,13 +918,13 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
0 },
#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_SHA512_C)
{ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384",
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
-#endif /* MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_SHA512_C */
#endif /* MBEDTLS_GCM_C */
#endif /* MBEDTLS_CAMELLIA_C */
diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c
index bd7f28134d..b977e5b7b1 100644
--- a/thirdparty/mbedtls/library/ssl_cli.c
+++ b/thirdparty/mbedtls/library/ssl_cli.c
@@ -1318,7 +1318,7 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
mbedtls_ssl_send_alert_message(
ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
@@ -1365,7 +1365,7 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
mbedtls_ssl_send_alert_message(
ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
@@ -1391,7 +1391,7 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
mbedtls_ssl_send_alert_message(
ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
@@ -1416,7 +1416,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
mbedtls_ssl_send_alert_message(
ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
@@ -1522,7 +1522,7 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
mbedtls_ssl_send_alert_message(
ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
@@ -2209,6 +2209,7 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
unsigned char *end )
{
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ size_t dhm_actual_bitlen;
/*
* Ephemeral DH parameters:
@@ -2226,10 +2227,11 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
return( ret );
}
- if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen )
+ dhm_actual_bitlen = mbedtls_mpi_bitlen( &ssl->handshake->dhm_ctx.P );
+ if( dhm_actual_bitlen < ssl->conf->dhm_min_bitlen )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d",
- ssl->handshake->dhm_ctx.len * 8,
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %u < %u",
+ (unsigned) dhm_actual_bitlen,
ssl->conf->dhm_min_bitlen ) );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c
index c749a8611c..3c1e917598 100644
--- a/thirdparty/mbedtls/library/ssl_tls.c
+++ b/thirdparty/mbedtls/library/ssl_tls.c
@@ -1895,6 +1895,9 @@ int mbedtls_ssl_cf_hmac(
MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) );
}
+ /* The context needs to finish() before it starts() again */
+ MD_CHK( mbedtls_md_finish( ctx, aux_out ) );
+
/* Now compute HASH(okey + inner_hash) */
MD_CHK( mbedtls_md_starts( ctx ) );
MD_CHK( mbedtls_md_update( ctx, okey, block_size ) );
@@ -6364,8 +6367,6 @@ static void ssl_calc_finished_tls_sha256(
#if defined(MBEDTLS_SHA512_C)
-typedef int (*finish_sha384_t)(mbedtls_sha512_context*, unsigned char*);
-
static void ssl_calc_finished_tls_sha384(
mbedtls_ssl_context *ssl, unsigned char *buf, int from )
{
@@ -6373,12 +6374,6 @@ static void ssl_calc_finished_tls_sha384(
const char *sender;
mbedtls_sha512_context sha512;
unsigned char padbuf[48];
- /*
- * For SHA-384, we can save 16 bytes by keeping padbuf 48 bytes long.
- * However, to avoid stringop-overflow warning in gcc, we have to cast
- * mbedtls_sha512_finish_ret().
- */
- finish_sha384_t finish_sha384 = (finish_sha384_t)mbedtls_sha512_finish_ret;
mbedtls_ssl_session *session = ssl->session_negotiate;
if( !session )
@@ -6404,8 +6399,19 @@ static void ssl_calc_finished_tls_sha384(
sender = ( from == MBEDTLS_SSL_IS_CLIENT )
? "client finished"
: "server finished";
-
- finish_sha384( &sha512, padbuf );
+ /* mbedtls_sha512_finish_ret's output parameter is declared as a
+ * 64-byte buffer, but sice we're using SHA-384, we know that the
+ * output fits in 48 bytes. This is correct C, but GCC 11.1 warns
+ * about it.
+ */
+#if defined(__GNUC__) && __GNUC__ >= 11
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
+ mbedtls_sha512_finish_ret( &sha512, padbuf );
+#if defined(__GNUC__) && __GNUC__ >= 11
+#pragma GCC diagnostic pop
+#endif
ssl->handshake->tls_prf( session->master, 48, sender,
padbuf, 48, buf, len );
@@ -6678,7 +6684,7 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+ MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED );
}
diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c
index c458c25ff4..52f6de8fc0 100644
--- a/thirdparty/mbedtls/library/x509_crt.c
+++ b/thirdparty/mbedtls/library/x509_crt.c
@@ -129,9 +129,8 @@ typedef struct {
*/
#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
-/*
- * Default profile
- */
+/* Default profile. Do not remove items unless there are serious security
+ * concerns. */
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
{
#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
diff --git a/thirdparty/spirv-reflect/patches/specialization-constants.patch b/thirdparty/spirv-reflect/patches/specialization-constants.patch
new file mode 100644
index 0000000000..8ff1dcc2e5
--- /dev/null
+++ b/thirdparty/spirv-reflect/patches/specialization-constants.patch
@@ -0,0 +1,293 @@
+diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
+index 0fc979a8a4..3e3643717a 100644
+--- a/thirdparty/spirv-reflect/spirv_reflect.c
++++ b/thirdparty/spirv-reflect/spirv_reflect.c
+@@ -124,6 +124,9 @@ typedef struct Decorations {
+ NumberDecoration location;
+ NumberDecoration offset;
+ NumberDecoration uav_counter_buffer;
++// -- GODOT begin --
++ NumberDecoration specialization_constant;
++// -- GODOT end --
+ StringDecoration semantic;
+ uint32_t array_stride;
+ uint32_t matrix_stride;
+@@ -610,6 +613,9 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
+ p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
+ p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
+ p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
++// -- GODOT begin --
++ p_parser->nodes[i].decorations.specialization_constant.value = (SpvBuiltIn)INVALID_VALUE;
++// -- GODOT end --
+ }
+ // Mark source file id node
+ p_parser->source_file_id = (uint32_t)INVALID_VALUE;
+@@ -800,10 +806,16 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+ }
+ break;
+-
++// -- GODOT begin --
+ case SpvOpSpecConstantTrue:
+ case SpvOpSpecConstantFalse:
+- case SpvOpSpecConstant:
++ case SpvOpSpecConstant: {
++ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
++ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
++ p_node->is_type = true;
++ }
++ break;
++// -- GODOT end --
+ case SpvOpSpecConstantComposite:
+ case SpvOpSpecConstantOp: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
+@@ -1309,6 +1321,9 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
+ skip = true;
+ }
+ break;
++// -- GODOT begin --
++ case SpvDecorationSpecId:
++// -- GODOT end --
+ case SpvDecorationBlock:
+ case SpvDecorationBufferBlock:
+ case SpvDecorationColMajor:
+@@ -1441,7 +1456,14 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
+ p_target_decorations->input_attachment_index.word_offset = word_offset;
+ }
+ break;
+-
++// -- GODOT begin --
++ case SpvDecorationSpecId: {
++ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
++ CHECKED_READU32(p_parser, word_offset, p_target_decorations->specialization_constant.value);
++ p_target_decorations->specialization_constant.word_offset = word_offset;
++ }
++ break;
++// -- GODOT end --
+ case SpvReflectDecorationHlslCounterBufferGOOGLE: {
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
+@@ -1731,6 +1753,13 @@ static SpvReflectResult ParseType(
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;
+ }
+ break;
++// -- GODOT begin --
++ case SpvOpSpecConstantTrue:
++ case SpvOpSpecConstantFalse:
++ case SpvOpSpecConstant: {
++ }
++ break;
++// -- GODOT end --
+ }
+
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+@@ -3187,6 +3216,69 @@ static SpvReflectResult ParseExecutionModes(Parser* p_parser, SpvReflectShaderMo
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
++// -- GODOT begin --
++static SpvReflectResult ParseSpecializationConstants(Parser* p_parser, SpvReflectShaderModule* p_module)
++{
++ p_module->specialization_constant_count = 0;
++ p_module->specialization_constants = NULL;
++ for (size_t i = 0; i < p_parser->node_count; ++i) {
++ Node* p_node = &(p_parser->nodes[i]);
++ if (p_node->op == SpvOpSpecConstantTrue || p_node->op == SpvOpSpecConstantFalse || p_node->op == SpvOpSpecConstant) {
++ p_module->specialization_constant_count++;
++ }
++ }
++
++ if (p_module->specialization_constant_count == 0) {
++ return SPV_REFLECT_RESULT_SUCCESS;
++ }
++
++ p_module->specialization_constants = (SpvReflectSpecializationConstant*)calloc(p_module->specialization_constant_count, sizeof(SpvReflectSpecializationConstant));
++
++ uint32_t index = 0;
++
++ for (size_t i = 0; i < p_parser->node_count; ++i) {
++ Node* p_node = &(p_parser->nodes[i]);
++ switch(p_node->op) {
++ default: continue;
++ case SpvOpSpecConstantTrue: {
++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
++ p_module->specialization_constants[index].default_value.int_bool_value = 1;
++ } break;
++ case SpvOpSpecConstantFalse: {
++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
++ p_module->specialization_constants[index].default_value.int_bool_value = 0;
++ } break;
++ case SpvOpSpecConstant: {
++ SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;
++ uint32_t element_type_id = (uint32_t)INVALID_VALUE;
++ uint32_t default_value = 0;
++ IF_READU32(result, p_parser, p_node->word_offset + 1, element_type_id);
++ IF_READU32(result, p_parser, p_node->word_offset + 3, default_value);
++
++ Node* p_next_node = FindNode(p_parser, element_type_id);
++
++ if (p_next_node->op == SpvOpTypeInt) {
++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_INT;
++ } else if (p_next_node->op == SpvOpTypeFloat) {
++ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT;
++ } else {
++ return SPV_REFLECT_RESULT_ERROR_PARSE_FAILED;
++ }
++
++ p_module->specialization_constants[index].default_value.int_bool_value = default_value; //bits are the same for int and float
++ } break;
++ }
++
++ p_module->specialization_constants[index].name = p_node->name;
++ p_module->specialization_constants[index].constant_id = p_node->decorations.specialization_constant.value;
++ p_module->specialization_constants[index].spirv_id = p_node->result_id;
++ index++;
++ }
++
++ return SPV_REFLECT_RESULT_SUCCESS;
++}
++// -- GODOT end --
++
+ static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module)
+ {
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+@@ -3562,6 +3654,12 @@ SpvReflectResult spvReflectCreateShaderModule(
+ result = ParsePushConstantBlocks(&parser, p_module);
+ SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
+ }
++// -- GODOT begin --
++ if (result == SPV_REFLECT_RESULT_SUCCESS) {
++ result = ParseSpecializationConstants(&parser, p_module);
++ SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
++ }
++// -- GODOT end --
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseEntryPoints(&parser, p_module);
+ SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
+@@ -3691,6 +3789,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
+ SafeFree(p_entry->used_push_constants);
+ }
+ SafeFree(p_module->entry_points);
++// -- GODOT begin --
++ SafeFree(p_module->specialization_constants);
++// -- GODOT end --
+
+ // Push constants
+ for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
+@@ -3959,6 +4060,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
++// -- GODOT begin --
++SpvReflectResult spvReflectEnumerateSpecializationConstants(
++ const SpvReflectShaderModule* p_module,
++ uint32_t* p_count,
++ SpvReflectSpecializationConstant** pp_constants
++)
++{
++ if (IsNull(p_module)) {
++ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
++ }
++ if (IsNull(p_count)) {
++ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
++ }
++
++ if (IsNotNull(pp_constants)) {
++ if (*p_count != p_module->specialization_constant_count) {
++ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
++ }
++
++ for (uint32_t index = 0; index < *p_count; ++index) {
++ SpvReflectSpecializationConstant *p_const = &p_module->specialization_constants[index];
++ pp_constants[index] = p_const;
++ }
++ }
++ else {
++ *p_count = p_module->specialization_constant_count;
++ }
++
++ return SPV_REFLECT_RESULT_SUCCESS;
++}
++// -- GODOT end --
++
+ SpvReflectResult spvReflectEnumerateInputVariables(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
+index a5a956e9e8..21f8160770 100644
+--- a/thirdparty/spirv-reflect/spirv_reflect.h
++++ b/thirdparty/spirv-reflect/spirv_reflect.h
+@@ -292,6 +292,28 @@ typedef struct SpvReflectTypeDescription {
+ struct SpvReflectTypeDescription* members;
+ } SpvReflectTypeDescription;
+
++// -- GODOT begin --
++/*! @struct SpvReflectSpecializationConstant
++
++*/
++
++typedef enum SpvReflectSpecializationConstantType {
++ SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL = 0,
++ SPV_REFLECT_SPECIALIZATION_CONSTANT_INT = 1,
++ SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT = 2,
++} SpvReflectSpecializationConstantType;
++
++typedef struct SpvReflectSpecializationConstant {
++ const char* name;
++ uint32_t spirv_id;
++ uint32_t constant_id;
++ SpvReflectSpecializationConstantType constant_type;
++ union {
++ float float_value;
++ uint32_t int_bool_value;
++ } default_value;
++} SpvReflectSpecializationConstant;
++// -- GODOT end --
+
+ /*! @struct SpvReflectInterfaceVariable
+
+@@ -439,6 +461,10 @@ typedef struct SpvReflectShaderModule {
+ SpvReflectInterfaceVariable* interface_variables;
+ uint32_t push_constant_block_count;
+ SpvReflectBlockVariable* push_constant_blocks;
++ // -- GODOT begin --
++ uint32_t specialization_constant_count;
++ SpvReflectSpecializationConstant* specialization_constants;
++ // -- GODOT end --
+
+ struct Internal {
+ size_t spirv_size;
+@@ -694,6 +720,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
+ SpvReflectInterfaceVariable** pp_variables
+ );
+
++// -- GOODT begin --
++/*! @fn spvReflectEnumerateSpecializationConstants
++ @brief If the module contains multiple entry points, this will only get
++ the specialization constants for the first one.
++ @param p_module Pointer to an instance of SpvReflectShaderModule.
++ @param p_count If pp_constants is NULL, the module's specialization constant
++ count will be stored here.
++ If pp_variables is not NULL, *p_count must contain
++ the module's specialization constant count.
++ @param pp_variables If NULL, the module's specialization constant count will be
++ written to *p_count.
++ If non-NULL, pp_constants must point to an array with
++ *p_count entries, where pointers to the module's
++ specialization constants will be written. The caller must not
++ free the specialization constants written to this array.
++ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
++ Otherwise, the error code indicates the cause of the
++ failure.
++
++*/
++SpvReflectResult spvReflectEnumerateSpecializationConstants(
++ const SpvReflectShaderModule* p_module,
++ uint32_t* p_count,
++ SpvReflectSpecializationConstant** pp_constants
++);
++// -- GODOT end --
++
+ /*! @fn spvReflectEnumerateEntryPointInputVariables
+ @brief Enumerate the input variables for a given entry point.
+ @param entry_point The name of the entry point to get the input variables for.
diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
index 0fc979a8a4..8f614c8874 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.c
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
@@ -124,6 +124,9 @@ typedef struct Decorations {
NumberDecoration location;
NumberDecoration offset;
NumberDecoration uav_counter_buffer;
+// -- GODOT begin --
+ NumberDecoration specialization_constant;
+// -- GODOT end --
StringDecoration semantic;
uint32_t array_stride;
uint32_t matrix_stride;
@@ -610,6 +613,9 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
+// -- GODOT begin --
+ p_parser->nodes[i].decorations.specialization_constant.value = (SpvBuiltIn)INVALID_VALUE;
+// -- GODOT end --
}
// Mark source file id node
p_parser->source_file_id = (uint32_t)INVALID_VALUE;
@@ -800,10 +806,16 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
}
break;
-
+// -- GODOT begin --
case SpvOpSpecConstantTrue:
case SpvOpSpecConstantFalse:
- case SpvOpSpecConstant:
+ case SpvOpSpecConstant: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+ p_node->is_type = true;
+ }
+ break;
+// -- GODOT end --
case SpvOpSpecConstantComposite:
case SpvOpSpecConstantOp: {
CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
@@ -1309,6 +1321,9 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
skip = true;
}
break;
+// -- GODOT begin --
+ case SpvDecorationSpecId:
+// -- GODOT end --
case SpvDecorationBlock:
case SpvDecorationBufferBlock:
case SpvDecorationColMajor:
@@ -1441,7 +1456,14 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
p_target_decorations->input_attachment_index.word_offset = word_offset;
}
break;
-
+// -- GODOT begin --
+ case SpvDecorationSpecId: {
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->specialization_constant.value);
+ p_target_decorations->specialization_constant.word_offset = word_offset;
+ }
+ break;
+// -- GODOT end --
case SpvReflectDecorationHlslCounterBufferGOOGLE: {
uint32_t word_offset = p_node->word_offset + member_offset+ 3;
CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
@@ -1731,6 +1753,13 @@ static SpvReflectResult ParseType(
p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;
}
break;
+// -- GODOT begin --
+ case SpvOpSpecConstantTrue:
+ case SpvOpSpecConstantFalse:
+ case SpvOpSpecConstant: {
+ }
+ break;
+// -- GODOT end --
}
if (result == SPV_REFLECT_RESULT_SUCCESS) {
@@ -3187,6 +3216,69 @@ static SpvReflectResult ParseExecutionModes(Parser* p_parser, SpvReflectShaderMo
return SPV_REFLECT_RESULT_SUCCESS;
}
+// -- GODOT begin --
+static SpvReflectResult ParseSpecializationConstants(Parser* p_parser, SpvReflectShaderModule* p_module)
+{
+ p_module->specialization_constant_count = 0;
+ p_module->specialization_constants = NULL;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (p_node->op == SpvOpSpecConstantTrue || p_node->op == SpvOpSpecConstantFalse || p_node->op == SpvOpSpecConstant) {
+ p_module->specialization_constant_count++;
+ }
+ }
+
+ if (p_module->specialization_constant_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ p_module->specialization_constants = (SpvReflectSpecializationConstant*)calloc(p_module->specialization_constant_count, sizeof(SpvReflectSpecializationConstant));
+
+ uint32_t index = 0;
+
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ switch(p_node->op) {
+ default: continue;
+ case SpvOpSpecConstantTrue: {
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
+ p_module->specialization_constants[index].default_value.int_bool_value = 1;
+ } break;
+ case SpvOpSpecConstantFalse: {
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
+ p_module->specialization_constants[index].default_value.int_bool_value = 0;
+ } break;
+ case SpvOpSpecConstant: {
+ SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;
+ uint32_t element_type_id = (uint32_t)INVALID_VALUE;
+ uint32_t default_value = 0;
+ IF_READU32(result, p_parser, p_node->word_offset + 1, element_type_id);
+ IF_READU32(result, p_parser, p_node->word_offset + 3, default_value);
+
+ Node* p_next_node = FindNode(p_parser, element_type_id);
+
+ if (p_next_node->op == SpvOpTypeInt) {
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_INT;
+ } else if (p_next_node->op == SpvOpTypeFloat) {
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT;
+ } else {
+ return SPV_REFLECT_RESULT_ERROR_PARSE_FAILED;
+ }
+
+ p_module->specialization_constants[index].default_value.int_bool_value = default_value; //bits are the same for int and float
+ } break;
+ }
+
+ p_module->specialization_constants[index].name = p_node->name;
+ p_module->specialization_constants[index].constant_id = p_node->decorations.specialization_constant.value;
+ p_module->specialization_constants[index].spirv_id = p_node->result_id;
+ index++;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+// -- GODOT end --
+
static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module)
{
for (size_t i = 0; i < p_parser->node_count; ++i) {
@@ -3562,6 +3654,12 @@ SpvReflectResult spvReflectCreateShaderModule(
result = ParsePushConstantBlocks(&parser, p_module);
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
}
+// -- GODOT begin --
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseSpecializationConstants(&parser, p_module);
+ SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
+ }
+// -- GODOT end --
if (result == SPV_REFLECT_RESULT_SUCCESS) {
result = ParseEntryPoints(&parser, p_module);
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
@@ -3691,6 +3789,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
SafeFree(p_entry->used_push_constants);
}
SafeFree(p_module->entry_points);
+// -- GODOT begin --
+ SafeFree(p_module->specialization_constants);
+// -- GODOT end --
// Push constants
for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
@@ -3959,6 +4060,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
return SPV_REFLECT_RESULT_SUCCESS;
}
+// -- GODOT begin --
+SpvReflectResult spvReflectEnumerateSpecializationConstants(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectSpecializationConstant** pp_constants
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ if (IsNotNull(pp_constants)) {
+ if (*p_count != p_module->specialization_constant_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectSpecializationConstant *p_const = &p_module->specialization_constants[index];
+ pp_constants[index] = p_const;
+ }
+ }
+ else {
+ *p_count = p_module->specialization_constant_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+// -- GODOT end --
+
SpvReflectResult spvReflectEnumerateInputVariables(
const SpvReflectShaderModule* p_module,
uint32_t* p_count,
diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
index a5a956e9e8..21f8160770 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.h
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
@@ -292,6 +292,28 @@ typedef struct SpvReflectTypeDescription {
struct SpvReflectTypeDescription* members;
} SpvReflectTypeDescription;
+// -- GODOT begin --
+/*! @struct SpvReflectSpecializationConstant
+
+*/
+
+typedef enum SpvReflectSpecializationConstantType {
+ SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL = 0,
+ SPV_REFLECT_SPECIALIZATION_CONSTANT_INT = 1,
+ SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT = 2,
+} SpvReflectSpecializationConstantType;
+
+typedef struct SpvReflectSpecializationConstant {
+ const char* name;
+ uint32_t spirv_id;
+ uint32_t constant_id;
+ SpvReflectSpecializationConstantType constant_type;
+ union {
+ float float_value;
+ uint32_t int_bool_value;
+ } default_value;
+} SpvReflectSpecializationConstant;
+// -- GODOT end --
/*! @struct SpvReflectInterfaceVariable
@@ -439,6 +461,10 @@ typedef struct SpvReflectShaderModule {
SpvReflectInterfaceVariable* interface_variables;
uint32_t push_constant_block_count;
SpvReflectBlockVariable* push_constant_blocks;
+ // -- GODOT begin --
+ uint32_t specialization_constant_count;
+ SpvReflectSpecializationConstant* specialization_constants;
+ // -- GODOT end --
struct Internal {
size_t spirv_size;
@@ -694,6 +720,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
SpvReflectInterfaceVariable** pp_variables
);
+// -- GOODT begin --
+/*! @fn spvReflectEnumerateSpecializationConstants
+ @brief If the module contains multiple entry points, this will only get
+ the specialization constants for the first one.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_constants is NULL, the module's specialization constant
+ count will be stored here.
+ If pp_variables is not NULL, *p_count must contain
+ the module's specialization constant count.
+ @param pp_variables If NULL, the module's specialization constant count will be
+ written to *p_count.
+ If non-NULL, pp_constants must point to an array with
+ *p_count entries, where pointers to the module's
+ specialization constants will be written. The caller must not
+ free the specialization constants written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateSpecializationConstants(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectSpecializationConstant** pp_constants
+);
+// -- GODOT end --
+
/*! @fn spvReflectEnumerateEntryPointInputVariables
@brief Enumerate the input variables for a given entry point.
@param entry_point The name of the entry point to get the input variables for.