summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/classes/CollisionPolygon2D.xml1
-rw-r--r--doc/classes/Image.xml11
-rw-r--r--doc/classes/Node.xml2
-rw-r--r--doc/classes/ProjectSettings.xml4
-rw-r--r--doc/classes/RenderingDevice.xml2
-rw-r--r--editor/import/3d/resource_importer_obj.cpp35
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp152
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h9
-rw-r--r--misc/extension_api_validation/4.2-stable.expected2
-rw-r--r--modules/mono/csharp_script.cpp2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs13
-rw-r--r--scene/gui/popup_menu.cpp4
-rw-r--r--scene/main/node.cpp34
-rw-r--r--scene/theme/default_theme.cpp16
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp3
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl2
-rw-r--r--servers/rendering/rendering_device.compat.inc2
-rw-r--r--servers/rendering/rendering_device.h2
19 files changed, 174 insertions, 124 deletions
diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml
index d6f3b7cb5d..acb3f66c17 100644
--- a/doc/classes/CollisionPolygon2D.xml
+++ b/doc/classes/CollisionPolygon2D.xml
@@ -25,6 +25,7 @@
</member>
<member name="polygon" type="PackedVector2Array" setter="set_polygon" getter="get_polygon" default="PackedVector2Array()">
The polygon's list of vertices. Each point will be connected to the next, and the final point will be connected to the first.
+ [b]Note:[/b] The returned vertices are in the local coordinate space of the given [CollisionPolygon2D].
[b]Warning:[/b] The returned value is a clone of the [PackedVector2Array], not a reference.
</member>
</members>
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 872277b033..6c1ecb3aea 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -19,6 +19,7 @@
<param index="1" name="contrast" type="float" />
<param index="2" name="saturation" type="float" />
<description>
+ Adjusts this image's [param brightness], [param contrast], and [param saturation] by the given values. Does not work if the image is compressed (see [method is_compressed]).
</description>
</method>
<method name="blend_rect">
@@ -163,6 +164,7 @@
<return type="int" enum="Image.UsedChannels" />
<param index="0" name="source" type="int" enum="Image.CompressSource" default="0" />
<description>
+ Returns the color channels used by this image, as one of the [enum UsedChannels] constants. If the image is compressed, the original [param source] must be specified.
</description>
</method>
<method name="fill">
@@ -612,6 +614,7 @@
OpenGL texture format [code]RGBA[/code] with four components, each with a bitdepth of 4.
</constant>
<constant name="FORMAT_RGB565" value="7" enum="Format">
+ OpenGL texture format [code]RGB[/code] with three components. Red and blue have a bitdepth of 5, and green has a bitdepth of 6.
</constant>
<constant name="FORMAT_RF" value="8" enum="Format">
OpenGL texture format [code]GL_R32F[/code] where there's one component, a 32-bit floating-point value.
@@ -696,8 +699,10 @@
[b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed.
</constant>
<constant name="FORMAT_ETC2_RA_AS_RG" value="33" enum="Format">
+ [url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]RGBA8[/code] variant), which compresses RA data and interprets it as two channels (red and green). See also [constant FORMAT_ETC2_RGBA8].
</constant>
<constant name="FORMAT_DXT5_RA_AS_RG" value="34" enum="Format">
+ The [url=https://en.wikipedia.org/wiki/S3_Texture_Compression]S3TC[/url] texture format also known as Block Compression 3 or BC3, which compresses RA data and interprets it as two channels (red and green). See also [constant FORMAT_DXT5].
</constant>
<constant name="FORMAT_ASTC_4x4" value="35" enum="Format">
[url=https://en.wikipedia.org/wiki/Adaptive_scalable_texture_compression]Adaptive Scalable Texture Compression[/url]. This implements the 4x4 (high quality) mode.
@@ -761,16 +766,22 @@
Represents the size of the [enum CompressMode] enum.
</constant>
<constant name="USED_CHANNELS_L" value="0" enum="UsedChannels">
+ The image only uses one channel for luminance (grayscale).
</constant>
<constant name="USED_CHANNELS_LA" value="1" enum="UsedChannels">
+ The image uses two channels for luminance and alpha, respectively.
</constant>
<constant name="USED_CHANNELS_R" value="2" enum="UsedChannels">
+ The image only uses the red channel.
</constant>
<constant name="USED_CHANNELS_RG" value="3" enum="UsedChannels">
+ The image uses two channels for red and green.
</constant>
<constant name="USED_CHANNELS_RGB" value="4" enum="UsedChannels">
+ The image uses three channels for red, green, and blue.
</constant>
<constant name="USED_CHANNELS_RGBA" value="5" enum="UsedChannels">
+ The image uses four channels for red, green, blue, and alpha.
</constant>
<constant name="COMPRESS_SOURCE_GENERIC" value="0" enum="CompressSource">
Source texture (before compression) is a regular texture. Default for all textures.
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 8fb2e65faf..5dd3d22062 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -739,7 +739,7 @@
<param index="0" name="new_parent" type="Node" />
<param index="1" name="keep_global_transform" type="bool" default="true" />
<description>
- Changes the parent of this [Node] to the [param new_parent]. The node needs to already have a parent.
+ Changes the parent of this [Node] to the [param new_parent]. The node needs to already have a parent. The node's [member owner] is preserved if its owner is still reachable from the new location (i.e., the node is still a descendant of the new parent after the operation).
If [param keep_global_transform] is [code]true[/code], the node's global transform will be preserved if supported. [Node2D], [Node3D] and [Control] support this argument (but [Control] keeps only position).
</description>
</method>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 8640879a4e..b351a6dae6 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -810,7 +810,9 @@
Main window can't be focused. No-focus window will ignore all input, except mouse clicks.
</member>
<member name="display/window/size/resizable" type="bool" setter="" getter="" default="true">
- Allows the window to be resizable by default.
+ If [code]true[/code], allows the window to be resizable by default.
+ [b]Note:[/b] This property is only read when the project starts. To change whether the window is resizable at runtime, set [member Window.unresizable] instead on the root Window, which can be retrieved using [code]get_viewport().get_window()[/code]. [member Window.unresizable] takes the opposite value of this setting.
+ [b]Note:[/b] Certain window managers can be configured to ignore the non-resizable status of a window. Do not rely on this setting as a guarantee that the window will [i]never[/i] be resizable.
[b]Note:[/b] This setting is ignored on iOS.
</member>
<member name="display/window/size/transparent" type="bool" setter="" getter="" default="false">
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index 495bec24dc..54f3281e17 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -2170,7 +2170,7 @@
<constant name="INITIAL_ACTION_CLEAR_REGION" value="1" enum="InitialAction" is_deprecated="true">
[i]Deprecated.[/i] Use [constant INITIAL_ACTION_CLEAR] instead.
</constant>
- <constant name="INITIAL_ACTION_CLEAR_REGION_CONTINUE" value="0" enum="InitialAction" is_deprecated="true">
+ <constant name="INITIAL_ACTION_CLEAR_REGION_CONTINUE" value="1" enum="InitialAction" is_deprecated="true">
[i]Deprecated.[/i] Use [constant INITIAL_ACTION_LOAD] instead.
</constant>
<constant name="INITIAL_ACTION_KEEP" value="0" enum="InitialAction" is_deprecated="true">
diff --git a/editor/import/3d/resource_importer_obj.cpp b/editor/import/3d/resource_importer_obj.cpp
index 082e78fdbe..a5e51636af 100644
--- a/editor/import/3d/resource_importer_obj.cpp
+++ b/editor/import/3d/resource_importer_obj.cpp
@@ -202,7 +202,7 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S
return OK;
}
-static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, Vector3 p_offset_mesh, bool p_disable_compression, List<String> *r_missing_deps) {
+static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, Vector3 p_offset_mesh, bool p_disable_compression, List<String> *r_missing_deps) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path));
@@ -220,7 +220,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
ERR_FAIL_COND_V_MSG(coff_header_machines.find(first_bytes) != -1, ERR_FILE_CORRUPT, vformat("Couldn't read OBJ file '%s', it seems to be binary, corrupted, or empty.", p_path));
f->seek(0);
- Ref<ArrayMesh> mesh;
+ Ref<ImporterMesh> mesh;
mesh.instantiate();
bool generate_tangents = p_generate_tangents;
@@ -400,24 +400,24 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
print_verbose("OBJ: Current material library " + current_material_library + " has " + itos(material_map.has(current_material_library)));
print_verbose("OBJ: Current material " + current_material + " has " + itos(material_map.has(current_material_library) && material_map[current_material_library].has(current_material)));
-
+ Ref<StandardMaterial3D> material;
if (material_map.has(current_material_library) && material_map[current_material_library].has(current_material)) {
- Ref<StandardMaterial3D> &material = material_map[current_material_library][current_material];
+ material = material_map[current_material_library][current_material];
if (!colors.is_empty()) {
material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
}
surf_tool->set_material(material);
}
- mesh = surf_tool->commit(mesh, mesh_flags);
-
if (!current_material.is_empty()) {
- mesh->surface_set_name(mesh->get_surface_count() - 1, current_material.get_basename());
+ mesh->set_surface_name(mesh->get_surface_count() - 1, current_material.get_basename());
} else if (!current_group.is_empty()) {
- mesh->surface_set_name(mesh->get_surface_count() - 1, current_group);
+ mesh->set_surface_name(mesh->get_surface_count() - 1, current_group);
}
+ Array array = surf_tool->commit_to_arrays();
+ mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, array, TypedArray<Array>(), Dictionary(), material, name, mesh_flags);
+ print_verbose("OBJ: Added surface :" + mesh->get_surface_name(mesh->get_surface_count() - 1));
- print_verbose("OBJ: Added surface :" + mesh->surface_get_name(mesh->get_surface_count() - 1));
surf_tool->clear();
surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
}
@@ -476,7 +476,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
}
Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) {
- List<Ref<Mesh>> meshes;
+ List<Ref<ImporterMesh>> meshes;
Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, Vector3(1, 1, 1), Vector3(0, 0, 0), p_flags & IMPORT_FORCE_DISABLE_MESH_COMPRESSION, r_missing_deps);
@@ -489,16 +489,9 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, co
Node3D *scene = memnew(Node3D);
- for (const Ref<Mesh> &m : meshes) {
- Ref<ImporterMesh> mesh;
- mesh.instantiate();
- mesh->set_name(m->get_name());
- for (int i = 0; i < m->get_surface_count(); i++) {
- mesh->add_surface(m->surface_get_primitive_type(i), m->surface_get_arrays(i), Array(), Dictionary(), m->surface_get_material(i), String(), m->surface_get_format(i));
- }
-
+ for (Ref<ImporterMesh> m : meshes) {
ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D);
- mi->set_mesh(mesh);
+ mi->set_mesh(m);
mi->set_name(m->get_name());
scene->add_child(mi, true);
mi->set_owner(scene);
@@ -565,7 +558,7 @@ bool ResourceImporterOBJ::get_option_visibility(const String &p_path, const Stri
}
Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
- List<Ref<Mesh>> meshes;
+ List<Ref<ImporterMesh>> meshes;
Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["optimize_mesh"], p_options["scale_mesh"], p_options["offset_mesh"], p_options["force_disable_mesh_compression"], nullptr);
@@ -574,7 +567,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s
String save_path = p_save_path + ".mesh";
- err = ResourceSaver::save(meshes.front()->get(), save_path);
+ err = ResourceSaver::save(meshes.front()->get()->get_mesh(), save_path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Mesh to file '" + save_path + "'.");
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index f8e6c71a4c..148ba7d7ca 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/gui/editor_zoom_widget.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "scene/2d/skeleton_2d.h"
#include "scene/gui/check_box.h"
@@ -96,10 +97,14 @@ void Polygon2DEditor::_notification(int p_what) {
b_snap_grid->set_icon(get_editor_theme_icon(SNAME("Grid")));
b_snap_enable->set_icon(get_editor_theme_icon(SNAME("SnapGrid")));
- uv_icon_zoom->set_texture(get_editor_theme_icon(SNAME("Zoom")));
uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
+ // Avoid scrollbar overlapping.
+ Size2 hmin = uv_hscroll->get_combined_minimum_size();
+ Size2 vmin = uv_vscroll->get_combined_minimum_size();
+ uv_hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -vmin.width);
+ uv_vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -hmin.height);
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
@@ -317,6 +322,7 @@ void Polygon2DEditor::_menu_option(int p_option) {
uv_edit->popup_centered_ratio(0.85);
}
_update_bone_list();
+ get_tree()->connect("process_frame", callable_mp(this, &Polygon2DEditor::_center_view), CONNECT_ONE_SHOT);
} break;
case UVEDIT_POLYGON_TO_UV: {
Vector<Vector2> points = node->get_polygon();
@@ -470,7 +476,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
}
Transform2D mtx;
- mtx.columns[2] = -uv_draw_ofs;
+ mtx.columns[2] = -uv_draw_ofs * uv_draw_zoom;
mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
@@ -941,36 +947,79 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
uv_edit_draw->queue_redraw();
}
}
+}
- Ref<InputEventMagnifyGesture> magnify_gesture = p_input;
- if (magnify_gesture.is_valid()) {
- uv_zoom->set_value(uv_zoom->get_value() * magnify_gesture->get_factor());
+void Polygon2DEditor::_center_view() {
+ Size2 texture_size;
+ if (node->get_texture().is_valid()) {
+ texture_size = node->get_texture()->get_size();
+ Vector2 zoom_factor = (uv_edit_draw->get_size() - Vector2(1, 1) * 50 * EDSCALE) / texture_size;
+ zoom_widget->set_zoom(MIN(zoom_factor.x, zoom_factor.y));
+ } else {
+ zoom_widget->set_zoom(EDSCALE);
}
+ // Recalculate scroll limits.
+ _update_zoom_and_pan(false);
- Ref<InputEventPanGesture> pan_gesture = p_input;
- if (pan_gesture.is_valid()) {
- uv_hscroll->set_value(uv_hscroll->get_value() + uv_hscroll->get_page() * pan_gesture->get_delta().x / 8);
- uv_vscroll->set_value(uv_vscroll->get_value() + uv_vscroll->get_page() * pan_gesture->get_delta().y / 8);
- }
+ Size2 offset = (texture_size - uv_edit_draw->get_size() / uv_draw_zoom) / 2;
+ uv_hscroll->set_value_no_signal(offset.x);
+ uv_vscroll->set_value_no_signal(offset.y);
+ _update_zoom_and_pan(false);
}
void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
- uv_hscroll->set_value(uv_hscroll->get_value() - p_scroll_vec.x);
- uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y);
+ uv_hscroll->set_value_no_signal(uv_hscroll->get_value() - p_scroll_vec.x / uv_draw_zoom);
+ uv_vscroll->set_value_no_signal(uv_vscroll->get_value() - p_scroll_vec.y / uv_draw_zoom);
+ _update_zoom_and_pan(false);
}
void Polygon2DEditor::_uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
- uv_zoom->set_value(uv_zoom->get_value() * p_zoom_factor);
+ zoom_widget->set_zoom(uv_draw_zoom * p_zoom_factor);
+ uv_draw_ofs += p_origin / uv_draw_zoom - p_origin / zoom_widget->get_zoom();
+ uv_hscroll->set_value_no_signal(uv_draw_ofs.x);
+ uv_vscroll->set_value_no_signal(uv_draw_ofs.y);
+ _update_zoom_and_pan(false);
}
-void Polygon2DEditor::_uv_scroll_changed(real_t) {
- if (updating_uv_scroll) {
- return;
+void Polygon2DEditor::_update_zoom_and_pan(bool p_zoom_at_center) {
+ uv_draw_ofs = Vector2(uv_hscroll->get_value(), uv_vscroll->get_value());
+ real_t previous_zoom = uv_draw_zoom;
+ uv_draw_zoom = zoom_widget->get_zoom();
+ if (p_zoom_at_center) {
+ Vector2 center = uv_edit_draw->get_size() / 2;
+ uv_draw_ofs += center / previous_zoom - center / uv_draw_zoom;
+ }
+
+ Point2 min_corner;
+ Point2 max_corner;
+ if (node->get_texture().is_valid()) {
+ max_corner += node->get_texture()->get_size();
+ }
+
+ Vector<Vector2> points = uv_edit_mode[0]->is_pressed() ? node->get_uv() : node->get_polygon();
+ for (int i = 0; i < points.size(); i++) {
+ min_corner = min_corner.min(points[i]);
+ max_corner = max_corner.max(points[i]);
}
+ Size2 page_size = uv_edit_draw->get_size() / uv_draw_zoom;
+ Vector2 margin = Vector2(50, 50) * EDSCALE / uv_draw_zoom;
+ min_corner -= page_size - margin;
+ max_corner += page_size - margin;
+
+ uv_hscroll->set_block_signals(true);
+ uv_hscroll->set_min(min_corner.x);
+ uv_hscroll->set_max(max_corner.x);
+ uv_hscroll->set_page(page_size.x);
+ uv_hscroll->set_value(uv_draw_ofs.x);
+ uv_hscroll->set_block_signals(false);
+
+ uv_vscroll->set_block_signals(true);
+ uv_vscroll->set_min(min_corner.y);
+ uv_vscroll->set_max(max_corner.y);
+ uv_vscroll->set_page(page_size.y);
+ uv_vscroll->set_value(uv_draw_ofs.y);
+ uv_vscroll->set_block_signals(false);
- uv_draw_ofs.x = uv_hscroll->get_value();
- uv_draw_ofs.y = uv_vscroll->get_value();
- uv_draw_zoom = uv_zoom->get_value();
uv_edit_draw->queue_redraw();
}
@@ -987,7 +1036,7 @@ void Polygon2DEditor::_uv_draw() {
String warning;
Transform2D mtx;
- mtx.columns[2] = -uv_draw_ofs;
+ mtx.columns[2] = -uv_draw_ofs * uv_draw_zoom;
mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
// Draw texture as a background if editing uvs or no uv mapping exist.
@@ -1094,7 +1143,6 @@ void Polygon2DEditor::_uv_draw() {
polygon_fill_color.push_back(pf);
}
Color prev_color = Color(0.5, 0.5, 0.5);
- Rect2 rect;
int uv_draw_max = uvs.size();
@@ -1222,40 +1270,6 @@ void Polygon2DEditor::_uv_draw() {
//draw paint circle
uv_edit_draw->draw_circle(bone_paint_pos, bone_paint_radius->get_value() * EDSCALE, Color(1, 1, 1, 0.1));
}
-
- rect.position = -uv_edit_draw->get_size();
- rect.size = uv_edit_draw->get_size() * 2.0 + base_tex->get_size() * uv_draw_zoom;
-
- updating_uv_scroll = true;
-
- uv_hscroll->set_min(rect.position.x);
- uv_hscroll->set_max(rect.position.x + rect.size.x);
- if (ABS(rect.position.x - (rect.position.x + rect.size.x)) <= uv_edit_draw->get_size().x) {
- uv_hscroll->hide();
- } else {
- uv_hscroll->show();
- uv_hscroll->set_page(uv_edit_draw->get_size().x);
- uv_hscroll->set_value(uv_draw_ofs.x);
- }
-
- uv_vscroll->set_min(rect.position.y);
- uv_vscroll->set_max(rect.position.y + rect.size.y);
- if (ABS(rect.position.y - (rect.position.y + rect.size.y)) <= uv_edit_draw->get_size().y) {
- uv_vscroll->hide();
- } else {
- uv_vscroll->show();
- uv_vscroll->set_page(uv_edit_draw->get_size().y);
- uv_vscroll->set_value(uv_draw_ofs.y);
- }
-
- Size2 hmin = uv_hscroll->get_combined_minimum_size();
- Size2 vmin = uv_vscroll->get_combined_minimum_size();
-
- // Avoid scrollbar overlapping.
- uv_hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, uv_vscroll->is_visible() ? -vmin.width : 0);
- uv_vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, uv_hscroll->is_visible() ? -hmin.height : 0);
-
- updating_uv_scroll = false;
}
void Polygon2DEditor::_bind_methods() {
@@ -1480,33 +1494,20 @@ Polygon2DEditor::Polygon2DEditor() {
sb_step_y->connect("value_changed", callable_mp(this, &Polygon2DEditor::_set_snap_step_y));
grid_settings_vb->add_margin_child(TTR("Grid Step Y:"), sb_step_y);
- uv_mode_hb->add_child(memnew(VSeparator));
- uv_icon_zoom = memnew(TextureRect);
- uv_icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
- uv_mode_hb->add_child(uv_icon_zoom);
- uv_zoom = memnew(HSlider);
- uv_zoom->set_min(0.01);
- uv_zoom->set_max(16);
- uv_zoom->set_value(1);
- uv_zoom->set_step(0.01);
- uv_zoom->set_v_size_flags(SIZE_SHRINK_CENTER);
-
- uv_mode_hb->add_child(uv_zoom);
- uv_zoom->set_custom_minimum_size(Size2(80 * EDSCALE, 0));
- uv_zoom_value = memnew(SpinBox);
- uv_zoom->share(uv_zoom_value);
- uv_zoom_value->set_custom_minimum_size(Size2(50, 0));
- uv_mode_hb->add_child(uv_zoom_value);
- uv_zoom->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed));
+ zoom_widget = memnew(EditorZoomWidget);
+ uv_edit_draw->add_child(zoom_widget);
+ zoom_widget->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT, Control::PRESET_MODE_MINSIZE, 2 * EDSCALE);
+ zoom_widget->connect("zoom_changed", callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(true));
+ zoom_widget->set_shortcut_context(nullptr);
uv_vscroll = memnew(VScrollBar);
uv_vscroll->set_step(0.001);
uv_edit_draw->add_child(uv_vscroll);
- uv_vscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed));
+ uv_vscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false));
uv_hscroll = memnew(HScrollBar);
uv_hscroll->set_step(0.001);
uv_edit_draw->add_child(uv_hscroll);
- uv_hscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed));
+ uv_hscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false));
bone_scroll_main_vb = memnew(VBoxContainer);
bone_scroll_main_vb->hide();
@@ -1535,7 +1536,6 @@ Polygon2DEditor::Polygon2DEditor() {
point_drag_index = -1;
uv_drag = false;
uv_create = false;
- updating_uv_scroll = false;
bone_painting = false;
error = memnew(AcceptDialog);
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index 8c52984b59..164aa3eccc 100644
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -35,6 +35,7 @@
class AcceptDialog;
class ButtonGroup;
+class EditorZoomWidget;
class HScrollBar;
class HSlider;
class Label;
@@ -85,12 +86,10 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
Panel *uv_edit_background = nullptr;
Polygon2D *preview_polygon = nullptr;
Control *uv_edit_draw = nullptr;
- HSlider *uv_zoom = nullptr;
- SpinBox *uv_zoom_value = nullptr;
+ EditorZoomWidget *zoom_widget = nullptr;
HScrollBar *uv_hscroll = nullptr;
VScrollBar *uv_vscroll = nullptr;
MenuButton *uv_menu = nullptr;
- TextureRect *uv_icon_zoom = nullptr;
Ref<ViewPanner> uv_panner;
void _uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
@@ -129,7 +128,6 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
Vector<int> polygon_create;
UVMode uv_move_current;
Vector2 uv_drag_from;
- bool updating_uv_scroll;
AcceptDialog *error = nullptr;
@@ -145,7 +143,8 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
void _cancel_editing();
void _update_polygon_editing_state();
- void _uv_scroll_changed(real_t);
+ void _center_view();
+ void _update_zoom_and_pan(bool p_zoom_at_center);
void _uv_input(const Ref<InputEvent> &p_input);
void _uv_draw();
void _uv_mode(int p_mode);
diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected
index 53303ebec4..2c52144896 100644
--- a/misc/extension_api_validation/4.2-stable.expected
+++ b/misc/extension_api_validation/4.2-stable.expected
@@ -35,7 +35,7 @@ GH-84976
Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/FinalAction/values/FINAL_ACTION_CONTINUE': value changed value in new API, from 2.0 to 0.
Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/FinalAction/values/FINAL_ACTION_MAX': value changed value in new API, from 3.0 to 2.
Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_CLEAR': value changed value in new API, from 0.0 to 1.
-Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_CLEAR_REGION_CONTINUE': value changed value in new API, from 2.0 to 0.
+Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_CLEAR_REGION_CONTINUE': value changed value in new API, from 2.0 to 1.
Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_CONTINUE': value changed value in new API, from 5.0 to 0.
Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_DROP': value changed value in new API, from 4.0 to 2.
Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_KEEP': value changed value in new API, from 3.0 to 0.
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 2bbd56776a..ac6977504a 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2365,6 +2365,8 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
MethodInfo mi;
mi.name = name;
+ mi.return_val = PropertyInfo::from_dict(method_info_dict["return_val"]);
+
Array params = method_info_dict["params"];
for (int j = 0; j < params.size(); j++) {
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
index 147ef852b3..1113629fef 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
@@ -146,7 +146,7 @@ namespace Godot.SourceGenerators
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description,
- helpLinkUri: string.Format(_helpLinkFormat, "GD1003")),
+ helpLinkUri: string.Format(_helpLinkFormat, "GD0103")),
location,
location?.SourceTree?.FilePath));
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
index a087b20308..968afa664b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
@@ -662,6 +662,19 @@ namespace Godot.Bridge
methodInfo.Add("name", method.Name);
+ var returnVal = new Collections.Dictionary()
+ {
+ { "name", method.ReturnVal.Name },
+ { "type", (int)method.ReturnVal.Type },
+ { "usage", (int)method.ReturnVal.Usage }
+ };
+ if (method.ReturnVal.ClassName != null)
+ {
+ returnVal["class_name"] = method.ReturnVal.ClassName;
+ }
+
+ methodInfo.Add("return_val", returnVal);
+
var methodParams = new Collections.Array();
if (method.Arguments != null)
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 8af05bd205..12e8d3eba9 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -794,9 +794,7 @@ void PopupMenu::_draw_items() {
}
}
- Color icon_color(1, 1, 1, items[i].disabled && !items[i].separator ? 0.5 : 1);
-
- icon_color *= items[i].icon_modulate;
+ Color icon_color = items[i].icon_modulate;
// For non-separator items, add some padding for the content.
if (!items[i].separator) {
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 1dd3b8bd1b..a6b7ca8188 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1736,8 +1736,40 @@ void Node::reparent(Node *p_parent, bool p_keep_global_transform) {
return;
}
+ bool preserve_owner = data.owner && (data.owner == p_parent || data.owner->is_ancestor_of(p_parent));
+ Node *owner_temp = data.owner;
+ LocalVector<Node *> common_parents;
+
+ // If the new parent is related to the owner, find all children of the reparented node who have the same owner so that we can reassign them.
+ if (preserve_owner) {
+ LocalVector<Node *> to_visit;
+
+ to_visit.push_back(this);
+ common_parents.push_back(this);
+
+ while (to_visit.size() > 0) {
+ Node *check = to_visit[to_visit.size() - 1];
+ to_visit.resize(to_visit.size() - 1);
+
+ for (int i = 0; i < check->get_child_count(); i++) {
+ Node *child = check->get_child(i, false);
+ to_visit.push_back(child);
+ if (child->data.owner == owner_temp) {
+ common_parents.push_back(child);
+ }
+ }
+ }
+ }
+
data.parent->remove_child(this);
p_parent->add_child(this);
+
+ // Reassign the old owner to those found nodes.
+ if (preserve_owner) {
+ for (Node *E : common_parents) {
+ E->set_owner(owner_temp);
+ }
+ }
}
Node *Node::get_parent() const {
@@ -1925,7 +1957,7 @@ void Node::set_owner(Node *p_owner) {
return;
}
- Node *check = this->get_parent();
+ Node *check = get_parent();
bool owner_valid = false;
while (check) {
diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp
index d1b854246b..2a1894e690 100644
--- a/scene/theme/default_theme.cpp
+++ b/scene/theme/default_theme.cpp
@@ -299,13 +299,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("focus", "CheckBox", cbx_focus);
theme->set_icon("checked", "CheckBox", icons["checked"]);
- theme->set_icon("checked_disabled", "CheckBox", icons["checked"]);
+ theme->set_icon("checked_disabled", "CheckBox", icons["checked_disabled"]);
theme->set_icon("unchecked", "CheckBox", icons["unchecked"]);
- theme->set_icon("unchecked_disabled", "CheckBox", icons["unchecked"]);
+ theme->set_icon("unchecked_disabled", "CheckBox", icons["unchecked_disabled"]);
theme->set_icon("radio_checked", "CheckBox", icons["radio_checked"]);
- theme->set_icon("radio_checked_disabled", "CheckBox", icons["radio_checked"]);
+ theme->set_icon("radio_checked_disabled", "CheckBox", icons["radio_checked_disabled"]);
theme->set_icon("radio_unchecked", "CheckBox", icons["radio_unchecked"]);
- theme->set_icon("radio_unchecked_disabled", "CheckBox", icons["radio_unchecked"]);
+ theme->set_icon("radio_unchecked_disabled", "CheckBox", icons["radio_unchecked_disabled"]);
theme->set_font("font", "CheckBox", Ref<Font>());
theme->set_font_size("font_size", "CheckBox", -1);
@@ -685,13 +685,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("labeled_separator_right", "PopupMenu", separator_horizontal);
theme->set_icon("checked", "PopupMenu", icons["checked"]);
- theme->set_icon("checked_disabled", "PopupMenu", icons["checked"]);
+ theme->set_icon("checked_disabled", "PopupMenu", icons["checked_disabled"]);
theme->set_icon("unchecked", "PopupMenu", icons["unchecked"]);
- theme->set_icon("unchecked_disabled", "PopupMenu", icons["unchecked"]);
+ theme->set_icon("unchecked_disabled", "PopupMenu", icons["unchecked_disabled"]);
theme->set_icon("radio_checked", "PopupMenu", icons["radio_checked"]);
- theme->set_icon("radio_checked_disabled", "PopupMenu", icons["radio_checked"]);
+ theme->set_icon("radio_checked_disabled", "PopupMenu", icons["radio_checked_disabled"]);
theme->set_icon("radio_unchecked", "PopupMenu", icons["radio_unchecked"]);
- theme->set_icon("radio_unchecked_disabled", "PopupMenu", icons["radio_unchecked"]);
+ theme->set_icon("radio_unchecked_disabled", "PopupMenu", icons["radio_unchecked_disabled"]);
theme->set_icon("submenu", "PopupMenu", icons["popup_menu_arrow_right"]);
theme->set_icon("submenu_mirrored", "PopupMenu", icons["popup_menu_arrow_left"]);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 28fccbaf88..283b3ee09a 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -1721,8 +1721,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
//light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
- RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, RD::FINAL_ACTION_STORE, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
Projection projection;
{
diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
index db710b7cdd..e87f644bb0 100644
--- a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
@@ -30,7 +30,7 @@ void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
uv_interp.xy = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
uv_interp.z = ViewIndex;
#endif
}
diff --git a/servers/rendering/rendering_device.compat.inc b/servers/rendering/rendering_device.compat.inc
index f79c9c9f7c..edc08e972d 100644
--- a/servers/rendering/rendering_device.compat.inc
+++ b/servers/rendering/rendering_device.compat.inc
@@ -59,8 +59,8 @@ RenderingDevice::InitialAction RenderingDevice::_convert_initial_action_84976(In
case 0: // INITIAL_ACTION_CLEAR
return INITIAL_ACTION_CLEAR;
case 1: // INITIAL_ACTION_CLEAR_REGION
- return INITIAL_ACTION_CLEAR;
case 2: // INITIAL_ACTION_CLEAR_REGION_CONTINUE
+ return INITIAL_ACTION_CLEAR;
case 3: // INITIAL_ACTION_KEEP
return INITIAL_ACTION_LOAD;
case 4: // INITIAL_ACTION_DROP
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 6c98ccfeda..2ccef66308 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -335,7 +335,7 @@ public:
INITIAL_ACTION_MAX,
#ifndef DISABLE_DEPRECATED
INITIAL_ACTION_CLEAR_REGION = INITIAL_ACTION_CLEAR,
- INITIAL_ACTION_CLEAR_REGION_CONTINUE = INITIAL_ACTION_LOAD,
+ INITIAL_ACTION_CLEAR_REGION_CONTINUE = INITIAL_ACTION_CLEAR,
INITIAL_ACTION_KEEP = INITIAL_ACTION_LOAD,
INITIAL_ACTION_DROP = INITIAL_ACTION_DISCARD,
INITIAL_ACTION_CONTINUE = INITIAL_ACTION_LOAD,