diff options
36 files changed, 226 insertions, 108 deletions
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index d1b4e6a30f..e02e7aa701 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -159,9 +159,7 @@ public: userdata = p_info->callable_userdata; token = p_info->token; - if (p_info->object != nullptr) { - object = ((Object *)p_info->object)->get_instance_id(); - } + object = p_info->object_id; call_func = p_info->call_func; is_valid_func = p_info->is_valid_func; diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 240da6e073..d58f0226d8 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -392,7 +392,7 @@ typedef GDExtensionBool (*GDExtensionCallableCustomLessThan)(void *callable_user typedef void (*GDExtensionCallableCustomToString)(void *callable_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out); typedef struct { - /* Only `call_func` and `token` are strictly required, however, `object` should be passed if its not a static method. + /* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method. * * `token` should point to an address that uniquely identifies the GDExtension (for example, the * `GDExtensionClassLibraryPtr` passed to the entry symbol function. @@ -409,7 +409,7 @@ typedef struct { void *callable_userdata; void *token; - GDExtensionObjectPtr object; + GDObjectInstanceID object_id; GDExtensionCallableCustomCall call_func; GDExtensionCallableCustomIsValid is_valid_func; diff --git a/doc/classes/LightOccluder2D.xml b/doc/classes/LightOccluder2D.xml index 533e87bce9..e42ecd1c49 100644 --- a/doc/classes/LightOccluder2D.xml +++ b/doc/classes/LightOccluder2D.xml @@ -17,6 +17,7 @@ The LightOccluder2D's occluder light mask. The LightOccluder2D will cast shadows only from Light2D(s) that have the same light mask(s). </member> <member name="sdf_collision" type="bool" setter="set_as_sdf_collision" getter="is_set_as_sdf_collision" default="true"> + If enabled, the occluder will be part of a real-time generated signed distance field that can be used in custom shaders. </member> </members> </class> diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index b35eb89d19..20faa70226 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -706,7 +706,7 @@ <param index="5" name="layer_count" type="int" /> <param index="6" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> - Clears the specified [param texture] by replacing all of its pixels with the specified [param color]. [param base_mipmap] and [param mipmap_count] determine which mipmaps of the texture are affected by this clear operation, while [param base_layer] and [param layer_count] determine which layers of a 3D texture (or texture array) are affected by this clear operation. For 2D textures (which only have one layer by design), [param base_layer] and [param layer_count] must both be [code]0[/code]. + Clears the specified [param texture] by replacing all of its pixels with the specified [param color]. [param base_mipmap] and [param mipmap_count] determine which mipmaps of the texture are affected by this clear operation, while [param base_layer] and [param layer_count] determine which layers of a 3D texture (or texture array) are affected by this clear operation. For 2D textures (which only have one layer by design), [param base_layer] must be [code]0[/code] and [param layer_count] must be [code]1[/code]. [b]Note:[/b] [param texture] can't be cleared while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to [constant FINAL_ACTION_CONTINUE]) to clear this texture. </description> </method> diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp index 0faae8cf6f..4c9d610935 100644 --- a/drivers/egl/egl_manager.cpp +++ b/drivers/egl/egl_manager.cpp @@ -52,9 +52,13 @@ int EGLManager::_get_gldisplay_id(void *p_display) { GLDisplay new_gldisplay; new_gldisplay.display = p_display; - Vector<EGLAttrib> attribs = _get_platform_display_attributes(); - - new_gldisplay.egl_display = eglGetPlatformDisplay(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr); + if (GLAD_EGL_VERSION_1_5) { + Vector<EGLAttrib> attribs = _get_platform_display_attributes(); + new_gldisplay.egl_display = eglGetPlatformDisplay(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr); + } else { + NativeDisplayType *native_display_type = (NativeDisplayType *)new_gldisplay.display; + new_gldisplay.egl_display = eglGetDisplay(*native_display_type); + } ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, -1); ERR_FAIL_COND_V_MSG(new_gldisplay.egl_display == EGL_NO_DISPLAY, -1, "Can't create an EGL display."); @@ -198,7 +202,12 @@ Error EGLManager::window_create(DisplayServer::WindowID p_window_id, void *p_dis GLWindow &glwindow = windows[p_window_id]; glwindow.gldisplay_id = gldisplay_id; - glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, nullptr); + if (GLAD_EGL_VERSION_1_5) { + glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, nullptr); + } else { + EGLNativeWindowType *native_window_type = (EGLNativeWindowType *)p_native_window; + glwindow.egl_surface = eglCreateWindowSurface(gldisplay.egl_display, gldisplay.egl_config, *native_window_type, nullptr); + } if (glwindow.egl_surface == EGL_NO_SURFACE) { return ERR_CANT_CREATE; @@ -345,7 +354,7 @@ Error EGLManager::initialize() { ERR_FAIL_COND_V_MSG(!version, ERR_UNAVAILABLE, "Can't load EGL."); print_verbose(vformat("Loaded EGL %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version))); - ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_5, ERR_UNAVAILABLE, "EGL version is too old!"); + ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, "EGL version is too old!"); eglTerminate(tmp_display); #endif diff --git a/drivers/gles3/environment/gi.cpp b/drivers/gles3/environment/gi.cpp index 8beee25c64..6b33e0aa22 100644 --- a/drivers/gles3/environment/gi.cpp +++ b/drivers/gles3/environment/gi.cpp @@ -137,4 +137,7 @@ uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const { return 0; } +void GI::sdfgi_reset() { +} + #endif // GLES3_ENABLED diff --git a/drivers/gles3/environment/gi.h b/drivers/gles3/environment/gi.h index 41958e43e6..3eaa687f4f 100644 --- a/drivers/gles3/environment/gi.h +++ b/drivers/gles3/environment/gi.h @@ -85,6 +85,8 @@ public: virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override; virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override; + + virtual void sdfgi_reset() override; }; }; // namespace GLES3 diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 7b0bea81d7..8c3637663d 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -68,6 +68,7 @@ #include "servers/display_server.h" #include "servers/navigation_server_3d.h" #include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" #include "editor/audio_stream_preview.h" #include "editor/debugger/editor_debugger_node.h" @@ -3577,6 +3578,9 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { ScriptEditor::get_singleton()->set_scene_root_script(editor_data.get_scene_root_script(editor_data.get_edited_scene())); editor_data.notify_edited_scene_changed(); emit_signal(SNAME("scene_changed")); + + // Reset SDFGI after everything else so that any last-second scene modifications will be processed. + RenderingServer::get_singleton()->sdfgi_reset(); } bool EditorNode::is_changing_scene() const { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index a491a9b214..afefd38b20 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1554,7 +1554,9 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin void FileSystemDock::_update_resource_paths_after_move(const HashMap<String, String> &p_renames, const HashMap<String, ResourceUID::ID> &p_uids) const { // Update the paths in ResourceUID, so that UIDs remain valid. for (const KeyValue<String, ResourceUID::ID> &pair : p_uids) { - ResourceUID::get_singleton()->set_id(pair.value, p_renames[pair.key]); + if (p_renames.has(pair.key)) { + ResourceUID::get_singleton()->set_id(pair.value, p_renames[pair.key]); + } } // Rename all resources loaded, be it subresources or actual resources. diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 20b91d8bfd..eeefd1c90d 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -871,7 +871,9 @@ void Skeleton3DEditor::_notification(int p_what) { skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties)); skeleton->set_transform_gizmo_visible(true); #endif - handles_mesh_instance->get_parent()->remove_child(handles_mesh_instance); + if (handles_mesh_instance->get_parent()) { + handles_mesh_instance->get_parent()->remove_child(handles_mesh_instance); + } } edit_mode_toggled(false); } break; diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 8c0a5b999a..87dbbd599d 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -569,5 +569,7 @@ PropertySelector::PropertySelector() { help_bit = memnew(EditorHelpBit); vbc->add_margin_child(TTR("Description:"), help_bit); + help_bit->get_rich_text()->set_fit_content(false); + help_bit->get_rich_text()->set_custom_minimum_size(Size2(help_bit->get_rich_text()->get_minimum_size().x, 135 * EDSCALE)); help_bit->connect("request_hide", callable_mp(this, &PropertySelector::_hide_requested)); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 0d106bf842..9722f656f7 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -681,10 +681,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } - if (!_validate_no_foreign()) { - break; - } - List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.size() == 0) { break; @@ -704,7 +700,15 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Node *parent = node->get_parent(); List<Node *> owned; - node->get_owned_by(node->get_owner(), &owned); + Node *owner = node; + while (owner) { + List<Node *> cur_owned; + node->get_owned_by(owner, &cur_owned); + owner = owner->get_owner(); + for (Node *F : cur_owned) { + owned.push_back(F); + } + } HashMap<const Node *, Node *> duplimap; Node *dup = node->duplicate_from_editor(duplimap); @@ -724,9 +728,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { continue; } Node *d = duplimap[F]; - undo_redo->add_do_method(d, "set_owner", node->get_owner()); + undo_redo->add_do_method(d, "set_owner", edited_scene); } undo_redo->add_do_method(editor_selection, "add_node", dup); + undo_redo->add_do_method(dup, "set_owner", edited_scene); undo_redo->add_undo_method(parent, "remove_child", dup); undo_redo->add_do_reference(dup); @@ -2162,8 +2167,13 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { } undo_redo->commit_action(); + // Avoid changing the currently edited object. + Object *edited_object = InspectorDock::get_inspector_singleton()->get_edited_object(); + _push_item(p_script.ptr()); _update_script_button(); + + InspectorDock::get_inspector_singleton()->edit(edited_object); } void SceneTreeDock::_shader_created(Ref<Shader> p_shader) { diff --git a/modules/navigation/nav_mesh_generator_2d.cpp b/modules/navigation/nav_mesh_generator_2d.cpp index 089744c8bd..f8c12935b4 100644 --- a/modules/navigation/nav_mesh_generator_2d.cpp +++ b/modules/navigation/nav_mesh_generator_2d.cpp @@ -587,6 +587,9 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo const Vector2i &cell = used_cells[used_cell_index]; const TileData *tile_data = tilemap->get_cell_tile_data(tilemap_layer, cell, false); + if (tile_data == nullptr) { + continue; + } Transform2D tile_transform; tile_transform.set_origin(tilemap->map_to_local(cell)); @@ -597,10 +600,19 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(tilemap_layer); if (navigation_polygon.is_valid()) { for (int outline_index = 0; outline_index < navigation_polygon->get_outline_count(); outline_index++) { - Vector<Vector2> traversable_outline = navigation_polygon->get_outline(outline_index); + const Vector<Vector2> &navigation_polygon_outline = navigation_polygon->get_outline(outline_index); + if (navigation_polygon_outline.size() == 0) { + continue; + } + + Vector<Vector2> traversable_outline; + traversable_outline.resize(navigation_polygon_outline.size()); + + const Vector2 *navigation_polygon_outline_ptr = navigation_polygon_outline.ptr(); + Vector2 *traversable_outline_ptrw = traversable_outline.ptrw(); for (int traversable_outline_index = 0; traversable_outline_index < traversable_outline.size(); traversable_outline_index++) { - traversable_outline.write[traversable_outline_index] = tile_transform_offset.xform(traversable_outline[traversable_outline_index]); + traversable_outline_ptrw[traversable_outline_index] = tile_transform_offset.xform(navigation_polygon_outline_ptr[traversable_outline_index]); } p_source_geometry_data->_add_traversable_outline(traversable_outline); @@ -610,10 +622,19 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo if (physics_layers_count > 0 && (parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH) && (tile_set->get_physics_layer_collision_layer(tilemap_layer) & parsed_collision_mask)) { for (int collision_polygon_index = 0; collision_polygon_index < tile_data->get_collision_polygons_count(tilemap_layer); collision_polygon_index++) { - Vector<Vector2> obstruction_outline = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index); + const Vector<Vector2> &collision_polygon_points = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index); + if (collision_polygon_points.size() == 0) { + continue; + } + + Vector<Vector2> obstruction_outline; + obstruction_outline.resize(collision_polygon_points.size()); + + const Vector2 *collision_polygon_points_ptr = collision_polygon_points.ptr(); + Vector2 *obstruction_outline_ptrw = obstruction_outline.ptrw(); for (int obstruction_outline_index = 0; obstruction_outline_index < obstruction_outline.size(); obstruction_outline_index++) { - obstruction_outline.write[obstruction_outline_index] = tile_transform_offset.xform(obstruction_outline[obstruction_outline_index]); + obstruction_outline_ptrw[obstruction_outline_index] = tile_transform_offset.xform(collision_polygon_points_ptr[obstruction_outline_index]); } p_source_geometry_data->_add_obstruction_outline(obstruction_outline); diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 1660101598..a1a844cb05 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -1571,7 +1571,7 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { //Use xrandr to get screen refresh rate. if (xrandr_ext_ok) { - XRRScreenResources *screen_info = XRRGetScreenResources(x11_display, windows[MAIN_WINDOW_ID].x11_window); + XRRScreenResources *screen_info = XRRGetScreenResourcesCurrent(x11_display, windows[MAIN_WINDOW_ID].x11_window); if (screen_info) { RRMode current_mode = 0; xrr_monitor_info *monitors = nullptr; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index b6da4d5082..6eca32fbb6 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -2294,11 +2294,12 @@ void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_ter TypedArray<Vector2i> TileMapLayer::get_used_cells() const { // Returns the cells used in the tilemap. TypedArray<Vector2i> a; - a.resize(tile_map.size()); - int i = 0; for (const KeyValue<Vector2i, CellData> &E : tile_map) { - Vector2i p(E.key.x, E.key.y); - a[i++] = p; + const TileMapCell &c = E.value.cell; + if (c.source_id == TileSet::INVALID_SOURCE) { + continue; + } + a.push_back(E.key); } return a; @@ -2308,9 +2309,13 @@ TypedArray<Vector2i> TileMapLayer::get_used_cells_by_id(int p_source_id, const V // Returns the cells used in the tilemap. TypedArray<Vector2i> a; for (const KeyValue<Vector2i, CellData> &E : tile_map) { - if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == E.value.cell.source_id) && - (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == E.value.cell.get_atlas_coords()) && - (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == E.value.cell.alternative_tile)) { + const TileMapCell &c = E.value.cell; + if (c.source_id == TileSet::INVALID_SOURCE) { + continue; + } + if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == c.source_id) && + (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == c.get_atlas_coords()) && + (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == c.alternative_tile)) { a.push_back(E.key); } } @@ -2323,13 +2328,23 @@ Rect2i TileMapLayer::get_used_rect() const { if (used_rect_cache_dirty) { used_rect_cache = Rect2i(); - if (tile_map.size() > 0) { - used_rect_cache = Rect2i(tile_map.begin()->key.x, tile_map.begin()->key.y, 0, 0); - - for (const KeyValue<Vector2i, CellData> &E : tile_map) { + bool first = true; + for (const KeyValue<Vector2i, CellData> &E : tile_map) { + const TileMapCell &c = E.value.cell; + if (c.source_id == TileSet::INVALID_SOURCE) { + continue; + } + if (first) { + used_rect_cache = Rect2i(E.key.x, E.key.y, 0, 0); + first = false; + } else { used_rect_cache.expand_to(E.key); } - used_rect_cache.size += Vector2i(1, 1); // The cache expands to top-left coordinate, so we add one full tile. + } + if (!first) { + // Only if we have at least one cell. + // The cache expands to top-left coordinate, so we add one full tile. + used_rect_cache.size += Vector2i(1, 1); } used_rect_cache_dirty = false; } diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index e533f08861..2e34f6aad0 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -68,8 +68,9 @@ Color ReflectionProbe::get_ambient_color() const { } void ReflectionProbe::set_max_distance(float p_distance) { - max_distance = p_distance; - RS::get_singleton()->reflection_probe_set_max_distance(probe, p_distance); + max_distance = CLAMP(p_distance, 0.0, 262'144.0); + // Reflection rendering breaks if distance exceeds 262,144 units (due to floating-point precision with the near plane being 0.01). + RS::get_singleton()->reflection_probe_set_max_distance(probe, max_distance); } float ReflectionProbe::get_max_distance() const { diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index f57afb66b3..66b14dc967 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -380,7 +380,7 @@ void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) { queue_redraw(); accept_event(); - if (shortcut_feedback) { + if (shortcut_feedback && is_inside_tree()) { if (shortcut_feedback_timer == nullptr) { shortcut_feedback_timer = memnew(Timer); shortcut_feedback_timer->set_one_shot(true); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 1fc501e980..8dddbf78cf 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -598,7 +598,7 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { // Determine slot height. int slot_index = graph_node->get_input_port_slot(j); - Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index)); + Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false)); port_size.height = MAX(port_size.height, child ? child->get_size().y : 0); @@ -612,7 +612,7 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { // Determine slot height. int slot_index = graph_node->get_output_port_slot(j); - Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index)); + Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false)); port_size.height = MAX(port_size.height, child ? child->get_size().y : 0); if (is_in_output_hotzone(graph_node, j, p_point / zoom, port_size)) { @@ -643,7 +643,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { // Determine slot height. int slot_index = graph_node->get_output_port_slot(j); - Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index)); + Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false)); port_size.height = MAX(port_size.height, child ? child->get_size().y : 0); if (is_in_output_hotzone(graph_node, j, click_pos, port_size)) { @@ -700,7 +700,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { // Determine slot height. int slot_index = graph_node->get_input_port_slot(j); - Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index)); + Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false)); port_size.height = MAX(port_size.height, child ? child->get_size().y : 0); if (is_in_input_hotzone(graph_node, j, click_pos, port_size)) { @@ -777,7 +777,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { // Determine slot height. int slot_index = graph_node->get_output_port_slot(j); - Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index)); + Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false)); port_size.height = MAX(port_size.height, child ? child->get_size().y : 0); int type = graph_node->get_output_port_type(j); @@ -801,7 +801,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { // Determine slot height. int slot_index = graph_node->get_input_port_slot(j); - Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index)); + Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false)); port_size.height = MAX(port_size.height, child ? child->get_size().y : 0); int type = graph_node->get_input_port_type(j); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index fdebca3d28..3b1c1a153f 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -620,7 +620,7 @@ void GraphNode::_port_pos_update() { port_cache.pos = Point2i(edgeofs, vertical_ofs + size.height / 2); port_cache.type = slot_table[i].type_left; port_cache.color = slot_table[i].color_left; - port_cache.slot_index = child->get_index(); // Index with internal nodes included. + port_cache.slot_index = child->get_index(false); left_port_cache.push_back(port_cache); } if (slot_table[i].enable_right) { @@ -628,7 +628,7 @@ void GraphNode::_port_pos_update() { port_cache.pos = Point2i(get_size().width - edgeofs, vertical_ofs + size.height / 2); port_cache.type = slot_table[i].type_right; port_cache.color = slot_table[i].color_right; - port_cache.slot_index = child->get_index(); // Index with internal nodes included. + port_cache.slot_index = child->get_index(false); right_port_cache.push_back(port_cache); } } diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index 371d6c69af..7418ba7333 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -561,6 +561,7 @@ void MenuBar::add_child_notify(Node *p_child) { int index = DisplayServer::get_singleton()->global_menu_add_submenu_item("_main", atr(menu.name), submenu_name, _find_global_start_index() + menu_cache.size() - 1); DisplayServer::get_singleton()->global_menu_set_item_tag("_main", index, global_menu_name + "#" + itos(menu_cache.size() - 1)); } + update_minimum_size(); } void MenuBar::move_child_notify(Node *p_child) { @@ -621,6 +622,8 @@ void MenuBar::remove_child_notify(Node *p_child) { p_child->disconnect("renamed", callable_mp(this, &MenuBar::_refresh_menu_names)); p_child->disconnect("about_to_popup", callable_mp(this, &MenuBar::_popup_visibility_changed)); p_child->disconnect("popup_hide", callable_mp(this, &MenuBar::_popup_visibility_changed)); + + update_minimum_size(); } void MenuBar::_bind_methods() { @@ -808,6 +811,7 @@ void MenuBar::set_menu_title(int p_menu, const String &p_title) { if (!global_menu_name.is_empty()) { DisplayServer::get_singleton()->global_menu_set_item_text("_main", _find_global_start_index() + p_menu, atr(menu_cache[p_menu].name)); } + update_minimum_size(); } String MenuBar::get_menu_title(int p_menu) const { @@ -849,6 +853,7 @@ void MenuBar::set_menu_hidden(int p_menu, bool p_hidden) { if (!global_menu_name.is_empty()) { DisplayServer::get_singleton()->global_menu_set_item_hidden("_main", _find_global_start_index() + p_menu, p_hidden); } + update_minimum_size(); } bool MenuBar::is_menu_hidden(int p_menu) const { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index dfaf7d88b7..ec9e2cacb4 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -2186,6 +2186,7 @@ void PopupMenu::scroll_to_item(int p_idx) { } bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only) { + ERR_FAIL_COND_V(p_event.is_null(), false); Key code = Key::NONE; Ref<InputEventKey> k = p_event; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 479480011c..86e726d9da 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2948,6 +2948,8 @@ void TextEdit::_update_placeholder() { return; // Not in tree? } + const String placeholder_translated = atr(placeholder_text); + // Placeholder is generally smaller then text documents, and updates less so this should be fast enough for now. placeholder_data_buf->clear(); placeholder_data_buf->set_width(text.get_width()); @@ -2958,9 +2960,9 @@ void TextEdit::_update_placeholder() { placeholder_data_buf->set_direction((TextServer::Direction)text_direction); } placeholder_data_buf->set_preserve_control(draw_control_chars); - placeholder_data_buf->add_string(placeholder_text, theme_cache.font, theme_cache.font_size, language); + placeholder_data_buf->add_string(placeholder_translated, theme_cache.font, theme_cache.font_size, language); - placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text); + placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_translated); if (placeholder_bidi_override.is_empty()) { TS->shaped_text_set_bidi_override(placeholder_data_buf->get_rid(), placeholder_bidi_override); } @@ -2985,7 +2987,7 @@ void TextEdit::_update_placeholder() { placeholder_wraped_rows.clear(); for (int i = 0; i <= wrap_amount; i++) { Vector2i line_range = placeholder_data_buf->get_line_range(i); - placeholder_wraped_rows.push_back(placeholder_text.substr(line_range.x, line_range.y - line_range.x)); + placeholder_wraped_rows.push_back(placeholder_translated.substr(line_range.x, line_range.y - line_range.x)); } } diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp index 9ceddbc7b1..6075db4ffb 100644 --- a/scene/resources/particle_process_material.cpp +++ b/scene/resources/particle_process_material.cpp @@ -985,10 +985,6 @@ void ParticleProcessMaterial::_update_shader() { code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n"; code += " } else {\n"; code += " VELOCITY = vec3(0.0);\n"; - // If turbulence is enabled, set the noise direction to up so the turbulence color is "neutral" - if (turbulence_enabled) { - code += " noise_direction = vec3(1.0, 0.0, 0.0);\n"; - } code += " }\n"; code += " }\n"; } else if (collision_mode == COLLISION_HIDE_ON_CONTACT) { @@ -1007,14 +1003,16 @@ void ParticleProcessMaterial::_update_shader() { } code += " \n"; code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz);\n"; - // The following snippet causes massive performance hit. We don't need it as long as collision is disabled. - // Refer to GH-83744 for more info. - if (collision_mode != COLLISION_DISABLED) { + + // Godot detects when the COLLIDED keyword is used. If it's used anywhere in the shader then Godot will generate the screen space SDF for collisions. + // We don't need it as long as collision is disabled. Refer to GH-83744 for more info. + if (collision_mode == COLLISION_RIGID) { code += " if (!COLLIDED) {\n"; - code += " \n"; - code += " float vel_mag = length(final_velocity);\n"; - code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0,1.0);\n"; - code += " final_velocity = mix(final_velocity, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; + } + code += " float vel_mag = length(final_velocity);\n"; + code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0,1.0);\n"; + code += " final_velocity = mix(final_velocity, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; + if (collision_mode == COLLISION_RIGID) { code += " }\n"; } } diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 121d29b728..7b4080517f 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -4787,15 +4787,17 @@ Ref<ImageTexture> TileSetAtlasSource::_create_padded_image_texture(const Ref<Tex image->blit_rect(*src_image, src_rect, base_pos); + // Sides image->blit_rect(*src_image, top_src_rect, base_pos + Vector2i(0, -1)); image->blit_rect(*src_image, bottom_src_rect, base_pos + Vector2i(0, src_rect.size.y)); image->blit_rect(*src_image, left_src_rect, base_pos + Vector2i(-1, 0)); image->blit_rect(*src_image, right_src_rect, base_pos + Vector2i(src_rect.size.x, 0)); - image->set_pixelv(base_pos + Vector2i(-1, -1), src_image->get_pixelv(src_rect.position)); - image->set_pixelv(base_pos + Vector2i(src_rect.size.x, -1), src_image->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, 0))); - image->set_pixelv(base_pos + Vector2i(-1, src_rect.size.y), src_image->get_pixelv(src_rect.position + Vector2i(0, src_rect.size.y - 1))); - image->set_pixelv(base_pos + Vector2i(src_rect.size.x, src_rect.size.y), src_image->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1))); + // Corners + image->blit_rect(*src_image, Rect2i(src_rect.position, Vector2i(1, 1)), base_pos + Vector2i(-1, -1)); + image->blit_rect(*src_image, Rect2i(src_rect.position + Vector2i(src_rect.size.x - 1, 0), Vector2i(1, 1)), base_pos + Vector2i(src_rect.size.x, -1)); + image->blit_rect(*src_image, Rect2i(src_rect.position + Vector2i(0, src_rect.size.y - 1), Vector2i(1, 1)), base_pos + Vector2i(-1, src_rect.size.y)); + image->blit_rect(*src_image, Rect2i(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1), Vector2i(1, 1)), base_pos + Vector2i(src_rect.size.x, src_rect.size.y)); } } @@ -4831,31 +4833,20 @@ void TileSetAtlasSource::_update_padded_texture() { Ref<Texture2D> src = src_canvas_texture->get_diffuse_texture(); Ref<ImageTexture> image_texture; if (src.is_valid()) { - image_texture = _create_padded_image_texture(src); - } else { - image_texture.instantiate(); + padded_texture->set_diffuse_texture(_create_padded_image_texture(src)); } - padded_texture->set_diffuse_texture(image_texture); // Normal src = src_canvas_texture->get_normal_texture(); - image_texture.instantiate(); if (src.is_valid()) { - image_texture = _create_padded_image_texture(src); - } else { - image_texture.instantiate(); + padded_texture->set_normal_texture(_create_padded_image_texture(src)); } - padded_texture->set_normal_texture(image_texture); // Specular src = src_canvas_texture->get_specular_texture(); - image_texture.instantiate(); if (src.is_valid()) { - image_texture = _create_padded_image_texture(src); - } else { - image_texture.instantiate(); + padded_texture->set_specular_texture(_create_padded_image_texture(src)); } - padded_texture->set_specular_texture(image_texture); // Other properties. padded_texture->set_specular_color(src_canvas_texture->get_specular_color()); diff --git a/servers/rendering/dummy/environment/gi.h b/servers/rendering/dummy/environment/gi.h index a26938c740..5d0e84ae43 100644 --- a/servers/rendering/dummy/environment/gi.h +++ b/servers/rendering/dummy/environment/gi.h @@ -78,6 +78,8 @@ public: virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; } virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override { return 0; } + + virtual void sdfgi_reset() override {} }; } // namespace RendererDummy diff --git a/servers/rendering/environment/renderer_gi.h b/servers/rendering/environment/renderer_gi.h index 6eff319882..94e2c1afda 100644 --- a/servers/rendering/environment/renderer_gi.h +++ b/servers/rendering/environment/renderer_gi.h @@ -79,6 +79,8 @@ public: virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0; virtual uint32_t voxel_gi_get_version(RID p_probe) const = 0; + + virtual void sdfgi_reset() = 0; }; #endif // RENDERER_GI_H diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 0667ae87e5..dce8fadb63 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -392,6 +392,10 @@ Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const { return &voxel_gi->dependency; } +void GI::sdfgi_reset() { + sdfgi_current_version++; +} + //////////////////////////////////////////////////////////////////////////////// // SDFGI @@ -416,6 +420,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re y_scale_mode = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_y_scale(p_env); static const float y_scale[3] = { 2.0, 1.5, 1.0 }; y_mult = y_scale[y_scale_mode]; + version = gi->sdfgi_current_version; cascades.resize(num_cascades); probe_axis_count = SDFGI::PROBE_DIVISOR + 1; solid_cell_ratio = gi->sdfgi_solid_cell_ratio; diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 9a45919a2f..c46d4cbd25 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -667,6 +667,7 @@ public: float y_mult = 1.0; + uint32_t version = 0; uint32_t render_pass = 0; int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically @@ -701,11 +702,14 @@ public: Vector3 sdfgi_debug_probe_dir; bool sdfgi_debug_probe_enabled = false; Vector3i sdfgi_debug_probe_index; + uint32_t sdfgi_current_version = 0; /* SDFGI UPDATE */ int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; } + virtual void sdfgi_reset() override; + struct SDFGIData { float grid_size[3]; uint32_t max_cascades; 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 dce97808b1..768701329b 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -3486,14 +3486,18 @@ void RenderForwardClustered::sdfgi_update(const Ref<RenderSceneBuffers> &p_rende } bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment); + bool needs_reset = sdfgi.is_valid() ? sdfgi->version != gi.sdfgi_current_version : false; - if (!needs_sdfgi) { + if (!needs_sdfgi || needs_reset) { if (sdfgi.is_valid()) { // delete it sdfgi.unref(); rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); } - return; + + if (!needs_sdfgi) { + return; + } } // Ensure advanced shaders are available if SDFGI is used. 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 9e8d654b4e..a6a32d9e86 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -264,7 +264,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe RID render_target = render_buffers->get_render_target(); ERR_FAIL_COND_V(render_target.is_null(), RID()); RID target_buffer; - if (texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) { + if (view_count > 1 || texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) { target_buffer = texture_storage->render_target_get_rd_texture(render_target); } else { target_buffer = texture_storage->render_target_get_rd_texture_msaa(render_target); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index d10443d6ad..1a33f1d6e0 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -365,6 +365,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RID color_texture = use_upscaled_texture ? rb->get_upscaled_texture() : rb->get_internal_texture(); Size2i color_size = use_upscaled_texture ? target_size : rb->get_internal_size(); + bool dest_is_msaa_2d = rb->get_view_count() == 1 && texture_storage->render_target_get_msaa(render_target) != RS::VIEWPORT_MSAA_DISABLED; + if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) { RENDER_TIMESTAMP("Depth of Field"); RD::get_singleton()->draw_command_begin_label("DOF"); @@ -581,7 +583,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende // If we do a bilinear upscale we just render into our render target and our shader will upscale automatically. // Target size in this case is lying as we never get our real target size communicated. // Bit nasty but... - dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target); + + if (dest_is_msaa_2d) { + dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target)); + } else { + dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target); + } } tone_mapper->tonemapper(color_texture, dest_fb, tonemap); @@ -599,6 +606,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende fsr->fsr_upscale(rb, source_texture, dest_texture); } + if (dest_is_msaa_2d) { + // We can't upscale directly into our MSAA buffer so we need to do a copy + RID source_texture = texture_storage->render_target_get_rd_texture(render_target); + RID dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target)); + copy_effects->copy_to_fb_rect(source_texture, dest_fb, Rect2i(Point2i(), rb->get_target_size())); + } + RD::get_singleton()->draw_command_end_label(); } diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 1c5cbe9612..73aacf311f 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2239,7 +2239,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in // 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 + soft_shadow_expand) * 2.0 / texture_size; + const real_t unit = (radius + soft_shadow_expand) * 4.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); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 34d6a93e36..6b47c29382 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -116,19 +116,30 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { if (p_viewport->size.width == 0 || p_viewport->size.height == 0) { p_viewport->render_buffers.unref(); } else { + const float EPSILON = 0.0001; float scaling_3d_scale = p_viewport->scaling_3d_scale; RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode; + bool upscaler_available = p_viewport->fsr_enabled; + + if ((!upscaler_available || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_BILINEAR || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && scaling_3d_scale >= (1.0 - EPSILON) && scaling_3d_scale <= (1.0 + EPSILON)) { + // No 3D scaling on bilinear or FSR? Ignore scaling mode, this just introduces overhead. + // - Mobile can't perform optimal path + // - FSR does an extra pass (or 2 extra passes if 2D-MSAA is enabled) + // Scaling = 1.0 on FSR2 has benefits + scaling_3d_scale = 1.0; + scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF; + } + bool scaling_3d_is_fsr = (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) || (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2); bool use_taa = p_viewport->use_taa; - if (scaling_3d_is_fsr && (scaling_3d_scale > 1.0)) { + if (scaling_3d_is_fsr && (scaling_3d_scale >= (1.0 + EPSILON))) { // FSR is not designed for downsampling. // Fall back to bilinear scaling. WARN_PRINT_ONCE("FSR 3D resolution scaling is not designed for downsampling. Falling back to bilinear 3D resolution scaling."); scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR; } - bool upscaler_available = p_viewport->fsr_enabled; if (scaling_3d_is_fsr && !upscaler_available) { // FSR is not actually available. // Fall back to bilinear scaling. @@ -143,8 +154,8 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { use_taa = false; } - int width; - int height; + int target_width; + int target_height; int render_width; int render_height; @@ -152,40 +163,40 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR: // Clamp 3D rendering resolution to reasonable values supported on most hardware. // This prevents freezing the engine or outright crashing on lower-end GPUs. - width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384); - height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384); - render_width = width; - render_height = height; + target_width = p_viewport->size.width; + target_height = p_viewport->size.height; + render_width = CLAMP(target_width * scaling_3d_scale, 1, 16384); + render_height = CLAMP(target_height * scaling_3d_scale, 1, 16384); break; case RS::VIEWPORT_SCALING_3D_MODE_FSR: case RS::VIEWPORT_SCALING_3D_MODE_FSR2: - width = p_viewport->size.width; - height = p_viewport->size.height; - render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling) - render_height = MAX(height * scaling_3d_scale, 1.0); + target_width = p_viewport->size.width; + target_height = p_viewport->size.height; + render_width = MAX(target_width * scaling_3d_scale, 1.0); // target_width / (target_width * scaling) + render_height = MAX(target_height * scaling_3d_scale, 1.0); break; case RS::VIEWPORT_SCALING_3D_MODE_OFF: - width = p_viewport->size.width; - height = p_viewport->size.height; - render_width = width; - render_height = height; + target_width = p_viewport->size.width; + target_height = p_viewport->size.height; + render_width = target_width; + render_height = target_height; break; default: // This is an unknown mode. WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode)); scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF; scaling_3d_scale = 1.0; - width = p_viewport->size.width; - height = p_viewport->size.height; - render_width = width; - render_height = height; + target_width = p_viewport->size.width; + target_height = p_viewport->size.height; + render_width = target_width; + render_height = target_height; break; } uint32_t jitter_phase_count = 0; if (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2) { // Implementation has been copied from ffxFsr2GetJitterPhaseCount. - jitter_phase_count = uint32_t(8.0f * pow(float(width) / render_width, 2.0f)); + jitter_phase_count = uint32_t(8.0f * pow(float(target_width) / render_width, 2.0f)); } else if (use_taa) { // Default jitter count for TAA. jitter_phase_count = 16; @@ -201,7 +212,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { RenderSceneBuffersConfiguration rb_config; rb_config.set_render_target(p_viewport->render_target); rb_config.set_internal_size(Size2i(render_width, render_height)); - rb_config.set_target_size(Size2(width, height)); + rb_config.set_target_size(Size2(target_width, target_height)); rb_config.set_view_count(p_viewport->view_count); rb_config.set_scaling_3d_mode(scaling_3d_mode); rb_config.set_msaa_3d(p_viewport->msaa_3d); @@ -259,6 +270,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { /* Camera should always be BEFORE any other 3D */ + bool can_draw_2d = !p_viewport->disable_2d && p_viewport->view_count == 1; // Stereo rendering does not support 2D, no depth data 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; bool force_clear_render_target = false; @@ -272,7 +284,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { if (RSG::scene->is_scenario(p_viewport->scenario)) { RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario); if (RSG::scene->is_environment(environment)) { - if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport)) { + if (can_draw_2d && !viewport_is_environment_disabled(p_viewport)) { scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS; scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment); } else if (RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS) { @@ -307,7 +319,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { _draw_3d(p_viewport); } - if (!p_viewport->disable_2d) { + if (can_draw_2d) { RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 3d75ced3e3..cd5904f175 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -476,6 +476,8 @@ public: FUNC2(voxel_gi_set_interior, RID, bool) FUNC2(voxel_gi_set_use_two_bounces, RID, bool) + FUNC0(sdfgi_reset) + /* PARTICLES */ #undef ServerName diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 41f2fbb03f..a2da26eb65 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -4639,6 +4639,10 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi return false; } + if (shader->varyings.has(var->name)) { + return _validate_varying_assign(shader->varyings[var->name], r_message); + } + if (!(p_function_info.built_ins.has(var->name) && p_function_info.built_ins[var->name].constant)) { return true; } diff --git a/servers/rendering_server.h b/servers/rendering_server.h index fb658aaee8..d23e0fb48d 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -633,6 +633,8 @@ public: virtual void voxel_gi_set_quality(VoxelGIQuality) = 0; + virtual void sdfgi_reset() = 0; + /* LIGHTMAP */ virtual RID lightmap_create() = 0; |