diff options
27 files changed, 231 insertions, 102 deletions
diff --git a/SConstruct b/SConstruct index 845b9be4a6..ee2247acf1 100644 --- a/SConstruct +++ b/SConstruct @@ -200,6 +200,7 @@ opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extr opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", False)) opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all generated binary files", "") opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False)) +opts.Add("vsproj_name", "Name of the Visual Studio solution", "godot") 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("build_profile", "Path to a file containing a feature build profile", "") @@ -923,7 +924,7 @@ if selected_platform in platform_list: print("Error: The `vsproj` option is only usable on Windows with Visual Studio.") Exit(255) env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]] - methods.generate_vs_project(env, GetOption("num_jobs")) + methods.generate_vs_project(env, GetOption("num_jobs"), env["vsproj_name"]) methods.generate_cpp_hint_file("cpp.hint") # Check for the existence of headers diff --git a/doc/classes/AnimatedTexture.xml b/doc/classes/AnimatedTexture.xml index 57a7f86901..454b9c1c32 100644 --- a/doc/classes/AnimatedTexture.xml +++ b/doc/classes/AnimatedTexture.xml @@ -46,7 +46,7 @@ </methods> <members> <member name="current_frame" type="int" setter="set_current_frame" getter="get_current_frame"> - Sets the currently visible frame of the texture. + Sets the currently visible frame of the texture. Setting this frame while playing resets the current frame time, so the newly selected frame plays for its whole configured frame duration. </member> <member name="frames" type="int" setter="set_frames" getter="get_frames" default="1"> Number of frames to use in the animation. While you can create the frames independently with [method set_frame_texture], you need to set this value for the animation to take new frames into account. The maximum number of frames is [constant MAX_FRAMES]. diff --git a/doc/classes/OmniLight3D.xml b/doc/classes/OmniLight3D.xml index 1df8c255dd..7c5b9aff46 100644 --- a/doc/classes/OmniLight3D.xml +++ b/doc/classes/OmniLight3D.xml @@ -13,7 +13,8 @@ </tutorials> <members> <member name="omni_attenuation" type="float" setter="set_param" getter="get_param" default="1.0"> - The light's attenuation (drop-off) curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. + The light's attenuation (drop-off) curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. Zero and negative values are allowed but can produce unusual effects. + [b]Note:[/b] Very high [member omni_attenuation] values (typically above 10) can impact performance negatively if the light is made to use a larger [member omni_range] to compensate. This is because culling opportunities will become less common and shading costs will be increased (as the light will cover more pixels on screen while resulting in the same amount of brightness). To improve performance, use the lowest [member omni_attenuation] value possible for the visuals you're trying to achieve. </member> <member name="omni_range" type="float" setter="set_param" getter="get_param" default="5.0"> The light's radius. Note that the effectively lit area may appear to be smaller depending on the [member omni_attenuation] in use. No matter the [member omni_attenuation] in use, the light will never reach anything outside this radius. diff --git a/doc/classes/SpotLight3D.xml b/doc/classes/SpotLight3D.xml index 6bb4ae548c..3b32923872 100644 --- a/doc/classes/SpotLight3D.xml +++ b/doc/classes/SpotLight3D.xml @@ -20,10 +20,11 @@ [b]Note:[/b] [member spot_angle] is not affected by [member Node3D.scale] (the light's scale or its parent's scale). </member> <member name="spot_angle_attenuation" type="float" setter="set_param" getter="get_param" default="1.0"> - The spotlight's angular attenuation curve. + The spotlight's [i]angular[/i] attenuation curve. See also [member spot_attenuation]. </member> <member name="spot_attenuation" type="float" setter="set_param" getter="get_param" default="1.0"> - The spotlight's light energy attenuation curve. + The spotlight's light energy (drop-off) attenuation curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. Zero and negative values are allowed but can produce unusual effects. See also [member spot_angle_attenuation]. + [b]Note:[/b] Very high [member spot_attenuation] values (typically above 10) can impact performance negatively if the light is made to use a larger [member spot_range] to compensate. This is because culling opportunities will become less common and shading costs will be increased (as the light will cover more pixels on screen while resulting in the same amount of brightness). To improve performance, use the lowest [member spot_attenuation] value possible for the visuals you're trying to achieve. </member> <member name="spot_range" type="float" setter="set_param" getter="get_param" default="5.0"> The maximal range that can be reached by the spotlight. Note that the effectively lit area may appear to be smaller depending on the [member spot_attenuation] in use. No matter the [member spot_attenuation] in use, the light will never reach anything outside this range. diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 6eebb84216..348aad1162 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -142,24 +142,23 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma String import_id; bool has_import_id = false; - bool created = false; - if (!material_set.has(p_material)) { - material_set.insert(p_material); - created = true; - } - if (p_material->has_meta("import_id")) { import_id = p_material->get_meta("import_id"); has_import_id = true; } else if (!p_material->get_name().is_empty()) { import_id = p_material->get_name(); has_import_id = true; + } else if (unnamed_material_name_map.has(p_material)) { + import_id = unnamed_material_name_map[p_material]; } else { - import_id = "@MATERIAL:" + itos(material_set.size() - 1); + import_id = "@MATERIAL:" + itos(material_map.size()); + unnamed_material_name_map[p_material] = import_id; } + bool created = false; if (!material_map.has(import_id)) { MaterialData md; + created = true; md.has_import_id = has_import_id; md.material = p_material; @@ -169,6 +168,7 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma } MaterialData &material_data = material_map[import_id]; + ERR_FAIL_COND(p_material != material_data.material); Ref<Texture2D> icon = get_theme_icon(SNAME("StandardMaterial3D"), SNAME("EditorIcons")); @@ -564,10 +564,10 @@ void SceneImportSettings::open_settings(const String &p_path, bool p_for_animati base_path = p_path; - material_set.clear(); mesh_set.clear(); animation_map.clear(); material_map.clear(); + unnamed_material_name_map.clear(); mesh_map.clear(); node_map.clear(); defaults.clear(); diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index 69bf58b627..d65bb1404a 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -107,6 +107,7 @@ class SceneImportSettings : public ConfirmationDialog { HashMap<StringName, Variant> settings; }; HashMap<String, MaterialData> material_map; + HashMap<Ref<Material>, String> unnamed_material_name_map; struct MeshData { bool has_import_id; @@ -141,7 +142,6 @@ class SceneImportSettings : public ConfirmationDialog { void _fill_scene(Node *p_node, TreeItem *p_parent_item); HashSet<Ref<Mesh>> mesh_set; - HashSet<Ref<Material>> material_set; String selected_type; String selected_id; diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 073adb467a..2519928ea3 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -3223,6 +3223,7 @@ void ThemeTypeEditor::_update_stylebox_from_leading() { if (!leading_stylebox.pinned || leading_stylebox.stylebox.is_null()) { return; } + ERR_FAIL_COND_MSG(edited_theme.is_null(), "Leading stylebox does not have an edited theme to update"); // Prevent changes from immediately being reported while the operation is still ongoing. edited_theme->_freeze_change_propagation(); @@ -3706,7 +3707,11 @@ void ThemeEditorPlugin::edit(Object *p_node) { if (Object::cast_to<Theme>(p_node)) { theme_editor->edit(Object::cast_to<Theme>(p_node)); } else { - theme_editor->edit(Ref<Theme>()); + // We intentionally keep a reference to the last used theme to work around + // the the editor being hidden while base resources are edited. Uncomment + // the following line again and remove this comment once that bug has been + // fixed (scheduled for Godot 4.1 in PR 73098): + // theme_editor->edit(Ref<Theme>()); } } diff --git a/methods.py b/methods.py index 7ede2592ff..dddac9bd86 100644 --- a/methods.py +++ b/methods.py @@ -732,7 +732,7 @@ def add_to_vs_project(env, sources): env.vs_srcs += [basename + ".cpp"] -def generate_vs_project(env, num_jobs): +def generate_vs_project(env, num_jobs, project_name="godot"): batch_file = find_visual_c_batch_file(env) if batch_file: @@ -873,7 +873,7 @@ def generate_vs_project(env, num_jobs): env["MSVS"]["PROJECTSUFFIX"] = ".vcxproj" env["MSVS"]["SOLUTIONSUFFIX"] = ".sln" env.MSVSProject( - target=["#godot" + env["MSVSPROJECTSUFFIX"]], + target=["#" + project_name + env["MSVSPROJECTSUFFIX"]], incs=env.vs_incs, srcs=env.vs_srcs, auto_build_solution=1, diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 46cd4b0d55..b34be11169 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -254,7 +254,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code if (codegen.script->member_indices.has(identifier)) { if (codegen.script->member_indices[identifier].getter != StringName() && codegen.script->member_indices[identifier].getter != codegen.function_name) { // Perform getter. - GDScriptCodeGenerator::Address temp = codegen.add_temporary(); + GDScriptCodeGenerator::Address temp = codegen.add_temporary(codegen.script->member_indices[identifier].data_type); Vector<GDScriptCodeGenerator::Address> args; // No argument needed. gen->write_call_self(temp, codegen.script->member_indices[identifier].getter, args); return temp; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 7a11ea52f0..4db41c4dfa 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -1244,7 +1244,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a "' to a variable of type '" + nc->get_name() + "'."; OPCODE_BREAK; } - Object *src_obj = src->operator Object *(); + + bool was_freed = false; + Object *src_obj = src->get_validated_object_with_check(was_freed); + if (!src_obj) { + if (was_freed) { + err_text = "Trying to assign invalid previously freed instance."; + } else { + err_text = "Trying to assign invalid null variable."; + } + OPCODE_BREAK; + } if (src_obj && !ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) { err_text = "Trying to assign value of type '" + src_obj->get_class_name() + @@ -1274,15 +1284,26 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } - if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) { - ScriptInstance *scr_inst = src->operator Object *()->get_script_instance(); + if (src->get_type() != Variant::NIL) { + bool was_freed = false; + Object *val_obj = src->get_validated_object_with_check(was_freed); + if (!val_obj) { + if (was_freed) { + err_text = "Trying to assign invalid previously freed instance."; + } else { + err_text = "Trying to assign invalid null variable."; + } + OPCODE_BREAK; + } + + ScriptInstance *scr_inst = val_obj->get_script_instance(); if (!scr_inst) { - err_text = "Trying to assign value of type '" + src->operator Object *()->get_class_name() + + err_text = "Trying to assign value of type '" + val_obj->get_class_name() + "' to a variable of type '" + base_type->get_path().get_file() + "'."; OPCODE_BREAK; } - Script *src_type = src->operator Object *()->get_script_instance()->get_script().ptr(); + Script *src_type = val_obj->get_script_instance()->get_script().ptr(); bool valid = false; while (src_type) { @@ -1294,7 +1315,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } if (!valid) { - err_text = "Trying to assign value of type '" + src->operator Object *()->get_script_instance()->get_script()->get_path().get_file() + + err_text = "Trying to assign value of type '" + val_obj->get_script_instance()->get_script()->get_path().get_file() + "' to a variable of type '" + base_type->get_path().get_file() + "'."; OPCODE_BREAK; } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd new file mode 100644 index 0000000000..dd2708b21d --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd @@ -0,0 +1,7 @@ +func test(): + var x = Node.new() + + x.free() + + var ok = x + var bad : Node = x diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out new file mode 100644 index 0000000000..679e51ed81 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> analyzer/errors/native_freed_instance.gd +>> 7 +>> Trying to assign invalid previously freed instance. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd new file mode 100644 index 0000000000..758fbaccc9 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd @@ -0,0 +1,10 @@ +class A extends Node: + pass + +func test(): + var x = A.new() + + x.free() + + var ok = x + var bad : A = x diff --git a/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out new file mode 100644 index 0000000000..dec7090322 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> analyzer/errors/script_freed_instance.gd +>> 10 +>> Trying to assign invalid previously freed instance. diff --git a/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd new file mode 100644 index 0000000000..38bb7f6e9c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd @@ -0,0 +1,9 @@ +var Value:int = 8 : + get: + return Value + set(v): + Value = v + +func test(): + var f:float = Value + print(int(f)) diff --git a/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out new file mode 100644 index 0000000000..b0cb63ef59 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out @@ -0,0 +1,2 @@ +GDTEST_OK +8 diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs index ed3a4c6e26..6c5c61acb9 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs @@ -302,7 +302,7 @@ namespace GodotTools.Build public static bool CleanProjectBlocking( [DisallowNull] string configuration, [AllowNull] string platform = null - ) => CleanProjectBlocking(CreateBuildInfo(configuration, platform, rebuild: false)); + ) => CleanProjectBlocking(CreateBuildInfo(configuration, platform, rebuild: false, onlyClean: true)); public static bool PublishProjectBlocking( [DisallowNull] string configuration, diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 0b0698188c..48e3759981 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -31,10 +31,12 @@ #include "color_picker.h" #include "core/input/input.h" +#include "core/io/image.h" #include "core/math/color.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "scene/gui/color_mode.h" +#include "servers/display_server.h" #include "thirdparty/misc/ok_color.h" #include "thirdparty/misc/ok_color_shader.h" @@ -90,8 +92,8 @@ void ColorPicker::_notification(int p_what) { } break; case NOTIFICATION_WM_CLOSE_REQUEST: { - if (screen != nullptr && screen->is_visible()) { - screen->hide(); + if (picker_window != nullptr && picker_window->is_visible()) { + picker_window->hide(); } } break; } @@ -1372,30 +1374,26 @@ void ColorPicker::_recent_preset_pressed(const bool p_pressed, ColorPresetButton emit_signal(SNAME("color_changed"), p_preset->get_preset_color()); } -void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { +void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) { if (!is_inside_tree()) { return; } Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) { + set_pick_color(picker_color); emit_signal(SNAME("color_changed"), color); - screen->hide(); + picker_window->hide(); } Ref<InputEventMouseMotion> mev = p_event; if (mev.is_valid()) { - Viewport *r = get_tree()->get_root(); - if (!r->get_visible_rect().has_point(mev->get_global_position())) { - return; - } - - Ref<Image> img = r->get_texture()->get_image(); + Ref<Image> img = picker_texture_rect->get_texture()->get_image(); if (img.is_valid() && !img->is_empty()) { - Vector2 ofs = mev->get_global_position(); - Color c = img->get_pixel(ofs.x, ofs.y); - - set_pick_color(c); + Vector2 ofs = mev->get_position(); + picker_color = img->get_pixel(ofs.x, ofs.y); + picker_preview_style_box->set_bg_color(picker_color); + picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); } } } @@ -1409,27 +1407,79 @@ void ColorPicker::_add_preset_pressed() { emit_signal(SNAME("preset_added"), color); } -void ColorPicker::_screen_pick_pressed() { +void ColorPicker::_pick_button_pressed() { if (!is_inside_tree()) { return; } - Viewport *r = get_tree()->get_root(); - if (!screen) { - screen = memnew(Control); - r->add_child(screen); - screen->set_as_top_level(true); - screen->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - 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(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed").bind(false)); + if (!picker_window) { + picker_window = memnew(Popup); + picker_window->hide(); + picker_window->set_transient(true); + add_child(picker_window); + + picker_texture_rect = memnew(TextureRect); + picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT); + picker_window->add_child(picker_texture_rect); + picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND); + picker_texture_rect->connect(SNAME("gui_input"), callable_mp(this, &ColorPicker::_picker_texture_input)); + + picker_preview = memnew(Panel); + picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE); + picker_window->add_child(picker_preview); + + picker_preview_label = memnew(Label); + picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview_label->set_text("Color Picking active"); + picker_preview->add_child(picker_preview_label); + + picker_preview_style_box = (Ref<StyleBoxFlat>)memnew(StyleBoxFlat); + picker_preview_style_box->set_bg_color(Color(1.0, 1.0, 1.0)); + picker_preview->add_theme_style_override("panel", picker_preview_style_box); + } + + Rect2i screen_rect; + if (picker_window->is_embedded()) { + screen_rect = picker_window->get_embedder()->get_visible_rect(); + picker_window->set_position(Point2i()); + picker_texture_rect->set_texture(ImageTexture::create_from_image(picker_window->get_embedder()->get_texture()->get_image())); } else { - screen->show(); + screen_rect = picker_window->get_parent_rect(); + picker_window->set_position(screen_rect.position); + + Ref<Image> target_image = Image::create_empty(screen_rect.size.x, screen_rect.size.y, false, Image::FORMAT_RGB8); + DisplayServer *ds = DisplayServer::get_singleton(); + + // Add the Texture of each Window to the Image. + Vector<DisplayServer::WindowID> wl = ds->get_window_list(); + // FIXME: sort windows by visibility. + for (int index = 0; index < wl.size(); index++) { + DisplayServer::WindowID wid = wl[index]; + if (wid == DisplayServer::INVALID_WINDOW_ID) { + continue; + } + + ObjectID woid = DisplayServer::get_singleton()->window_get_attached_instance_id(wid); + if (woid == ObjectID()) { + continue; + } + + Window *w = Object::cast_to<Window>(ObjectDB::get_instance(woid)); + Ref<Image> img = w->get_texture()->get_image(); + if (!img.is_valid() || img->is_empty()) { + continue; + } + img->convert(Image::FORMAT_RGB8); + target_image->blit_rect(img, Rect2i(Point2i(0, 0), img->get_size()), w->get_position()); + } + + picker_texture_rect->set_texture(ImageTexture::create_from_image(target_image)); } - screen->move_to_front(); - // TODO: show modal no longer works, needs to be converted to a popup. - //screen->show_modal(); + + picker_window->set_size(screen_rect.size); + picker_preview->set_size(screen_rect.size / 10.0); // 10% of size in each axis. + picker_window->popup(); } void ColorPicker::_html_focus_exit() { @@ -1595,9 +1645,8 @@ ColorPicker::ColorPicker() { btn_pick = memnew(Button); sample_hbc->add_child(btn_pick); - btn_pick->set_toggle_mode(true); - btn_pick->set_tooltip_text(RTR("Pick a color from the editor window.")); - btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed)); + btn_pick->set_tooltip_text(RTR("Pick a color from the application window.")); + btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed)); sample = memnew(TextureRect); sample_hbc->add_child(sample); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index f7578612cd..d02c3278e6 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -40,6 +40,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" +#include "scene/gui/panel.h" #include "scene/gui/popup.h" #include "scene/gui/separator.h" #include "scene/gui/slider.h" @@ -111,7 +112,12 @@ private: Vector<ColorMode *> modes; - Control *screen = nullptr; + Popup *picker_window = nullptr; + TextureRect *picker_texture_rect = nullptr; + Panel *picker_preview = nullptr; + Label *picker_preview_label = nullptr; + Ref<StyleBoxFlat> picker_preview_style_box; + Color picker_color; Control *uv_edit = nullptr; Control *w_edit = nullptr; AspectRatioContainer *wheel_edit = nullptr; @@ -211,10 +217,10 @@ private: void _line_edit_input(const Ref<InputEvent> &p_event); void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color); void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset); - void _screen_input(const Ref<InputEvent> &p_event); + void _picker_texture_input(const Ref<InputEvent> &p_event); void _text_changed(const String &p_new_text); void _add_preset_pressed(); - void _screen_pick_pressed(); + void _pick_button_pressed(); void _html_focus_exit(); inline int _get_preset_size(); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index e5dcdd2afd..1c7d42ad36 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -515,12 +515,13 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); float length = (p_to - p_from).length(); - if (length < p_dash) { + Vector2 step = p_dash * (p_to - p_from).normalized(); + + if (length < p_dash || step == Vector2() || p_dash <= 0.0) { RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); return; } - Vector2 step = p_dash * (p_to - p_from).normalized(); int steps = (p_aligned) ? Math::ceil(length / p_dash) : Math::floor(length / p_dash); if (steps % 2 == 0) { steps--; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 126b1d54fc..244e0d5b93 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1330,7 +1330,7 @@ void Viewport::_gui_show_tooltip() { Window *window = gui.tooltip_popup->get_parent_visible_window(); Rect2i vr; if (gui.tooltip_popup->is_embedded()) { - vr = gui.tooltip_popup->_get_embedder()->get_visible_rect(); + vr = gui.tooltip_popup->get_embedder()->get_visible_rect(); } else { vr = window->get_usable_parent_rect(); } @@ -1851,7 +1851,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Window *w = Object::cast_to<Window>(this); if (w) { if (w->is_embedded()) { - embedder = w->_get_embedder(); + embedder = w->get_embedder(); viewport_pos = get_final_transform().xform(mpos) + w->get_position(); // To parent coords. } diff --git a/scene/main/window.cpp b/scene/main/window.cpp index b79a9ba444..59e3d307c6 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -485,7 +485,7 @@ void Window::set_ime_position(const Point2i &p_pos) { bool Window::is_embedded() const { ERR_FAIL_COND_V(!is_inside_tree(), false); - return _get_embedder() != nullptr; + return get_embedder() != nullptr; } bool Window::is_in_edited_scene_root() const { @@ -710,7 +710,7 @@ void Window::set_visible(bool p_visible) { // Stop any queued resizing, as the window will be resized right now. updating_child_controls = false; - Viewport *embedder_vp = _get_embedder(); + Viewport *embedder_vp = get_embedder(); if (!embedder_vp) { if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) { @@ -1053,7 +1053,7 @@ void Window::_update_window_callbacks() { DisplayServer::get_singleton()->window_set_drop_files_callback(callable_mp(this, &Window::_window_drop_files), window_id); } -Viewport *Window::_get_embedder() const { +Viewport *Window::get_embedder() const { Viewport *vp = get_parent_viewport(); while (vp) { @@ -1088,7 +1088,7 @@ void Window::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { bool embedded = false; { - embedder = _get_embedder(); + embedder = get_embedder(); if (embedder) { embedded = true; if (!visible) { @@ -1431,7 +1431,7 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio Rect2 parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1462,7 +1462,7 @@ void Window::popup_centered(const Size2i &p_minsize) { Rect2 parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1488,7 +1488,7 @@ void Window::popup_centered_ratio(float p_ratio) { Rect2 parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1509,7 +1509,7 @@ void Window::popup_centered_ratio(float p_ratio) { void Window::popup(const Rect2i &p_screen_rect) { emit_signal(SNAME("about_to_popup")); - if (!_get_embedder() && get_flag(FLAG_POPUP)) { + if (!get_embedder() && get_flag(FLAG_POPUP)) { // Send a focus-out notification when opening a Window Manager Popup. SceneTree *scene_tree = get_tree(); if (scene_tree) { @@ -1545,7 +1545,7 @@ void Window::popup(const Rect2i &p_screen_rect) { Rect2i parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { int screen_id = DisplayServer::get_singleton()->window_get_current_screen(get_window_id()); parent_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id); @@ -1587,7 +1587,7 @@ Rect2i Window::get_usable_parent_rect() const { ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); Rect2i parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { const Window *w = is_visible() ? this : get_parent_visible_window(); //find a parent that can contain us @@ -2154,9 +2154,9 @@ Transform2D Window::get_final_transform() const { Transform2D Window::get_screen_transform_internal(bool p_absolute_position) const { Transform2D embedder_transform; - if (_get_embedder()) { + if (get_embedder()) { embedder_transform.translate_local(get_position()); - embedder_transform = _get_embedder()->get_screen_transform_internal(p_absolute_position) * embedder_transform; + embedder_transform = get_embedder()->get_screen_transform_internal(p_absolute_position) * embedder_transform; } else if (p_absolute_position) { embedder_transform.translate_local(get_position()); } @@ -2170,8 +2170,8 @@ Transform2D Window::get_popup_base_transform() const { Transform2D popup_base_transform; popup_base_transform.set_origin(get_position()); popup_base_transform *= get_final_transform(); - if (_get_embedder()) { - return _get_embedder()->get_popup_base_transform() * popup_base_transform; + if (get_embedder()) { + return get_embedder()->get_popup_base_transform() * popup_base_transform; } return popup_base_transform; } diff --git a/scene/main/window.h b/scene/main/window.h index 5359c37e9a..40b629ed11 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -192,7 +192,6 @@ private: Ref<Shortcut> debugger_stop_shortcut; protected: - Viewport *_get_embedder() const; virtual Rect2i _popup_adjust_rect() const { return Rect2i(); } virtual void _update_theme_item_cache(); @@ -278,6 +277,7 @@ public: void set_ime_position(const Point2i &p_pos); bool is_embedded() const; + Viewport *get_embedder() const; void set_content_scale_size(const Size2i &p_size); Size2i get_content_scale_size() const; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 7e3156d2ff..085becb033 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -2704,6 +2704,7 @@ void AnimatedTexture::set_current_frame(int p_frame) { RWLockWrite r(rw_lock); current_frame = p_frame; + time = 0; } int AnimatedTexture::get_current_frame() const { diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 300dca4e08..d566d612ce 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -1092,6 +1092,8 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) { if (err != OK) { ERR_PRINT("Failed to build convex hull"); } + extreme_vertices.resize(0); + vertex_neighbors.resize(0); AABB _aabb; diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index e031e33041..9389f8149e 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -484,7 +484,7 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths); } - float depth_linearize_mul = -p_projection.columns[3][2]; + float depth_linearize_mul = -p_projection.columns[3][2] * 0.5; float depth_linearize_add = p_projection.columns[2][2]; if (depth_linearize_mul * depth_linearize_add < 0) { depth_linearize_add = -depth_linearize_add; @@ -668,8 +668,14 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; - ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x; + ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y; + if (ssil_half_size) { + ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0; + ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0; + } + ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75; + ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75; float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; @@ -680,9 +686,6 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende ssil.gather_push_constant.z_far = p_projection.get_z_far(); ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25; - ssil.gather_push_constant.radius = p_settings.radius; float radius_near_limit = (p_settings.radius * 1.2f); if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) { @@ -733,7 +736,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende RD::Uniform u_depth_texture_view; u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u_depth_texture_view.binding = 0; - u_depth_texture_view.append_id(default_sampler); + u_depth_texture_view.append_id(ss_effects.mirror_sampler); u_depth_texture_view.append_id(depth_texture_view); RD::Uniform u_normal_buffer; @@ -1056,8 +1059,14 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; - ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x; + ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y; + if (ssao_half_size) { + ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0; + ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0; + } + ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75; + ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75; float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; @@ -1066,9 +1075,6 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; - ssao.gather_push_constant.radius = p_settings.radius; float radius_near_limit = (p_settings.radius * 1.2f); if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) { @@ -1105,7 +1111,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe RD::Uniform u_depth_texture_view; u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u_depth_texture_view.binding = 0; - u_depth_texture_view.append_id(default_sampler); + u_depth_texture_view.append_id(ss_effects.mirror_sampler); u_depth_texture_view.append_id(depth_texture_view); RD::Uniform u_normal_buffer; diff --git a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl index b1ff46dd3b..4f81e36c58 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl @@ -161,17 +161,11 @@ void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid) still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y; p_output_coord /= 2; - groupMemoryBarrier(); - barrier(); if (still_alive) { + // Use the previous average, not ideal, but still not bad. float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0]; - float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 8]; - float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 0]; - float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 8]; - - float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11)); - imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg)); + imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(sample_00)); } #endif } @@ -190,6 +184,7 @@ void prepare_depths(vec4 p_samples, uvec2 p_tid) { void main() { #ifdef USE_HALF_BUFFERS +// Half buffers means that we divide depth into two half res buffers (we only capture 1/4 of pixels). #ifdef USE_HALF_SIZE float sample_00 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 0, 4 * gl_GlobalInvocationID.y + 0), 0).x; float sample_11 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 2, 4 * gl_GlobalInvocationID.y + 2), 0).x; @@ -219,11 +214,11 @@ void main() { vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size; vec4 samples = textureGather(source_depth, uv); -#endif +#endif //USE_HALF_SIZE #ifdef GENERATE_MIPS prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy); #else prepare_depths(samples, gl_GlobalInvocationID.xy); #endif -#endif +#endif //USE_HALF_BUFFERS } |