summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct3
-rw-r--r--doc/classes/AnimatedTexture.xml2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp7
-rw-r--r--editor/import/scene_import_settings.cpp16
-rw-r--r--editor/import/scene_import_settings.h2
-rw-r--r--editor/plugins/theme_editor_plugin.cpp7
-rw-r--r--methods.py4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/gdscript_vm.cpp33
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs2
-rw-r--r--scene/gui/color_picker.cpp113
-rw-r--r--scene/gui/color_picker.h12
-rw-r--r--scene/main/canvas_item.cpp5
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/main/window.cpp28
-rw-r--r--scene/main/window.h2
-rw-r--r--scene/resources/texture.cpp1
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp2
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp32
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl15
26 files changed, 230 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/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 1a18f35e64..6cc6b8224c 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1895,6 +1895,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glViewport(0, 0, rb->width, rb->height);
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+ scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
+
// Do depth prepass if it's explicitly enabled
bool use_depth_prepass = config->use_depth_prepass;
@@ -1910,9 +1914,6 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDisable(GL_SCISSOR_TEST);
- glCullFace(GL_BACK);
- glEnable(GL_CULL_FACE);
- scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
glColorMask(0, 0, 0, 0);
glClearDepth(1.0f);
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
}