summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml7
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--doc/classes/Curve3D.xml9
-rw-r--r--doc/classes/PathFollow3D.xml13
-rwxr-xr-xdoc/tools/make_rst.py169
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp8
-rw-r--r--drivers/vulkan/vulkan_context.cpp7
-rw-r--r--drivers/vulkan/vulkan_context.h2
-rw-r--r--editor/editor_help.cpp50
-rw-r--r--editor/editor_help.h2
-rw-r--r--editor/project_converter_3_to_4.cpp1
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp16
-rw-r--r--modules/gdscript/gdscript_analyzer.h2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs8
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs2
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs62
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs77
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs58
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs44
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs46
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs46
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs44
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs60
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs32
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs94
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs50
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs90
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs60
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs28
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java2
-rw-r--r--scene/3d/path_3d.cpp177
-rw-r--r--scene/3d/path_3d.h7
-rw-r--r--scene/gui/rich_text_label.cpp4
-rw-r--r--scene/resources/curve.cpp395
-rw-r--r--scene/resources/curve.h17
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp25
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h21
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp17
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp4
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp5
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl55
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl14
-rw-r--r--servers/rendering/renderer_scene_cull.cpp2
-rw-r--r--servers/rendering/renderer_viewport.cpp3
-rw-r--r--servers/rendering/rendering_device.h2
-rw-r--r--servers/rendering/shader_language.cpp30
-rw-r--r--servers/xr/xr_interface.cpp7
61 files changed, 1174 insertions, 817 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 690e74855f..0b4abac1af 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -52,5 +52,8 @@ body:
attributes:
label: Minimal reproduction project
description: |
- A small Godot project which reproduces the issue. Highly recommended to speed up troubleshooting.
- Drag and drop a ZIP archive to upload it. Be sure to not include the ".godot" folder in the archive.
+ A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
+ Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field.
+ Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.**
+ validations:
+ required: true
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a1e8d3a59d..63e6a89e64 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -63,6 +63,8 @@ understand that:
- What happens to you may not happen to other users.
- We can't take the time to look at your project, understand how it is set up
and then figure out why it's failing.
+- On the contributors' end, recreating a test project from scratch takes valuable
+ time that can be saved by uploading a *minimal* project.
To speed up our work, **please upload a minimal project** that isolates
and reproduces the issue. This is always the **best way for us to fix it**.
@@ -74,7 +76,7 @@ if your ZIP file isn't accepted by GitHub because it's too large.
We recommend always attaching a minimal reproduction project, even if the issue
may seem simple to reproduce manually.
-**Note for C# users:** If your issue is not .NET-specific, please upload a
+**Note for C# users:** If your issue is *not* .NET-specific, please upload a
minimal reproduction project written in GDScript.
This will make it easier for contributors to reproduce the issue
locally as not everyone has a .NET setup available.
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 3e4e05f51a..63134417b1 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -132,6 +132,15 @@
If the curve has no up vectors, the function sends an error to the console, and returns [code](0, 1, 0)[/code].
</description>
</method>
+ <method name="sample_baked_with_rotation" qualifiers="const">
+ <return type="Transform3D" />
+ <param index="0" name="offset" type="float" />
+ <param index="1" name="cubic" type="bool" default="false" />
+ <param index="2" name="apply_tilt" type="bool" default="false" />
+ <description>
+ Similar with [code]interpolate_baked()[/code]. The the return value is [code]Transform3D[/code], with [code]origin[/code] as point position, [code]basis.x[/code] as sideway vector, [code]basis.y[/code] as up vector, [code]basis.z[/code] as forward vector. When the curve length is 0, there is no reasonable way to caculate the rotation, all vectors aligned with global space axes.
+ </description>
+ </method>
<method name="samplef" qualifiers="const">
<return type="Vector3" />
<param index="0" name="fofs" type="float" />
diff --git a/doc/classes/PathFollow3D.xml b/doc/classes/PathFollow3D.xml
index ba7207be8f..fa7580b7b6 100644
--- a/doc/classes/PathFollow3D.xml
+++ b/doc/classes/PathFollow3D.xml
@@ -9,6 +9,16 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="correct_posture" qualifiers="static">
+ <return type="Transform3D" />
+ <param index="0" name="transform" type="Transform3D" />
+ <param index="1" name="rotation_mode" type="int" enum="PathFollow3D.RotationMode" />
+ <description>
+ Correct the [code]transform[/code]. [code]rotation_mode[/code] implicitly specifies how posture (forward, up and sideway direction) is caculated.
+ </description>
+ </method>
+ </methods>
<members>
<member name="cubic_interp" type="bool" setter="set_cubic_interpolation" getter="get_cubic_interpolation" default="true">
If [code]true[/code], the position between two cached points is interpolated cubically, and linearly otherwise.
@@ -30,6 +40,9 @@
<member name="rotation_mode" type="int" setter="set_rotation_mode" getter="get_rotation_mode" enum="PathFollow3D.RotationMode" default="3">
Allows or forbids rotation on one or more axes, depending on the [enum RotationMode] constants being used.
</member>
+ <member name="tilt_enabled" type="bool" setter="set_tilt_enabled" getter="is_tilt_enabled" default="true">
+ If [code]true[/code], the tilt property of [Curve3D] takes effect.
+ </member>
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The node's offset perpendicular to the curve.
</member>
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 492a438d9b..4f41baebf7 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -29,6 +29,10 @@ MARKUP_ALLOWED_SUBSEQUENT = " -.,:;!?\\/'\")]}>"
# write in this script (check `translate()` uses), and also hardcoded in
# `doc/translations/extract.py` to include them in the source POT file.
BASE_STRINGS = [
+ "Objects",
+ "Nodes",
+ "Resources",
+ "Globals",
"Description",
"Tutorials",
"Properties",
@@ -63,6 +67,13 @@ strings_l10n: Dict[str, str] = {}
STYLES: Dict[str, str] = {}
+CLASS_GROUPS: Dict[str, str] = {
+ "global": "Globals",
+ "node": "Nodes",
+ "resource": "Resources",
+ "class": "Objects",
+}
+
class State:
def __init__(self) -> None:
@@ -329,7 +340,7 @@ class State:
return cast
def sort_classes(self) -> None:
- self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0]))
+ self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0].lower()))
class TypeName:
@@ -601,12 +612,25 @@ def main() -> None:
print("Generating the RST class reference...")
+ grouped_classes: Dict[str, List[str]] = {}
+
for class_name, class_def in state.classes.items():
if args.filter and not pattern.search(class_def.filepath):
continue
state.current_class = class_name
make_rst_class(class_def, state, args.dry_run, args.output)
+ group_name = get_class_group(class_def, state)
+
+ if group_name not in grouped_classes:
+ grouped_classes[group_name] = []
+ grouped_classes[group_name].append(class_name)
+
+ print("")
+ print("Generating the index file...")
+
+ make_rst_index(grouped_classes, args.dry_run, args.output)
+
print("")
if state.num_warnings >= 2:
@@ -655,6 +679,39 @@ def translate(string: str) -> str:
return strings_l10n.get(string, string)
+def get_git_branch() -> str:
+ if hasattr(version, "docs") and version.docs != "latest":
+ return version.docs
+
+ return "master"
+
+
+def get_class_group(class_def: ClassDef, state: State) -> str:
+ group_name = "class"
+ class_name = class_def.name
+
+ if class_name.startswith("@"):
+ group_name = "global"
+ elif class_def.inherits:
+ inherits = class_def.inherits.strip()
+
+ while inherits in state.classes:
+ if inherits == "Node":
+ group_name = "node"
+ break
+ if inherits == "Resource":
+ group_name = "resource"
+ break
+
+ inode = state.classes[inherits].inherits
+ if inode:
+ inherits = inode.strip()
+ else:
+ break
+
+ return group_name
+
+
# Generator methods.
@@ -672,10 +729,7 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
# Warn contributors not to edit this file directly.
# Also provide links to the source files for reference.
- git_branch = "master"
- if hasattr(version, "docs") and version.docs != "latest":
- git_branch = version.docs
-
+ git_branch = get_git_branch()
source_xml_path = os.path.relpath(class_def.filepath, root_directory).replace("\\", "/")
source_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/{source_xml_path}"
generator_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/doc/tools/make_rst.py"
@@ -723,15 +777,30 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
f.write(make_type(child, state))
f.write("\n\n")
+ has_description = False
+
# Brief description
- if class_def.brief_description is not None:
+ if class_def.brief_description is not None and class_def.brief_description.strip() != "":
+ has_description = True
+
f.write(f"{format_text_block(class_def.brief_description.strip(), class_def, state)}\n\n")
# Class description
if class_def.description is not None and class_def.description.strip() != "":
+ has_description = True
+
f.write(make_heading("Description", "-"))
f.write(f"{format_text_block(class_def.description.strip(), class_def, state)}\n\n")
+ if not has_description:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this class. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
+
# Online tutorials
if len(class_def.tutorials) > 0:
f.write(make_heading("Tutorials", "-"))
@@ -872,6 +941,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this annotation. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -904,6 +981,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if property_def.text is not None and property_def.text.strip() != "":
f.write(f"{format_text_block(property_def.text.strip(), property_def, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this property. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -925,6 +1010,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this constructor. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -945,6 +1038,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this method. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -967,6 +1068,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this operator. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -992,6 +1101,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if theme_item_def.text is not None and theme_item_def.text.strip() != "":
f.write(f"{format_text_block(theme_item_def.text.strip(), theme_item_def, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this theme property. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -1142,6 +1259,46 @@ def make_link(url: str, title: str) -> str:
return f"`{url} <{url}>`__"
+def make_rst_index(grouped_classes: Dict[str, List[str]], dry_run: bool, output_dir: str) -> None:
+
+ if dry_run:
+ f = open(os.devnull, "w", encoding="utf-8")
+ else:
+ f = open(os.path.join(output_dir, "index.rst"), "w", encoding="utf-8")
+
+ # Remove the "Edit on Github" button from the online docs page.
+ f.write(":github_url: hide\n\n")
+
+ # Warn contributors not to edit this file directly.
+ # Also provide links to the source files for reference.
+
+ git_branch = get_git_branch()
+ generator_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/doc/tools/make_rst.py"
+
+ f.write(".. DO NOT EDIT THIS FILE!!!\n")
+ f.write(".. Generated automatically from Godot engine sources.\n")
+ f.write(f".. Generator: {generator_github_url}.\n\n")
+
+ f.write(".. _doc_class_reference:\n\n")
+
+ for group_name in CLASS_GROUPS:
+ if group_name in grouped_classes:
+ group_title = translate(CLASS_GROUPS[group_name])
+
+ f.write(f"{group_title}\n")
+ f.write(f"{'=' * len(group_title)}\n\n")
+
+ f.write(".. toctree::\n")
+ f.write(" :maxdepth: 1\n")
+ f.write(" :name: toc-class-ref-globals\n")
+ f.write("\n")
+
+ for class_name in grouped_classes[group_name]:
+ f.write(f" class_{class_name.lower()}\n")
+
+ f.write("\n")
+
+
# Formatting helpers.
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index c7c5fadbeb..6e61006395 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -3826,7 +3826,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
vrs_reference.aspectMask = VK_IMAGE_ASPECT_NONE;
- Size2i texel_size = context->get_vrs_capabilities().max_texel_size;
+ Size2i texel_size = context->get_vrs_capabilities().texel_size;
VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i];
vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
@@ -9724,6 +9724,12 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const {
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
return subgroup_capabilities.supported_operations_flags_rd();
}
+ case LIMIT_VRS_TEXEL_WIDTH: {
+ return context->get_vrs_capabilities().texel_size.x;
+ }
+ case LIMIT_VRS_TEXEL_HEIGHT: {
+ return context->get_vrs_capabilities().texel_size.y;
+ }
default:
ERR_FAIL_V(0);
}
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 464ab474e1..381df6d65e 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -625,6 +625,9 @@ Error VulkanContext::_check_capabilities() {
vrs_capabilities.pipeline_vrs_supported = false;
vrs_capabilities.primitive_vrs_supported = false;
vrs_capabilities.attachment_vrs_supported = false;
+ vrs_capabilities.min_texel_size = Size2i();
+ vrs_capabilities.max_texel_size = Size2i();
+ vrs_capabilities.texel_size = Size2i();
multiview_capabilities.is_supported = false;
multiview_capabilities.geometry_shader_is_supported = false;
multiview_capabilities.tessellation_shader_is_supported = false;
@@ -788,6 +791,10 @@ Error VulkanContext::_check_capabilities() {
vrs_capabilities.max_texel_size.x = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.width;
vrs_capabilities.max_texel_size.y = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.height;
+ // We'll attempt to default to a texel size of 16x16
+ vrs_capabilities.texel_size.x = CLAMP(16, vrs_capabilities.min_texel_size.x, vrs_capabilities.max_texel_size.x);
+ vrs_capabilities.texel_size.y = CLAMP(16, vrs_capabilities.min_texel_size.y, vrs_capabilities.max_texel_size.y);
+
print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")"));
}
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index d6a25c5cd7..8cf33fa463 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -76,6 +76,8 @@ public:
Size2i min_texel_size;
Size2i max_texel_size;
+
+ Size2i texel_size; // The texel size we'll use
};
struct ShaderCapabilities {
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index efa85dadee..0a443ee645 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -446,7 +446,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
return OK;
}
-void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods, bool &r_method_descrpitons) {
+void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods) {
Ref<Font> font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
class_desc->pop(); // title font size
class_desc->pop(); // title font
@@ -496,10 +496,6 @@ void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods,
class_desc->pop(); //cell
}
- if (!m[i].description.strip_edges().is_empty() || m[i].errors_returned.size() > 0) {
- r_method_descrpitons = true;
- }
-
_add_method(m[i], true);
}
@@ -717,11 +713,15 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
}
+ bool has_description = false;
+
class_desc->add_newline();
class_desc->add_newline();
// Brief description
if (!cd.brief_description.strip_edges().is_empty()) {
+ has_description = true;
+
class_desc->push_color(text_color);
class_desc->push_font(doc_bold_font);
class_desc->push_indent(1);
@@ -736,6 +736,8 @@ void EditorHelp::_update_doc() {
// Class description
if (!cd.description.strip_edges().is_empty()) {
+ has_description = true;
+
section_line.push_back(Pair<String, int>(TTR("Description"), class_desc->get_paragraph_count() - 2));
description_line = class_desc->get_paragraph_count() - 2;
class_desc->push_color(title_color);
@@ -760,6 +762,22 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
}
+ if (!has_description) {
+ class_desc->add_image(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ class_desc->add_text(" ");
+ class_desc->push_color(comment_color);
+
+ if (cd.is_script_doc) {
+ class_desc->append_text(TTR("There is currently no description for this class."));
+ } else {
+ class_desc->append_text(TTR("There is currently no description for this class. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ }
+
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
// Online tutorials
if (cd.tutorials.size()) {
class_desc->push_color(title_color);
@@ -796,7 +814,6 @@ void EditorHelp::_update_doc() {
// Properties overview
HashSet<String> skip_methods;
- bool property_descr = false;
bool has_properties = cd.properties.size() != 0;
if (cd.is_script_doc) {
@@ -874,7 +891,6 @@ void EditorHelp::_update_doc() {
if (describe) {
class_desc->pop();
- property_descr = true;
}
class_desc->pop();
@@ -959,9 +975,6 @@ void EditorHelp::_update_doc() {
}
// Methods overview
- bool constructor_descriptions = false;
- bool method_descriptions = false;
- bool operator_descriptions = false;
bool sort_methods = EDITOR_GET("text_editor/help/sort_functions_alphabetically");
Vector<DocData::MethodDoc> methods;
@@ -989,19 +1002,20 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Constructors"));
- _update_method_list(cd.constructors, constructor_descriptions);
+ _update_method_list(cd.constructors);
}
if (!methods.is_empty()) {
if (sort_methods) {
methods.sort();
}
+
section_line.push_back(Pair<String, int>(TTR("Methods"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Methods"));
- _update_method_list(methods, method_descriptions);
+ _update_method_list(methods);
}
if (!cd.operators.is_empty()) {
@@ -1014,7 +1028,7 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Operators"));
- _update_method_list(cd.operators, operator_descriptions);
+ _update_method_list(cd.operators);
}
// Theme properties
@@ -1507,7 +1521,7 @@ void EditorHelp::_update_doc() {
}
// Property descriptions
- if (property_descr) {
+ if (has_properties) {
section_line.push_back(Pair<String, int>(TTR("Property Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1682,7 +1696,7 @@ void EditorHelp::_update_doc() {
}
// Constructor descriptions
- if (constructor_descriptions) {
+ if (!cd.constructors.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Constructor Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1692,7 +1706,7 @@ void EditorHelp::_update_doc() {
}
// Method descriptions
- if (method_descriptions) {
+ if (!methods.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Method Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1702,7 +1716,7 @@ void EditorHelp::_update_doc() {
}
// Operator descriptions
- if (operator_descriptions) {
+ if (!cd.operators.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Operator Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1710,6 +1724,8 @@ void EditorHelp::_update_doc() {
class_desc->add_text(TTR("Operator Descriptions"));
_update_method_descriptions(cd, cd.operators, "operator");
}
+
+ // Free the scroll.
scroll_locked = false;
}
diff --git a/editor/editor_help.h b/editor/editor_help.h
index c9c1afb51b..15bfdc7c91 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -167,7 +167,7 @@ class EditorHelp : public VBoxContainer {
Error _goto_desc(const String &p_class, int p_vscr = -1);
//void _update_history_buttons();
- void _update_method_list(const Vector<DocData::MethodDoc> p_methods, bool &r_method_descrpitons);
+ void _update_method_list(const Vector<DocData::MethodDoc> p_methods);
void _update_method_descriptions(const DocData::ClassDoc p_classdoc, const Vector<DocData::MethodDoc> p_methods, const String &p_method_type);
void _update_doc();
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 8de2833240..3b764a9466 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -465,6 +465,7 @@ static const char *gdscript_function_renames[][2] = {
{ "post_import", "_post_import" }, // EditorScenePostImport
{ "print_stray_nodes", "print_orphan_nodes" }, // Node
{ "property_list_changed_notify", "notify_property_list_changed" }, // Object
+ { "raise", "move_to_front" }, // CanvasItem
{ "recognize", "_recognize" }, // ResourceFormatLoader
{ "regen_normalmaps", "regen_normal_maps" }, // ArrayMesh
{ "remove", "remove_at" }, // Array, broke Directory
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 8da77b9e5b..3d248e3da7 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -32,6 +32,7 @@
#include "core/config/engine.h"
#include "core/config/project_settings.h"
+#include "core/core_string_names.h"
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/object/class_db.h"
@@ -132,7 +133,7 @@ static GDScriptParser::DataType make_builtin_meta_type(Variant::Type p_type) {
return type;
}
-bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class) {
+bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_member) {
if (p_class->members_indices.has(p_member_name)) {
int index = p_class->members_indices[p_member_name];
const GDScriptParser::ClassNode::Member *member = &p_class->members[index];
@@ -145,6 +146,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName
member->type == GDScriptParser::ClassNode::Member::SIGNAL) {
return true;
}
+ if (p_member->type != GDScriptParser::Node::FUNCTION && member->type == GDScriptParser::ClassNode::Member::FUNCTION) {
+ return true;
+ }
}
return false;
@@ -160,6 +164,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_native_type(const StringName
if (ClassDB::has_integer_constant(p_native_type_string, p_member_name)) {
return true;
}
+ if (p_member_name == CoreStringNames::get_singleton()->_script) {
+ return true;
+ }
return false;
}
@@ -187,14 +194,15 @@ Error GDScriptAnalyzer::check_class_member_name_conflict(const GDScriptParser::C
const GDScriptParser::DataType *current_data_type = &p_class_node->base_type;
while (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::CLASS) {
GDScriptParser::ClassNode *current_class_node = current_data_type->class_type;
- if (has_member_name_conflict_in_script_class(p_member_name, current_class_node)) {
- push_error(vformat(R"(The member "%s" already exists in a parent class.)", p_member_name),
+ if (has_member_name_conflict_in_script_class(p_member_name, current_class_node, p_member_node)) {
+ push_error(vformat(R"(The member "%s" already exists in parent class %s.)", p_member_name, current_class_node->identifier->name),
p_member_node);
return ERR_PARSE_ERROR;
}
current_data_type = &current_class_node->base_type;
}
+ // No need for native class recursion because Node exposes all Object's properties.
if (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::NATIVE) {
if (current_data_type->native_type != StringName()) {
return check_native_member_name_conflict(
@@ -2912,7 +2920,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
base_class = base_class->base_type.class_type;
}
- // Check native members.
+ // Check native members. No need for native class recursion because Node exposes all Object's properties.
const StringName &native = base.native_type;
if (class_exists(native)) {
diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h
index 217a856ce0..23a3ad39a5 100644
--- a/modules/gdscript/gdscript_analyzer.h
+++ b/modules/gdscript/gdscript_analyzer.h
@@ -45,7 +45,7 @@ class GDScriptAnalyzer {
List<GDScriptParser::LambdaNode *> lambda_stack;
// Tests for detecting invalid overloading of script members
- static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node);
+ static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node, const GDScriptParser::Node *p_member);
static _FORCE_INLINE_ bool has_member_name_conflict_in_native_type(const StringName &p_name, const StringName &p_native_type_string);
Error check_native_member_name_conflict(const StringName &p_member_name, const GDScriptParser::Node *p_member_node, const StringName &p_native_type_string);
Error check_class_member_name_conflict(const GDScriptParser::ClassNode *p_class_node, const StringName &p_member_name, const GDScriptParser::Node *p_member_node);
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd
new file mode 100644
index 0000000000..5c8b9fa4ae
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd
@@ -0,0 +1,6 @@
+extends Node
+
+var script: int
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out
new file mode 100644
index 0000000000..8454aaa404
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Member "script" redefined (original in native class 'Node')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd
new file mode 100644
index 0000000000..28561ff94b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd
@@ -0,0 +1,9 @@
+func test():
+ pass
+
+class A:
+ func overload_me():
+ pass
+
+class B extends A:
+ var overload_me
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out
new file mode 100644
index 0000000000..32357f9f6a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The member "overload_me" already exists in parent class A.
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
index db395e21cb..abd8079922 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
@@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis;
namespace Godot.SourceGenerators
{
- public struct GodotMethodData
+ public readonly struct GodotMethodData
{
public GodotMethodData(IMethodSymbol method, ImmutableArray<MarshalType> paramTypes,
ImmutableArray<ITypeSymbol> paramTypeSymbols, MarshalType? retType, ITypeSymbol? retSymbol)
@@ -22,7 +22,7 @@ namespace Godot.SourceGenerators
public ITypeSymbol? RetSymbol { get; }
}
- public struct GodotSignalDelegateData
+ public readonly struct GodotSignalDelegateData
{
public GodotSignalDelegateData(string name, INamedTypeSymbol delegateSymbol, GodotMethodData invokeMethodData)
{
@@ -36,7 +36,7 @@ namespace Godot.SourceGenerators
public GodotMethodData InvokeMethodData { get; }
}
- public struct GodotPropertyData
+ public readonly struct GodotPropertyData
{
public GodotPropertyData(IPropertySymbol propertySymbol, MarshalType type)
{
@@ -48,7 +48,7 @@ namespace Godot.SourceGenerators
public MarshalType Type { get; }
}
- public struct GodotFieldData
+ public readonly struct GodotFieldData
{
public GodotFieldData(IFieldSymbol fieldSymbol, MarshalType type)
{
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
index 81c6f2b7d5..bb9be862c4 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Godot.SourceGenerators
{
- internal struct MethodInfo
+ internal readonly struct MethodInfo
{
public MethodInfo(string name, PropertyInfo returnVal, MethodFlags flags,
List<PropertyInfo>? arguments,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
index b345f5f84d..2b89633ef6 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
@@ -1,6 +1,6 @@
namespace Godot.SourceGenerators
{
- internal struct PropertyInfo
+ internal readonly struct PropertyInfo
{
public PropertyInfo(VariantType type, string name, PropertyHint hint,
string? hintString, PropertyUsageFlags usage, bool exported)
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
index 9d593fbf8a..ab21527344 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
@@ -13,7 +13,7 @@ namespace GodotTools.IdeMessaging.Utils
return waitAsyncTask.ContinueWith<IDisposable>(t => wrapper, cancellationToken).ConfigureAwait(false);
}
- private struct SemaphoreSlimWaitReleaseWrapper : IDisposable
+ private readonly struct SemaphoreSlimWaitReleaseWrapper : IDisposable
{
private readonly SemaphoreSlim semaphoreSlim;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
index 2184cae6d6..94efcba3f1 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
@@ -22,7 +22,7 @@ namespace GodotTools.Export
public bool FullAot;
private bool _useInterpreter;
- public bool UseInterpreter { get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; }
+ public bool UseInterpreter { readonly get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; }
public string[] ExtraAotOptions;
public string[] ExtraOptimizerOptions;
diff --git a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
index 820d0c0b83..9a8fdcc7c5 100644
--- a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
@@ -1,6 +1,6 @@
namespace GodotTools
{
- public struct PlaySettings
+ public readonly struct PlaySettings
{
public bool HasDebugger { get; }
public string DebuggerHost { get; }
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
index 686023a077..ae51c07386 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
@@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis;
namespace Godot.SourceGenerators.Internal;
-internal struct CallbacksData
+internal readonly struct CallbacksData
{
public CallbacksData(INamedTypeSymbol nativeTypeSymbol, INamedTypeSymbol funcStructSymbol)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
index d8a6644a66..a2916d4ae8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector3 Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector3 Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector3 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -54,7 +54,7 @@ namespace Godot
/// the most-negative corner is the origin and the size is positive.
/// </summary>
/// <returns>The modified <see cref="AABB"/>.</returns>
- public AABB Abs()
+ public readonly AABB Abs()
{
Vector3 end = End;
Vector3 topLeft = new Vector3(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y), Mathf.Min(_position.z, end.z));
@@ -66,7 +66,7 @@ namespace Godot
/// to <see cref="Position"/> + (<see cref="Size"/> / 2).
/// </summary>
/// <returns>The center.</returns>
- public Vector3 GetCenter()
+ public readonly Vector3 GetCenter()
{
return _position + (_size * 0.5f);
}
@@ -78,7 +78,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="AABB"/> encloses <paramref name="with"/>.
/// </returns>
- public bool Encloses(AABB with)
+ public readonly bool Encloses(AABB with)
{
Vector3 srcMin = _position;
Vector3 srcMax = _position + _size;
@@ -98,7 +98,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to include.</param>
/// <returns>The expanded <see cref="AABB"/>.</returns>
- public AABB Expand(Vector3 point)
+ public readonly AABB Expand(Vector3 point)
{
Vector3 begin = _position;
Vector3 end = _position + _size;
@@ -140,7 +140,7 @@ namespace Godot
/// <paramref name="idx"/> is less than 0 or greater than 7.
/// </exception>
/// <returns>An endpoint of the <see cref="AABB"/>.</returns>
- public Vector3 GetEndpoint(int idx)
+ public readonly Vector3 GetEndpoint(int idx)
{
switch (idx)
{
@@ -172,7 +172,7 @@ namespace Godot
/// Returns the normalized longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A vector representing the normalized longest axis of the <see cref="AABB"/>.</returns>
- public Vector3 GetLongestAxis()
+ public readonly Vector3 GetLongestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
real_t maxSize = _size.x;
@@ -195,7 +195,7 @@ namespace Godot
/// Returns the <see cref="Vector3.Axis"/> index of the longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is longest.</returns>
- public Vector3.Axis GetLongestAxisIndex()
+ public readonly Vector3.Axis GetLongestAxisIndex()
{
var axis = Vector3.Axis.X;
real_t maxSize = _size.x;
@@ -218,7 +218,7 @@ namespace Godot
/// Returns the scalar length of the longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>The scalar length of the longest axis of the <see cref="AABB"/>.</returns>
- public real_t GetLongestAxisSize()
+ public readonly real_t GetLongestAxisSize()
{
real_t maxSize = _size.x;
@@ -235,7 +235,7 @@ namespace Godot
/// Returns the normalized shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A vector representing the normalized shortest axis of the <see cref="AABB"/>.</returns>
- public Vector3 GetShortestAxis()
+ public readonly Vector3 GetShortestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
real_t maxSize = _size.x;
@@ -258,7 +258,7 @@ namespace Godot
/// Returns the <see cref="Vector3.Axis"/> index of the shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is shortest.</returns>
- public Vector3.Axis GetShortestAxisIndex()
+ public readonly Vector3.Axis GetShortestAxisIndex()
{
var axis = Vector3.Axis.X;
real_t maxSize = _size.x;
@@ -281,7 +281,7 @@ namespace Godot
/// Returns the scalar length of the shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>The scalar length of the shortest axis of the <see cref="AABB"/>.</returns>
- public real_t GetShortestAxisSize()
+ public readonly real_t GetShortestAxisSize()
{
real_t maxSize = _size.x;
@@ -300,7 +300,7 @@ namespace Godot
/// </summary>
/// <param name="dir">The direction to find support for.</param>
/// <returns>A vector representing the support.</returns>
- public Vector3 GetSupport(Vector3 dir)
+ public readonly Vector3 GetSupport(Vector3 dir)
{
Vector3 halfExtents = _size * 0.5f;
Vector3 ofs = _position + halfExtents;
@@ -315,7 +315,7 @@ namespace Godot
/// Returns the volume of the <see cref="AABB"/>.
/// </summary>
/// <returns>The volume.</returns>
- public real_t GetVolume()
+ public readonly real_t GetVolume()
{
return _size.x * _size.y * _size.z;
}
@@ -325,7 +325,7 @@ namespace Godot
/// </summary>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="AABB"/>.</returns>
- public AABB Grow(real_t by)
+ public readonly AABB Grow(real_t by)
{
AABB res = this;
@@ -347,7 +347,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector3 point)
+ public readonly bool HasPoint(Vector3 point)
{
if (point.x < _position.x)
return false;
@@ -374,7 +374,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has surface.
/// </returns>
- public bool HasSurface()
+ public readonly bool HasSurface()
{
return _size.x > 0.0f || _size.y > 0.0f || _size.z > 0.0f;
}
@@ -388,7 +388,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has volume.
/// </returns>
- public bool HasVolume()
+ public readonly bool HasVolume()
{
return _size.x > 0.0f && _size.y > 0.0f && _size.z > 0.0f;
}
@@ -398,7 +398,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other <see cref="AABB"/>.</param>
/// <returns>The clipped <see cref="AABB"/>.</returns>
- public AABB Intersection(AABB with)
+ public readonly AABB Intersection(AABB with)
{
Vector3 srcMin = _position;
Vector3 srcMax = _position + _size;
@@ -447,7 +447,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not they are intersecting.
/// </returns>
- public bool Intersects(AABB with, bool includeBorders = false)
+ public readonly bool Intersects(AABB with, bool includeBorders = false)
{
if (includeBorders)
{
@@ -490,7 +490,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the <see cref="Plane"/>.
/// </returns>
- public bool IntersectsPlane(Plane plane)
+ public readonly bool IntersectsPlane(Plane plane)
{
Vector3[] points =
{
@@ -531,7 +531,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the line segment.
/// </returns>
- public bool IntersectsSegment(Vector3 from, Vector3 to)
+ public readonly bool IntersectsSegment(Vector3 from, Vector3 to)
{
real_t min = 0f;
real_t max = 1f;
@@ -590,7 +590,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other <see cref="AABB"/>.</param>
/// <returns>The merged <see cref="AABB"/>.</returns>
- public AABB Merge(AABB with)
+ public readonly AABB Merge(AABB with)
{
Vector3 beg1 = _position;
Vector3 beg2 = with._position;
@@ -702,7 +702,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the AABB and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is AABB other && Equals(other);
}
@@ -714,7 +714,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other AABB.</param>
/// <returns>Whether or not the AABBs are exactly equal.</returns>
- public bool Equals(AABB other)
+ public readonly bool Equals(AABB other)
{
return _position == other._position && _size == other._size;
}
@@ -725,7 +725,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other AABB to compare.</param>
/// <returns>Whether or not the AABBs structures are approximately equal.</returns>
- public bool IsEqualApprox(AABB other)
+ public readonly bool IsEqualApprox(AABB other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size);
}
@@ -734,7 +734,7 @@ namespace Godot
/// Serves as the hash function for <see cref="AABB"/>.
/// </summary>
/// <returns>A hash code for this AABB.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -743,7 +743,7 @@ namespace Godot
/// Converts this <see cref="AABB"/> to a string.
/// </summary>
/// <returns>A string representation of this AABB.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -752,7 +752,7 @@ namespace Godot
/// Converts this <see cref="AABB"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this AABB.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index bb1d6e1661..5d390a298d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -29,7 +29,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column0"/> and array index <c>[0]</c>.</value>
public Vector3 x
{
- get => Column0;
+ readonly get => Column0;
set => Column0 = value;
}
@@ -39,7 +39,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column1"/> and array index <c>[1]</c>.</value>
public Vector3 y
{
- get => Column1;
+ readonly get => Column1;
set => Column1 = value;
}
@@ -49,7 +49,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column2"/> and array index <c>[2]</c>.</value>
public Vector3 z
{
- get => Column2;
+ readonly get => Column2;
set => Column2 = value;
}
@@ -80,7 +80,7 @@ namespace Godot
/// <value>Equivalent to <see cref="x"/> and array index <c>[0]</c>.</value>
public Vector3 Column0
{
- get => new Vector3(Row0.x, Row1.x, Row2.x);
+ readonly get => new Vector3(Row0.x, Row1.x, Row2.x);
set
{
Row0.x = value.x;
@@ -95,7 +95,7 @@ namespace Godot
/// <value>Equivalent to <see cref="y"/> and array index <c>[1]</c>.</value>
public Vector3 Column1
{
- get => new Vector3(Row0.y, Row1.y, Row2.y);
+ readonly get => new Vector3(Row0.y, Row1.y, Row2.y);
set
{
Row0.y = value.x;
@@ -110,7 +110,7 @@ namespace Godot
/// <value>Equivalent to <see cref="z"/> and array index <c>[2]</c>.</value>
public Vector3 Column2
{
- get => new Vector3(Row0.z, Row1.z, Row2.z);
+ readonly get => new Vector3(Row0.z, Row1.z, Row2.z);
set
{
Row0.z = value.x;
@@ -125,7 +125,7 @@ namespace Godot
/// <value>Equivalent to the lengths of each column vector, but negative if the determinant is negative.</value>
public Vector3 Scale
{
- get
+ readonly get
{
real_t detSign = Mathf.Sign(Determinant());
return detSign * new Vector3
@@ -154,7 +154,7 @@ namespace Godot
/// <value>The basis column.</value>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -195,7 +195,7 @@ namespace Godot
/// <value>The matrix element.</value>
public real_t this[int column, int row]
{
- get
+ readonly get
{
return this[column][row];
}
@@ -234,7 +234,7 @@ namespace Godot
/// and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
- public real_t Determinant()
+ public readonly real_t Determinant()
{
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
@@ -255,7 +255,7 @@ namespace Godot
/// </summary>
/// <param name="order">The Euler order to use. By default, use YXZ order (most common).</param>
/// <returns>A <see cref="Vector3"/> representing the basis rotation in Euler angles.</returns>
- public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
+ public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
{
switch (order)
{
@@ -499,7 +499,7 @@ namespace Godot
/// mind that quaternions should generally be preferred to Euler angles.
/// </summary>
/// <returns>A <see cref="Quaternion"/> representing the basis's rotation.</returns>
- internal Quaternion GetQuaternion()
+ internal readonly Quaternion GetQuaternion()
{
real_t trace = Row0[0] + Row1[1] + Row2[2];
@@ -558,7 +558,7 @@ namespace Godot
/// be preferred to Euler angles.
/// </summary>
/// <returns>The basis rotation.</returns>
- public Quaternion GetRotationQuaternion()
+ public readonly Quaternion GetRotationQuaternion()
{
Basis orthonormalizedBasis = Orthonormalized();
real_t det = orthonormalizedBasis.Determinant();
@@ -581,7 +581,7 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1 or 2.
/// </exception>
/// <returns>One of <c>Row0</c>, <c>Row1</c>, or <c>Row2</c>.</returns>
- public Vector3 GetRow(int index)
+ public readonly Vector3 GetRow(int index)
{
switch (index)
{
@@ -633,7 +633,7 @@ namespace Godot
/// For further details, refer to the Godot source code.
/// </summary>
/// <returns>The orthogonal index.</returns>
- public int GetOrthogonalIndex()
+ public readonly int GetOrthogonalIndex()
{
var orth = this;
@@ -679,7 +679,7 @@ namespace Godot
/// Returns the inverse of the matrix.
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Basis Inverse()
+ public readonly Basis Inverse()
{
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
@@ -709,7 +709,7 @@ namespace Godot
);
}
- internal Basis Lerp(Basis to, real_t weight)
+ internal readonly Basis Lerp(Basis to, real_t weight)
{
Basis b = this;
b.Row0 = Row0.Lerp(to.Row0, weight);
@@ -724,7 +724,7 @@ namespace Godot
/// This performs a Gram-Schmidt orthonormalization on the basis of the matrix.
/// </summary>
/// <returns>An orthonormalized basis matrix.</returns>
- public Basis Orthonormalized()
+ public readonly Basis Orthonormalized()
{
Vector3 column0 = this[0];
Vector3 column1 = this[1];
@@ -746,7 +746,7 @@ namespace Godot
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated basis matrix.</returns>
- public Basis Rotated(Vector3 axis, real_t angle)
+ public readonly Basis Rotated(Vector3 axis, real_t angle)
{
return new Basis(axis, angle) * this;
}
@@ -756,7 +756,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled basis matrix.</returns>
- public Basis Scaled(Vector3 scale)
+ public readonly Basis Scaled(Vector3 scale)
{
Basis b = this;
b.Row0 *= scale.x;
@@ -772,7 +772,7 @@ namespace Godot
/// <param name="target">The destination basis for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting basis matrix of the interpolation.</returns>
- public Basis Slerp(Basis target, real_t weight)
+ public readonly Basis Slerp(Basis target, real_t weight)
{
Quaternion from = new Quaternion(this);
Quaternion to = new Quaternion(target);
@@ -790,7 +790,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdotx(Vector3 with)
+ public readonly real_t Tdotx(Vector3 with)
{
return Row0[0] * with[0] + Row1[0] * with[1] + Row2[0] * with[2];
}
@@ -800,7 +800,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdoty(Vector3 with)
+ public readonly real_t Tdoty(Vector3 with)
{
return Row0[1] * with[0] + Row1[1] * with[1] + Row2[1] * with[2];
}
@@ -810,7 +810,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdotz(Vector3 with)
+ public readonly real_t Tdotz(Vector3 with)
{
return Row0[2] * with[0] + Row1[2] * with[1] + Row2[2] * with[2];
}
@@ -819,21 +819,18 @@ namespace Godot
/// Returns the transposed version of the basis matrix.
/// </summary>
/// <returns>The transposed basis matrix.</returns>
- public Basis Transposed()
+ public readonly Basis Transposed()
{
Basis tr = this;
- real_t temp = tr.Row0[1];
- tr.Row0[1] = tr.Row1[0];
- tr.Row1[0] = temp;
+ tr.Row0[1] = Row1[0];
+ tr.Row1[0] = Row0[1];
- temp = tr.Row0[2];
- tr.Row0[2] = tr.Row2[0];
- tr.Row2[0] = temp;
+ tr.Row0[2] = Row2[0];
+ tr.Row2[0] = Row0[2];
- temp = tr.Row1[2];
- tr.Row1[2] = tr.Row2[1];
- tr.Row2[1] = temp;
+ tr.Row1[2] = Row2[1];
+ tr.Row2[1] = Row1[2];
return tr;
}
@@ -1121,7 +1118,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the basis matrix and the object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Basis other && Equals(other);
}
@@ -1133,7 +1130,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other basis.</param>
/// <returns>Whether or not the basis matrices are exactly equal.</returns>
- public bool Equals(Basis other)
+ public readonly bool Equals(Basis other)
{
return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2);
}
@@ -1144,7 +1141,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other basis to compare.</param>
/// <returns>Whether or not the bases are approximately equal.</returns>
- public bool IsEqualApprox(Basis other)
+ public readonly bool IsEqualApprox(Basis other)
{
return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2);
}
@@ -1153,7 +1150,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Basis"/>.
/// </summary>
/// <returns>A hash code for this basis.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode();
}
@@ -1162,7 +1159,7 @@ namespace Godot
/// Converts this <see cref="Basis"/> to a string.
/// </summary>
/// <returns>A string representation of this basis.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {x}, Y: {y}, Z: {z}]";
}
@@ -1171,7 +1168,7 @@ namespace Godot
/// Converts this <see cref="Basis"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this basis.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, Z: {z.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
index 647ae436ff..85d38f9727 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
@@ -4,7 +4,7 @@ namespace Godot.Bridge;
#nullable enable
-public struct MethodInfo
+public readonly struct MethodInfo
{
public StringName Name { get; init; }
public PropertyInfo ReturnVal { get; init; }
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
index 80d6f7b4a5..0f447b93c8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
@@ -2,7 +2,7 @@ namespace Godot.Bridge;
#nullable enable
-public struct PropertyInfo
+public readonly struct PropertyInfo
{
public Variant.Type Type { get; init; }
public StringName Name { get; init; }
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index ee9e59f9fa..f49023555b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -43,7 +43,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int r8
{
- get
+ readonly get
{
return (int)Math.Round(r * 255.0f);
}
@@ -59,7 +59,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int g8
{
- get
+ readonly get
{
return (int)Math.Round(g * 255.0f);
}
@@ -75,7 +75,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int b8
{
- get
+ readonly get
{
return (int)Math.Round(b * 255.0f);
}
@@ -91,7 +91,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int a8
{
- get
+ readonly get
{
return (int)Math.Round(a * 255.0f);
}
@@ -107,7 +107,7 @@ namespace Godot
/// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHSV"/>.</value>
public float h
{
- get
+ readonly get
{
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
@@ -155,7 +155,7 @@ namespace Godot
/// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHSV"/>.</value>
public float s
{
- get
+ readonly get
{
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
@@ -176,7 +176,7 @@ namespace Godot
/// <value>Getting is equivalent to using <see cref="Math.Max(float, float)"/> on the RGB components. Setting uses <see cref="FromHSV"/>.</value>
public float v
{
- get
+ readonly get
{
return Math.Max(r, Math.Max(g, b));
}
@@ -197,7 +197,7 @@ namespace Godot
/// </value>
public float this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -242,7 +242,7 @@ namespace Godot
/// </summary>
/// <param name="over">The color to blend over.</param>
/// <returns>This color blended over <paramref name="over"/>.</returns>
- public Color Blend(Color over)
+ public readonly Color Blend(Color over)
{
Color res;
@@ -269,7 +269,7 @@ namespace Godot
/// <param name="min">The color with minimum allowed values.</param>
/// <param name="max">The color with maximum allowed values.</param>
/// <returns>The color with all components clamped.</returns>
- public Color Clamp(Color? min = null, Color? max = null)
+ public readonly Color Clamp(Color? min = null, Color? max = null)
{
Color minimum = min ?? new Color(0, 0, 0, 0);
Color maximum = max ?? new Color(1, 1, 1, 1);
@@ -288,7 +288,7 @@ namespace Godot
/// </summary>
/// <param name="amount">The ratio to darken by.</param>
/// <returns>The darkened color.</returns>
- public Color Darkened(float amount)
+ public readonly Color Darkened(float amount)
{
Color res = this;
res.r *= 1.0f - amount;
@@ -301,7 +301,7 @@ namespace Godot
/// Returns the inverted color: <c>(1 - r, 1 - g, 1 - b, a)</c>.
/// </summary>
/// <returns>The inverted color.</returns>
- public Color Inverted()
+ public readonly Color Inverted()
{
return new Color(
1.0f - r,
@@ -317,7 +317,7 @@ namespace Godot
/// </summary>
/// <param name="amount">The ratio to lighten by.</param>
/// <returns>The darkened color.</returns>
- public Color Lightened(float amount)
+ public readonly Color Lightened(float amount)
{
Color res = this;
res.r += (1.0f - res.r) * amount;
@@ -333,7 +333,7 @@ namespace Godot
/// <param name="to">The destination color for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting color of the interpolation.</returns>
- public Color Lerp(Color to, real_t weight)
+ public readonly Color Lerp(Color to, real_t weight)
{
return new Color
(
@@ -351,7 +351,7 @@ namespace Godot
/// <param name="to">The destination color for interpolation.</param>
/// <param name="weight">A color with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting color of the interpolation.</returns>
- public Color Lerp(Color to, Color weight)
+ public readonly Color Lerp(Color to, Color weight)
{
return new Color
(
@@ -368,7 +368,7 @@ namespace Godot
/// ABGR is the reversed version of the default format.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in ABGR32 format.</returns>
- public uint ToAbgr32()
+ public readonly uint ToAbgr32()
{
uint c = (byte)Math.Round(a * 255);
c <<= 8;
@@ -387,7 +387,7 @@ namespace Godot
/// ABGR is the reversed version of the default format.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in ABGR64 format.</returns>
- public ulong ToAbgr64()
+ public readonly ulong ToAbgr64()
{
ulong c = (ushort)Math.Round(a * 65535);
c <<= 16;
@@ -406,7 +406,7 @@ namespace Godot
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in ARGB32 format.</returns>
- public uint ToArgb32()
+ public readonly uint ToArgb32()
{
uint c = (byte)Math.Round(a * 255);
c <<= 8;
@@ -425,7 +425,7 @@ namespace Godot
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in ARGB64 format.</returns>
- public ulong ToArgb64()
+ public readonly ulong ToArgb64()
{
ulong c = (ushort)Math.Round(a * 65535);
c <<= 16;
@@ -444,7 +444,7 @@ namespace Godot
/// RGBA is Godot's default and recommended format.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in RGBA32 format.</returns>
- public uint ToRgba32()
+ public readonly uint ToRgba32()
{
uint c = (byte)Math.Round(r * 255);
c <<= 8;
@@ -463,7 +463,7 @@ namespace Godot
/// RGBA is Godot's default and recommended format.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in RGBA64 format.</returns>
- public ulong ToRgba64()
+ public readonly ulong ToRgba64()
{
ulong c = (ushort)Math.Round(r * 65535);
c <<= 16;
@@ -483,7 +483,7 @@ namespace Godot
/// Whether or not to include alpha. If <see langword="false"/>, the color is RGB instead of RGBA.
/// </param>
/// <returns>A string for the HTML hexadecimal representation of this color.</returns>
- public string ToHTML(bool includeAlpha = true)
+ public readonly string ToHTML(bool includeAlpha = true)
{
string txt = string.Empty;
@@ -777,7 +777,7 @@ namespace Godot
/// <param name="hue">Output parameter for the HSV hue.</param>
/// <param name="saturation">Output parameter for the HSV saturation.</param>
/// <param name="value">Output parameter for the HSV value.</param>
- public void ToHSV(out float hue, out float saturation, out float value)
+ public readonly void ToHSV(out float hue, out float saturation, out float value)
{
float max = (float)Mathf.Max(r, Mathf.Max(g, b));
float min = (float)Mathf.Min(r, Mathf.Min(g, b));
@@ -1149,7 +1149,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the color and the other object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Color other && Equals(other);
}
@@ -1161,7 +1161,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other color.</param>
/// <returns>Whether or not the colors are equal.</returns>
- public bool Equals(Color other)
+ public readonly bool Equals(Color other)
{
return r == other.r && g == other.g && b == other.b && a == other.a;
}
@@ -1172,7 +1172,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other color to compare.</param>
/// <returns>Whether or not the colors are approximately equal.</returns>
- public bool IsEqualApprox(Color other)
+ public readonly bool IsEqualApprox(Color other)
{
return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a);
}
@@ -1181,7 +1181,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Color"/>.
/// </summary>
/// <returns>A hash code for this color.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode();
}
@@ -1190,7 +1190,7 @@ namespace Godot
/// Converts this <see cref="Color"/> to a string.
/// </summary>
/// <returns>A string representation of this color.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({r}, {g}, {b}, {a})";
}
@@ -1199,7 +1199,7 @@ namespace Godot
/// Converts this <see cref="Color"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this color.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({r.ToString(format)}, {g.ToString(format)}, {b.ToString(format)}, {a.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index 664b2e0f34..42c6b0a37e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -22,7 +22,7 @@ namespace Godot
/// <value>Equivalent to <see cref="x"/>, <see cref="y"/>, and <see cref="z"/>.</value>
public Vector3 Normal
{
- get { return _normal; }
+ readonly get { return _normal; }
set { _normal = value; }
}
@@ -32,7 +32,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s X value.</value>
public real_t x
{
- get
+ readonly get
{
return _normal.x;
}
@@ -48,7 +48,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s Y value.</value>
public real_t y
{
- get
+ readonly get
{
return _normal.y;
}
@@ -64,7 +64,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s Z value.</value>
public real_t z
{
- get
+ readonly get
{
return _normal.z;
}
@@ -90,7 +90,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/> multiplied by <see cref="D"/>.</value>
public Vector3 Center
{
- get
+ readonly get
{
return _normal * D;
}
@@ -106,7 +106,7 @@ namespace Godot
/// </summary>
/// <param name="point">The position to use for the calculation.</param>
/// <returns>The shortest distance.</returns>
- public real_t DistanceTo(Vector3 point)
+ public readonly real_t DistanceTo(Vector3 point)
{
return _normal.Dot(point) - D;
}
@@ -118,7 +118,7 @@ namespace Godot
/// <param name="point">The point to check.</param>
/// <param name="tolerance">The tolerance threshold.</param>
/// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns>
- public bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon)
+ public readonly bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon)
{
real_t dist = _normal.Dot(point) - D;
return Mathf.Abs(dist) <= tolerance;
@@ -131,7 +131,7 @@ namespace Godot
/// <param name="b">One of the three planes to use in the calculation.</param>
/// <param name="c">One of the three planes to use in the calculation.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? Intersect3(Plane b, Plane c)
+ public readonly Vector3? Intersect3(Plane b, Plane c)
{
real_t denom = _normal.Cross(b._normal).Dot(c._normal);
@@ -155,7 +155,7 @@ namespace Godot
/// <param name="from">The start of the ray.</param>
/// <param name="dir">The direction of the ray, normalized.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? IntersectRay(Vector3 from, Vector3 dir)
+ public readonly Vector3? IntersectRay(Vector3 from, Vector3 dir)
{
real_t den = _normal.Dot(dir);
@@ -183,7 +183,7 @@ namespace Godot
/// <param name="begin">The start of the line segment.</param>
/// <param name="end">The end of the line segment.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? IntersectSegment(Vector3 begin, Vector3 end)
+ public readonly Vector3? IntersectSegment(Vector3 begin, Vector3 end)
{
Vector3 segment = begin - end;
real_t den = _normal.Dot(segment);
@@ -209,7 +209,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to check.</param>
/// <returns>A <see langword="bool"/> for whether or not the point is above the plane.</returns>
- public bool IsPointOver(Vector3 point)
+ public readonly bool IsPointOver(Vector3 point)
{
return _normal.Dot(point) > D;
}
@@ -218,7 +218,7 @@ namespace Godot
/// Returns the plane scaled to unit length.
/// </summary>
/// <returns>A normalized version of the plane.</returns>
- public Plane Normalized()
+ public readonly Plane Normalized()
{
real_t len = _normal.Length();
@@ -235,7 +235,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to project.</param>
/// <returns>The projected point.</returns>
- public Vector3 Project(Vector3 point)
+ public readonly Vector3 Project(Vector3 point)
{
return point - (_normal * DistanceTo(point));
}
@@ -363,7 +363,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the plane and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Plane other && Equals(other);
}
@@ -373,7 +373,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other plane to compare.</param>
/// <returns>Whether or not the planes are exactly equal.</returns>
- public bool Equals(Plane other)
+ public readonly bool Equals(Plane other)
{
return _normal == other._normal && D == other.D;
}
@@ -384,7 +384,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other plane to compare.</param>
/// <returns>Whether or not the planes are approximately equal.</returns>
- public bool IsEqualApprox(Plane other)
+ public readonly bool IsEqualApprox(Plane other)
{
return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(D, other.D);
}
@@ -393,7 +393,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Plane"/>.
/// </summary>
/// <returns>A hash code for this plane.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _normal.GetHashCode() ^ D.GetHashCode();
}
@@ -402,7 +402,7 @@ namespace Godot
/// Converts this <see cref="Plane"/> to a string.
/// </summary>
/// <returns>A string representation of this plane.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_normal}, {D}";
}
@@ -411,7 +411,7 @@ namespace Godot
/// Converts this <see cref="Plane"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this plane.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_normal.ToString(format)}, {D.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
index da895fd121..371729ebec 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
@@ -286,7 +286,7 @@ namespace Godot
return proj * cm;
}
- public real_t Determinant()
+ public readonly real_t Determinant()
{
return x.w * y.z * z.y * w.x - x.z * y.w * z.y * w.x -
x.w * y.y * z.z * w.x + x.y * y.w * z.z * w.x +
@@ -302,13 +302,13 @@ namespace Godot
x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w;
}
- public real_t GetAspect()
+ public readonly real_t GetAspect()
{
Vector2 vpHe = GetViewportHalfExtents();
return vpHe.x / vpHe.y;
}
- public real_t GetFov()
+ public readonly real_t GetFov()
{
Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized();
if (z.x == 0 && z.y == 0)
@@ -327,7 +327,7 @@ namespace Godot
return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0);
}
- public real_t GetLodMultiplier()
+ public readonly real_t GetLodMultiplier()
{
if (IsOrthogonal())
{
@@ -341,14 +341,14 @@ namespace Godot
}
}
- public int GetPixelsPerMeter(int forPixelWidth)
+ public readonly int GetPixelsPerMeter(int forPixelWidth)
{
Vector3 result = this * new Vector3(1, 0, -1);
return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth);
}
- public Plane GetProjectionPlane(Planes plane)
+ public readonly Plane GetProjectionPlane(Planes plane)
{
Plane newPlane = plane switch
{
@@ -364,36 +364,36 @@ namespace Godot
return newPlane.Normalized();
}
- public Vector2 GetFarPlaneHalfExtents()
+ public readonly Vector2 GetFarPlaneHalfExtents()
{
var res = GetProjectionPlane(Planes.Far).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
return new Vector2(res.Value.x, res.Value.y);
}
- public Vector2 GetViewportHalfExtents()
+ public readonly Vector2 GetViewportHalfExtents()
{
var res = GetProjectionPlane(Planes.Near).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
return new Vector2(res.Value.x, res.Value.y);
}
- public real_t GetZFar()
+ public readonly real_t GetZFar()
{
return GetProjectionPlane(Planes.Far).D;
}
- public real_t GetZNear()
+ public readonly real_t GetZNear()
{
return -GetProjectionPlane(Planes.Near).D;
}
- public Projection FlippedY()
+ public readonly Projection FlippedY()
{
Projection proj = this;
proj.y = -proj.y;
return proj;
}
- public Projection PerspectiveZNearAdjusted(real_t newZNear)
+ public readonly Projection PerspectiveZNearAdjusted(real_t newZNear)
{
Projection proj = this;
real_t zFar = GetZFar();
@@ -404,7 +404,7 @@ namespace Godot
return proj;
}
- public Projection JitterOffseted(Vector2 offset)
+ public readonly Projection JitterOffseted(Vector2 offset)
{
Projection proj = this;
proj.w.x += offset.x;
@@ -412,7 +412,7 @@ namespace Godot
return proj;
}
- public Projection Inverse()
+ public readonly Projection Inverse()
{
Projection proj = this;
int i, j, k;
@@ -535,7 +535,7 @@ namespace Godot
return proj;
}
- public bool IsOrthogonal()
+ public readonly bool IsOrthogonal()
{
return w.w == (real_t)1.0;
}
@@ -654,7 +654,7 @@ namespace Godot
/// </exception>
public Vector4 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -702,7 +702,7 @@ namespace Godot
/// </exception>
public real_t this[int column, int row]
{
- get
+ readonly get
{
switch (column)
{
@@ -772,7 +772,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Projection"/>.
/// </summary>
/// <returns>A hash code for this projection.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -781,7 +781,7 @@ namespace Godot
/// Converts this <see cref="Projection"/> to a string.
/// </summary>
/// <returns>A string representation of this projection.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{x.x}, {x.y}, {x.z}, {x.w}\n{y.x}, {y.y}, {y.z}, {y.w}\n{z.x}, {z.y}, {z.z}, {z.w}\n{w.x}, {w.y}, {w.z}, {w.w}\n";
}
@@ -790,7 +790,7 @@ namespace Godot
/// Converts this <see cref="Projection"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this projection.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{x.x.ToString(format)}, {x.y.ToString(format)}, {x.z.ToString(format)}, {x.w.ToString(format)}\n" +
$"{y.x.ToString(format)}, {y.y.ToString(format)}, {y.z.ToString(format)}, {y.w.ToString(format)}\n" +
@@ -804,7 +804,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Projection other && Equals(other);
}
@@ -814,7 +814,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other projection.</param>
/// <returns>Whether or not the projections are exactly equal.</returns>
- public bool Equals(Projection other)
+ public readonly bool Equals(Projection other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
index f01f0be985..c55003586b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -101,7 +101,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <value>Equivalent to <c>Mathf.Sqrt(LengthSquared)</c>.</value>
- public real_t Length
+ public readonly real_t Length
{
get { return Mathf.Sqrt(LengthSquared); }
}
@@ -112,7 +112,7 @@ namespace Godot
/// you need to compare quaternions or need the squared length for some formula.
/// </summary>
/// <value>Equivalent to <c>Dot(this)</c>.</value>
- public real_t LengthSquared
+ public readonly real_t LengthSquared
{
get { return Dot(this); }
}
@@ -128,7 +128,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other quaternion.</param>
/// <returns>The angle between the quaternions.</returns>
- public real_t AngleTo(Quaternion to)
+ public readonly real_t AngleTo(Quaternion to)
{
real_t dot = Dot(to);
return Mathf.Acos(Mathf.Clamp(dot * dot * 2 - 1, -1, 1));
@@ -143,7 +143,7 @@ namespace Godot
/// <param name="postB">A quaternion after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated quaternion.</returns>
- public Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
+ public readonly Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -212,7 +212,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated quaternion.</returns>
- public Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT)
+ public readonly Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT)
{
#if DEBUG
if (!IsNormalized())
@@ -272,12 +272,12 @@ namespace Godot
/// </summary>
/// <param name="b">The other quaternion.</param>
/// <returns>The dot product.</returns>
- public real_t Dot(Quaternion b)
+ public readonly real_t Dot(Quaternion b)
{
return (x * b.x) + (y * b.y) + (z * b.z) + (w * b.w);
}
- public Quaternion Exp()
+ public readonly Quaternion Exp()
{
Vector3 v = new Vector3(x, y, z);
real_t theta = v.Length();
@@ -289,12 +289,12 @@ namespace Godot
return new Quaternion(v, theta);
}
- public real_t GetAngle()
+ public readonly real_t GetAngle()
{
return 2 * Mathf.Acos(w);
}
- public Vector3 GetAxis()
+ public readonly Vector3 GetAxis()
{
if (Mathf.Abs(w) > 1 - Mathf.Epsilon)
{
@@ -312,7 +312,7 @@ namespace Godot
/// the rotation angles in the format (X angle, Y angle, Z angle).
/// </summary>
/// <returns>The Euler angle representation of this quaternion.</returns>
- public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
+ public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
{
#if DEBUG
if (!IsNormalized())
@@ -328,7 +328,7 @@ namespace Godot
/// Returns the inverse of the quaternion.
/// </summary>
/// <returns>The inverse quaternion.</returns>
- public Quaternion Inverse()
+ public readonly Quaternion Inverse()
{
#if DEBUG
if (!IsNormalized())
@@ -343,12 +343,12 @@ namespace Godot
/// Returns whether the quaternion is normalized or not.
/// </summary>
/// <returns>A <see langword="bool"/> for whether the quaternion is normalized or not.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
}
- public Quaternion Log()
+ public readonly Quaternion Log()
{
Vector3 v = GetAxis() * GetAngle();
return new Quaternion(v.x, v.y, v.z, 0);
@@ -358,7 +358,7 @@ namespace Godot
/// Returns a copy of the quaternion, normalized to unit length.
/// </summary>
/// <returns>The normalized quaternion.</returns>
- public Quaternion Normalized()
+ public readonly Quaternion Normalized()
{
return this / Length;
}
@@ -372,7 +372,7 @@ namespace Godot
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting quaternion of the interpolation.</returns>
- public Quaternion Slerp(Quaternion to, real_t weight)
+ public readonly Quaternion Slerp(Quaternion to, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -437,7 +437,7 @@ namespace Godot
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting quaternion of the interpolation.</returns>
- public Quaternion Slerpni(Quaternion to, real_t weight)
+ public readonly Quaternion Slerpni(Quaternion to, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -762,7 +762,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the quaternion and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Quaternion other && Equals(other);
}
@@ -772,7 +772,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other quaternion to compare.</param>
/// <returns>Whether or not the quaternions are exactly equal.</returns>
- public bool Equals(Quaternion other)
+ public readonly bool Equals(Quaternion other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -783,7 +783,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other quaternion to compare.</param>
/// <returns>Whether or not the quaternions are approximately equal.</returns>
- public bool IsEqualApprox(Quaternion other)
+ public readonly bool IsEqualApprox(Quaternion other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
}
@@ -792,7 +792,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Quaternion"/>.
/// </summary>
/// <returns>A hash code for this quaternion.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -801,7 +801,7 @@ namespace Godot
/// Converts this <see cref="Quaternion"/> to a string.
/// </summary>
/// <returns>A string representation of this quaternion.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z}, {w})";
}
@@ -810,7 +810,7 @@ namespace Godot
/// Converts this <see cref="Quaternion"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this quaternion.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
index a31fef8360..59b9faf16c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
@@ -12,9 +12,9 @@ namespace Godot
/// classes such as <see cref="RenderingServer"/>.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
- public struct RID
+ public readonly struct RID
{
- private ulong _id; // Default is 0
+ private readonly ulong _id; // Default is 0
internal RID(ulong id)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index e80d75dacf..b0e0e75a34 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2 Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2 Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector2 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -53,7 +53,7 @@ namespace Godot
/// The area of this <see cref="Rect2"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public real_t Area
+ public readonly real_t Area
{
get { return GetArea(); }
}
@@ -63,7 +63,7 @@ namespace Godot
/// the top-left corner is the origin and width and height are positive.
/// </summary>
/// <returns>The modified <see cref="Rect2"/>.</returns>
- public Rect2 Abs()
+ public readonly Rect2 Abs()
{
Vector2 end = End;
Vector2 topLeft = new Vector2(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
@@ -79,7 +79,7 @@ namespace Godot
/// The intersection of this <see cref="Rect2"/> and <paramref name="b"/>,
/// or an empty <see cref="Rect2"/> if they do not intersect.
/// </returns>
- public Rect2 Intersection(Rect2 b)
+ public readonly Rect2 Intersection(Rect2 b)
{
Rect2 newRect = b;
@@ -107,7 +107,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="Rect2"/> encloses <paramref name="b"/>.
/// </returns>
- public bool Encloses(Rect2 b)
+ public readonly bool Encloses(Rect2 b)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
b._position.x + b._size.x < _position.x + _size.x &&
@@ -119,7 +119,7 @@ namespace Godot
/// </summary>
/// <param name="to">The point to include.</param>
/// <returns>The expanded <see cref="Rect2"/>.</returns>
- public Rect2 Expand(Vector2 to)
+ public readonly Rect2 Expand(Vector2 to)
{
Rect2 expanded = this;
@@ -154,7 +154,7 @@ namespace Godot
/// Returns the area of the <see cref="Rect2"/>.
/// </summary>
/// <returns>The area.</returns>
- public real_t GetArea()
+ public readonly real_t GetArea()
{
return _size.x * _size.y;
}
@@ -164,7 +164,7 @@ namespace Godot
/// to <see cref="Position"/> + (<see cref="Size"/> / 2).
/// </summary>
/// <returns>The center.</returns>
- public Vector2 GetCenter()
+ public readonly Vector2 GetCenter()
{
return _position + (_size * 0.5f);
}
@@ -177,7 +177,7 @@ namespace Godot
/// <seealso cref="GrowSide(Side, real_t)"/>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 Grow(real_t by)
+ public readonly Rect2 Grow(real_t by)
{
Rect2 g = this;
@@ -200,7 +200,7 @@ namespace Godot
/// <param name="right">The amount to grow by on the right side.</param>
/// <param name="bottom">The amount to grow by on the bottom side.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
+ public readonly Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
{
Rect2 g = this;
@@ -221,7 +221,7 @@ namespace Godot
/// <param name="side">The side to grow.</param>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 GrowSide(Side side, real_t by)
+ public readonly Rect2 GrowSide(Side side, real_t by)
{
Rect2 g = this;
@@ -242,7 +242,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> has area.
/// </returns>
- public bool HasArea()
+ public readonly bool HasArea()
{
return _size.x > 0.0f && _size.y > 0.0f;
}
@@ -255,7 +255,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector2 point)
+ public readonly bool HasPoint(Vector2 point)
{
if (point.x < _position.x)
return false;
@@ -281,7 +281,7 @@ namespace Godot
/// <param name="b">The other <see cref="Rect2"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
/// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
- public bool Intersects(Rect2 b, bool includeBorders = false)
+ public readonly bool Intersects(Rect2 b, bool includeBorders = false)
{
if (includeBorders)
{
@@ -330,7 +330,7 @@ namespace Godot
/// </summary>
/// <param name="b">The other <see cref="Rect2"/>.</param>
/// <returns>The merged <see cref="Rect2"/>.</returns>
- public Rect2 Merge(Rect2 b)
+ public readonly Rect2 Merge(Rect2 b)
{
Rect2 newRect;
@@ -426,7 +426,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the rect and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Rect2 other && Equals(other);
}
@@ -436,7 +436,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are exactly equal.</returns>
- public bool Equals(Rect2 other)
+ public readonly bool Equals(Rect2 other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
@@ -447,7 +447,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are approximately equal.</returns>
- public bool IsEqualApprox(Rect2 other)
+ public readonly bool IsEqualApprox(Rect2 other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size);
}
@@ -456,7 +456,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Rect2"/>.
/// </summary>
/// <returns>A hash code for this rect.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -465,7 +465,7 @@ namespace Godot
/// Converts this <see cref="Rect2"/> to a string.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -474,7 +474,7 @@ namespace Godot
/// Converts this <see cref="Rect2"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
index b2768476cc..faee81a98a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2i Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2i Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector2i End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -53,7 +53,7 @@ namespace Godot
/// The area of this <see cref="Rect2i"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public int Area
+ public readonly int Area
{
get { return GetArea(); }
}
@@ -63,7 +63,7 @@ namespace Godot
/// the top-left corner is the origin and width and height are positive.
/// </summary>
/// <returns>The modified <see cref="Rect2i"/>.</returns>
- public Rect2i Abs()
+ public readonly Rect2i Abs()
{
Vector2i end = End;
Vector2i topLeft = new Vector2i(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
@@ -79,7 +79,7 @@ namespace Godot
/// The intersection of this <see cref="Rect2i"/> and <paramref name="b"/>,
/// or an empty <see cref="Rect2i"/> if they do not intersect.
/// </returns>
- public Rect2i Intersection(Rect2i b)
+ public readonly Rect2i Intersection(Rect2i b)
{
Rect2i newRect = b;
@@ -107,7 +107,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="Rect2i"/> encloses <paramref name="b"/>.
/// </returns>
- public bool Encloses(Rect2i b)
+ public readonly bool Encloses(Rect2i b)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
b._position.x + b._size.x < _position.x + _size.x &&
@@ -119,7 +119,7 @@ namespace Godot
/// </summary>
/// <param name="to">The point to include.</param>
/// <returns>The expanded <see cref="Rect2i"/>.</returns>
- public Rect2i Expand(Vector2i to)
+ public readonly Rect2i Expand(Vector2i to)
{
Rect2i expanded = this;
@@ -154,7 +154,7 @@ namespace Godot
/// Returns the area of the <see cref="Rect2i"/>.
/// </summary>
/// <returns>The area.</returns>
- public int GetArea()
+ public readonly int GetArea()
{
return _size.x * _size.y;
}
@@ -166,7 +166,7 @@ namespace Godot
/// value will be rounded towards <see cref="Position"/>.
/// </summary>
/// <returns>The center.</returns>
- public Vector2i GetCenter()
+ public readonly Vector2i GetCenter()
{
return _position + (_size / 2);
}
@@ -179,7 +179,7 @@ namespace Godot
/// <seealso cref="GrowSide(Side, int)"/>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i Grow(int by)
+ public readonly Rect2i Grow(int by)
{
Rect2i g = this;
@@ -202,7 +202,7 @@ namespace Godot
/// <param name="right">The amount to grow by on the right side.</param>
/// <param name="bottom">The amount to grow by on the bottom side.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i GrowIndividual(int left, int top, int right, int bottom)
+ public readonly Rect2i GrowIndividual(int left, int top, int right, int bottom)
{
Rect2i g = this;
@@ -223,7 +223,7 @@ namespace Godot
/// <param name="side">The side to grow.</param>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i GrowSide(Side side, int by)
+ public readonly Rect2i GrowSide(Side side, int by)
{
Rect2i g = this;
@@ -244,7 +244,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> has area.
/// </returns>
- public bool HasArea()
+ public readonly bool HasArea()
{
return _size.x > 0 && _size.y > 0;
}
@@ -257,7 +257,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector2i point)
+ public readonly bool HasPoint(Vector2i point)
{
if (point.x < _position.x)
return false;
@@ -283,7 +283,7 @@ namespace Godot
/// <param name="b">The other <see cref="Rect2i"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
/// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
- public bool Intersects(Rect2i b, bool includeBorders = false)
+ public readonly bool Intersects(Rect2i b, bool includeBorders = false)
{
if (includeBorders)
{
@@ -316,7 +316,7 @@ namespace Godot
/// </summary>
/// <param name="b">The other <see cref="Rect2i"/>.</param>
/// <returns>The merged <see cref="Rect2i"/>.</returns>
- public Rect2i Merge(Rect2i b)
+ public readonly Rect2i Merge(Rect2i b)
{
Rect2i newRect;
@@ -426,7 +426,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the rect and the other object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Rect2i other && Equals(other);
}
@@ -436,7 +436,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are equal.</returns>
- public bool Equals(Rect2i other)
+ public readonly bool Equals(Rect2i other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
@@ -445,7 +445,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Rect2i"/>.
/// </summary>
/// <returns>A hash code for this rect.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -454,7 +454,7 @@ namespace Godot
/// Converts this <see cref="Rect2i"/> to a string.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -463,7 +463,7 @@ namespace Godot
/// Converts this <see cref="Rect2i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index 894667db76..756f71e5b2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -37,7 +37,7 @@ namespace Godot
/// <value>Getting is equivalent to calling <see cref="Mathf.Atan2(real_t, real_t)"/> with the values of <see cref="x"/>.</value>
public real_t Rotation
{
- get
+ readonly get
{
return Mathf.Atan2(x.y, x.x);
}
@@ -57,7 +57,7 @@ namespace Godot
/// <value>Equivalent to the lengths of each column vector, but Y is negative if the determinant is negative.</value>
public Vector2 Scale
{
- get
+ readonly get
{
real_t detSign = Mathf.Sign(BasisDeterminant());
return new Vector2(x.Length(), detSign * y.Length());
@@ -80,7 +80,7 @@ namespace Godot
/// </exception>
public Vector2 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -121,7 +121,7 @@ namespace Godot
/// <param name="row">Which row, the matrix vertical position.</param>
public real_t this[int column, int row]
{
- get
+ readonly get
{
return this[column][row];
}
@@ -139,7 +139,7 @@ namespace Godot
/// </summary>
/// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
- public Transform2D AffineInverse()
+ public readonly Transform2D AffineInverse()
{
real_t det = BasisDeterminant();
@@ -148,9 +148,8 @@ namespace Godot
Transform2D inv = this;
- real_t temp = inv[0, 0];
- inv[0, 0] = inv[1, 1];
- inv[1, 1] = temp;
+ inv[0, 0] = this[1, 1];
+ inv[1, 1] = this[0, 0];
real_t detInv = 1.0f / det;
@@ -171,7 +170,7 @@ namespace Godot
/// and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
- private real_t BasisDeterminant()
+ private readonly real_t BasisDeterminant()
{
return (x.x * y.y) - (x.y * y.x);
}
@@ -183,7 +182,7 @@ namespace Godot
/// <seealso cref="BasisXformInv(Vector2)"/>
/// <param name="v">A vector to transform.</param>
/// <returns>The transformed vector.</returns>
- public Vector2 BasisXform(Vector2 v)
+ public readonly Vector2 BasisXform(Vector2 v)
{
return new Vector2(Tdotx(v), Tdoty(v));
}
@@ -198,7 +197,7 @@ namespace Godot
/// <seealso cref="BasisXform(Vector2)"/>
/// <param name="v">A vector to inversely transform.</param>
/// <returns>The inversely transformed vector.</returns>
- public Vector2 BasisXformInv(Vector2 v)
+ public readonly Vector2 BasisXformInv(Vector2 v)
{
return new Vector2(x.Dot(v), y.Dot(v));
}
@@ -209,7 +208,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform2D InterpolateWith(Transform2D transform, real_t weight)
+ public readonly Transform2D InterpolateWith(Transform2D transform, real_t weight)
{
real_t r1 = Rotation;
real_t r2 = transform.Rotation;
@@ -258,14 +257,13 @@ namespace Godot
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Transform2D Inverse()
+ public readonly Transform2D Inverse()
{
Transform2D inv = this;
// Swap
- real_t temp = inv.x.y;
- inv.x.y = inv.y.x;
- inv.y.x = temp;
+ inv.x.y = y.x;
+ inv.y.x = x.y;
inv.origin = inv.BasisXform(-inv.origin);
@@ -277,7 +275,7 @@ namespace Godot
/// and normalized axis vectors (scale of 1 or -1).
/// </summary>
/// <returns>The orthonormalized transform.</returns>
- public Transform2D Orthonormalized()
+ public readonly Transform2D Orthonormalized()
{
Transform2D on = this;
@@ -301,7 +299,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform2D Rotated(real_t angle)
+ public readonly Transform2D Rotated(real_t angle)
{
return this * new Transform2D(angle, new Vector2());
}
@@ -313,7 +311,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform2D RotatedLocal(real_t angle)
+ public readonly Transform2D RotatedLocal(real_t angle)
{
return new Transform2D(angle, new Vector2()) * this;
}
@@ -325,7 +323,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform2D Scaled(Vector2 scale)
+ public readonly Transform2D Scaled(Vector2 scale)
{
Transform2D copy = this;
copy.x *= scale;
@@ -341,7 +339,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform2D ScaledLocal(Vector2 scale)
+ public readonly Transform2D ScaledLocal(Vector2 scale)
{
Transform2D copy = this;
copy.x *= scale;
@@ -349,12 +347,12 @@ namespace Godot
return copy;
}
- private real_t Tdotx(Vector2 with)
+ private readonly real_t Tdotx(Vector2 with)
{
return (this[0, 0] * with[0]) + (this[1, 0] * with[1]);
}
- private real_t Tdoty(Vector2 with)
+ private readonly real_t Tdoty(Vector2 with)
{
return (this[0, 1] * with[0]) + (this[1, 1] * with[1]);
}
@@ -366,7 +364,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform2D Translated(Vector2 offset)
+ public readonly Transform2D Translated(Vector2 offset)
{
Transform2D copy = this;
copy.origin += offset;
@@ -380,7 +378,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform2D TranslatedLocal(Vector2 offset)
+ public readonly Transform2D TranslatedLocal(Vector2 offset)
{
Transform2D copy = this;
copy.origin += copy.BasisXform(offset);
@@ -603,7 +601,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the transform and the object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Transform2D other && Equals(other);
}
@@ -615,7 +613,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are exactly equal.</returns>
- public bool Equals(Transform2D other)
+ public readonly bool Equals(Transform2D other)
{
return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin);
}
@@ -626,7 +624,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform2D other)
+ public readonly bool IsEqualApprox(Transform2D other)
{
return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && origin.IsEqualApprox(other.origin);
}
@@ -635,7 +633,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Transform2D"/>.
/// </summary>
/// <returns>A hash code for this transform.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ origin.GetHashCode();
}
@@ -644,7 +642,7 @@ namespace Godot
/// Converts this <see cref="Transform2D"/> to a string.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {x}, Y: {y}, O: {origin}]";
}
@@ -653,7 +651,7 @@ namespace Godot
/// Converts this <see cref="Transform2D"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, O: {origin.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index 2f7891e7ef..39167bd116 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -37,7 +37,7 @@ namespace Godot
/// </exception>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -83,7 +83,7 @@ namespace Godot
/// <param name="row">Which row, the matrix vertical position.</param>
public real_t this[int column, int row]
{
- get
+ readonly get
{
if (column == 3)
{
@@ -108,7 +108,7 @@ namespace Godot
/// </summary>
/// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
- public Transform3D AffineInverse()
+ public readonly Transform3D AffineInverse()
{
Basis basisInv = basis.Inverse();
return new Transform3D(basisInv, basisInv * -origin);
@@ -120,7 +120,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform3D InterpolateWith(Transform3D transform, real_t weight)
+ public readonly Transform3D InterpolateWith(Transform3D transform, real_t weight)
{
Basis retBasis = basis.Lerp(transform.basis, weight);
Vector3 retOrigin = origin.Lerp(transform.origin, weight);
@@ -133,7 +133,7 @@ namespace Godot
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Transform3D Inverse()
+ public readonly Transform3D Inverse()
{
Basis basisTr = basis.Transposed();
return new Transform3D(basisTr, basisTr * -origin);
@@ -164,7 +164,7 @@ namespace Godot
/// and normalized axis vectors (scale of 1 or -1).
/// </summary>
/// <returns>The orthonormalized transform.</returns>
- public Transform3D Orthonormalized()
+ public readonly Transform3D Orthonormalized()
{
return new Transform3D(basis.Orthonormalized(), origin);
}
@@ -192,7 +192,7 @@ namespace Godot
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform3D RotatedLocal(Vector3 axis, real_t angle)
+ public readonly Transform3D RotatedLocal(Vector3 axis, real_t angle)
{
Basis tmpBasis = new Basis(axis, angle);
return new Transform3D(basis * tmpBasis, origin);
@@ -205,7 +205,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform3D Scaled(Vector3 scale)
+ public readonly Transform3D Scaled(Vector3 scale)
{
return new Transform3D(basis.Scaled(scale), origin * scale);
}
@@ -217,7 +217,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform3D ScaledLocal(Vector3 scale)
+ public readonly Transform3D ScaledLocal(Vector3 scale)
{
Basis tmpBasis = Basis.FromScale(scale);
return new Transform3D(basis * tmpBasis, origin);
@@ -230,7 +230,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight)
+ public readonly Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight)
{
/* not sure if very "efficient" but good enough? */
@@ -281,7 +281,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform3D Translated(Vector3 offset)
+ public readonly Transform3D Translated(Vector3 offset)
{
return new Transform3D(basis, origin + offset);
}
@@ -293,7 +293,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform3D TranslatedLocal(Vector3 offset)
+ public readonly Transform3D TranslatedLocal(Vector3 offset)
{
return new Transform3D(basis, new Vector3
(
@@ -617,7 +617,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform3D other)
+ public readonly bool IsEqualApprox(Transform3D other)
{
return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
}
@@ -626,7 +626,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Transform3D"/>.
/// </summary>
/// <returns>A hash code for this transform.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return basis.GetHashCode() ^ origin.GetHashCode();
}
@@ -635,7 +635,7 @@ namespace Godot
/// Converts this <see cref="Transform3D"/> to a string.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {basis.x}, Y: {basis.y}, Z: {basis.z}, O: {origin}]";
}
@@ -644,7 +644,7 @@ namespace Godot
/// Converts this <see cref="Transform3D"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {basis.x.ToString(format)}, Y: {basis.y.ToString(format)}, Z: {basis.z.ToString(format)}, O: {origin.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 87f397891e..535391f447 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -48,7 +48,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -79,7 +79,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y)
+ public readonly void Deconstruct(out real_t x, out real_t y)
{
x = this.x;
y = this.y;
@@ -105,7 +105,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
- public Vector2 Abs()
+ public readonly Vector2 Abs()
{
return new Vector2(Mathf.Abs(x), Mathf.Abs(y));
}
@@ -117,7 +117,7 @@ namespace Godot
/// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
/// </summary>
/// <returns>The angle of this vector, in radians.</returns>
- public real_t Angle()
+ public readonly real_t Angle()
{
return Mathf.Atan2(y, x);
}
@@ -127,7 +127,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector2 to)
+ public readonly real_t AngleTo(Vector2 to)
{
return Mathf.Atan2(Cross(to), Dot(to));
}
@@ -137,7 +137,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleToPoint(Vector2 to)
+ public readonly real_t AngleToPoint(Vector2 to)
{
return Mathf.Atan2(y - to.y, x - to.x);
}
@@ -146,7 +146,7 @@ namespace Godot
/// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
/// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
- public real_t Aspect()
+ public readonly real_t Aspect()
{
return x / y;
}
@@ -156,7 +156,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
/// <returns>The bounced vector.</returns>
- public Vector2 Bounce(Vector2 normal)
+ public readonly Vector2 Bounce(Vector2 normal)
{
return -Reflect(normal);
}
@@ -165,7 +165,7 @@ namespace Godot
/// Returns a new vector with all components rounded up (towards positive infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
- public Vector2 Ceil()
+ public readonly Vector2 Ceil()
{
return new Vector2(Mathf.Ceil(x), Mathf.Ceil(y));
}
@@ -178,7 +178,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector2 Clamp(Vector2 min, Vector2 max)
+ public readonly Vector2 Clamp(Vector2 min, Vector2 max)
{
return new Vector2
(
@@ -192,7 +192,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product value.</returns>
- public real_t Cross(Vector2 with)
+ public readonly real_t Cross(Vector2 with)
{
return (x * with.y) - (y * with.x);
}
@@ -206,7 +206,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight)
+ public readonly Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight)
{
return new Vector2
(
@@ -229,7 +229,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector2
(
@@ -247,7 +247,7 @@ namespace Godot
/// <param name="end">The destination vector.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
+ public readonly Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
{
// Formula from Wikipedia article on Bezier curves
real_t omt = 1 - t;
@@ -264,7 +264,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector2 DirectionTo(Vector2 to)
+ public readonly Vector2 DirectionTo(Vector2 to)
{
return new Vector2(to.x - x, to.y - y).Normalized();
}
@@ -276,7 +276,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector2 to)
+ public readonly real_t DistanceSquaredTo(Vector2 to)
{
return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y);
}
@@ -286,7 +286,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector2 to)
+ public readonly real_t DistanceTo(Vector2 to)
{
return Mathf.Sqrt((x - to.x) * (x - to.x) + (y - to.y) * (y - to.y));
}
@@ -296,7 +296,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector2 with)
+ public readonly real_t Dot(Vector2 with)
{
return (x * with.x) + (y * with.y);
}
@@ -305,7 +305,7 @@ namespace Godot
/// Returns a new vector with all components rounded down (towards negative infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
- public Vector2 Floor()
+ public readonly Vector2 Floor()
{
return new Vector2(Mathf.Floor(x), Mathf.Floor(y));
}
@@ -314,7 +314,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector2(1 / v.x, 1 / v.y)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector2 Inverse()
+ public readonly Vector2 Inverse()
{
return new Vector2(1 / x, 1 / y);
}
@@ -323,7 +323,7 @@ namespace Godot
/// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
/// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -333,7 +333,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
return Mathf.Sqrt((x * x) + (y * y));
}
@@ -344,7 +344,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public real_t LengthSquared()
+ public readonly real_t LengthSquared()
{
return (x * x) + (y * y);
}
@@ -356,7 +356,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector2 Lerp(Vector2 to, real_t weight)
+ public readonly Vector2 Lerp(Vector2 to, real_t weight)
{
return new Vector2
(
@@ -374,7 +374,7 @@ namespace Godot
/// A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.
/// </param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector2 Lerp(Vector2 to, Vector2 weight)
+ public readonly Vector2 Lerp(Vector2 to, Vector2 weight)
{
return new Vector2
(
@@ -388,7 +388,7 @@ namespace Godot
/// </summary>
/// <param name="length">The length to limit to.</param>
/// <returns>The vector with its length limited.</returns>
- public Vector2 LimitLength(real_t length = 1.0f)
+ public readonly Vector2 LimitLength(real_t length = 1.0f)
{
Vector2 v = this;
real_t l = Length();
@@ -407,7 +407,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? Axis.Y : Axis.X;
}
@@ -417,7 +417,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? Axis.X : Axis.Y;
}
@@ -428,7 +428,7 @@ namespace Godot
/// <param name="to">The vector to move towards.</param>
/// <param name="delta">The amount to move towards by.</param>
/// <returns>The resulting vector.</returns>
- public Vector2 MoveToward(Vector2 to, real_t delta)
+ public readonly Vector2 MoveToward(Vector2 to, real_t delta)
{
Vector2 v = this;
Vector2 vd = to - v;
@@ -443,7 +443,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector2 Normalized()
+ public readonly Vector2 Normalized()
{
Vector2 v = this;
v.Normalize();
@@ -458,7 +458,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector2 PosMod(real_t mod)
+ public readonly Vector2 PosMod(real_t mod)
{
Vector2 v;
v.x = Mathf.PosMod(x, mod);
@@ -474,7 +474,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector2 PosMod(Vector2 modv)
+ public readonly Vector2 PosMod(Vector2 modv)
{
Vector2 v;
v.x = Mathf.PosMod(x, modv.x);
@@ -487,7 +487,7 @@ namespace Godot
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
- public Vector2 Project(Vector2 onNormal)
+ public readonly Vector2 Project(Vector2 onNormal)
{
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
}
@@ -497,7 +497,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
- public Vector2 Reflect(Vector2 normal)
+ public readonly Vector2 Reflect(Vector2 normal)
{
#if DEBUG
if (!normal.IsNormalized())
@@ -513,7 +513,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
- public Vector2 Rotated(real_t angle)
+ public readonly Vector2 Rotated(real_t angle)
{
real_t sine = Mathf.Sin(angle);
real_t cosi = Mathf.Cos(angle);
@@ -527,7 +527,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector2 Round()
+ public readonly Vector2 Round()
{
return new Vector2(Mathf.Round(x), Mathf.Round(y));
}
@@ -538,7 +538,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector2 Sign()
+ public readonly Vector2 Sign()
{
Vector2 v;
v.x = Mathf.Sign(x);
@@ -557,7 +557,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector2 Slerp(Vector2 to, real_t weight)
+ public readonly Vector2 Slerp(Vector2 to, real_t weight)
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
@@ -577,7 +577,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
- public Vector2 Slide(Vector2 normal)
+ public readonly Vector2 Slide(Vector2 normal)
{
return this - (normal * Dot(normal));
}
@@ -588,7 +588,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector2 Snapped(Vector2 step)
+ public readonly Vector2 Snapped(Vector2 step)
{
return new Vector2(Mathf.Snapped(x, step.x), Mathf.Snapped(y, step.y));
}
@@ -598,7 +598,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Orthogonal()
+ public readonly Vector2 Orthogonal()
{
return new Vector2(y, -x);
}
@@ -946,7 +946,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector2 other && Equals(other);
}
@@ -958,7 +958,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector2 other)
+ public readonly bool Equals(Vector2 other)
{
return x == other.x && y == other.y;
}
@@ -969,7 +969,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector2 other)
+ public readonly bool IsEqualApprox(Vector2 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
}
@@ -978,7 +978,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector2"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
}
@@ -987,7 +987,7 @@ namespace Godot
/// Converts this <see cref="Vector2"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y})";
}
@@ -996,7 +996,7 @@ namespace Godot
/// Converts this <see cref="Vector2"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
index bdadf696e3..08f2a3a8af 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -48,7 +48,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -79,7 +79,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y)
+ public readonly void Deconstruct(out int x, out int y)
{
x = this.x;
y = this.y;
@@ -89,7 +89,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
- public Vector2i Abs()
+ public readonly Vector2i Abs()
{
return new Vector2i(Mathf.Abs(x), Mathf.Abs(y));
}
@@ -101,7 +101,7 @@ namespace Godot
/// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
/// </summary>
/// <returns>The angle of this vector, in radians.</returns>
- public real_t Angle()
+ public readonly real_t Angle()
{
return Mathf.Atan2(y, x);
}
@@ -111,7 +111,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector2i to)
+ public readonly real_t AngleTo(Vector2i to)
{
return Mathf.Atan2(Cross(to), Dot(to));
}
@@ -121,7 +121,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleToPoint(Vector2i to)
+ public readonly real_t AngleToPoint(Vector2i to)
{
return Mathf.Atan2(y - to.y, x - to.x);
}
@@ -130,7 +130,7 @@ namespace Godot
/// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
/// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
- public real_t Aspect()
+ public readonly real_t Aspect()
{
return x / (real_t)y;
}
@@ -143,7 +143,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector2i Clamp(Vector2i min, Vector2i max)
+ public readonly Vector2i Clamp(Vector2i min, Vector2i max)
{
return new Vector2i
(
@@ -157,7 +157,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product vector.</returns>
- public int Cross(Vector2i with)
+ public readonly int Cross(Vector2i with)
{
return x * with.y - y * with.x;
}
@@ -169,7 +169,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector2i to)
+ public readonly int DistanceSquaredTo(Vector2i to)
{
return (to - this).LengthSquared();
}
@@ -179,7 +179,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector2i to)
+ public readonly real_t DistanceTo(Vector2i to)
{
return (to - this).Length();
}
@@ -189,7 +189,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector2i with)
+ public readonly int Dot(Vector2i with)
{
return x * with.x + y * with.y;
}
@@ -199,7 +199,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -213,7 +213,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public int LengthSquared()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -226,7 +226,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? Axis.Y : Axis.X;
}
@@ -236,7 +236,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? Axis.X : Axis.Y;
}
@@ -249,7 +249,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector2i PosMod(int mod)
+ public readonly Vector2i PosMod(int mod)
{
Vector2i v = this;
v.x = Mathf.PosMod(v.x, mod);
@@ -265,7 +265,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector2i PosMod(Vector2i modv)
+ public readonly Vector2i PosMod(Vector2i modv)
{
Vector2i v = this;
v.x = Mathf.PosMod(v.x, modv.x);
@@ -279,7 +279,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector2i Sign()
+ public readonly Vector2i Sign()
{
Vector2i v = this;
v.x = Mathf.Sign(v.x);
@@ -292,7 +292,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2i Orthogonal()
+ public readonly Vector2i Orthogonal()
{
return new Vector2i(y, -x);
}
@@ -665,7 +665,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector2i other && Equals(other);
}
@@ -675,7 +675,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector2i other)
+ public readonly bool Equals(Vector2i other)
{
return x == other.x && y == other.y;
}
@@ -684,7 +684,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector2i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
}
@@ -693,7 +693,7 @@ namespace Godot
/// Converts this <see cref="Vector2i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y})";
}
@@ -702,7 +702,7 @@ namespace Godot
/// Converts this <see cref="Vector2i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 6649f3b784..53bd0b0908 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -94,7 +94,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y, out real_t z)
+ public readonly void Deconstruct(out real_t x, out real_t y, out real_t z)
{
x = this.x;
y = this.y;
@@ -122,7 +122,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
- public Vector3 Abs()
+ public readonly Vector3 Abs()
{
return new Vector3(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
}
@@ -132,7 +132,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The unsigned angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector3 to)
+ public readonly real_t AngleTo(Vector3 to)
{
return Mathf.Atan2(Cross(to).Length(), Dot(to));
}
@@ -142,7 +142,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
/// <returns>The bounced vector.</returns>
- public Vector3 Bounce(Vector3 normal)
+ public readonly Vector3 Bounce(Vector3 normal)
{
return -Reflect(normal);
}
@@ -151,7 +151,7 @@ namespace Godot
/// Returns a new vector with all components rounded up (towards positive infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
- public Vector3 Ceil()
+ public readonly Vector3 Ceil()
{
return new Vector3(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z));
}
@@ -164,7 +164,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector3 Clamp(Vector3 min, Vector3 max)
+ public readonly Vector3 Clamp(Vector3 min, Vector3 max)
{
return new Vector3
(
@@ -179,7 +179,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product vector.</returns>
- public Vector3 Cross(Vector3 with)
+ public readonly Vector3 Cross(Vector3 with)
{
return new Vector3
(
@@ -198,7 +198,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight)
+ public readonly Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight)
{
return new Vector3
(
@@ -222,7 +222,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector3
(
@@ -241,7 +241,7 @@ namespace Godot
/// <param name="end">The destination vector.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
+ public readonly Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
{
// Formula from Wikipedia article on Bezier curves
real_t omt = 1 - t;
@@ -258,7 +258,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector3 DirectionTo(Vector3 to)
+ public readonly Vector3 DirectionTo(Vector3 to)
{
return new Vector3(to.x - x, to.y - y, to.z - z).Normalized();
}
@@ -270,7 +270,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector3 to)
+ public readonly real_t DistanceSquaredTo(Vector3 to)
{
return (to - this).LengthSquared();
}
@@ -281,7 +281,7 @@ namespace Godot
/// <seealso cref="DistanceSquaredTo(Vector3)"/>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector3 to)
+ public readonly real_t DistanceTo(Vector3 to)
{
return (to - this).Length();
}
@@ -291,7 +291,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector3 with)
+ public readonly real_t Dot(Vector3 with)
{
return (x * with.x) + (y * with.y) + (z * with.z);
}
@@ -300,7 +300,7 @@ namespace Godot
/// Returns a new vector with all components rounded down (towards negative infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
- public Vector3 Floor()
+ public readonly Vector3 Floor()
{
return new Vector3(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z));
}
@@ -309,7 +309,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector3(1 / v.x, 1 / v.y, 1 / v.z)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector3 Inverse()
+ public readonly Vector3 Inverse()
{
return new Vector3(1 / x, 1 / y, 1 / z);
}
@@ -318,7 +318,7 @@ namespace Godot
/// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
/// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -328,7 +328,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -343,7 +343,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public real_t LengthSquared()
+ public readonly real_t LengthSquared()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -359,7 +359,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector3 Lerp(Vector3 to, real_t weight)
+ public readonly Vector3 Lerp(Vector3 to, real_t weight)
{
return new Vector3
(
@@ -376,7 +376,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector3 Lerp(Vector3 to, Vector3 weight)
+ public readonly Vector3 Lerp(Vector3 to, Vector3 weight)
{
return new Vector3
(
@@ -391,7 +391,7 @@ namespace Godot
/// </summary>
/// <param name="length">The length to limit to.</param>
/// <returns>The vector with its length limited.</returns>
- public Vector3 LimitLength(real_t length = 1.0f)
+ public readonly Vector3 LimitLength(real_t length = 1.0f)
{
Vector3 v = this;
real_t l = Length();
@@ -410,7 +410,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
}
@@ -420,7 +420,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
}
@@ -431,7 +431,7 @@ namespace Godot
/// <param name="to">The vector to move towards.</param>
/// <param name="delta">The amount to move towards by.</param>
/// <returns>The resulting vector.</returns>
- public Vector3 MoveToward(Vector3 to, real_t delta)
+ public readonly Vector3 MoveToward(Vector3 to, real_t delta)
{
Vector3 v = this;
Vector3 vd = to - v;
@@ -446,7 +446,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector3 Normalized()
+ public readonly Vector3 Normalized()
{
Vector3 v = this;
v.Normalize();
@@ -458,7 +458,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>A <see cref="Basis"/> representing the outer product matrix.</returns>
- public Basis Outer(Vector3 with)
+ public readonly Basis Outer(Vector3 with)
{
return new Basis(
x * with.x, x * with.y, x * with.z,
@@ -475,7 +475,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector3 PosMod(real_t mod)
+ public readonly Vector3 PosMod(real_t mod)
{
Vector3 v;
v.x = Mathf.PosMod(x, mod);
@@ -492,7 +492,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector3 PosMod(Vector3 modv)
+ public readonly Vector3 PosMod(Vector3 modv)
{
Vector3 v;
v.x = Mathf.PosMod(x, modv.x);
@@ -506,7 +506,7 @@ namespace Godot
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
- public Vector3 Project(Vector3 onNormal)
+ public readonly Vector3 Project(Vector3 onNormal)
{
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
}
@@ -516,7 +516,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
- public Vector3 Reflect(Vector3 normal)
+ public readonly Vector3 Reflect(Vector3 normal)
{
#if DEBUG
if (!normal.IsNormalized())
@@ -534,7 +534,7 @@ namespace Godot
/// <param name="axis">The vector to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
- public Vector3 Rotated(Vector3 axis, real_t angle)
+ public readonly Vector3 Rotated(Vector3 axis, real_t angle)
{
#if DEBUG
if (!axis.IsNormalized())
@@ -550,7 +550,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector3 Round()
+ public readonly Vector3 Round()
{
return new Vector3(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z));
}
@@ -561,7 +561,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector3 Sign()
+ public readonly Vector3 Sign()
{
Vector3 v;
v.x = Mathf.Sign(x);
@@ -579,7 +579,7 @@ namespace Godot
/// <param name="to">The other vector to compare this vector to.</param>
/// <param name="axis">The reference axis to use for the angle sign.</param>
/// <returns>The signed angle between the two vectors, in radians.</returns>
- public real_t SignedAngleTo(Vector3 to, Vector3 axis)
+ public readonly real_t SignedAngleTo(Vector3 to, Vector3 axis)
{
Vector3 crossTo = Cross(to);
real_t unsignedAngle = Mathf.Atan2(crossTo.Length(), Dot(to));
@@ -598,7 +598,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector3 Slerp(Vector3 to, real_t weight)
+ public readonly Vector3 Slerp(Vector3 to, real_t weight)
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
@@ -618,7 +618,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
- public Vector3 Slide(Vector3 normal)
+ public readonly Vector3 Slide(Vector3 normal)
{
return this - (normal * Dot(normal));
}
@@ -629,7 +629,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector3 Snapped(Vector3 step)
+ public readonly Vector3 Snapped(Vector3 step)
{
return new Vector3
(
@@ -1015,7 +1015,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector3 other && Equals(other);
}
@@ -1027,7 +1027,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector3 other)
+ public readonly bool Equals(Vector3 other)
{
return x == other.x && y == other.y && z == other.z;
}
@@ -1038,7 +1038,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector3 other)
+ public readonly bool IsEqualApprox(Vector3 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
}
@@ -1047,7 +1047,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector3"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
@@ -1056,7 +1056,7 @@ namespace Godot
/// Converts this <see cref="Vector3"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z})";
}
@@ -1065,7 +1065,7 @@ namespace Godot
/// Converts this <see cref="Vector3"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
index e88a043cb3..e631a9f443 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -94,7 +94,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y, out int z)
+ public readonly void Deconstruct(out int x, out int y, out int z)
{
x = this.x;
y = this.y;
@@ -105,7 +105,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
- public Vector3i Abs()
+ public readonly Vector3i Abs()
{
return new Vector3i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
}
@@ -118,7 +118,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector3i Clamp(Vector3i min, Vector3i max)
+ public readonly Vector3i Clamp(Vector3i min, Vector3i max)
{
return new Vector3i
(
@@ -135,7 +135,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector3i to)
+ public readonly int DistanceSquaredTo(Vector3i to)
{
return (to - this).LengthSquared();
}
@@ -146,7 +146,7 @@ namespace Godot
/// <seealso cref="DistanceSquaredTo(Vector3i)"/>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector3i to)
+ public readonly real_t DistanceTo(Vector3i to)
{
return (to - this).Length();
}
@@ -156,7 +156,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector3i with)
+ public readonly int Dot(Vector3i with)
{
return x * with.x + y * with.y + z * with.z;
}
@@ -166,7 +166,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -181,7 +181,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public int LengthSquared()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -195,7 +195,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
}
@@ -205,7 +205,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
}
@@ -218,7 +218,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector3i PosMod(int mod)
+ public readonly Vector3i PosMod(int mod)
{
Vector3i v = this;
v.x = Mathf.PosMod(v.x, mod);
@@ -235,7 +235,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector3i PosMod(Vector3i modv)
+ public readonly Vector3i PosMod(Vector3i modv)
{
Vector3i v = this;
v.x = Mathf.PosMod(v.x, modv.x);
@@ -250,7 +250,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector3i Sign()
+ public readonly Vector3i Sign()
{
Vector3i v = this;
v.x = Mathf.Sign(v.x);
@@ -674,7 +674,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector3i other && Equals(other);
}
@@ -684,7 +684,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector3i other)
+ public readonly bool Equals(Vector3i other)
{
return x == other.x && y == other.y && z == other.z;
}
@@ -693,7 +693,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector3i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
@@ -702,7 +702,7 @@ namespace Godot
/// Converts this <see cref="Vector3i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z})";
}
@@ -711,7 +711,7 @@ namespace Godot
/// Converts this <see cref="Vector3i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
index e2da41ff47..3191e8adc0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
@@ -68,7 +68,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -109,7 +109,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w)
+ public readonly void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w)
{
x = this.x;
y = this.y;
@@ -139,7 +139,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
- public Vector4 Abs()
+ public readonly Vector4 Abs()
{
return new Vector4(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
}
@@ -148,7 +148,7 @@ namespace Godot
/// Returns a new vector with all components rounded up (towards positive infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
- public Vector4 Ceil()
+ public readonly Vector4 Ceil()
{
return new Vector4(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z), Mathf.Ceil(w));
}
@@ -161,7 +161,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector4 Clamp(Vector4 min, Vector4 max)
+ public readonly Vector4 Clamp(Vector4 min, Vector4 max)
{
return new Vector4
(
@@ -181,7 +181,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight)
+ public readonly Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight)
{
return new Vector4
(
@@ -206,7 +206,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector4
(
@@ -222,7 +222,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector4 DirectionTo(Vector4 to)
+ public readonly Vector4 DirectionTo(Vector4 to)
{
Vector4 ret = new Vector4(to.x - x, to.y - y, to.z - z, to.w - w);
ret.Normalize();
@@ -236,7 +236,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector4 to)
+ public readonly real_t DistanceSquaredTo(Vector4 to)
{
return (to - this).LengthSquared();
}
@@ -246,7 +246,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector4 to)
+ public readonly real_t DistanceTo(Vector4 to)
{
return (to - this).Length();
}
@@ -256,7 +256,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector4 with)
+ public readonly real_t Dot(Vector4 with)
{
return (x * with.x) + (y * with.y) + (z * with.z) + (w * with.w);
}
@@ -265,7 +265,7 @@ namespace Godot
/// Returns a new vector with all components rounded down (towards negative infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
- public Vector4 Floor()
+ public readonly Vector4 Floor()
{
return new Vector4(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z), Mathf.Floor(w));
}
@@ -274,7 +274,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector4(1 / v.x, 1 / v.y, 1 / v.z, 1 / v.w)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector4 Inverse()
+ public readonly Vector4 Inverse()
{
return new Vector4(1 / x, 1 / y, 1 / z, 1 / w);
}
@@ -283,7 +283,7 @@ namespace Godot
/// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
/// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -293,7 +293,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -309,7 +309,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public real_t LengthSquared()
+ public readonly real_t LengthSquared()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -326,7 +326,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector4 Lerp(Vector4 to, real_t weight)
+ public readonly Vector4 Lerp(Vector4 to, real_t weight)
{
return new Vector4
(
@@ -342,7 +342,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
int max_index = 0;
real_t max_value = x;
@@ -362,7 +362,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.W"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
int min_index = 0;
real_t min_value = x;
@@ -381,7 +381,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector4 Normalized()
+ public readonly Vector4 Normalized()
{
Vector4 v = this;
v.Normalize();
@@ -396,7 +396,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector4 PosMod(real_t mod)
+ public readonly Vector4 PosMod(real_t mod)
{
return new Vector4(
Mathf.PosMod(x, mod),
@@ -414,7 +414,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector4 PosMod(Vector4 modv)
+ public readonly Vector4 PosMod(Vector4 modv)
{
return new Vector4(
Mathf.PosMod(x, modv.x),
@@ -429,7 +429,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector4 Round()
+ public readonly Vector4 Round()
{
return new Vector4(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z), Mathf.Round(w));
}
@@ -440,7 +440,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector4 Sign()
+ public readonly Vector4 Sign()
{
Vector4 v;
v.x = Mathf.Sign(x);
@@ -456,7 +456,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector4 Snapped(Vector4 step)
+ public readonly Vector4 Snapped(Vector4 step)
{
return new Vector4(
Mathf.Snapped(x, step.x),
@@ -828,7 +828,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector4 other && Equals(other);
}
@@ -840,7 +840,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector4 other)
+ public readonly bool Equals(Vector4 other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -851,7 +851,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector4 other)
+ public readonly bool IsEqualApprox(Vector4 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
}
@@ -860,7 +860,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector4"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -878,7 +878,7 @@ namespace Godot
/// Converts this <see cref="Vector4"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
index 4b1bb3ba19..8146991fd7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
@@ -68,7 +68,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -109,7 +109,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y, out int z, out int w)
+ public readonly void Deconstruct(out int x, out int y, out int z, out int w)
{
x = this.x;
y = this.y;
@@ -121,7 +121,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
- public Vector4i Abs()
+ public readonly Vector4i Abs()
{
return new Vector4i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
}
@@ -134,7 +134,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector4i Clamp(Vector4i min, Vector4i max)
+ public readonly Vector4i Clamp(Vector4i min, Vector4i max)
{
return new Vector4i
(
@@ -150,7 +150,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -166,7 +166,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public int LengthSquared()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -181,7 +181,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
int max_index = 0;
int max_value = x;
@@ -201,7 +201,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.W"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
int min_index = 0;
int min_value = x;
@@ -222,7 +222,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector4i Sign()
+ public readonly Vector4i Sign()
{
return new Vector4i(Mathf.Sign(x), Mathf.Sign(y), Mathf.Sign(z), Mathf.Sign(w));
}
@@ -627,7 +627,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector4i other && Equals(other);
}
@@ -637,7 +637,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector4i other)
+ public readonly bool Equals(Vector4i other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -646,7 +646,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector4i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -655,7 +655,7 @@ namespace Godot
/// Converts this <see cref="Vector4i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z}, {w})";
}
@@ -664,7 +664,7 @@ namespace Godot
/// Converts this <see cref="Vector4i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}), {w.ToString(format)})";
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index f73f8aaa31..a002a37ab9 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -299,7 +299,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
plugin.onRegisterPluginWithGodotNative();
}
- setKeepScreenOn("true".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
+ setKeepScreenOn(Boolean.parseBoolean(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
});
// Include the returned non-null views in the Godot view hierarchy.
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index ab4cba86fb..02ab297d8e 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -182,125 +182,31 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
if (bl == 0.0) {
return;
}
- real_t bi = c->get_bake_interval();
- real_t o_next = progress + bi;
- real_t o_prev = progress - bi;
-
- if (loop) {
- o_next = Math::fposmod(o_next, bl);
- o_prev = Math::fposmod(o_prev, bl);
- } else if (rotation_mode == ROTATION_ORIENTED) {
- if (o_next >= bl) {
- o_next = bl;
- }
- if (o_prev <= 0) {
- o_prev = 0;
- }
- }
-
- Vector3 pos = c->sample_baked(progress, cubic);
- Transform3D t = get_transform();
- // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
- // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
-
- if (rotation_mode == ROTATION_ORIENTED) {
- Vector3 forward = c->sample_baked(o_next, cubic) - pos;
-
- // Try with the previous position
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = pos - c->sample_baked(o_prev, cubic);
- }
-
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = Vector3(0, 0, 1);
- } else {
- forward.normalize();
- }
-
- Vector3 up = c->sample_baked_up_vector(progress, true);
- if (o_next < progress) {
- Vector3 up1 = c->sample_baked_up_vector(o_next, true);
- Vector3 axis = up.cross(up1);
-
- if (axis.length_squared() < CMP_EPSILON2) {
- axis = forward;
- } else {
- axis.normalize();
- }
-
- up.rotate(axis, up.angle_to(up1) * 0.5f);
- }
-
- Vector3 scale = t.basis.get_scale();
- Vector3 sideways = up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
-
- t.basis.set_columns(sideways, up, forward);
- t.basis.scale_local(scale);
-
- t.origin = pos + sideways * h_offset + up * v_offset;
- } else if (rotation_mode != ROTATION_NONE) {
- // perform parallel transport
- //
- // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
- // for a discussion about why not Frenet frame.
+ Transform3D t;
+ if (rotation_mode == ROTATION_NONE) {
+ Vector3 pos = c->sample_baked(progress, cubic);
t.origin = pos;
- if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
- real_t sample_distance = bi * 0.01;
- Vector3 t_prev_pos_a = c->sample_baked(prev_offset - sample_distance, cubic);
- Vector3 t_prev_pos_b = c->sample_baked(prev_offset + sample_distance, cubic);
- Vector3 t_cur_pos_a = c->sample_baked(progress - sample_distance, cubic);
- Vector3 t_cur_pos_b = c->sample_baked(progress + sample_distance, cubic);
- Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized();
- Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized();
-
- Vector3 axis = t_prev.cross(t_cur);
- real_t dot = t_prev.dot(t_cur);
- real_t angle = Math::acos(CLAMP(dot, -1, 1));
-
- if (likely(!Math::is_zero_approx(angle))) {
- if (rotation_mode == ROTATION_Y) {
- // assuming we're referring to global Y-axis. is this correct?
- axis.x = 0;
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
+ } else {
+ t = c->sample_baked_with_rotation(progress, cubic, false);
+ Vector3 forward = t.basis.get_column(2); // Retain tangent for applying tilt
+ t = PathFollow3D::correct_posture(t, rotation_mode);
- if (likely(!Math::is_zero_approx(axis.length()))) {
- t.rotate_basis(axis.normalized(), angle);
- }
- }
+ // Apply tilt *after* correct_posture
+ if (tilt_enabled) {
+ const real_t tilt = c->sample_baked_tilt(progress);
- // do the additional tilting
- real_t tilt_angle = c->sample_baked_tilt(progress);
- Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
-
- if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
- if (rotation_mode == ROTATION_Y) {
- tilt_axis.x = 0;
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
-
- if (likely(!Math::is_zero_approx(tilt_axis.length()))) {
- t.rotate_basis(tilt_axis.normalized(), tilt_angle);
- }
- }
+ const Basis twist(forward, tilt);
+ t.basis = twist * t.basis;
}
-
- t.translate_local(Vector3(h_offset, v_offset, 0));
- } else {
- t.origin = pos + Vector3(h_offset, v_offset, 0);
}
+ Vector3 scale = get_transform().basis.get_scale();
+
+ t.translate_local(Vector3(h_offset, v_offset, 0));
+ t.basis.scale_local(scale);
+
set_transform(t);
}
@@ -358,6 +264,38 @@ PackedStringArray PathFollow3D::get_configuration_warnings() const {
return warnings;
}
+Transform3D PathFollow3D::correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode) {
+ Transform3D t = p_transform;
+
+ // Modify frame according to rotation mode.
+ if (p_rotation_mode == PathFollow3D::ROTATION_NONE) {
+ // Clear rotation.
+ t.basis = Basis();
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_ORIENTED) {
+ // Y-axis always straight up.
+ Vector3 up(0.0, 1.0, 0.0);
+ Vector3 forward = t.basis.get_column(2);
+
+ t.basis = Basis::looking_at(-forward, up);
+ } else {
+ // Lock some euler axes.
+ Vector3 euler = t.basis.get_euler_normalized(EulerOrder::YXZ);
+ if (p_rotation_mode == PathFollow3D::ROTATION_Y) {
+ // Only Y-axis allowed.
+ euler[0] = 0;
+ euler[2] = 0;
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_XY) {
+ // XY allowed.
+ euler[2] = 0;
+ }
+
+ Basis locked = Basis::from_euler(euler, EulerOrder::YXZ);
+ t.basis = locked;
+ }
+
+ return t;
+}
+
void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow3D::set_progress);
ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow3D::get_progress);
@@ -380,6 +318,11 @@ void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop);
+ ClassDB::bind_method(D_METHOD("set_tilt_enabled", "enabled"), &PathFollow3D::set_tilt_enabled);
+ ClassDB::bind_method(D_METHOD("is_tilt_enabled"), &PathFollow3D::is_tilt_enabled);
+
+ ClassDB::bind_static_method("PathFollow3D", D_METHOD("correct_posture", "transform", "rotation_mode"), &PathFollow3D::correct_posture);
+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_less,or_greater,suffix:m"), "set_progress", "get_progress");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_less,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
@@ -387,6 +330,7 @@ void PathFollow3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tilt_enabled"), "set_tilt_enabled", "is_tilt_enabled");
BIND_ENUM_CONSTANT(ROTATION_NONE);
BIND_ENUM_CONSTANT(ROTATION_Y);
@@ -397,7 +341,6 @@ void PathFollow3D::_bind_methods() {
void PathFollow3D::set_progress(real_t p_progress) {
ERR_FAIL_COND(!isfinite(p_progress));
- prev_offset = progress;
progress = p_progress;
if (path) {
@@ -409,8 +352,6 @@ void PathFollow3D::set_progress(real_t p_progress) {
if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) {
progress = path_length;
}
- } else {
- progress = CLAMP(progress, 0, path_length);
}
}
@@ -476,3 +417,11 @@ void PathFollow3D::set_loop(bool p_loop) {
bool PathFollow3D::has_loop() const {
return loop;
}
+
+void PathFollow3D::set_tilt_enabled(bool p_enable) {
+ tilt_enabled = p_enable;
+}
+
+bool PathFollow3D::is_tilt_enabled() const {
+ return tilt_enabled;
+}
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index b161b12185..9d5f694247 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -72,14 +72,16 @@ public:
ROTATION_ORIENTED
};
+ static Transform3D correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode);
+
private:
Path3D *path = nullptr;
- real_t prev_offset = 0.0; // Offset during the last _update_transform.
real_t progress = 0.0;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
bool cubic = true;
bool loop = true;
+ bool tilt_enabled = true;
RotationMode rotation_mode = ROTATION_XYZ;
void _update_transform(bool p_update_xyz_rot = true);
@@ -106,6 +108,9 @@ public:
void set_loop(bool p_loop);
bool has_loop() const;
+ void set_tilt_enabled(bool p_enable);
+ bool is_tilt_enabled() const;
+
void set_rotation_mode(RotationMode p_rotation_mode);
RotationMode get_rotation_mode() const;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 93ae9db8ba..889610e071 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2689,6 +2689,7 @@ bool RichTextLabel::_validate_line_caches() {
int ctrl_height = get_size().height;
// Update fonts.
+ float old_scroll = vscroll->get_value();
if (main->first_invalid_font_line.load() != (int)main->lines.size()) {
for (int i = main->first_invalid_font_line.load(); i < (int)main->lines.size(); i++) {
_update_line_font(main, i, theme_cache.normal_font, theme_cache.normal_font_size);
@@ -2698,6 +2699,7 @@ bool RichTextLabel::_validate_line_caches() {
}
if (main->first_resized_line.load() == (int)main->lines.size()) {
+ vscroll->set_value(old_scroll);
return true;
}
@@ -2736,6 +2738,8 @@ bool RichTextLabel::_validate_line_caches() {
vscroll->set_page(text_rect.size.height);
if (scroll_follow && scroll_following) {
vscroll->set_value(total_height);
+ } else {
+ vscroll->set_value(old_scroll);
}
updating_scroll = false;
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index eda9af9dde..0c36abc148 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -31,6 +31,7 @@
#include "curve.h"
#include "core/core_string_names.h"
+#include "core/math/math_funcs.h"
const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed";
@@ -1413,8 +1414,9 @@ void Curve3D::_bake() const {
if (points.size() == 0) {
baked_point_cache.clear();
baked_tilt_cache.clear();
- baked_up_vector_cache.clear();
baked_dist_cache.clear();
+
+ baked_up_vector_cache.clear();
return;
}
@@ -1438,15 +1440,16 @@ void Curve3D::_bake() const {
Vector3 position = points[0].position;
real_t dist = 0.0;
- List<Plane> pointlist;
+ List<Plane> pointlist; // Abuse Plane for (position, dist)
List<real_t> distlist;
// Start always from origin.
pointlist.push_back(Plane(position, points[0].tilt));
distlist.push_back(0.0);
+ // Step 1: Sample points
+ const real_t step = 0.1; // At least 10 substeps ought to be enough?
for (int i = 0; i < points.size() - 1; i++) {
- real_t step = 0.1; // at least 10 substeps ought to be enough?
real_t p = 0.0;
while (p < 1.0) {
@@ -1461,7 +1464,7 @@ void Curve3D::_bake() const {
if (d > bake_interval) {
// OK! between P and NP there _has_ to be Something, let's go searching!
- int iterations = 10; //lots of detail!
+ const int iterations = 10; // Lots of detail!
real_t low = p;
real_t hi = np;
@@ -1496,76 +1499,135 @@ void Curve3D::_bake() const {
Vector3 npp = points[i + 1].position;
real_t d = position.distance_to(npp);
- position = npp;
- Plane post;
- post.normal = position;
- post.d = points[i + 1].tilt;
+ if (d > CMP_EPSILON) { // Avoid the degenerate case of two very close points.
+ position = npp;
+ Plane post;
+ post.normal = position;
+ post.d = points[i + 1].tilt;
- dist += d;
+ dist += d;
- pointlist.push_back(post);
- distlist.push_back(dist);
+ pointlist.push_back(post);
+ distlist.push_back(dist);
+ }
}
baked_max_ofs = dist;
- baked_point_cache.resize(pointlist.size());
- Vector3 *w = baked_point_cache.ptrw();
- int idx = 0;
+ const int point_count = pointlist.size();
+ {
+ baked_point_cache.resize(point_count);
+ Vector3 *w = baked_point_cache.ptrw();
- baked_tilt_cache.resize(pointlist.size());
- real_t *wt = baked_tilt_cache.ptrw();
+ baked_tilt_cache.resize(point_count);
+ real_t *wt = baked_tilt_cache.ptrw();
- baked_up_vector_cache.resize(up_vector_enabled ? pointlist.size() : 0);
- Vector3 *up_write = baked_up_vector_cache.ptrw();
+ baked_dist_cache.resize(point_count);
+ real_t *wd = baked_dist_cache.ptrw();
- baked_dist_cache.resize(pointlist.size());
- real_t *wd = baked_dist_cache.ptrw();
+ int idx = 0;
+ for (const Plane &E : pointlist) {
+ w[idx] = E.normal;
+ wt[idx] = E.d;
+ wd[idx] = distlist[idx];
- Vector3 sideways;
- Vector3 up;
- Vector3 forward;
+ idx++;
+ }
+ }
+
+ if (!up_vector_enabled) {
+ baked_up_vector_cache.resize(0);
+ return;
+ }
- Vector3 prev_sideways = Vector3(1, 0, 0);
- Vector3 prev_up = Vector3(0, 1, 0);
- Vector3 prev_forward = Vector3(0, 0, 1);
+ // Step 2: Calculate the up vectors and the whole local reference frame
+ //
+ // See Dougan, Carl. "The parallel transport frame." Game Programming Gems 2 (2001): 215-219.
+ // for an example discussing about why not the Frenet frame.
+ {
+ PackedVector3Array forward_vectors;
- for (const Plane &E : pointlist) {
- w[idx] = E.normal;
- wt[idx] = E.d;
- wd[idx] = distlist[idx];
+ baked_up_vector_cache.resize(point_count);
+ forward_vectors.resize(point_count);
- if (!up_vector_enabled) {
- idx++;
- continue;
+ Vector3 *up_write = baked_up_vector_cache.ptrw();
+ Vector3 *forward_write = forward_vectors.ptrw();
+
+ const Vector3 *points_ptr = baked_point_cache.ptr();
+
+ Basis frame; // X-right, Y-up, Z-forward.
+ Basis frame_prev;
+
+ // Set the initial frame based on Y-up rule.
+ {
+ Vector3 up(0, 1, 0);
+ Vector3 forward = (points_ptr[1] - points_ptr[0]).normalized();
+ if (forward.is_equal_approx(Vector3())) {
+ forward = Vector3(1, 0, 0);
+ }
+
+ if (abs(forward.dot(up)) > 1.0 - UNIT_EPSILON) {
+ frame_prev = Basis::looking_at(-forward, up);
+ } else {
+ frame_prev = Basis::looking_at(-forward, Vector3(1, 0, 0));
+ }
+
+ up_write[0] = frame_prev.get_column(1);
+ forward_write[0] = frame_prev.get_column(2);
}
- forward = idx > 0 ? (w[idx] - w[idx - 1]).normalized() : prev_forward;
+ // Calculate the Parallel Transport Frame.
+ for (int idx = 1; idx < point_count; idx++) {
+ Vector3 forward = (points_ptr[idx] - points_ptr[idx - 1]).normalized();
+ if (forward.is_equal_approx(Vector3())) {
+ forward = frame_prev.get_column(2);
+ }
- real_t y_dot = prev_up.dot(forward);
+ Basis rotate;
+ rotate.rotate_to_align(frame_prev.get_column(2), forward);
+ frame = rotate * frame_prev;
+ frame.orthonormalize(); // guard against float error accumulation
- if (y_dot > (1.0f - CMP_EPSILON)) {
- sideways = prev_sideways;
- up = -prev_forward;
- } else if (y_dot < -(1.0f - CMP_EPSILON)) {
- sideways = prev_sideways;
- up = prev_forward;
- } else {
- sideways = prev_up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
+ up_write[idx] = frame.get_column(1);
+ forward_write[idx] = frame.get_column(2);
+
+ frame_prev = frame;
}
- if (idx == 1) {
- up_write[0] = up;
+ bool is_loop = true;
+ // Loop smoothing only applies when the curve is a loop, which means two ends meet, and share forward directions.
+ {
+ if (!points_ptr[0].is_equal_approx(points_ptr[point_count - 1])) {
+ is_loop = false;
+ }
+
+ real_t dot = forward_write[0].dot(forward_write[point_count - 1]);
+ if (dot < 1.0 - 0.01) { // Alignment should not be too tight, or it dosen't work for coarse bake interval
+ is_loop = false;
+ }
}
- up_write[idx] = up;
+ // Twist up vectors, so that they align at two ends of the curve.
+ if (is_loop) {
+ const Vector3 up_start = up_write[0];
+ const Vector3 up_end = up_write[point_count - 1];
+
+ real_t sign = SIGN(up_end.cross(up_start).dot(forward_write[0]));
+ real_t full_angle = Quaternion(up_end, up_start).get_angle();
- prev_sideways = sideways;
- prev_up = up;
- prev_forward = forward;
+ if (abs(full_angle) < UNIT_EPSILON) {
+ return;
+ } else {
+ const real_t *dists = baked_dist_cache.ptr();
+ for (int idx = 1; idx < point_count; idx++) {
+ const real_t frac = dists[idx] / baked_max_ofs;
+ const real_t angle = Math::lerp((real_t)0.0, full_angle, frac);
+ Basis twist(forward_write[idx] * sign, angle);
- idx++;
+ up_write[idx] = twist.xform(up_write[idx]);
+ }
+ }
+ }
}
}
@@ -1577,27 +1639,15 @@ real_t Curve3D::get_baked_length() const {
return baked_max_ofs;
}
-Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
- if (baked_cache_dirty) {
- _bake();
- }
+Curve3D::Interval Curve3D::_find_interval(real_t p_offset) const {
+ Interval interval = {
+ -1,
+ 0.0
+ };
+ ERR_FAIL_COND_V_MSG(baked_cache_dirty, interval, "Backed cache is dirty");
- // Validate: Curve may not have baked points.
int pc = baked_point_cache.size();
- ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D.");
-
- if (pc == 1) {
- return baked_point_cache.get(0);
- }
-
- const Vector3 *r = baked_point_cache.ptr();
-
- if (p_offset < 0) {
- return r[0];
- }
- if (p_offset >= baked_max_ofs) {
- return r[pc - 1];
- }
+ ERR_FAIL_COND_V_MSG(pc < 2, interval, "Less than two points in cache");
int start = 0;
int end = pc;
@@ -1617,9 +1667,27 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(), "Couldn't find baked segment.");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, interval, "Offset out of range.");
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ interval.idx = idx;
+ if (idx_interval < FLT_EPSILON) {
+ interval.frac = 0.5; // For a very short interval, 0.5 is a reasonable choice.
+ ERR_FAIL_V_MSG(interval, "Zero length interval.");
+ }
+
+ interval.frac = (p_offset - offset_begin) / idx_interval;
+ return interval;
+}
+
+Vector3 Curve3D::_sample_baked(Interval p_interval, bool p_cubic) const {
+ // Assuming p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Vector3(), "Invalid interval");
+
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
+
+ const Vector3 *r = baked_point_cache.ptr();
+ int pc = baked_point_cache.size();
if (p_cubic) {
Vector3 pre = idx > 0 ? r[idx - 1] : r[idx];
@@ -1630,114 +1698,150 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
}
}
-real_t Curve3D::sample_baked_tilt(real_t p_offset) const {
- if (baked_cache_dirty) {
- _bake();
- }
-
- // Validate: Curve may not have baked tilts.
- int pc = baked_tilt_cache.size();
- ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D.");
+real_t Curve3D::_sample_baked_tilt(Interval p_interval) const {
+ // Assuming that p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_tilt_cache.size(), 0.0, "Invalid interval");
- if (pc == 1) {
- return baked_tilt_cache.get(0);
- }
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
const real_t *r = baked_tilt_cache.ptr();
- if (p_offset < 0) {
- return r[0];
+ return Math::lerp(r[idx], r[idx + 1], frac);
+}
+
+Basis Curve3D::_sample_posture(Interval p_interval, bool p_apply_tilt) const {
+ // Assuming that p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Basis(), "Invalid interval");
+ if (up_vector_enabled) {
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_up_vector_cache.size(), Basis(), "Invalid interval");
}
- if (p_offset >= baked_max_ofs) {
- return r[pc - 1];
+
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
+
+ Vector3 forward_begin;
+ Vector3 forward_end;
+ if (idx == 0) {
+ forward_begin = (baked_point_cache[1] - baked_point_cache[0]).normalized();
+ forward_end = (baked_point_cache[1] - baked_point_cache[0]).normalized();
+ } else {
+ forward_begin = (baked_point_cache[idx] - baked_point_cache[idx - 1]).normalized();
+ forward_end = (baked_point_cache[idx + 1] - baked_point_cache[idx]).normalized();
}
- int start = 0;
- int end = pc;
- int idx = (end + start) / 2;
- // Binary search to find baked points.
- while (start < idx) {
- real_t offset = baked_dist_cache[idx];
- if (p_offset <= offset) {
- end = idx;
- } else {
- start = idx;
- }
- idx = (end + start) / 2;
+ Vector3 up_begin;
+ Vector3 up_end;
+ if (up_vector_enabled) {
+ const Vector3 *up_ptr = baked_up_vector_cache.ptr();
+ up_begin = up_ptr[idx];
+ up_end = up_ptr[idx + 1];
+ } else {
+ up_begin = Vector3(0.0, 1.0, 0.0);
+ up_end = Vector3(0.0, 1.0, 0.0);
}
- real_t offset_begin = baked_dist_cache[idx];
- real_t offset_end = baked_dist_cache[idx + 1];
+ // Build frames at both ends of the interval, then interpolate.
+ const Basis frame_begin = Basis::looking_at(-forward_begin, up_begin);
+ const Basis frame_end = Basis::looking_at(-forward_end, up_end);
+ const Basis frame = frame_begin.slerp(frame_end, frac).orthonormalized();
- real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, 0, "Couldn't find baked segment.");
+ if (!p_apply_tilt) {
+ return frame;
+ }
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ // Applying tilt.
+ const real_t tilt = _sample_baked_tilt(p_interval);
+ Vector3 forward = frame.get_column(2);
- return Math::lerp(r[idx], r[idx + 1], (real_t)frac);
+ const Basis twist(forward, tilt);
+ return twist * frame;
}
-Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
+Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
if (baked_cache_dirty) {
_bake();
}
- // Validate: Curve may not have baked up vectors.
- int count = baked_up_vector_cache.size();
- ERR_FAIL_COND_V_MSG(count == 0, Vector3(0, 1, 0), "No up vectors in Curve3D.");
+ // Validate: Curve may not have baked points.
+ int pc = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D.");
- if (count == 1) {
- return baked_up_vector_cache.get(0);
+ if (pc == 1) {
+ return baked_point_cache[0];
}
- const Vector3 *r = baked_up_vector_cache.ptr();
- const Vector3 *rp = baked_point_cache.ptr();
- const real_t *rt = baked_tilt_cache.ptr();
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
- int start = 0;
- int end = count;
- int idx = (end + start) / 2;
- // Binary search to find baked points.
- while (start < idx) {
- real_t offset = baked_dist_cache[idx];
- if (p_offset <= offset) {
- end = idx;
- } else {
- start = idx;
- }
- idx = (end + start) / 2;
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_baked(interval, p_cubic);
+}
+
+Transform3D Curve3D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, bool p_apply_tilt) const {
+ if (baked_cache_dirty) {
+ _bake();
}
- if (idx == count - 1) {
- return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx];
+ // Validate: Curve may not have baked points.
+ const int point_count = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(point_count == 0, Transform3D(), "No points in Curve3D.");
+
+ if (point_count == 1) {
+ Transform3D t;
+ t.origin = baked_point_cache.get(0);
+ ERR_FAIL_V_MSG(t, "Only 1 point in Curve3D.");
}
- real_t offset_begin = baked_dist_cache[idx];
- real_t offset_end = baked_dist_cache[idx + 1];
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
- real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(0, 1, 0), "Couldn't find baked segment.");
+ // 0. Find interval for all sampling steps.
+ Curve3D::Interval interval = _find_interval(p_offset);
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ // 1. Sample position.
+ Vector3 pos = _sample_baked(interval, p_cubic);
+
+ // 2. Sample rotation frame.
+ Basis frame = _sample_posture(interval, p_apply_tilt);
+
+ return Transform3D(frame, pos);
+}
+
+real_t Curve3D::sample_baked_tilt(real_t p_offset) const {
+ if (baked_cache_dirty) {
+ _bake();
+ }
- Vector3 forward = (rp[idx + 1] - rp[idx]).normalized();
- Vector3 up = r[idx];
- Vector3 up1 = r[idx + 1];
+ // Validate: Curve may not have baked tilts.
+ int pc = baked_tilt_cache.size();
+ ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D.");
- if (p_apply_tilt) {
- up.rotate(forward, rt[idx]);
- up1.rotate(idx + 2 >= count ? forward : (rp[idx + 2] - rp[idx + 1]).normalized(), rt[idx + 1]);
+ if (pc == 1) {
+ return baked_tilt_cache.get(0);
}
- Vector3 axis = up.cross(up1);
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic
- if (axis.length_squared() < CMP_EPSILON2) {
- axis = forward;
- } else {
- axis.normalize();
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_baked_tilt(interval);
+}
+
+Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
+ if (baked_cache_dirty) {
+ _bake();
+ }
+
+ // Validate: Curve may not have baked up vectors.
+ ERR_FAIL_COND_V_MSG(!up_vector_enabled, Vector3(0, 1, 0), "No up vectors in Curve3D.");
+
+ int count = baked_up_vector_cache.size();
+ if (count == 1) {
+ return baked_up_vector_cache.get(0);
}
- return up.rotated(axis, up.angle_to(up1) * frac);
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
+
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_posture(interval, p_apply_tilt).get_column(1);
}
PackedVector3Array Curve3D::get_baked_points() const {
@@ -2034,6 +2138,7 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve3D::get_baked_length);
ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve3D::sample_baked, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked_with_rotation", "offset", "cubic", "apply_tilt"), &Curve3D::sample_baked_with_rotation, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("sample_baked_up_vector", "offset", "apply_tilt"), &Curve3D::sample_baked_up_vector, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index fa1d35aab1..d0c813f262 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -238,11 +238,6 @@ class Curve3D : public Resource {
Vector<Point> points;
- struct BakedPoint {
- real_t ofs = 0.0;
- Vector3 point;
- };
-
mutable bool baked_cache_dirty = false;
mutable PackedVector3Array baked_point_cache;
mutable Vector<real_t> baked_tilt_cache;
@@ -254,6 +249,15 @@ class Curve3D : public Resource {
void _bake() const;
+ struct Interval {
+ int idx;
+ real_t frac;
+ };
+ Interval _find_interval(real_t p_offset) const;
+ Vector3 _sample_baked(Interval p_interval, bool p_cubic) const;
+ real_t _sample_baked_tilt(Interval p_interval) const;
+ Basis _sample_posture(Interval p_interval, bool p_apply_tilt = false) const;
+
real_t bake_interval = 0.2;
bool up_vector_enabled = true;
@@ -296,9 +300,10 @@ public:
real_t get_baked_length() const;
Vector3 sample_baked(real_t p_offset, bool p_cubic = false) const;
+ Transform3D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false, bool p_apply_tilt = false) const;
real_t sample_baked_tilt(real_t p_offset) const;
Vector3 sample_baked_up_vector(real_t p_offset, bool p_apply_tilt = false) const;
- PackedVector3Array get_baked_points() const; //useful for going through
+ PackedVector3Array get_baked_points() const; // Useful for going through.
Vector<real_t> get_baked_tilts() const; //useful for going through
PackedVector3Array get_baked_up_vectors() const;
Vector3 get_closest_point(const Vector3 &p_to_point) const;
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index 0ab21bc4ef..a05db8c563 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -510,16 +510,18 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
- copy_to_fb.push_constant.use_section = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_USE_SECTION;
copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
+
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -537,28 +539,35 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
RD::get_singleton()->draw_list_draw(draw_list, true);
}
-void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one) {
+void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
if (p_force_luminance) {
- copy_to_fb.push_constant.force_luminance = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FORCE_LUMINANCE;
}
if (p_alpha_to_zero) {
- copy_to_fb.push_constant.alpha_to_zero = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ZERO;
}
if (p_srgb) {
- copy_to_fb.push_constant.srgb = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_SRGB;
}
if (p_alpha_to_one) {
- copy_to_fb.push_constant.alpha_to_one = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ONE;
+ }
+ if (p_linear) {
+ // Used for copying to a linear buffer. In the mobile renderer we divide the contents of the linear buffer
+ // to allow for a wider effective range.
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_LINEAR;
+ copy_to_fb.push_constant.luminance_multiplier = prefer_raster_effects ? 2.0 : 1.0;
}
// setup our uniforms
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index cda4f70730..83f7a51a36 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -181,16 +181,21 @@ private:
COPY_TO_FB_MAX,
};
+ enum CopyToFBFlags {
+ COPY_TO_FB_FLAG_FLIP_Y = (1 << 0),
+ COPY_TO_FB_FLAG_USE_SECTION = (1 << 1),
+ COPY_TO_FB_FLAG_FORCE_LUMINANCE = (1 << 2),
+ COPY_TO_FB_FLAG_ALPHA_TO_ZERO = (1 << 3),
+ COPY_TO_FB_FLAG_SRGB = (1 << 4),
+ COPY_TO_FB_FLAG_ALPHA_TO_ONE = (1 << 5),
+ COPY_TO_FB_FLAG_LINEAR = (1 << 6),
+ };
+
struct CopyToFbPushConstant {
float section[4];
float pixel_size[2];
- uint32_t flip_y;
- uint32_t use_section;
-
- uint32_t force_luminance;
- uint32_t alpha_to_zero;
- uint32_t srgb;
- uint32_t alpha_to_one;
+ float luminance_multiplier;
+ uint32_t flags;
float set_color[4];
};
@@ -322,7 +327,7 @@ public:
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
- void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false);
+ void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false);
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 5ff00aa94c..701d53b41d 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -92,18 +92,15 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
}
Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
- // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
- // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
- // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
- // of the VRS buffer to supply.
- Size2i texel_size = Size2i(16, 16);
-
- int width = p_base_size.x / texel_size.x;
- if (p_base_size.x % texel_size.x != 0) {
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
+
+ int width = p_base_size.x / texel_width;
+ if (p_base_size.x % texel_width != 0) {
width++;
}
- int height = p_base_size.y / texel_size.y;
- if (p_base_size.y % texel_size.y != 0) {
+ int height = p_base_size.y / texel_height;
+ if (p_base_size.y % texel_height != 0) {
height++;
}
return Size2i(width, height);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 2d1d0e0951..41fceac7c2 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -1765,6 +1765,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
+ if (rb.is_valid()) {
+ RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ }
keep_color = true;
} break;
case RS::ENV_BG_KEEP: {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 558aba62e1..2506f4578b 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -796,6 +796,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
+ if (rb.is_valid()) {
+ RID dest_framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
+ RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ }
keep_color = true;
} break;
case RS::ENV_BG_KEEP: {
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
index 4d4e983b7f..46bb99794d 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
@@ -13,6 +13,14 @@
#endif // has_VK_KHR_multiview
#endif //MULTIVIEW
+#define FLAG_FLIP_Y (1 << 0)
+#define FLAG_USE_SECTION (1 << 1)
+#define FLAG_FORCE_LUMINANCE (1 << 2)
+#define FLAG_ALPHA_TO_ZERO (1 << 3)
+#define FLAG_SRGB (1 << 4)
+#define FLAG_ALPHA_TO_ONE (1 << 5)
+#define FLAG_LINEAR (1 << 6)
+
#ifdef MULTIVIEW
layout(location = 0) out vec3 uv_interp;
#else
@@ -22,13 +30,8 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, std430) uniform Params {
vec4 section;
vec2 pixel_size;
- bool flip_y;
- bool use_section;
-
- bool force_luminance;
- bool alpha_to_zero;
- bool srgb;
- bool alpha_to_one;
+ float luminance_multiplier;
+ uint flags;
vec4 color;
}
@@ -41,13 +44,13 @@ void main() {
uv_interp.z = ViewIndex;
#endif
vec2 vpos = uv_interp.xy;
- if (params.use_section) {
+ if (bool(params.flags & FLAG_USE_SECTION)) {
vpos = params.section.xy + vpos * params.section.zw;
}
gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0);
- if (params.flip_y) {
+ if (bool(params.flags & FLAG_FLIP_Y)) {
uv_interp.y = 1.0 - uv_interp.y;
}
}
@@ -67,16 +70,19 @@ void main() {
#endif // has_VK_KHR_multiview
#endif //MULTIVIEW
+#define FLAG_FLIP_Y (1 << 0)
+#define FLAG_USE_SECTION (1 << 1)
+#define FLAG_FORCE_LUMINANCE (1 << 2)
+#define FLAG_ALPHA_TO_ZERO (1 << 3)
+#define FLAG_SRGB (1 << 4)
+#define FLAG_ALPHA_TO_ONE (1 << 5)
+#define FLAG_LINEAR (1 << 6)
+
layout(push_constant, std430) uniform Params {
vec4 section;
vec2 pixel_size;
- bool flip_y;
- bool use_section;
-
- bool force_luminance;
- bool alpha_to_zero;
- bool srgb;
- bool alpha_to_one;
+ float luminance_multiplier;
+ uint flags;
vec4 color;
}
@@ -110,6 +116,10 @@ vec3 linear_to_srgb(vec3 color) {
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
+vec3 srgb_to_linear(vec3 color) {
+ return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045)));
+}
+
void main() {
#ifdef MODE_SET_COLOR
frag_color = params.color;
@@ -165,19 +175,22 @@ void main() {
#endif /* MODE_TWO_SOURCES */
#endif /* MULTIVIEW */
- if (params.force_luminance) {
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
color.rgb = vec3(max(max(color.r, color.g), color.b));
}
- if (params.alpha_to_zero) {
+ if (bool(params.flags & FLAG_ALPHA_TO_ZERO)) {
color.rgb *= color.a;
}
- if (params.srgb) {
+ if (bool(params.flags & FLAG_SRGB)) {
color.rgb = linear_to_srgb(color.rgb);
}
- if (params.alpha_to_one) {
+ if (bool(params.flags & FLAG_ALPHA_TO_ONE)) {
color.a = 1.0;
}
+ if (bool(params.flags & FLAG_LINEAR)) {
+ color.rgb = srgb_to_linear(color.rgb);
+ }
- frag_color = color;
+ frag_color = color / params.luminance_multiplier;
#endif // MODE_SET_COLOR
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index 5ef83c0b44..b450bb9fe9 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -63,10 +63,18 @@ void main() {
#ifdef MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
+ frag_color = uint(color.r * 255.0);
#else /* MULTIVIEW */
vec4 color = textureLod(source_color, uv, 0.0);
-#endif /* MULTIVIEW */
- // See if we can change the sampler to one that returns int...
- frag_color = uint(color.r * 256.0);
+ // for user supplied VRS map we do a color mapping
+ color.r *= 3.0;
+ frag_color = int(color.r) << 2;
+
+ color.g *= 3.0;
+ frag_color += int(color.g);
+
+ // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported
+ // 4x8, 8x4 and 8x8 are only available on some GPUs
+#endif /* MULTIVIEW */
}
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 348f6e4695..4ee355ee9f 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -3319,7 +3319,7 @@ void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_rend
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(Transform3D(), Projection(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), environment, RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 2836889de5..8cec531393 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -550,6 +550,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
+ // There may be an outstanding clear request if a clear was requested, but no 2D elements were drawn.
+ // Clear now otherwise we copy over garbage from the render target.
+ RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target);
_draw_3d(p_viewport);
}
}
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index d0b85d8220..d99cc9a350 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1257,6 +1257,8 @@ public:
LIMIT_SUBGROUP_SIZE,
LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
LIMIT_SUBGROUP_OPERATIONS,
+ LIMIT_VRS_TEXEL_WIDTH,
+ LIMIT_VRS_TEXEL_HEIGHT,
};
virtual uint64_t limit_get(Limit p_limit) const = 0;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 497e4476d0..62f061c9c0 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -8190,25 +8190,27 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
};
[[fallthrough]];
case TK_INSTANCE: {
+ if (tk.type == TK_INSTANCE) {
#ifdef DEBUG_ENABLED
- keyword_completion_context = CF_UNIFORM_KEYWORD;
- if (_lookup_next(next)) {
- if (next.type == TK_UNIFORM) {
- keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ keyword_completion_context = CF_UNIFORM_KEYWORD;
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ }
}
- }
#endif // DEBUG_ENABLED
- if (String(shader_type_identifier) != "spatial") {
- _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
- return ERR_PARSE_ERROR;
- }
- if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
- tk = _get_token();
- if (tk.type != TK_UNIFORM) {
- _set_expected_after_error("uniform", "instance");
+ if (String(shader_type_identifier) != "spatial") {
+ _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
- uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
+ tk = _get_token();
+ if (tk.type != TK_UNIFORM) {
+ _set_expected_after_error("uniform", "instance");
+ return ERR_PARSE_ERROR;
+ }
+ uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
+ }
}
};
[[fallthrough]];
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 4d58d24405..ec4ae98397 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -167,11 +167,12 @@ RID XRInterface::get_vrs_texture() {
// Default logic will return a standard VRS image based on our target size and default projections.
// Note that this only gets called if VRS is supported on the hardware.
- Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard.
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
int view_count = get_view_count();
Size2 target_size = get_render_target_size();
real_t aspect = target_size.x / target_size.y; // is this y/x ?
- Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y));
+ Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_width), round(0.5 + target_size.y / texel_height));
real_t radius = vrs_size.length() * 0.5;
Size2 vrs_sizei = vrs_size;
@@ -179,6 +180,8 @@ RID XRInterface::get_vrs_texture() {
const uint8_t densities[] = {
0, // 1x1
1, // 1x2
+ // 2, // 1x4 - not supported
+ // 3, // 1x8 - not supported
// 4, // 2x1
5, // 2x2
6, // 2x4