summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/README.md6
-rwxr-xr-xmodules/mono/build_scripts/build_assemblies.py18
-rw-r--r--modules/mono/class_db_api_json.cpp58
-rw-r--r--modules/mono/class_db_api_json.h58
-rw-r--r--modules/mono/csharp_script.cpp168
-rw-r--r--modules/mono/csharp_script.h64
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props3
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/EventSignals.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs27
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs111
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Methods.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs19
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs10
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs81
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs88
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs14
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs16
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs429
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs24
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs24
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs13
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs44
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs100
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs12
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs61
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs13
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs18
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs72
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs30
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs24
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs74
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs11
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs28
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs22
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/VerbosityLevelId.cs11
-rw-r--r--modules/mono/editor/bindings_generator.cpp500
-rw-r--r--modules/mono/editor/bindings_generator.h140
-rw-r--r--modules/mono/editor/code_completion.cpp58
-rw-r--r--modules/mono/editor/code_completion.h58
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp58
-rw-r--r--modules/mono/editor/editor_internal_calls.h58
-rw-r--r--modules/mono/editor/hostfxr_resolver.cpp58
-rw-r--r--modules/mono/editor/hostfxr_resolver.h58
-rw-r--r--modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs8
-rw-r--r--modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs14
-rw-r--r--modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs2
-rw-r--r--modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs2
-rw-r--r--modules/mono/editor/semver.cpp58
-rw-r--r--modules/mono/editor/semver.h58
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs4
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs28
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs26
-rw-r--r--modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj1
-rw-r--r--modules/mono/glue/GodotSharp/GodotPlugins/Main.cs34
-rw-r--r--modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs)457
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs1107
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs23
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotClassNameAttribute.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs)16
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs5
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ToolAttribute.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs509
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs33
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/GodotSerializationInfo.cs4
-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/Bridge/ScriptManagerBridge.cs131
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs26
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs238
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs649
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs299
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs330
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs5
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs14
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/GodotObjectExtensions.cs86
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs9
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs48
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs450
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs)26
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.exceptions.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Object.exceptions.cs)2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs44
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs1151
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs117
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs103
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs14
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs583
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs70
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs18
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs1057
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs33
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs180
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs414
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs34
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs169
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs764
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs288
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs42
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs151
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2I.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs)308
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs104
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs)16
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs759
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs317
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs279
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Variant.cs)204
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs356
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs)448
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs407
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs)463
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs388
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs)412
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj28
-rw-r--r--modules/mono/glue/runtime_interop.cpp226
-rw-r--r--modules/mono/glue/runtime_interop.h58
-rw-r--r--modules/mono/godotsharp_defs.h58
-rw-r--r--modules/mono/godotsharp_dirs.cpp58
-rw-r--r--modules/mono/godotsharp_dirs.h58
-rw-r--r--modules/mono/interop_types.h58
-rw-r--r--modules/mono/managed_callable.cpp58
-rw-r--r--modules/mono/managed_callable.h58
-rw-r--r--modules/mono/mono_gc_handle.cpp58
-rw-r--r--modules/mono/mono_gc_handle.h58
-rw-r--r--modules/mono/mono_gd/android_mono_config.h58
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp62
-rw-r--r--modules/mono/mono_gd/gd_mono.h58
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp58
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h58
-rw-r--r--modules/mono/mono_gd/support/android_support.cpp58
-rw-r--r--modules/mono/mono_gd/support/android_support.h58
-rw-r--r--modules/mono/mono_gd/support/ios_support.h58
-rw-r--r--modules/mono/mono_gd/support/ios_support.mm58
-rw-r--r--modules/mono/register_types.cpp58
-rw-r--r--modules/mono/register_types.h58
-rw-r--r--modules/mono/signal_awaiter_utils.cpp58
-rw-r--r--modules/mono/signal_awaiter_utils.h58
-rw-r--r--modules/mono/utils/macos_utils.cpp58
-rw-r--r--modules/mono/utils/macos_utils.h58
-rw-r--r--modules/mono/utils/macros.h58
-rw-r--r--modules/mono/utils/naming_utils.cpp293
-rw-r--r--modules/mono/utils/naming_utils.h42
-rw-r--r--modules/mono/utils/path_utils.cpp58
-rw-r--r--modules/mono/utils/path_utils.h58
-rw-r--r--modules/mono/utils/string_utils.cpp58
-rw-r--r--modules/mono/utils/string_utils.h58
171 files changed, 11066 insertions, 8538 deletions
diff --git a/modules/mono/README.md b/modules/mono/README.md
index 366777cfc1..74b4531dfb 100644
--- a/modules/mono/README.md
+++ b/modules/mono/README.md
@@ -46,10 +46,10 @@ C# solutions during development to avoid mistakes.
# Double Precision Support (REAL_T_IS_DOUBLE)
-Follow the above instructions but build Godot with the float=64 argument to scons
+Follow the above instructions but build Godot with the precision=double argument to scons
-When building the NuGet packages, specify `--float=64` - for example:
+When building the NuGet packages, specify `--precision=double` - for example:
```sh
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir ./bin \
- --push-nupkgs-local ~/MyLocalNugetSource --float=64
+ --push-nupkgs-local ~/MyLocalNugetSource --precision=double
```
diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py
index 7343af0b39..0b91cda9b8 100755
--- a/modules/mono/build_scripts/build_assemblies.py
+++ b/modules/mono/build_scripts/build_assemblies.py
@@ -193,7 +193,7 @@ def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: Optional[List[str]
return subprocess.call(args, env=msbuild_env)
-def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size):
+def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision):
target_filenames = [
"GodotSharp.dll",
"GodotSharp.pdb",
@@ -214,7 +214,7 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, flo
args = ["/restore", "/t:Build", "/p:Configuration=" + build_config, "/p:NoWarn=1591"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
@@ -303,12 +303,12 @@ def generate_sdk_package_versions():
f.close()
-def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, float_size):
+def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, precision):
# Generate SdkPackageVersions.props
generate_sdk_package_versions()
# Godot API
- exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size)
+ exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision)
if exit_code != 0:
return exit_code
@@ -319,7 +319,7 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
)
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
if exit_code != 0:
@@ -329,7 +329,7 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
args = ["/restore", "/t:Build", "/p:Configuration=Release"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
@@ -354,7 +354,9 @@ def main():
parser.add_argument("--godot-platform", type=str, default="")
parser.add_argument("--mono-prefix", type=str, default="")
parser.add_argument("--push-nupkgs-local", type=str, default="")
- parser.add_argument("--float", type=str, default="32", choices=["32", "64"], help="Floating-point precision")
+ parser.add_argument(
+ "--precision", type=str, default="single", choices=["single", "double"], help="Floating-point precision level"
+ )
args = parser.parse_args()
@@ -378,7 +380,7 @@ def main():
args.godot_platform,
args.dev_debug,
push_nupkgs_local,
- args.float,
+ args.precision,
)
sys.exit(exit_code)
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
index 1f4b085bfb..733f1dbe34 100644
--- a/modules/mono/class_db_api_json.cpp
+++ b/modules/mono/class_db_api_json.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* class_db_api_json.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* class_db_api_json.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "class_db_api_json.h"
diff --git a/modules/mono/class_db_api_json.h b/modules/mono/class_db_api_json.h
index 1d2000b033..d222988f1d 100644
--- a/modules/mono/class_db_api_json.h
+++ b/modules/mono/class_db_api_json.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* class_db_api_json.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* class_db_api_json.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef CLASS_DB_API_JSON_H
#define CLASS_DB_API_JSON_H
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 345d2e4694..fe0f4aae81 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* csharp_script.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* csharp_script.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "csharp_script.h"
@@ -46,6 +46,7 @@
#include "editor/editor_internal_calls.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "editor/inspector_dock.h"
#include "editor/node_dock.h"
#include "editor/script_templates/templates.gen.h"
#endif
@@ -59,6 +60,7 @@
#include "mono_gd/gd_mono_cache.h"
#include "signal_awaiter_utils.h"
#include "utils/macros.h"
+#include "utils/naming_utils.h"
#include "utils/string_utils.h"
#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->get_string_names().m_var)
@@ -72,7 +74,7 @@ static bool _create_project_solution_if_needed() {
CSharpLanguage *CSharpLanguage::singleton = nullptr;
-GDNativeInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = {
+GDExtensionInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = {
&_instance_binding_create_callback,
&_instance_binding_free_callback,
&_instance_binding_reference_callback
@@ -112,6 +114,11 @@ void CSharpLanguage::init() {
BindingsGenerator::handle_cmdline_args(cmdline_args);
#endif
+ GLOBAL_DEF("dotnet/project/assembly_name", "");
+#ifdef TOOLS_ENABLED
+ GLOBAL_DEF("dotnet/project/solution_directory", "");
+#endif
+
gdmono = memnew(GDMono);
gdmono->initialize();
@@ -327,7 +334,7 @@ void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const {
}
static String get_base_class_name(const String &p_base_class_name, const String p_class_name) {
- String base_class = p_base_class_name;
+ String base_class = pascal_to_pascal_case(p_base_class_name);
if (p_class_name == base_class) {
base_class = "Godot." + base_class;
}
@@ -388,25 +395,30 @@ bool CSharpLanguage::supports_builtin_mode() const {
}
#ifdef TOOLS_ENABLED
+struct VariantCsName {
+ Variant::Type variant_type;
+ const String cs_type;
+};
+
static String variant_type_to_managed_name(const String &p_var_type_name) {
if (p_var_type_name.is_empty()) {
- return "object";
+ return "Variant";
}
- if (!ClassDB::class_exists(p_var_type_name)) {
- return p_var_type_name;
+ if (ClassDB::class_exists(p_var_type_name)) {
+ return pascal_to_pascal_case(p_var_type_name);
}
if (p_var_type_name == Variant::get_type_name(Variant::OBJECT)) {
- return "Godot.Object";
+ return "GodotObject";
+ }
+
+ if (p_var_type_name == Variant::get_type_name(Variant::INT)) {
+ return "long";
}
if (p_var_type_name == Variant::get_type_name(Variant::FLOAT)) {
-#ifdef REAL_T_IS_DOUBLE
return "double";
-#else
- return "float";
-#endif
}
if (p_var_type_name == Variant::get_type_name(Variant::STRING)) {
@@ -450,41 +462,41 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
}
if (p_var_type_name == Variant::get_type_name(Variant::SIGNAL)) {
- return "SignalInfo";
- }
-
- Variant::Type var_types[] = {
- Variant::BOOL,
- Variant::INT,
- Variant::VECTOR2,
- Variant::VECTOR2I,
- Variant::RECT2,
- Variant::RECT2I,
- Variant::VECTOR3,
- Variant::VECTOR3I,
- Variant::TRANSFORM2D,
- Variant::VECTOR4,
- Variant::VECTOR4I,
- Variant::PLANE,
- Variant::QUATERNION,
- Variant::AABB,
- Variant::BASIS,
- Variant::TRANSFORM3D,
- Variant::PROJECTION,
- Variant::COLOR,
- Variant::STRING_NAME,
- Variant::NODE_PATH,
- Variant::RID,
- Variant::CALLABLE
+ return "Signal";
+ }
+
+ const VariantCsName var_types[] = {
+ { Variant::BOOL, "bool" },
+ { Variant::INT, "long" },
+ { Variant::VECTOR2, "Vector2" },
+ { Variant::VECTOR2I, "Vector2I" },
+ { Variant::RECT2, "Rect2" },
+ { Variant::RECT2I, "Rect2I" },
+ { Variant::VECTOR3, "Vector3" },
+ { Variant::VECTOR3I, "Vector3I" },
+ { Variant::TRANSFORM2D, "Transform2D" },
+ { Variant::VECTOR4, "Vector4" },
+ { Variant::VECTOR4I, "Vector4I" },
+ { Variant::PLANE, "Plane" },
+ { Variant::QUATERNION, "Quaternion" },
+ { Variant::AABB, "Aabb" },
+ { Variant::BASIS, "Basis" },
+ { Variant::TRANSFORM3D, "Transform3D" },
+ { Variant::PROJECTION, "Projection" },
+ { Variant::COLOR, "Color" },
+ { Variant::STRING_NAME, "StringName" },
+ { Variant::NODE_PATH, "NodePath" },
+ { Variant::RID, "Rid" },
+ { Variant::CALLABLE, "Callable" },
};
- for (unsigned int i = 0; i < sizeof(var_types) / sizeof(Variant::Type); i++) {
- if (p_var_type_name == Variant::get_type_name(var_types[i])) {
- return p_var_type_name;
+ for (unsigned int i = 0; i < sizeof(var_types) / sizeof(VariantCsName); i++) {
+ if (p_var_type_name == Variant::get_type_name(var_types[i].variant_type)) {
+ return var_types[i].cs_type;
}
}
- return "object";
+ return "Variant";
}
String CSharpLanguage::make_function(const String &, const String &p_name, const PackedStringArray &p_args) const {
@@ -687,7 +699,7 @@ bool CSharpLanguage::is_assembly_reloading_needed() {
return false; // Already up to date
}
} else {
- String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
+ String assembly_name = GLOBAL_GET("dotnet/project/assembly_name");
if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
@@ -710,6 +722,12 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
return;
}
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ // We disable collectible assemblies in the game player, because the limitations cause
+ // issues with mocking libraries. As such, we can only reload assemblies in the editor.
+ return;
+ }
+
// TODO:
// Currently, this reloads all scripts, including those whose class is not part of the
// assembly load context being unloaded. As such, we unnecessarily reload GodotTools.
@@ -1286,7 +1304,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin
}
}
-GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) {
+GDExtensionBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference) {
CRASH_COND(!p_binding);
CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
@@ -2195,7 +2213,7 @@ void CSharpScript::reload_registered_script(Ref<CSharpScript> p_script) {
void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
bool tool = false;
- // TODO: Use GDNative godot_dictionary
+ // TODO: Use GDExtension godot_dictionary
Array methods_array;
methods_array.~Array();
Dictionary rpc_functions_dict;
@@ -2285,7 +2303,7 @@ bool CSharpScript::can_instantiate() const {
// For tool scripts, this will never fire if the class is not found. That's because we
// don't know if it's a tool script if we can't find the class to access the attributes.
if (extra_cond && !valid) {
- ERR_FAIL_V_MSG(false, "Cannot instance script because the associated class could not be found. Script: '" + get_path() + "'.");
+ ERR_FAIL_V_MSG(false, "Cannot instance script because the associated class could not be found. Script: '" + get_path() + "'. Make sure the script exists and contains a class definition with a name that matches the filename of the script exactly (it's case-sensitive).");
}
return valid && extra_cond;
@@ -2594,6 +2612,10 @@ Ref<Script> CSharpScript::get_base_script() const {
return base_script;
}
+StringName CSharpScript::get_global_name() const {
+ return StringName();
+}
+
void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
#ifdef TOOLS_ENABLED
const CSharpScript *top = this;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index e5e53acb07..6021555255 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* csharp_script.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* csharp_script.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef CSHARP_SCRIPT_H
#define CSHARP_SCRIPT_H
@@ -186,6 +186,8 @@ public:
bool inherits_script(const Ref<Script> &p_script) const override;
Ref<Script> get_base_script() const override;
+ StringName get_global_name() const override;
+
ScriptLanguage *get_language() const override;
void get_script_method_list(List<MethodInfo> *p_list) const override;
@@ -352,9 +354,9 @@ class CSharpLanguage : public ScriptLanguage {
static void *_instance_binding_create_callback(void *p_token, void *p_instance);
static void _instance_binding_free_callback(void *p_token, void *p_instance, void *p_binding);
- static GDNativeBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference);
+ static GDExtensionBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference);
- static GDNativeInstanceBindingCallbacks _instance_binding_callbacks;
+ static GDExtensionInstanceBindingCallbacks _instance_binding_callbacks;
public:
static void *get_instance_binding(Object *p_object);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
index 0459257106..0d0889c491 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
@@ -12,8 +12,7 @@
<Configurations>Debug;ExportDebug;ExportRelease</Configurations>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <GodotProjectDir Condition=" '$(SolutionDir)' != '' ">$(SolutionDir)</GodotProjectDir>
- <GodotProjectDir Condition=" '$(SolutionDir)' == '' ">$(MSBuildProjectDirectory)</GodotProjectDir>
+ <GodotProjectDir Condition=" '$(GodotProjectDir)' == '' ">$(MSBuildProjectDirectory)</GodotProjectDir>
<GodotProjectDir>$([MSBuild]::EnsureTrailingSlash('$(GodotProjectDir)'))</GodotProjectDir>
<!-- Custom output paths for Godot projects. In brief, 'bin\' and 'obj\' are moved to '$(GodotProjectDir)\.godot\mono\temp\'. -->
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
index 5eaebc4474..2d797e2f46 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
@@ -1,6 +1,6 @@
namespace Godot.SourceGenerators.Sample
{
- partial class Bar : Godot.Object
+ partial class Bar : GodotObject
{
}
@@ -9,7 +9,7 @@ namespace Godot.SourceGenerators.Sample
{
}
- partial class NotSameNameAsFile : Godot.Object
+ partial class NotSameNameAsFile : GodotObject
{
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/EventSignals.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/EventSignals.cs
index 764ba8f121..ee6aa857fc 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/EventSignals.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/EventSignals.cs
@@ -1,6 +1,6 @@
namespace Godot.SourceGenerators.Sample;
-public partial class EventSignals : Godot.Object
+public partial class EventSignals : GodotObject
{
[Signal]
public delegate void MySignalEventHandler(string str, int num);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
index ac8d6473a6..31e66ac306 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
#pragma warning disable CS0169
@@ -10,7 +11,7 @@ namespace Godot.SourceGenerators.Sample
[SuppressMessage("ReSharper", "RedundantNameQualifier")]
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeEvident")]
[SuppressMessage("ReSharper", "InconsistentNaming")]
- public partial class ExportedFields : Godot.Object
+ public partial class ExportedFields : GodotObject
{
[Export] private Boolean field_Boolean = true;
[Export] private Char field_Char = 'f';
@@ -28,23 +29,23 @@ namespace Godot.SourceGenerators.Sample
// Godot structs
[Export] private Vector2 field_Vector2 = new(10f, 10f);
- [Export] private Vector2i field_Vector2i = Vector2i.Up;
+ [Export] private Vector2I field_Vector2I = Vector2I.Up;
[Export] private Rect2 field_Rect2 = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
- [Export] private Rect2i field_Rect2i = new(new Vector2i(10, 10), new Vector2i(10, 10));
+ [Export] private Rect2I field_Rect2I = new(new Vector2I(10, 10), new Vector2I(10, 10));
[Export] private Transform2D field_Transform2D = Transform2D.Identity;
[Export] private Vector3 field_Vector3 = new(10f, 10f, 10f);
- [Export] private Vector3i field_Vector3i = Vector3i.Back;
+ [Export] private Vector3I field_Vector3I = Vector3I.Back;
[Export] private Basis field_Basis = new Basis(Quaternion.Identity);
[Export] private Quaternion field_Quaternion = new Quaternion(Basis.Identity);
[Export] private Transform3D field_Transform3D = Transform3D.Identity;
[Export] private Vector4 field_Vector4 = new(10f, 10f, 10f, 10f);
- [Export] private Vector4i field_Vector4i = Vector4i.One;
+ [Export] private Vector4I field_Vector4I = Vector4I.One;
[Export] private Projection field_Projection = Projection.Identity;
- [Export] private AABB field_AABB = new AABB(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
+ [Export] private Aabb field_Aabb = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
[Export] private Color field_Color = Colors.Aquamarine;
[Export] private Plane field_Plane = Plane.PlaneXZ;
[Export] private Callable field_Callable = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private SignalInfo field_SignalInfo = new SignalInfo(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Signal field_Signal = new Signal(Engine.GetMainLoop(), "property_list_changed");
// Enums
[SuppressMessage("ReSharper", "UnusedMember.Local")]
@@ -79,20 +80,24 @@ namespace Godot.SourceGenerators.Sample
[Export] private Vector2[] field_Vector2Array = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
[Export] private Vector3[] field_Vector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
[Export] private Color[] field_ColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
- [Export] private Godot.Object[] field_GodotObjectOrDerivedArray = { null };
+ [Export] private GodotObject[] field_GodotObjectOrDerivedArray = { null };
[Export] private StringName[] field_StringNameArray = { "foo", "bar" };
[Export] private NodePath[] field_NodePathArray = { "foo", "bar" };
- [Export] private RID[] field_RIDArray = { default, default, default };
+ [Export] private Rid[] field_RidArray = { default, default, default };
+ // Note we use Array and not System.Array. This tests the generated namespace qualification.
+ [Export] private Int32[] field_empty_Int32Array = Array.Empty<Int32>();
+ // Note we use List and not System.Collections.Generic.
+ [Export] private int[] field_array_from_list = new List<int>(Array.Empty<int>()).ToArray();
// Variant
[Export] private Variant field_Variant = "foo";
// Classes
- [Export] private Godot.Object field_GodotObjectOrDerived;
+ [Export] private GodotObject field_GodotObjectOrDerived;
[Export] private Godot.Texture field_GodotResourceTexture;
[Export] private StringName field_StringName = new StringName("foo");
[Export] private NodePath field_NodePath = new NodePath("foo");
- [Export] private RID field_RID;
+ [Export] private Rid field_Rid;
[Export]
private Godot.Collections.Dictionary field_GodotDictionary =
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
index 3020cfbc50..aef2a8824e 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
@@ -10,8 +10,97 @@ namespace Godot.SourceGenerators.Sample
[SuppressMessage("ReSharper", "RedundantNameQualifier")]
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeEvident")]
[SuppressMessage("ReSharper", "InconsistentNaming")]
- public partial class ExportedProperties : Godot.Object
+ public partial class ExportedProperties : GodotObject
{
+ // Do not generate default value
+ private String _notGenerate_Property_String = new string("not generate");
+ [Export]
+ public String NotGenerate_Complex_Lamda_Property
+ {
+ get => _notGenerate_Property_String + Convert.ToInt32("1");
+ set => _notGenerate_Property_String = value;
+ }
+
+ [Export]
+ public String NotGenerate_Lamda_NoField_Property
+ {
+ get => new string("not generate");
+ set => _notGenerate_Property_String = value;
+ }
+
+ [Export]
+ public String NotGenerate_Complex_Return_Property
+ {
+ get
+ {
+ return _notGenerate_Property_String + Convert.ToInt32("1");
+ }
+ set
+ {
+ _notGenerate_Property_String = value;
+ }
+ }
+
+ private int _notGenerate_Property_Int = 1;
+ [Export]
+ public string NotGenerate_Returns_Property
+ {
+ get
+ {
+ if (_notGenerate_Property_Int == 1)
+ {
+ return "a";
+ }
+ else
+ {
+ return "b";
+ }
+ }
+ set
+ {
+ _notGenerate_Property_Int = value == "a" ? 1 : 2;
+ }
+ }
+
+ // Full Property
+ private String _fullProperty_String = "FullProperty_String";
+ [Export]
+ public String FullProperty_String
+ {
+ get
+ {
+ return _fullProperty_String;
+ }
+ set
+ {
+ _fullProperty_String = value;
+ }
+ }
+
+ private String _fullProperty_String_Complex = new string("FullProperty_String_Complex") + Convert.ToInt32("1");
+ [Export]
+ public String FullProperty_String_Complex
+ {
+ get
+ {
+ return _fullProperty_String_Complex;
+ }
+ set
+ {
+ _fullProperty_String_Complex = value;
+ }
+ }
+
+ // Lambda Property
+ private String _lamdaProperty_String = "LamdaProperty_String";
+ [Export]
+ public String LamdaProperty_String
+ {
+ get => _lamdaProperty_String;
+ set => _lamdaProperty_String = value;
+ }
+
+ // Auto Property
[Export] private Boolean property_Boolean { get; set; } = true;
[Export] private Char property_Char { get; set; } = 'f';
[Export] private SByte property_SByte { get; set; } = 10;
@@ -28,23 +117,23 @@ namespace Godot.SourceGenerators.Sample
// Godot structs
[Export] private Vector2 property_Vector2 { get; set; } = new(10f, 10f);
- [Export] private Vector2i property_Vector2i { get; set; } = Vector2i.Up;
+ [Export] private Vector2I property_Vector2I { get; set; } = Vector2I.Up;
[Export] private Rect2 property_Rect2 { get; set; } = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
- [Export] private Rect2i property_Rect2i { get; set; } = new(new Vector2i(10, 10), new Vector2i(10, 10));
+ [Export] private Rect2I property_Rect2I { get; set; } = new(new Vector2I(10, 10), new Vector2I(10, 10));
[Export] private Transform2D property_Transform2D { get; set; } = Transform2D.Identity;
[Export] private Vector3 property_Vector3 { get; set; } = new(10f, 10f, 10f);
- [Export] private Vector3i property_Vector3i { get; set; } = Vector3i.Back;
+ [Export] private Vector3I property_Vector3I { get; set; } = Vector3I.Back;
[Export] private Basis property_Basis { get; set; } = new Basis(Quaternion.Identity);
[Export] private Quaternion property_Quaternion { get; set; } = new Quaternion(Basis.Identity);
[Export] private Transform3D property_Transform3D { get; set; } = Transform3D.Identity;
[Export] private Vector4 property_Vector4 { get; set; } = new(10f, 10f, 10f, 10f);
- [Export] private Vector4i property_Vector4i { get; set; } = Vector4i.One;
+ [Export] private Vector4I property_Vector4I { get; set; } = Vector4I.One;
[Export] private Projection property_Projection { get; set; } = Projection.Identity;
- [Export] private AABB property_AABB { get; set; } = new AABB(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
+ [Export] private Aabb property_Aabb { get; set; } = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
[Export] private Color property_Color { get; set; } = Colors.Aquamarine;
[Export] private Plane property_Plane { get; set; } = Plane.PlaneXZ;
[Export] private Callable property_Callable { get; set; } = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private SignalInfo property_SignalInfo { get; set; } = new SignalInfo(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Signal property_Signal { get; set; } = new Signal(Engine.GetMainLoop(), "property_list_changed");
// Enums
[SuppressMessage("ReSharper", "UnusedMember.Local")]
@@ -79,20 +168,20 @@ namespace Godot.SourceGenerators.Sample
[Export] private Vector2[] property_Vector2Array { get; set; } = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
[Export] private Vector3[] property_Vector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
[Export] private Color[] property_ColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
- [Export] private Godot.Object[] property_GodotObjectOrDerivedArray { get; set; } = { null };
+ [Export] private GodotObject[] property_GodotObjectOrDerivedArray { get; set; } = { null };
[Export] private StringName[] field_StringNameArray { get; set; } = { "foo", "bar" };
[Export] private NodePath[] field_NodePathArray { get; set; } = { "foo", "bar" };
- [Export] private RID[] field_RIDArray { get; set; } = { default, default, default };
+ [Export] private Rid[] field_RidArray { get; set; } = { default, default, default };
// Variant
[Export] private Variant property_Variant { get; set; } = "foo";
// Classes
- [Export] private Godot.Object property_GodotObjectOrDerived { get; set; }
+ [Export] private GodotObject property_GodotObjectOrDerived { get; set; }
[Export] private Godot.Texture property_GodotResourceTexture { get; set; }
[Export] private StringName property_StringName { get; set; } = new StringName("foo");
[Export] private NodePath property_NodePath { get; set; } = new NodePath("foo");
- [Export] private RID property_RID { get; set; }
+ [Export] private Rid property_Rid { get; set; }
[Export]
private Godot.Collections.Dictionary property_GodotDictionary { get; set; } =
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
index 21a5bfe560..9ef72d9e02 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
@@ -1,6 +1,6 @@
namespace Godot.SourceGenerators.Sample
{
- partial class Foo : Godot.Object
+ partial class Foo : GodotObject
{
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs
index b21b035b4d..2cd1a08c0e 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs
@@ -2,19 +2,19 @@
namespace Godot.SourceGenerators.Sample
{
- partial class Generic<T> : Godot.Object
+ partial class Generic<T> : GodotObject
{
private int _field;
}
// Generic again but different generic parameters
- partial class Generic<T, R> : Godot.Object
+ partial class Generic<T, R> : GodotObject
{
private int _field;
}
// Generic again but without generic parameters
- partial class Generic : Godot.Object
+ partial class Generic : GodotObject
{
private int _field;
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Methods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Methods.cs
index 618ba24abc..9aa6be3972 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Methods.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Methods.cs
@@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis;
namespace Godot.SourceGenerators.Sample;
[SuppressMessage("ReSharper", "RedundantNameQualifier")]
-public partial class Methods : Godot.Object
+public partial class Methods : GodotObject
{
private void MethodWithOverload()
{
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs
new file mode 100644
index 0000000000..64088215e9
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+#pragma warning disable CS0169
+#pragma warning disable CS0414
+
+namespace Godot.SourceGenerators.Sample
+{
+ [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeEvident")]
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ // We split the definition of ExportedFields to verify properties work across multiple files.
+ public partial class ExportedFields : GodotObject
+ {
+ // Note we use Array and not System.Array. This tests the generated namespace qualification.
+ [Export] private Int64[] field_empty_Int64Array = Array.Empty<Int64>();
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
index e28788ec0b..41bf89e6d8 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
@@ -14,9 +14,9 @@ namespace Godot.SourceGenerators
{
string message =
"Missing partial modifier on declaration of type '" +
- $"{symbol.FullQualifiedName()}' which is a subclass of '{GodotClasses.Object}'";
+ $"{symbol.FullQualifiedNameOmitGlobal()}' which is a subclass of '{GodotClasses.GodotObject}'";
- string description = $"{message}. Subclasses of '{GodotClasses.Object}' " +
+ string description = $"{message}. Subclasses of '{GodotClasses.GodotObject}' " +
"must be declared with the partial modifier.";
context.ReportDiagnostic(Diagnostic.Create(
@@ -41,14 +41,14 @@ namespace Godot.SourceGenerators
.GetDeclaredSymbol(outerTypeDeclSyntax);
string fullQualifiedName = outerSymbol is INamedTypeSymbol namedTypeSymbol ?
- namedTypeSymbol.FullQualifiedName() :
+ namedTypeSymbol.FullQualifiedNameOmitGlobal() :
"type not found";
string message =
$"Missing partial modifier on declaration of type '{fullQualifiedName}', " +
- $"which contains one or more subclasses of '{GodotClasses.Object}'";
+ $"which contains one or more subclasses of '{GodotClasses.GodotObject}'";
- string description = $"{message}. Subclasses of '{GodotClasses.Object}' and their " +
+ string description = $"{message}. Subclasses of '{GodotClasses.GodotObject}' and their " +
"containing types must be declared with the partial modifier.";
context.ReportDiagnostic(Diagnostic.Create(
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
index 8de12de23b..f0c9043fd5 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
+using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -84,7 +85,7 @@ namespace Godot.SourceGenerators
var classTypeSymbol = sm.GetDeclaredSymbol(cds);
if (classTypeSymbol?.BaseType == null
- || !classTypeSymbol.BaseType.InheritsFrom("GodotSharp", GodotClasses.Object))
+ || !classTypeSymbol.BaseType.InheritsFrom("GodotSharp", GodotClasses.GodotObject))
{
symbol = null;
return false;
@@ -148,22 +149,73 @@ namespace Godot.SourceGenerators
};
}
+ public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
+ {
+ return symbol.IsGenericType ?
+ string.Concat(symbol.Name, "<", string.Join(", ", symbol.TypeParameters), ">") :
+ symbol.Name;
+ }
+
private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
SymbolDisplayFormat.FullyQualifiedFormat
.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
- public static string FullQualifiedName(this ITypeSymbol symbol)
+ private static SymbolDisplayFormat FullyQualifiedFormatIncludeGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Included);
+
+ public static string FullQualifiedNameOmitGlobal(this ITypeSymbol symbol)
=> symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
- public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
+ public static string FullQualifiedNameOmitGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this ITypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatIncludeGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatIncludeGlobal);
+
+ public static string FullQualifiedSyntax(this SyntaxNode node, SemanticModel sm)
{
- return symbol.IsGenericType ?
- string.Concat(symbol.Name, "<", string.Join(", ", symbol.TypeParameters), ">") :
- symbol.Name;
+ StringBuilder sb = new();
+ FullQualifiedSyntax(node, sm, sb, true);
+ return sb.ToString();
}
- public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol)
- => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+ private static void FullQualifiedSyntax(SyntaxNode node, SemanticModel sm, StringBuilder sb, bool isFirstNode)
+ {
+ if (node is NameSyntax ns && isFirstNode)
+ {
+ SymbolInfo nameInfo = sm.GetSymbolInfo(ns);
+ sb.Append(nameInfo.Symbol?.ToDisplayString(FullyQualifiedFormatIncludeGlobal) ?? ns.ToString());
+ return;
+ }
+
+ bool innerIsFirstNode = true;
+ foreach (var child in node.ChildNodesAndTokens())
+ {
+ if (child.HasLeadingTrivia)
+ {
+ sb.Append(child.GetLeadingTrivia());
+ }
+
+ if (child.IsNode)
+ {
+ FullQualifiedSyntax(child.AsNode()!, sm, sb, isFirstNode: innerIsFirstNode);
+ innerIsFirstNode = false;
+ }
+ else
+ {
+ sb.Append(child);
+ }
+
+ if (child.HasTrailingTrivia)
+ {
+ sb.Append(child.GetTrailingTrivia());
+ }
+ }
+ }
public static string SanitizeQualifiedNameForUniqueHint(this string qualifiedName)
=> qualifiedName
@@ -216,8 +268,9 @@ namespace Godot.SourceGenerators
if (parameters.Length > paramTypes.Length)
return null; // Ignore incompatible method
- return new GodotMethodData(method, paramTypes, parameters
- .Select(p => p.Type).ToImmutableArray(), retType, retSymbol);
+ return new GodotMethodData(method, paramTypes,
+ parameters.Select(p => p.Type).ToImmutableArray(),
+ retType != null ? (retType.Value, retSymbol) : null);
}
public static IEnumerable<GodotMethodData> WhereHasGodotCompatibleSignature(
@@ -242,8 +295,8 @@ namespace Godot.SourceGenerators
foreach (var property in properties)
{
// TODO: We should still restore read-only properties after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload.
- // Ignore properties without a getter or without a setter. Godot properties must be both readable and writable.
- if (property.IsWriteOnly || property.IsReadOnly)
+ // Ignore properties without a getter, without a setter or with an init-only setter. Godot properties must be both readable and writable.
+ if (property.IsWriteOnly || property.IsReadOnly || property.SetMethod!.IsInitOnly)
continue;
var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(property.Type, typeCache);
@@ -278,10 +331,10 @@ namespace Godot.SourceGenerators
public static string Path(this Location location)
=> location.SourceTree?.GetLineSpan(location.SourceSpan).Path
- ?? location.GetLineSpan().Path;
+ ?? location.GetLineSpan().Path;
public static int StartLine(this Location location)
=> location.SourceTree?.GetLineSpan(location.SourceSpan).StartLinePosition.Line
- ?? location.GetLineSpan().StartLinePosition.Line;
+ ?? location.GetLineSpan().StartLinePosition.Line;
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
index 1d8ddbabf2..b60148b34f 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
@@ -2,7 +2,7 @@ namespace Godot.SourceGenerators
{
public static class GodotClasses
{
- public const string Object = "Godot.Object";
+ public const string GodotObject = "Godot.GodotObject";
public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
public const string ExportAttr = "Godot.ExportAttribute";
public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
@@ -10,7 +10,7 @@ namespace Godot.SourceGenerators
public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute";
public const string SignalAttr = "Godot.SignalAttribute";
public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute";
- public const string GodotClassNameAttr = "Godot.GodotClassName";
+ public const string GodotClassNameAttr = "Godot.GodotClassNameAttribute";
public const string SystemFlagsAttr = "System.FlagsAttribute";
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
index 1a25d684a0..b30c8c240e 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
@@ -12,19 +12,19 @@ namespace Godot.SourceGenerators
Float = 3,
String = 4,
Vector2 = 5,
- Vector2i = 6,
+ Vector2I = 6,
Rect2 = 7,
- Rect2i = 8,
+ Rect2I = 8,
Vector3 = 9,
- Vector3i = 10,
- Transform2d = 11,
+ Vector3I = 10,
+ Transform2D = 11,
Vector4 = 12,
- Vector4i = 13,
+ Vector4I = 13,
Plane = 14,
Quaternion = 15,
Aabb = 16,
Basis = 17,
- Transform3d = 18,
+ Transform3D = 18,
Projection = 19,
Color = 20,
StringName = 21,
@@ -56,12 +56,12 @@ namespace Godot.SourceGenerators
ExpEasing = 4,
Link = 5,
Flags = 6,
- Layers2dRender = 7,
- Layers2dPhysics = 8,
- Layers2dNavigation = 9,
- Layers3dRender = 10,
- Layers3dPhysics = 11,
- Layers3dNavigation = 12,
+ Layers2DRender = 7,
+ Layers2DPhysics = 8,
+ Layers2DNavigation = 9,
+ Layers3DRender = 10,
+ Layers3DPhysics = 11,
+ Layers3DNavigation = 12,
File = 13,
Dir = 14,
GlobalFile = 15,
@@ -71,30 +71,22 @@ namespace Godot.SourceGenerators
Expression = 19,
PlaceholderText = 20,
ColorNoAlpha = 21,
- ImageCompressLossy = 22,
- ImageCompressLossless = 23,
- ObjectId = 24,
- TypeString = 25,
- NodePathToEditedNode = 26,
- MethodOfVariantType = 27,
- MethodOfBaseType = 28,
- MethodOfInstance = 29,
- MethodOfScript = 30,
- PropertyOfVariantType = 31,
- PropertyOfBaseType = 32,
- PropertyOfInstance = 33,
- PropertyOfScript = 34,
- ObjectTooBig = 35,
- NodePathValidTypes = 36,
- SaveFile = 37,
- GlobalSaveFile = 38,
- IntIsObjectid = 39,
- IntIsPointer = 41,
- ArrayType = 40,
- LocaleId = 42,
- LocalizableString = 43,
- NodeType = 44,
- Max = 45
+ ObjectId = 22,
+ TypeString = 23,
+ NodePathToEditedNode = 24,
+ ObjectTooBig = 25,
+ NodePathValidTypes = 26,
+ SaveFile = 27,
+ GlobalSaveFile = 28,
+ IntIsObjectid = 29,
+ IntIsPointer = 30,
+ ArrayType = 31,
+ LocaleId = 32,
+ LocalizableString = 33,
+ NodeType = 34,
+ HideQuaternionEdit = 35,
+ Password = 36,
+ Max = 37
}
[Flags]
@@ -103,9 +95,9 @@ namespace Godot.SourceGenerators
None = 0,
Storage = 2,
Editor = 4,
- Checkable = 8,
- Checked = 16,
- Internationalized = 32,
+ Internal = 8,
+ Checkable = 16,
+ Checked = 32,
Group = 64,
Category = 128,
Subgroup = 256,
@@ -114,13 +106,13 @@ namespace Godot.SourceGenerators
RestartIfChanged = 2048,
ScriptVariable = 4096,
StoreIfNull = 8192,
- AnimateAsTrigger = 16384,
- UpdateAllIfModified = 32768,
- ScriptDefaultValue = 65536,
- ClassIsEnum = 131072,
- NilIsVariant = 262144,
- Internal = 524288,
- DoNotShareOnDuplicate = 1048576,
+ UpdateAllIfModified = 16384,
+ ScriptDefaultValue = 32768,
+ ClassIsEnum = 65536,
+ NilIsVariant = 131072,
+ Array = 262144,
+ AlwaysDuplicate = 524288,
+ NeverDuplicate = 1048576,
HighEndGfx = 2097152,
NodePathFromSceneRoot = 4194304,
ResourceNotPersistent = 8388608,
@@ -128,12 +120,12 @@ namespace Godot.SourceGenerators
DeferredSetResource = 33554432,
EditorInstantiateObject = 67108864,
EditorBasicSetting = 134217728,
- Array = 536870912,
+ ReadOnly = 268435456,
Default = 6,
- DefaultIntl = 38,
NoEditor = 2
}
+ [Flags]
public enum MethodFlags
{
Normal = 1,
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..0760ea11bb 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
@@ -3,26 +3,24 @@ 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)
+ ImmutableArray<ITypeSymbol> paramTypeSymbols, (MarshalType MarshalType, ITypeSymbol TypeSymbol)? retType)
{
Method = method;
ParamTypes = paramTypes;
ParamTypeSymbols = paramTypeSymbols;
RetType = retType;
- RetSymbol = retSymbol;
}
public IMethodSymbol Method { get; }
public ImmutableArray<MarshalType> ParamTypes { get; }
public ImmutableArray<ITypeSymbol> ParamTypeSymbols { get; }
- public MarshalType? RetType { get; }
- public ITypeSymbol? RetSymbol { get; }
+ public (MarshalType MarshalType, ITypeSymbol TypeSymbol)? RetType { get; }
}
- public struct GodotSignalDelegateData
+ public readonly struct GodotSignalDelegateData
{
public GodotSignalDelegateData(string name, INamedTypeSymbol delegateSymbol, GodotMethodData invokeMethodData)
{
@@ -36,7 +34,7 @@ namespace Godot.SourceGenerators
public GodotMethodData InvokeMethodData { get; }
}
- public struct GodotPropertyData
+ public readonly struct GodotPropertyData
{
public GodotPropertyData(IPropertySymbol propertySymbol, MarshalType type)
{
@@ -48,7 +46,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/GodotPluginsInitializerGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs
index 19fdd51dab..47a4516948 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs
@@ -34,7 +34,7 @@ namespace GodotPlugins.Game
{
DllImportResolver dllImportResolver = new GodotDllImportResolver(godotDllHandle).OnResolveDllImport;
- var coreApiAssembly = typeof(Godot.Object).Assembly;
+ var coreApiAssembly = typeof(global::Godot.GodotObject).Assembly;
NativeLibrary.SetDllImportResolver(coreApiAssembly, dllImportResolver);
@@ -42,13 +42,13 @@ namespace GodotPlugins.Game
ManagedCallbacks.Create(outManagedCallbacks);
- ScriptManagerBridge.LookupScriptsInAssembly(typeof(GodotPlugins.Game.Main).Assembly);
+ ScriptManagerBridge.LookupScriptsInAssembly(typeof(global::GodotPlugins.Game.Main).Assembly);
return godot_bool.True;
}
catch (Exception e)
{
- Console.Error.WriteLine(e);
+ global::System.Console.Error.WriteLine(e);
return false.ToGodotBool();
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
index 15f5803bf0..be6af117eb 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
@@ -21,23 +21,23 @@ namespace Godot.SourceGenerators
// Godot structs
Vector2,
- Vector2i,
+ Vector2I,
Rect2,
- Rect2i,
+ Rect2I,
Transform2D,
Vector3,
- Vector3i,
+ Vector3I,
Basis,
Quaternion,
Transform3D,
Vector4,
- Vector4i,
+ Vector4I,
Projection,
- AABB,
+ Aabb,
Color,
Plane,
Callable,
- SignalInfo,
+ Signal,
// Enums
Enum,
@@ -55,7 +55,7 @@ namespace Godot.SourceGenerators
GodotObjectOrDerivedArray,
SystemArrayOfStringName,
SystemArrayOfNodePath,
- SystemArrayOfRID,
+ SystemArrayOfRid,
// Variant
Variant,
@@ -64,7 +64,7 @@ namespace Godot.SourceGenerators
GodotObjectOrDerived,
StringName,
NodePath,
- RID,
+ Rid,
GodotDictionary,
GodotArray,
GodotGenericDictionary,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
index bd40675fd3..0258f53062 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
@@ -19,7 +19,7 @@ namespace Godot.SourceGenerators
throw new InvalidOperationException($"Type not found: '{fullyQualifiedMetadataName}'.");
}
- GodotObjectType = GetTypeByMetadataNameOrThrow("Godot.Object");
+ GodotObjectType = GetTypeByMetadataNameOrThrow(GodotClasses.GodotObject);
}
}
@@ -40,23 +40,23 @@ namespace Godot.SourceGenerators
MarshalType.Double => VariantType.Float,
MarshalType.String => VariantType.String,
MarshalType.Vector2 => VariantType.Vector2,
- MarshalType.Vector2i => VariantType.Vector2i,
+ MarshalType.Vector2I => VariantType.Vector2I,
MarshalType.Rect2 => VariantType.Rect2,
- MarshalType.Rect2i => VariantType.Rect2i,
- MarshalType.Transform2D => VariantType.Transform2d,
+ MarshalType.Rect2I => VariantType.Rect2I,
+ MarshalType.Transform2D => VariantType.Transform2D,
MarshalType.Vector3 => VariantType.Vector3,
- MarshalType.Vector3i => VariantType.Vector3i,
+ MarshalType.Vector3I => VariantType.Vector3I,
MarshalType.Basis => VariantType.Basis,
MarshalType.Quaternion => VariantType.Quaternion,
- MarshalType.Transform3D => VariantType.Transform3d,
+ MarshalType.Transform3D => VariantType.Transform3D,
MarshalType.Vector4 => VariantType.Vector4,
- MarshalType.Vector4i => VariantType.Vector4i,
+ MarshalType.Vector4I => VariantType.Vector4I,
MarshalType.Projection => VariantType.Projection,
- MarshalType.AABB => VariantType.Aabb,
+ MarshalType.Aabb => VariantType.Aabb,
MarshalType.Color => VariantType.Color,
MarshalType.Plane => VariantType.Plane,
MarshalType.Callable => VariantType.Callable,
- MarshalType.SignalInfo => VariantType.Signal,
+ MarshalType.Signal => VariantType.Signal,
MarshalType.Enum => VariantType.Int,
MarshalType.ByteArray => VariantType.PackedByteArray,
MarshalType.Int32Array => VariantType.PackedInt32Array,
@@ -70,12 +70,12 @@ namespace Godot.SourceGenerators
MarshalType.GodotObjectOrDerivedArray => VariantType.Array,
MarshalType.SystemArrayOfStringName => VariantType.Array,
MarshalType.SystemArrayOfNodePath => VariantType.Array,
- MarshalType.SystemArrayOfRID => VariantType.Array,
+ MarshalType.SystemArrayOfRid => VariantType.Array,
MarshalType.Variant => VariantType.Nil,
MarshalType.GodotObjectOrDerived => VariantType.Object,
MarshalType.StringName => VariantType.StringName,
MarshalType.NodePath => VariantType.NodePath,
- MarshalType.RID => VariantType.Rid,
+ MarshalType.Rid => VariantType.Rid,
MarshalType.GodotDictionary => VariantType.Dictionary,
MarshalType.GodotArray => VariantType.Array,
MarshalType.GodotGenericDictionary => VariantType.Dictionary,
@@ -130,24 +130,24 @@ namespace Godot.SourceGenerators
return type switch
{
{ Name: "Vector2" } => MarshalType.Vector2,
- { Name: "Vector2i" } => MarshalType.Vector2i,
+ { Name: "Vector2I" } => MarshalType.Vector2I,
{ Name: "Rect2" } => MarshalType.Rect2,
- { Name: "Rect2i" } => MarshalType.Rect2i,
+ { Name: "Rect2I" } => MarshalType.Rect2I,
{ Name: "Transform2D" } => MarshalType.Transform2D,
{ Name: "Vector3" } => MarshalType.Vector3,
- { Name: "Vector3i" } => MarshalType.Vector3i,
+ { Name: "Vector3I" } => MarshalType.Vector3I,
{ Name: "Basis" } => MarshalType.Basis,
{ Name: "Quaternion" } => MarshalType.Quaternion,
{ Name: "Transform3D" } => MarshalType.Transform3D,
{ Name: "Vector4" } => MarshalType.Vector4,
- { Name: "Vector4i" } => MarshalType.Vector4i,
+ { Name: "Vector4I" } => MarshalType.Vector4I,
{ Name: "Projection" } => MarshalType.Projection,
- { Name: "AABB" } => MarshalType.AABB,
+ { Name: "Aabb" } => MarshalType.Aabb,
{ Name: "Color" } => MarshalType.Color,
{ Name: "Plane" } => MarshalType.Plane,
- { Name: "RID" } => MarshalType.RID,
+ { Name: "Rid" } => MarshalType.Rid,
{ Name: "Callable" } => MarshalType.Callable,
- { Name: "SignalInfo" } => MarshalType.SignalInfo,
+ { Name: "Signal" } => MarshalType.Signal,
{ Name: "Variant" } => MarshalType.Variant,
_ => null
};
@@ -196,8 +196,8 @@ namespace Godot.SourceGenerators
return MarshalType.SystemArrayOfStringName;
case { Name: "NodePath" }:
return MarshalType.SystemArrayOfNodePath;
- case { Name: "RID" }:
- return MarshalType.SystemArrayOfRID;
+ case { Name: "Rid" }:
+ return MarshalType.SystemArrayOfRid;
}
}
@@ -220,7 +220,7 @@ namespace Godot.SourceGenerators
_ => null
};
case "Collections"
- when type.ContainingNamespace?.FullQualifiedName() == "Godot.Collections":
+ when type.ContainingNamespace?.FullQualifiedNameOmitGlobal() == "Godot.Collections":
return type switch
{
{ Name: "Dictionary" } =>
@@ -304,240 +304,41 @@ namespace Godot.SourceGenerators
{
return marshalType switch
{
- MarshalType.Boolean =>
- source.Append(VariantUtils, ".ConvertToBool(", inputExpr, ")"),
- MarshalType.Char =>
- source.Append("(char)", VariantUtils, ".ConvertToUInt16(", inputExpr, ")"),
- MarshalType.SByte =>
- source.Append(VariantUtils, ".ConvertToInt8(", inputExpr, ")"),
- MarshalType.Int16 =>
- source.Append(VariantUtils, ".ConvertToInt16(", inputExpr, ")"),
- MarshalType.Int32 =>
- source.Append(VariantUtils, ".ConvertToInt32(", inputExpr, ")"),
- MarshalType.Int64 =>
- source.Append(VariantUtils, ".ConvertToInt64(", inputExpr, ")"),
- MarshalType.Byte =>
- source.Append(VariantUtils, ".ConvertToUInt8(", inputExpr, ")"),
- MarshalType.UInt16 =>
- source.Append(VariantUtils, ".ConvertToUInt16(", inputExpr, ")"),
- MarshalType.UInt32 =>
- source.Append(VariantUtils, ".ConvertToUInt32(", inputExpr, ")"),
- MarshalType.UInt64 =>
- source.Append(VariantUtils, ".ConvertToUInt64(", inputExpr, ")"),
- MarshalType.Single =>
- source.Append(VariantUtils, ".ConvertToFloat32(", inputExpr, ")"),
- MarshalType.Double =>
- source.Append(VariantUtils, ".ConvertToFloat64(", inputExpr, ")"),
- MarshalType.String =>
- source.Append(VariantUtils, ".ConvertToStringObject(", inputExpr, ")"),
- MarshalType.Vector2 =>
- source.Append(VariantUtils, ".ConvertToVector2(", inputExpr, ")"),
- MarshalType.Vector2i =>
- source.Append(VariantUtils, ".ConvertToVector2i(", inputExpr, ")"),
- MarshalType.Rect2 =>
- source.Append(VariantUtils, ".ConvertToRect2(", inputExpr, ")"),
- MarshalType.Rect2i =>
- source.Append(VariantUtils, ".ConvertToRect2i(", inputExpr, ")"),
- MarshalType.Transform2D =>
- source.Append(VariantUtils, ".ConvertToTransform2D(", inputExpr, ")"),
- MarshalType.Vector3 =>
- source.Append(VariantUtils, ".ConvertToVector3(", inputExpr, ")"),
- MarshalType.Vector3i =>
- source.Append(VariantUtils, ".ConvertToVector3i(", inputExpr, ")"),
- MarshalType.Basis =>
- source.Append(VariantUtils, ".ConvertToBasis(", inputExpr, ")"),
- MarshalType.Quaternion =>
- source.Append(VariantUtils, ".ConvertToQuaternion(", inputExpr, ")"),
- MarshalType.Transform3D =>
- source.Append(VariantUtils, ".ConvertToTransform3D(", inputExpr, ")"),
- MarshalType.Vector4 =>
- source.Append(VariantUtils, ".ConvertToVector4(", inputExpr, ")"),
- MarshalType.Vector4i =>
- source.Append(VariantUtils, ".ConvertToVector4i(", inputExpr, ")"),
- MarshalType.Projection =>
- source.Append(VariantUtils, ".ConvertToProjection(", inputExpr, ")"),
- MarshalType.AABB =>
- source.Append(VariantUtils, ".ConvertToAABB(", inputExpr, ")"),
- MarshalType.Color =>
- source.Append(VariantUtils, ".ConvertToColor(", inputExpr, ")"),
- MarshalType.Plane =>
- source.Append(VariantUtils, ".ConvertToPlane(", inputExpr, ")"),
- MarshalType.Callable =>
- source.Append(VariantUtils, ".ConvertToCallableManaged(", inputExpr, ")"),
- MarshalType.SignalInfo =>
- source.Append(VariantUtils, ".ConvertToSignalInfo(", inputExpr, ")"),
- MarshalType.Enum =>
- source.Append("(", typeSymbol.FullQualifiedName(),
- ")", VariantUtils, ".ConvertToInt32(", inputExpr, ")"),
- MarshalType.ByteArray =>
- source.Append(VariantUtils, ".ConvertAsPackedByteArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Int32Array =>
- source.Append(VariantUtils, ".ConvertAsPackedInt32ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Int64Array =>
- source.Append(VariantUtils, ".ConvertAsPackedInt64ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Float32Array =>
- source.Append(VariantUtils, ".ConvertAsPackedFloat32ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Float64Array =>
- source.Append(VariantUtils, ".ConvertAsPackedFloat64ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.StringArray =>
- source.Append(VariantUtils, ".ConvertAsPackedStringArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Vector2Array =>
- source.Append(VariantUtils, ".ConvertAsPackedVector2ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.Vector3Array =>
- source.Append(VariantUtils, ".ConvertAsPackedVector3ArrayToSystemArray(", inputExpr, ")"),
- MarshalType.ColorArray =>
- source.Append(VariantUtils, ".ConvertAsPackedColorArrayToSystemArray(", inputExpr, ")"),
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by VariantUtils.ConvertTo<T>
MarshalType.GodotObjectOrDerivedArray =>
source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<",
- ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"),
- MarshalType.SystemArrayOfStringName =>
- source.Append(VariantUtils, ".ConvertToSystemArrayOfStringName(", inputExpr, ")"),
- MarshalType.SystemArrayOfNodePath =>
- source.Append(VariantUtils, ".ConvertToSystemArrayOfNodePath(", inputExpr, ")"),
- MarshalType.SystemArrayOfRID =>
- source.Append(VariantUtils, ".ConvertToSystemArrayOfRID(", inputExpr, ")"),
- MarshalType.Variant =>
- source.Append("global::Godot.Variant.CreateCopyingBorrowed(", inputExpr, ")"),
- MarshalType.GodotObjectOrDerived =>
- source.Append("(", typeSymbol.FullQualifiedName(),
- ")", VariantUtils, ".ConvertToGodotObject(", inputExpr, ")"),
- MarshalType.StringName =>
- source.Append(VariantUtils, ".ConvertToStringNameObject(", inputExpr, ")"),
- MarshalType.NodePath =>
- source.Append(VariantUtils, ".ConvertToNodePathObject(", inputExpr, ")"),
- MarshalType.RID =>
- source.Append(VariantUtils, ".ConvertToRID(", inputExpr, ")"),
- MarshalType.GodotDictionary =>
- source.Append(VariantUtils, ".ConvertToDictionaryObject(", inputExpr, ")"),
- MarshalType.GodotArray =>
- source.Append(VariantUtils, ".ConvertToArrayObject(", inputExpr, ")"),
+ ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">(",
+ inputExpr, ")"),
+ // We need a special case for generic Godot collections and GodotObjectOrDerived[], because VariantUtils.ConvertTo<T> is slower
MarshalType.GodotGenericDictionary =>
- source.Append(VariantUtils, ".ConvertToDictionaryObject<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">(", inputExpr, ")"),
+ source.Append(VariantUtils, ".ConvertToDictionary<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedNameIncludeGlobal(), ">(",
+ inputExpr, ")"),
MarshalType.GodotGenericArray =>
- source.Append(VariantUtils, ".ConvertToArrayObject<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">(", inputExpr, ")"),
- _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type")
+ source.Append(VariantUtils, ".ConvertToArray<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ">(",
+ inputExpr, ")"),
+ _ => source.Append(VariantUtils, ".ConvertTo<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")"),
};
}
- public static StringBuilder AppendManagedToNativeVariantExpr(
- this StringBuilder source, string inputExpr, MarshalType marshalType)
+ public static StringBuilder AppendManagedToNativeVariantExpr(this StringBuilder source,
+ string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
{
return marshalType switch
{
- MarshalType.Boolean =>
- source.Append(VariantUtils, ".CreateFromBool(", inputExpr, ")"),
- MarshalType.Char =>
- source.Append(VariantUtils, ".CreateFromInt((ushort)", inputExpr, ")"),
- MarshalType.SByte =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Int16 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Int32 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Int64 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Byte =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.UInt16 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.UInt32 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.UInt64 =>
- source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
- MarshalType.Single =>
- source.Append(VariantUtils, ".CreateFromFloat(", inputExpr, ")"),
- MarshalType.Double =>
- source.Append(VariantUtils, ".CreateFromFloat(", inputExpr, ")"),
- MarshalType.String =>
- source.Append(VariantUtils, ".CreateFromString(", inputExpr, ")"),
- MarshalType.Vector2 =>
- source.Append(VariantUtils, ".CreateFromVector2(", inputExpr, ")"),
- MarshalType.Vector2i =>
- source.Append(VariantUtils, ".CreateFromVector2i(", inputExpr, ")"),
- MarshalType.Rect2 =>
- source.Append(VariantUtils, ".CreateFromRect2(", inputExpr, ")"),
- MarshalType.Rect2i =>
- source.Append(VariantUtils, ".CreateFromRect2i(", inputExpr, ")"),
- MarshalType.Transform2D =>
- source.Append(VariantUtils, ".CreateFromTransform2D(", inputExpr, ")"),
- MarshalType.Vector3 =>
- source.Append(VariantUtils, ".CreateFromVector3(", inputExpr, ")"),
- MarshalType.Vector3i =>
- source.Append(VariantUtils, ".CreateFromVector3i(", inputExpr, ")"),
- MarshalType.Basis =>
- source.Append(VariantUtils, ".CreateFromBasis(", inputExpr, ")"),
- MarshalType.Quaternion =>
- source.Append(VariantUtils, ".CreateFromQuaternion(", inputExpr, ")"),
- MarshalType.Transform3D =>
- source.Append(VariantUtils, ".CreateFromTransform3D(", inputExpr, ")"),
- MarshalType.Vector4 =>
- source.Append(VariantUtils, ".CreateFromVector4(", inputExpr, ")"),
- MarshalType.Vector4i =>
- source.Append(VariantUtils, ".CreateFromVector4i(", inputExpr, ")"),
- MarshalType.Projection =>
- source.Append(VariantUtils, ".CreateFromProjection(", inputExpr, ")"),
- MarshalType.AABB =>
- source.Append(VariantUtils, ".CreateFromAABB(", inputExpr, ")"),
- MarshalType.Color =>
- source.Append(VariantUtils, ".CreateFromColor(", inputExpr, ")"),
- MarshalType.Plane =>
- source.Append(VariantUtils, ".CreateFromPlane(", inputExpr, ")"),
- MarshalType.Callable =>
- source.Append(VariantUtils, ".CreateFromCallable(", inputExpr, ")"),
- MarshalType.SignalInfo =>
- source.Append(VariantUtils, ".CreateFromSignalInfo(", inputExpr, ")"),
- MarshalType.Enum =>
- source.Append(VariantUtils, ".CreateFromInt((int)", inputExpr, ")"),
- MarshalType.ByteArray =>
- source.Append(VariantUtils, ".CreateFromPackedByteArray(", inputExpr, ")"),
- MarshalType.Int32Array =>
- source.Append(VariantUtils, ".CreateFromPackedInt32Array(", inputExpr, ")"),
- MarshalType.Int64Array =>
- source.Append(VariantUtils, ".CreateFromPackedInt64Array(", inputExpr, ")"),
- MarshalType.Float32Array =>
- source.Append(VariantUtils, ".CreateFromPackedFloat32Array(", inputExpr, ")"),
- MarshalType.Float64Array =>
- source.Append(VariantUtils, ".CreateFromPackedFloat64Array(", inputExpr, ")"),
- MarshalType.StringArray =>
- source.Append(VariantUtils, ".CreateFromPackedStringArray(", inputExpr, ")"),
- MarshalType.Vector2Array =>
- source.Append(VariantUtils, ".CreateFromPackedVector2Array(", inputExpr, ")"),
- MarshalType.Vector3Array =>
- source.Append(VariantUtils, ".CreateFromPackedVector3Array(", inputExpr, ")"),
- MarshalType.ColorArray =>
- source.Append(VariantUtils, ".CreateFromPackedColorArray(", inputExpr, ")"),
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by VariantUtils.CreateFrom<T>
MarshalType.GodotObjectOrDerivedArray =>
source.Append(VariantUtils, ".CreateFromSystemArrayOfGodotObject(", inputExpr, ")"),
- MarshalType.SystemArrayOfStringName =>
- source.Append(VariantUtils, ".CreateFromSystemArrayOfStringName(", inputExpr, ")"),
- MarshalType.SystemArrayOfNodePath =>
- source.Append(VariantUtils, ".CreateFromSystemArrayOfNodePath(", inputExpr, ")"),
- MarshalType.SystemArrayOfRID =>
- source.Append(VariantUtils, ".CreateFromSystemArrayOfRID(", inputExpr, ")"),
- MarshalType.Variant =>
- source.Append(inputExpr, ".CopyNativeVariant()"),
- MarshalType.GodotObjectOrDerived =>
- source.Append(VariantUtils, ".CreateFromGodotObject(", inputExpr, ")"),
- MarshalType.StringName =>
- source.Append(VariantUtils, ".CreateFromStringName(", inputExpr, ")"),
- MarshalType.NodePath =>
- source.Append(VariantUtils, ".CreateFromNodePath(", inputExpr, ")"),
- MarshalType.RID =>
- source.Append(VariantUtils, ".CreateFromRID(", inputExpr, ")"),
- MarshalType.GodotDictionary =>
- source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
- MarshalType.GodotArray =>
- source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
+ // We need a special case for generic Godot collections and GodotObjectOrDerived[], because VariantUtils.CreateFrom<T> is slower
MarshalType.GodotGenericDictionary =>
source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
MarshalType.GodotGenericArray =>
source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
- _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type")
+ _ => source.Append(VariantUtils, ".CreateFrom<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")"),
};
}
@@ -546,137 +347,37 @@ namespace Godot.SourceGenerators
{
return marshalType switch
{
- MarshalType.Boolean => source.Append(inputExpr, ".AsBool()"),
- MarshalType.Char => source.Append(inputExpr, ".AsChar()"),
- MarshalType.SByte => source.Append(inputExpr, ".AsSByte()"),
- MarshalType.Int16 => source.Append(inputExpr, ".AsInt16()"),
- MarshalType.Int32 => source.Append(inputExpr, ".AsInt32()"),
- MarshalType.Int64 => source.Append(inputExpr, ".AsInt64()"),
- MarshalType.Byte => source.Append(inputExpr, ".AsByte()"),
- MarshalType.UInt16 => source.Append(inputExpr, ".AsUInt16()"),
- MarshalType.UInt32 => source.Append(inputExpr, ".AsUInt32()"),
- MarshalType.UInt64 => source.Append(inputExpr, ".AsUInt64()"),
- MarshalType.Single => source.Append(inputExpr, ".AsSingle()"),
- MarshalType.Double => source.Append(inputExpr, ".AsDouble()"),
- MarshalType.String => source.Append(inputExpr, ".AsString()"),
- MarshalType.Vector2 => source.Append(inputExpr, ".AsVector2()"),
- MarshalType.Vector2i => source.Append(inputExpr, ".AsVector2i()"),
- MarshalType.Rect2 => source.Append(inputExpr, ".AsRect2()"),
- MarshalType.Rect2i => source.Append(inputExpr, ".AsRect2i()"),
- MarshalType.Transform2D => source.Append(inputExpr, ".AsTransform2D()"),
- MarshalType.Vector3 => source.Append(inputExpr, ".AsVector3()"),
- MarshalType.Vector3i => source.Append(inputExpr, ".AsVector3i()"),
- MarshalType.Basis => source.Append(inputExpr, ".AsBasis()"),
- MarshalType.Quaternion => source.Append(inputExpr, ".AsQuaternion()"),
- MarshalType.Transform3D => source.Append(inputExpr, ".AsTransform3D()"),
- MarshalType.Vector4 => source.Append(inputExpr, ".AsVector4()"),
- MarshalType.Vector4i => source.Append(inputExpr, ".AsVector4i()"),
- MarshalType.Projection => source.Append(inputExpr, ".AsProjection()"),
- MarshalType.AABB => source.Append(inputExpr, ".AsAABB()"),
- MarshalType.Color => source.Append(inputExpr, ".AsColor()"),
- MarshalType.Plane => source.Append(inputExpr, ".AsPlane()"),
- MarshalType.Callable => source.Append(inputExpr, ".AsCallable()"),
- MarshalType.SignalInfo => source.Append(inputExpr, ".AsSignalInfo()"),
- MarshalType.Enum =>
- source.Append("(", typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsInt64()"),
- MarshalType.ByteArray => source.Append(inputExpr, ".AsByteArray()"),
- MarshalType.Int32Array => source.Append(inputExpr, ".AsInt32Array()"),
- MarshalType.Int64Array => source.Append(inputExpr, ".AsInt64Array()"),
- MarshalType.Float32Array => source.Append(inputExpr, ".AsFloat32Array()"),
- MarshalType.Float64Array => source.Append(inputExpr, ".AsFloat64Array()"),
- MarshalType.StringArray => source.Append(inputExpr, ".AsStringArray()"),
- MarshalType.Vector2Array => source.Append(inputExpr, ".AsVector2Array()"),
- MarshalType.Vector3Array => source.Append(inputExpr, ".AsVector3Array()"),
- MarshalType.ColorArray => source.Append(inputExpr, ".AsColorArray()"),
- MarshalType.GodotObjectOrDerivedArray => source.Append(inputExpr, ".AsGodotObjectArray<",
- ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">()"),
- MarshalType.SystemArrayOfStringName => source.Append(inputExpr, ".AsSystemArrayOfStringName()"),
- MarshalType.SystemArrayOfNodePath => source.Append(inputExpr, ".AsSystemArrayOfNodePath()"),
- MarshalType.SystemArrayOfRID => source.Append(inputExpr, ".AsSystemArrayOfRID()"),
- MarshalType.Variant => source.Append(inputExpr),
- MarshalType.GodotObjectOrDerived => source.Append("(",
- typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsGodotObject()"),
- MarshalType.StringName => source.Append(inputExpr, ".AsStringName()"),
- MarshalType.NodePath => source.Append(inputExpr, ".AsNodePath()"),
- MarshalType.RID => source.Append(inputExpr, ".AsRID()"),
- MarshalType.GodotDictionary => source.Append(inputExpr, ".AsGodotDictionary()"),
- MarshalType.GodotArray => source.Append(inputExpr, ".AsGodotArray()"),
- MarshalType.GodotGenericDictionary => source.Append(inputExpr, ".AsGodotDictionary<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">()"),
- MarshalType.GodotGenericArray => source.Append(inputExpr, ".AsGodotArray<",
- ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">()"),
- _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type")
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by Variant.As<T>
+ MarshalType.GodotObjectOrDerivedArray =>
+ source.Append(inputExpr, ".AsGodotObjectArray<",
+ ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">()"),
+ // We need a special case for generic Godot collections and GodotObjectOrDerived[], because Variant.As<T> is slower
+ MarshalType.GodotGenericDictionary =>
+ source.Append(inputExpr, ".AsGodotDictionary<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedNameIncludeGlobal(), ">()"),
+ MarshalType.GodotGenericArray =>
+ source.Append(inputExpr, ".AsGodotArray<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ">()"),
+ _ => source.Append(inputExpr, ".As<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">()")
};
}
public static StringBuilder AppendManagedToVariantExpr(this StringBuilder source,
- string inputExpr, MarshalType marshalType)
+ string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
{
- switch (marshalType)
+ return marshalType switch
{
- case MarshalType.Boolean:
- case MarshalType.Char:
- case MarshalType.SByte:
- case MarshalType.Int16:
- case MarshalType.Int32:
- case MarshalType.Int64:
- case MarshalType.Byte:
- case MarshalType.UInt16:
- case MarshalType.UInt32:
- case MarshalType.UInt64:
- case MarshalType.Single:
- case MarshalType.Double:
- case MarshalType.String:
- case MarshalType.Vector2:
- case MarshalType.Vector2i:
- case MarshalType.Rect2:
- case MarshalType.Rect2i:
- case MarshalType.Transform2D:
- case MarshalType.Vector3:
- case MarshalType.Vector3i:
- case MarshalType.Basis:
- case MarshalType.Quaternion:
- case MarshalType.Transform3D:
- case MarshalType.Vector4:
- case MarshalType.Vector4i:
- case MarshalType.Projection:
- case MarshalType.AABB:
- case MarshalType.Color:
- case MarshalType.Plane:
- case MarshalType.Callable:
- case MarshalType.SignalInfo:
- case MarshalType.ByteArray:
- case MarshalType.Int32Array:
- case MarshalType.Int64Array:
- case MarshalType.Float32Array:
- case MarshalType.Float64Array:
- case MarshalType.StringArray:
- case MarshalType.Vector2Array:
- case MarshalType.Vector3Array:
- case MarshalType.ColorArray:
- case MarshalType.GodotObjectOrDerivedArray:
- case MarshalType.SystemArrayOfStringName:
- case MarshalType.SystemArrayOfNodePath:
- case MarshalType.SystemArrayOfRID:
- case MarshalType.GodotObjectOrDerived:
- case MarshalType.StringName:
- case MarshalType.NodePath:
- case MarshalType.RID:
- case MarshalType.GodotDictionary:
- case MarshalType.GodotArray:
- case MarshalType.GodotGenericDictionary:
- case MarshalType.GodotGenericArray:
- return source.Append("Variant.CreateFrom(", inputExpr, ")");
- case MarshalType.Enum:
- return source.Append("Variant.CreateFrom((long)", inputExpr, ")");
- case MarshalType.Variant:
- return source.Append(inputExpr);
- default:
- throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
- "Received unexpected marshal type");
- }
+ // We need a special case for GodotObjectOrDerived[], because it's not supported by Variant.From<T>
+ MarshalType.GodotObjectOrDerivedArray =>
+ source.Append("global::Godot.Variant.CreateFrom(", inputExpr, ")"),
+ // We need a special case for generic Godot collections, because Variant.From<T> is slower
+ MarshalType.GodotGenericDictionary or MarshalType.GodotGenericArray =>
+ source.Append("global::Godot.Variant.CreateFrom(", inputExpr, ")"),
+ _ => source.Append("global::Godot.Variant.From<",
+ typeSymbol.FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")")
+ };
}
}
}
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/MustBeVariantAnalyzer.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs
index 98ca534c66..2a9758516c 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs
@@ -26,6 +26,10 @@ namespace Godot.SourceGenerators
private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
+ // Ignore syntax inside comments
+ if (IsInsideDocumentation(context.Node))
+ return;
+
var typeArgListSyntax = (TypeArgumentListSyntax)context.Node;
// Method invocation or variable declaration that contained the type arguments
@@ -74,6 +78,26 @@ namespace Godot.SourceGenerators
}
/// <summary>
+ /// Check if the syntax node is inside a documentation syntax.
+ /// </summary>
+ /// <param name="syntax">Syntax node to check.</param>
+ /// <returns><see langword="true"/> if the syntax node is inside a documentation syntax.</returns>
+ private bool IsInsideDocumentation(SyntaxNode? syntax)
+ {
+ while (syntax != null)
+ {
+ if (syntax is DocumentationCommentTriviaSyntax)
+ {
+ return true;
+ }
+
+ syntax = syntax.Parent;
+ }
+
+ return false;
+ }
+
+ /// <summary>
/// Check if the given type argument is being used in a type parameter that contains
/// the <c>MustBeVariantAttribute</c>; otherwise, we ignore the attribute.
/// </summary>
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/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
index d5d80df643..f79909589e 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
@@ -80,13 +80,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptMethods.generated";
var source = new StringBuilder();
@@ -135,7 +135,8 @@ namespace Godot.SourceGenerators
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- source.Append($" public new class MethodName : {symbol.BaseType.FullQualifiedName()}.MethodName {{\n");
+ source.Append(
+ $" public new class MethodName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.MethodName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
@@ -146,7 +147,7 @@ namespace Godot.SourceGenerators
foreach (string methodName in distinctMethodNames)
{
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(methodName);
source.Append(" = \"");
source.Append(methodName);
@@ -159,7 +160,7 @@ namespace Godot.SourceGenerators
if (godotClassMethods.Length > 0)
{
- const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
+ const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" internal new static ")
.Append(listType)
@@ -248,7 +249,7 @@ namespace Godot.SourceGenerators
AppendPropertyInfo(source, methodInfo.ReturnVal);
- source.Append(", flags: (Godot.MethodFlags)")
+ source.Append(", flags: (global::Godot.MethodFlags)")
.Append((int)methodInfo.Flags)
.Append(", arguments: ");
@@ -276,15 +277,15 @@ namespace Godot.SourceGenerators
private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append("new(type: (Godot.Variant.Type)")
+ source.Append("new(type: (global::Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
.Append(", name: \"")
.Append(propertyInfo.Name)
- .Append("\", hint: (Godot.PropertyHint)")
+ .Append("\", hint: (global::Godot.PropertyHint)")
.Append((int)propertyInfo.Hint)
.Append(", hintString: \"")
.Append(propertyInfo.HintString)
- .Append("\", usage: (Godot.PropertyUsageFlags)")
+ .Append("\", usage: (global::Godot.PropertyUsageFlags)")
.Append((int)propertyInfo.Usage)
.Append(", exported: ")
.Append(propertyInfo.Exported ? "true" : "false")
@@ -297,7 +298,7 @@ namespace Godot.SourceGenerators
if (method.RetType != null)
{
- returnVal = DeterminePropertyInfo(method.RetType.Value, name: string.Empty);
+ returnVal = DeterminePropertyInfo(method.RetType.Value.MarshalType, name: string.Empty);
}
else
{
@@ -391,7 +392,8 @@ namespace Godot.SourceGenerators
{
source.Append(" ret = ");
- source.AppendManagedToNativeVariantExpr("callRet", method.RetType.Value);
+ source.AppendManagedToNativeVariantExpr("callRet",
+ method.RetType.Value.TypeSymbol, method.RetType.Value.MarshalType);
source.Append(";\n");
source.Append(" return true;\n");
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
index ccfb405d26..eae7e41da8 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
@@ -45,8 +45,11 @@ namespace Godot.SourceGenerators
return false;
})
)
- // Ignore classes whose name is not the same as the file name
- .Where(x => Path.GetFileNameWithoutExtension(x.cds.SyntaxTree.FilePath) == x.symbol.Name)
+ .Where(x =>
+ // Ignore classes whose name is not the same as the file name
+ Path.GetFileNameWithoutExtension(x.cds.SyntaxTree.FilePath) == x.symbol.Name &&
+ // Ignore generic classes
+ !x.symbol.IsGenericType)
.GroupBy(x => x.symbol)
.ToDictionary(g => g.Key, g => g.Select(x => x.cds));
@@ -92,11 +95,11 @@ namespace Godot.SourceGenerators
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptPath.generated";
var source = new StringBuilder();
@@ -150,8 +153,6 @@ namespace Godot.SourceGenerators
first = false;
sourceBuilder.Append("typeof(");
sourceBuilder.Append(qualifiedName);
- if (godotClass.Key.IsGenericType)
- sourceBuilder.Append($"<{new string(',', godotClass.Key.TypeParameters.Count() - 1)}>");
sourceBuilder.Append(")");
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
index 1198c633d9..b720fb93a3 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -66,13 +66,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptProperties.generated";
var source = new StringBuilder();
@@ -124,14 +124,15 @@ namespace Godot.SourceGenerators
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- source.Append($" public new class PropertyName : {symbol.BaseType.FullQualifiedName()}.PropertyName {{\n");
+ source.Append(
+ $" public new class PropertyName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.PropertyName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
foreach (var property in godotClassProperties)
{
string propertyName = property.PropertySymbol.Name;
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(propertyName);
source.Append(" = \"");
source.Append(propertyName);
@@ -141,7 +142,7 @@ namespace Godot.SourceGenerators
foreach (var field in godotClassFields)
{
string fieldName = field.FieldSymbol.Name;
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(fieldName);
source.Append(" = \"");
source.Append(fieldName);
@@ -157,7 +158,7 @@ namespace Godot.SourceGenerators
// Generate SetGodotClassPropertyValue
bool allPropertiesAreReadOnly = godotClassFields.All(fi => fi.FieldSymbol.IsReadOnly) &&
- godotClassProperties.All(pi => pi.PropertySymbol.IsReadOnly);
+ godotClassProperties.All(pi => pi.PropertySymbol.IsReadOnly || pi.PropertySymbol.SetMethod!.IsInitOnly);
if (!allPropertiesAreReadOnly)
{
@@ -167,7 +168,7 @@ namespace Godot.SourceGenerators
isFirstEntry = true;
foreach (var property in godotClassProperties)
{
- if (property.PropertySymbol.IsReadOnly)
+ if (property.PropertySymbol.IsReadOnly || property.PropertySymbol.SetMethod!.IsInitOnly)
continue;
GeneratePropertySetter(property.PropertySymbol.Name,
@@ -199,14 +200,14 @@ namespace Godot.SourceGenerators
foreach (var property in godotClassProperties)
{
GeneratePropertyGetter(property.PropertySymbol.Name,
- property.Type, source, isFirstEntry);
+ property.PropertySymbol.Type, property.Type, source, isFirstEntry);
isFirstEntry = false;
}
foreach (var field in godotClassFields)
{
GeneratePropertyGetter(field.FieldSymbol.Name,
- field.Type, source, isFirstEntry);
+ field.FieldSymbol.Type, field.Type, source, isFirstEntry);
isFirstEntry = false;
}
@@ -216,7 +217,7 @@ namespace Godot.SourceGenerators
// Generate GetGodotPropertyList
- string dictionaryType = "System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
+ string dictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
source.Append(" internal new static ")
.Append(dictionaryType)
@@ -292,7 +293,7 @@ namespace Godot.SourceGenerators
source.Append("if (name == PropertyName.")
.Append(propertyMemberName)
.Append(") {\n")
- .Append(" ")
+ .Append(" this.")
.Append(propertyMemberName)
.Append(" = ")
.AppendNativeVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType)
@@ -303,6 +304,7 @@ namespace Godot.SourceGenerators
private static void GeneratePropertyGetter(
string propertyMemberName,
+ ITypeSymbol propertyTypeSymbol,
MarshalType propertyMarshalType,
StringBuilder source,
bool isFirstEntry
@@ -317,7 +319,8 @@ namespace Godot.SourceGenerators
.Append(propertyMemberName)
.Append(") {\n")
.Append(" value = ")
- .AppendManagedToNativeVariantExpr(propertyMemberName, propertyMarshalType)
+ .AppendManagedToNativeVariantExpr("this." + propertyMemberName,
+ propertyTypeSymbol, propertyMarshalType)
.Append(";\n")
.Append(" return true;\n")
.Append(" }\n");
@@ -325,30 +328,30 @@ namespace Godot.SourceGenerators
private static void AppendGroupingPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append(" properties.Add(new(type: (Godot.Variant.Type)")
+ source.Append(" properties.Add(new(type: (global::Godot.Variant.Type)")
.Append((int)VariantType.Nil)
.Append(", name: \"")
.Append(propertyInfo.Name)
- .Append("\", hint: (Godot.PropertyHint)")
+ .Append("\", hint: (global::Godot.PropertyHint)")
.Append((int)PropertyHint.None)
.Append(", hintString: \"")
.Append(propertyInfo.HintString)
- .Append("\", usage: (Godot.PropertyUsageFlags)")
+ .Append("\", usage: (global::Godot.PropertyUsageFlags)")
.Append((int)propertyInfo.Usage)
.Append(", exported: true));\n");
}
private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append(" properties.Add(new(type: (Godot.Variant.Type)")
+ source.Append(" properties.Add(new(type: (global::Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
.Append(", name: PropertyName.")
.Append(propertyInfo.Name)
- .Append(", hint: (Godot.PropertyHint)")
+ .Append(", hint: (global::Godot.PropertyHint)")
.Append((int)propertyInfo.Hint)
.Append(", hintString: \"")
.Append(propertyInfo.HintString)
- .Append("\", usage: (Godot.PropertyUsageFlags)")
+ .Append("\", usage: (global::Godot.PropertyUsageFlags)")
.Append((int)propertyInfo.Usage)
.Append(", exported: ")
.Append(propertyInfo.Exported ? "true" : "false")
@@ -376,7 +379,8 @@ namespace Godot.SourceGenerators
if (propertyUsage != PropertyUsageFlags.Category && attr.ConstructorArguments.Length > 1)
hintString = attr.ConstructorArguments[1].Value?.ToString();
- yield return new PropertyInfo(VariantType.Nil, name, PropertyHint.None, hintString, propertyUsage.Value, true);
+ yield return new PropertyInfo(VariantType.Nil, name, PropertyHint.None, hintString,
+ propertyUsage.Value, true);
}
}
}
@@ -403,7 +407,7 @@ namespace Godot.SourceGenerators
return null;
}
- if (propertySymbol.SetMethod == null)
+ if (propertySymbol.SetMethod == null || propertySymbol.SetMethod.IsInitOnly)
{
// This should never happen, as we filtered ReadOnly properties, but just in case.
Common.ReportExportedMemberIsReadOnly(context, propertySymbol);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
index 98b9745c16..99a4c95e73 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
@@ -66,21 +67,17 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptPropertyDefVal.generated";
var source = new StringBuilder();
- source.Append("using Godot;\n");
- source.Append("using Godot.NativeInterop;\n");
- source.Append("\n");
-
if (hasNamespace)
{
source.Append("namespace ");
@@ -141,14 +138,14 @@ namespace Godot.SourceGenerators
}
// TODO: We should still restore read-only properties after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload.
- // Ignore properties without a getter or without a setter. Godot properties must be both readable and writable.
+ // Ignore properties without a getter, without a setter or with an init-only setter. Godot properties must be both readable and writable.
if (property.IsWriteOnly)
{
Common.ReportExportedMemberIsWriteOnly(context, property);
continue;
}
- if (property.IsReadOnly)
+ if (property.IsReadOnly || property.SetMethod!.IsInitOnly)
{
Common.ReportExportedMemberIsReadOnly(context, property);
continue;
@@ -163,14 +160,71 @@ namespace Godot.SourceGenerators
continue;
}
- // TODO: Detect default value from simple property getters (currently we only detect from initializers)
-
- EqualsValueClauseSyntax? initializer = property.DeclaringSyntaxReferences
- .Select(r => r.GetSyntax() as PropertyDeclarationSyntax)
- .Select(s => s?.Initializer ?? null)
- .FirstOrDefault();
+ var propertyDeclarationSyntax = property.DeclaringSyntaxReferences
+ .Select(r => r.GetSyntax() as PropertyDeclarationSyntax).FirstOrDefault();
- string? value = initializer?.Value.ToString();
+ // Fully qualify the value to avoid issues with namespaces.
+ string? value = null;
+ if (propertyDeclarationSyntax != null)
+ {
+ if (propertyDeclarationSyntax.Initializer != null)
+ {
+ var sm = context.Compilation.GetSemanticModel(propertyDeclarationSyntax.Initializer.SyntaxTree);
+ value = propertyDeclarationSyntax.Initializer.Value.FullQualifiedSyntax(sm);
+ }
+ else
+ {
+ var propertyGet = propertyDeclarationSyntax.AccessorList?.Accessors
+ .Where(a => a.Keyword.IsKind(SyntaxKind.GetKeyword)).FirstOrDefault();
+ if (propertyGet != null)
+ {
+ if (propertyGet.ExpressionBody != null)
+ {
+ if (propertyGet.ExpressionBody.Expression is IdentifierNameSyntax identifierNameSyntax)
+ {
+ var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree);
+ var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol;
+ EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences
+ .Select(r => r.GetSyntax())
+ .OfType<VariableDeclaratorSyntax>()
+ .Select(s => s.Initializer)
+ .FirstOrDefault(i => i != null);
+
+ if (initializer != null)
+ {
+ sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
+ value = initializer.Value.FullQualifiedSyntax(sm);
+ }
+ }
+ }
+ else
+ {
+ var returns = propertyGet.DescendantNodes().OfType<ReturnStatementSyntax>();
+ if (returns.Count() == 1)
+ {
+ // Generate only single return
+ var returnStatementSyntax = returns.Single();
+ if (returnStatementSyntax.Expression is IdentifierNameSyntax identifierNameSyntax)
+ {
+ var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree);
+ var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol;
+ EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences
+ .Select(r => r.GetSyntax())
+ .OfType<VariableDeclaratorSyntax>()
+ .Select(s => s.Initializer)
+ .FirstOrDefault(i => i != null);
+
+ if (initializer != null)
+ {
+ sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
+ value = initializer.Value.FullQualifiedSyntax(sm);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
exportedMembers.Add(new ExportedPropertyMetadata(
property.Name, marshalType.Value, propertyType, value));
@@ -207,7 +261,13 @@ namespace Godot.SourceGenerators
.Select(s => s.Initializer)
.FirstOrDefault(i => i != null);
- string? value = initializer?.Value.ToString();
+ // This needs to be fully qualified to avoid issues with namespaces.
+ string? value = null;
+ if (initializer != null)
+ {
+ var sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
+ value = initializer.Value.FullQualifiedSyntax(sm);
+ }
exportedMembers.Add(new ExportedPropertyMetadata(
field.Name, marshalType.Value, fieldType, value));
@@ -219,7 +279,8 @@ namespace Godot.SourceGenerators
{
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- string dictionaryType = "System.Collections.Generic.Dictionary<StringName, object>";
+ string dictionaryType =
+ "global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>";
source.Append("#if TOOLS\n");
source.Append(" internal new static ");
@@ -237,7 +298,7 @@ namespace Godot.SourceGenerators
string defaultValueLocalName = string.Concat("__", exportedMember.Name, "_default_value");
source.Append(" ");
- source.Append(exportedMember.TypeSymbol.FullQualifiedName());
+ source.Append(exportedMember.TypeSymbol.FullQualifiedNameIncludeGlobal());
source.Append(" ");
source.Append(defaultValueLocalName);
source.Append(" = ");
@@ -246,7 +307,8 @@ namespace Godot.SourceGenerators
source.Append(" values.Add(PropertyName.");
source.Append(exportedMember.Name);
source.Append(", ");
- source.Append(defaultValueLocalName);
+ source.AppendManagedToVariantExpr(defaultValueLocalName,
+ exportedMember.TypeSymbol, exportedMember.Type);
source.Append(");\n");
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
index 11e0a6fa21..821f3af75f 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
@@ -66,13 +66,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptSerialization.generated";
var source = new StringBuilder();
@@ -162,7 +162,8 @@ namespace Godot.SourceGenerators
source.Append(" info.AddProperty(PropertyName.")
.Append(propertyName)
.Append(", ")
- .AppendManagedToVariantExpr(string.Concat("this.", propertyName), property.Type)
+ .AppendManagedToVariantExpr(string.Concat("this.", propertyName),
+ property.PropertySymbol.Type, property.Type)
.Append(");\n");
}
@@ -175,7 +176,8 @@ namespace Godot.SourceGenerators
source.Append(" info.AddProperty(PropertyName.")
.Append(fieldName)
.Append(", ")
- .AppendManagedToVariantExpr(string.Concat("this.", fieldName), field.Type)
+ .AppendManagedToVariantExpr(string.Concat("this.", fieldName),
+ field.FieldSymbol.Type, field.Type)
.Append(");\n");
}
@@ -241,7 +243,7 @@ namespace Godot.SourceGenerators
foreach (var signalDelegate in godotSignalDelegates)
{
string signalName = signalDelegate.Name;
- string signalDelegateQualifiedName = signalDelegate.DelegateSymbol.FullQualifiedName();
+ string signalDelegateQualifiedName = signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal();
source.Append(" if (info.TryGetSignalEventDelegate<")
.Append(signalDelegateQualifiedName)
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
index 50196b84f0..d67cb5349d 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
@@ -75,13 +75,13 @@ namespace Godot.SourceGenerators
{
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
- string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()
+ string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptSignals.generated";
var source = new StringBuilder();
@@ -176,14 +176,15 @@ namespace Godot.SourceGenerators
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- source.Append($" public new class SignalName : {symbol.BaseType.FullQualifiedName()}.SignalName {{\n");
+ source.Append(
+ $" public new class SignalName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.SignalName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
foreach (var signalDelegate in godotSignalDelegates)
{
string signalName = signalDelegate.Name;
- source.Append(" public new static readonly StringName ");
+ source.Append(" public new static readonly global::Godot.StringName ");
source.Append(signalName);
source.Append(" = \"");
source.Append(signalName);
@@ -196,7 +197,7 @@ namespace Godot.SourceGenerators
if (godotSignalDelegates.Count > 0)
{
- const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
+ const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" internal new static ")
.Append(listType)
@@ -231,15 +232,16 @@ namespace Godot.SourceGenerators
// as it doesn't emit the signal, only the event delegates. This can confuse users.
// Maybe we should directly connect the delegates, as we do with native signals?
source.Append(" private ")
- .Append(signalDelegate.DelegateSymbol.FullQualifiedName())
+ .Append(signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal())
.Append(" backing_")
.Append(signalName)
.Append(";\n");
- source.Append($" /// <inheritdoc cref=\"{signalDelegate.DelegateSymbol.FullQualifiedName()}\"/>\n");
+ source.Append(
+ $" /// <inheritdoc cref=\"{signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal()}\"/>\n");
source.Append(" public event ")
- .Append(signalDelegate.DelegateSymbol.FullQualifiedName())
+ .Append(signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal())
.Append(" ")
.Append(signalName)
.Append(" {\n")
@@ -270,6 +272,25 @@ namespace Godot.SourceGenerators
source.Append(" }\n");
}
+ // Generate HasGodotClassSignal
+
+ if (godotSignalDelegates.Count > 0)
+ {
+ source.Append(
+ " protected override bool HasGodotClassSignal(in godot_string_name signal)\n {\n");
+
+ bool isFirstEntry = true;
+ foreach (var signal in godotSignalDelegates)
+ {
+ GenerateHasSignalEntry(signal.Name, source, isFirstEntry);
+ isFirstEntry = false;
+ }
+
+ source.Append(" return base.HasGodotClassSignal(signal);\n");
+
+ source.Append(" }\n");
+ }
+
source.Append("}\n"); // partial class
if (isInnerClass)
@@ -300,7 +321,7 @@ namespace Godot.SourceGenerators
AppendPropertyInfo(source, methodInfo.ReturnVal);
- source.Append(", flags: (Godot.MethodFlags)")
+ source.Append(", flags: (global::Godot.MethodFlags)")
.Append((int)methodInfo.Flags)
.Append(", arguments: ");
@@ -328,15 +349,15 @@ namespace Godot.SourceGenerators
private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append("new(type: (Godot.Variant.Type)")
+ source.Append("new(type: (global::Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
.Append(", name: \"")
.Append(propertyInfo.Name)
- .Append("\", hint: (Godot.PropertyHint)")
+ .Append("\", hint: (global::Godot.PropertyHint)")
.Append((int)propertyInfo.Hint)
.Append(", hintString: \"")
.Append(propertyInfo.HintString)
- .Append("\", usage: (Godot.PropertyUsageFlags)")
+ .Append("\", usage: (global::Godot.PropertyUsageFlags)")
.Append((int)propertyInfo.Usage)
.Append(", exported: ")
.Append(propertyInfo.Exported ? "true" : "false")
@@ -351,7 +372,7 @@ namespace Godot.SourceGenerators
if (invokeMethodData.RetType != null)
{
- returnVal = DeterminePropertyInfo(invokeMethodData.RetType.Value, name: string.Empty);
+ returnVal = DeterminePropertyInfo(invokeMethodData.RetType.Value.MarshalType, name: string.Empty);
}
else
{
@@ -395,6 +416,20 @@ namespace Godot.SourceGenerators
PropertyHint.None, string.Empty, propUsage, exported: false);
}
+ private static void GenerateHasSignalEntry(
+ string signalName,
+ StringBuilder source,
+ bool isFirstEntry
+ )
+ {
+ source.Append(" ");
+ if (!isFirstEntry)
+ source.Append("else ");
+ source.Append("if (signal == SignalName.");
+ source.Append(signalName);
+ source.Append(") {\n return true;\n }\n");
+ }
+
private static void GenerateSignalEventInvoker(
GodotSignalDelegateData signal,
StringBuilder source
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/Build/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
index edbf53a389..7c02f29606 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
@@ -12,6 +12,7 @@ namespace GodotTools.Build
public sealed partial class BuildInfo : RefCounted // TODO Remove RefCounted once we have proper serialization
{
public string Solution { get; private set; }
+ public string Project { get; private set; }
public string Configuration { get; private set; }
public string? RuntimeIdentifier { get; private set; }
public string? PublishOutputDir { get; private set; }
@@ -22,13 +23,13 @@ namespace GodotTools.Build
// TODO Use List once we have proper serialization
public Godot.Collections.Array CustomProperties { get; private set; } = new();
- public string LogsDirPath =>
- Path.Combine(GodotSharpDirs.BuildLogsDirs, $"{Solution.MD5Text()}_{Configuration}");
+ public string LogsDirPath => GodotSharpDirs.LogsDirPathFor(Solution, Configuration);
public override bool Equals(object? obj)
{
return obj is BuildInfo other &&
other.Solution == Solution &&
+ other.Project == Project &&
other.Configuration == Configuration && other.RuntimeIdentifier == RuntimeIdentifier &&
other.PublishOutputDir == PublishOutputDir && other.Restore == Restore &&
other.Rebuild == Rebuild && other.OnlyClean == OnlyClean &&
@@ -42,6 +43,7 @@ namespace GodotTools.Build
{
int hash = 17;
hash = (hash * 29) + Solution.GetHashCode();
+ hash = (hash * 29) + Project.GetHashCode();
hash = (hash * 29) + Configuration.GetHashCode();
hash = (hash * 29) + (RuntimeIdentifier?.GetHashCode() ?? 0);
hash = (hash * 29) + (PublishOutputDir?.GetHashCode() ?? 0);
@@ -58,22 +60,25 @@ namespace GodotTools.Build
private BuildInfo()
{
Solution = string.Empty;
+ Project = string.Empty;
Configuration = string.Empty;
}
- public BuildInfo(string solution, string configuration, bool restore, bool rebuild, bool onlyClean)
+ public BuildInfo(string solution, string project, string configuration, bool restore, bool rebuild, bool onlyClean)
{
Solution = solution;
+ Project = project;
Configuration = configuration;
Restore = restore;
Rebuild = rebuild;
OnlyClean = onlyClean;
}
- public BuildInfo(string solution, string configuration, string runtimeIdentifier,
+ public BuildInfo(string solution, string project, string configuration, string runtimeIdentifier,
string publishOutputDir, bool restore, bool rebuild, bool onlyClean)
{
Solution = solution;
+ Project = project;
Configuration = configuration;
RuntimeIdentifier = runtimeIdentifier;
PublishOutputDir = publishOutputDir;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
index 993c6d9217..ed3a4c6e26 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
@@ -55,7 +55,7 @@ namespace GodotTools.Build
private static void PrintVerbose(string text)
{
- if (OS.IsStdoutVerbose())
+ if (OS.IsStdOutVerbose())
GD.Print(text);
}
@@ -262,7 +262,7 @@ namespace GodotTools.Build
bool onlyClean = false
)
{
- var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, configuration,
+ var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, GodotSharpDirs.ProjectCsProjPath, configuration,
restore: true, rebuild, onlyClean);
// If a platform was not specified, try determining the current one. If that fails, let MSBuild auto-detect it.
@@ -282,7 +282,7 @@ namespace GodotTools.Build
[DisallowNull] string publishOutputDir
)
{
- var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, configuration,
+ var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, GodotSharpDirs.ProjectCsProjPath, configuration,
runtimeIdentifier, publishOutputDir, restore: true, rebuild: false, onlyClean: false);
buildInfo.CustomProperties.Add($"GodotTargetPlatform={platform}");
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
index 4d40724a83..c083b9cc60 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
@@ -336,7 +336,7 @@ namespace GodotTools.Build
_ = index; // Unused
_issuesListContextMenu.Clear();
- _issuesListContextMenu.Size = new Vector2i(1, 1);
+ _issuesListContextMenu.Size = new Vector2I(1, 1);
if (_issuesList.IsAnythingSelected())
{
@@ -347,7 +347,7 @@ namespace GodotTools.Build
if (_issuesListContextMenu.ItemCount > 0)
{
- _issuesListContextMenu.Position = (Vector2i)(_issuesList.GlobalPosition + atPosition);
+ _issuesListContextMenu.Position = (Vector2I)(_issuesList.GlobalPosition + atPosition);
_issuesListContextMenu.Popup();
}
}
@@ -356,19 +356,19 @@ namespace GodotTools.Build
{
base._Ready();
- SizeFlagsVertical = (int)SizeFlags.ExpandFill;
+ SizeFlagsVertical = SizeFlags.ExpandFill;
var hsc = new HSplitContainer
{
- SizeFlagsHorizontal = (int)SizeFlags.ExpandFill,
- SizeFlagsVertical = (int)SizeFlags.ExpandFill
+ SizeFlagsHorizontal = SizeFlags.ExpandFill,
+ SizeFlagsVertical = SizeFlags.ExpandFill
};
AddChild(hsc);
_issuesList = new ItemList
{
- SizeFlagsVertical = (int)SizeFlags.ExpandFill,
- SizeFlagsHorizontal = (int)SizeFlags.ExpandFill // Avoid being squashed by the build log
+ SizeFlagsVertical = SizeFlags.ExpandFill,
+ SizeFlagsHorizontal = SizeFlags.ExpandFill // Avoid being squashed by the build log
};
_issuesList.ItemActivated += IssueActivated;
_issuesList.AllowRmbSelect = true;
@@ -382,8 +382,8 @@ namespace GodotTools.Build
_buildLog = new TextEdit
{
Editable = false,
- SizeFlagsVertical = (int)SizeFlags.ExpandFill,
- SizeFlagsHorizontal = (int)SizeFlags.ExpandFill // Avoid being squashed by the issues list
+ SizeFlagsVertical = SizeFlags.ExpandFill,
+ SizeFlagsHorizontal = SizeFlags.ExpandFill // Avoid being squashed by the issues list
};
hsc.AddChild(_buildLog);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
index d0cd529d1f..d550c36b82 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
@@ -7,6 +7,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Godot;
using GodotTools.BuildLogger;
using GodotTools.Utils;
@@ -22,19 +23,23 @@ namespace GodotTools.Build
if (dotnetPath == null)
throw new FileNotFoundException("Cannot find the dotnet executable.");
+ var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
+
var startInfo = new ProcessStartInfo(dotnetPath);
- BuildArguments(buildInfo, startInfo.ArgumentList);
+ BuildArguments(buildInfo, startInfo.ArgumentList, editorSettings);
string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
stdOutHandler?.Invoke(launchMessage);
- if (Godot.OS.IsStdoutVerbose())
+ if (Godot.OS.IsStdOutVerbose())
Console.WriteLine(launchMessage);
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
+ startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"]
+ = ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-');
// Needed when running from Developer Command Prompt for VS
RemovePlatformVariable(startInfo.EnvironmentVariables);
@@ -83,18 +88,22 @@ namespace GodotTools.Build
if (dotnetPath == null)
throw new FileNotFoundException("Cannot find the dotnet executable.");
+ var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
+
var startInfo = new ProcessStartInfo(dotnetPath);
- BuildPublishArguments(buildInfo, startInfo.ArgumentList);
+ BuildPublishArguments(buildInfo, startInfo.ArgumentList, editorSettings);
string launchMessage = startInfo.GetCommandLineDisplay(new StringBuilder("Running: ")).ToString();
stdOutHandler?.Invoke(launchMessage);
- if (Godot.OS.IsStdoutVerbose())
+ if (Godot.OS.IsStdOutVerbose())
Console.WriteLine(launchMessage);
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
+ startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"]
+ = ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-');
// Needed when running from Developer Command Prompt for VS
RemovePlatformVariable(startInfo.EnvironmentVariables);
@@ -124,13 +133,14 @@ namespace GodotTools.Build
}
}
- private static void BuildArguments(BuildInfo buildInfo, Collection<string> arguments)
+ private static void BuildArguments(BuildInfo buildInfo, Collection<string> arguments,
+ EditorSettings editorSettings)
{
// `dotnet clean` / `dotnet build` commands
arguments.Add(buildInfo.OnlyClean ? "clean" : "build");
- // Solution
- arguments.Add(buildInfo.Solution);
+ // C# Project
+ arguments.Add(buildInfo.Project);
// `dotnet clean` doesn't recognize these options
if (!buildInfo.OnlyClean)
@@ -150,12 +160,14 @@ namespace GodotTools.Build
arguments.Add(buildInfo.Configuration);
// Verbosity
- arguments.Add("-v");
- arguments.Add("normal");
+ AddVerbosityArguments(buildInfo, arguments, editorSettings);
// Logger
AddLoggerArgument(buildInfo, arguments);
+ // Binary log
+ AddBinaryLogArgument(buildInfo, arguments, editorSettings);
+
// Custom properties
foreach (var customProperty in buildInfo.CustomProperties)
{
@@ -163,12 +175,13 @@ namespace GodotTools.Build
}
}
- private static void BuildPublishArguments(BuildInfo buildInfo, Collection<string> arguments)
+ private static void BuildPublishArguments(BuildInfo buildInfo, Collection<string> arguments,
+ EditorSettings editorSettings)
{
arguments.Add("publish"); // `dotnet publish` command
- // Solution
- arguments.Add(buildInfo.Solution);
+ // C# Project
+ arguments.Add(buildInfo.Project);
// Restore
// `dotnet publish` restores by default, unless requested not to
@@ -193,12 +206,14 @@ namespace GodotTools.Build
arguments.Add("true");
// Verbosity
- arguments.Add("-v");
- arguments.Add("normal");
+ AddVerbosityArguments(buildInfo, arguments, editorSettings);
// Logger
AddLoggerArgument(buildInfo, arguments);
+ // Binary log
+ AddBinaryLogArgument(buildInfo, arguments, editorSettings);
+
// Custom properties
foreach (var customProperty in buildInfo.CustomProperties)
{
@@ -213,6 +228,25 @@ namespace GodotTools.Build
}
}
+ private static void AddVerbosityArguments(BuildInfo buildInfo, Collection<string> arguments,
+ EditorSettings editorSettings)
+ {
+ var verbosityLevel =
+ editorSettings.GetSetting(GodotSharpEditor.Settings.VerbosityLevel).As<VerbosityLevelId>();
+ arguments.Add("-v");
+ arguments.Add(verbosityLevel switch
+ {
+ VerbosityLevelId.Quiet => "quiet",
+ VerbosityLevelId.Minimal => "minimal",
+ VerbosityLevelId.Detailed => "detailed",
+ VerbosityLevelId.Diagnostic => "diagnostic",
+ _ => "normal",
+ });
+
+ if ((bool)editorSettings.GetSetting(GodotSharpEditor.Settings.NoConsoleLogging))
+ arguments.Add("-noconlog");
+ }
+
private static void AddLoggerArgument(BuildInfo buildInfo, Collection<string> arguments)
{
string buildLoggerPath = Path.Combine(Internals.GodotSharpDirs.DataEditorToolsDir,
@@ -222,6 +256,16 @@ namespace GodotTools.Build
$"-l:{typeof(GodotBuildLogger).FullName},{buildLoggerPath};{buildInfo.LogsDirPath}");
}
+ private static void AddBinaryLogArgument(BuildInfo buildInfo, Collection<string> arguments,
+ EditorSettings editorSettings)
+ {
+ if (!(bool)editorSettings.GetSetting(GodotSharpEditor.Settings.CreateBinaryLog))
+ return;
+
+ arguments.Add($"-bl:{Path.Combine(buildInfo.LogsDirPath, "msbuild.binlog")}");
+ arguments.Add("-ds:False"); // Honestly never understood why -bl also switches -ds on.
+ }
+
private static void RemovePlatformVariable(StringDictionary environmentVariables)
{
// EnvironmentVariables is case sensitive? Seriously?
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
index 237ac85267..cf1b84e37f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Godot;
using GodotTools.Internals;
using static GodotTools.Internals.Globals;
@@ -14,6 +15,7 @@ namespace GodotTools.Build
private Button _errorsBtn;
private Button _warningsBtn;
private Button _viewLogBtn;
+ private Button _openLogsFolderBtn;
private void WarningsToggled(bool pressed)
{
@@ -93,6 +95,10 @@ namespace GodotTools.Build
private void ViewLogToggled(bool pressed) => BuildOutputView.LogVisible = pressed;
+ private void OpenLogsFolderPressed() => OS.ShellOpen(
+ $"file://{GodotSharpDirs.LogsDirPathFor("Debug")}"
+ );
+
private void BuildMenuOptionPressed(long id)
{
switch ((BuildMenuOptions)id)
@@ -122,10 +128,10 @@ namespace GodotTools.Build
{
base._Ready();
- CustomMinimumSize = new Vector2i(0, (int)(228 * EditorScale));
- SizeFlagsVertical = (int)SizeFlags.ExpandFill;
+ CustomMinimumSize = new Vector2(0, 228 * EditorScale);
+ SizeFlagsVertical = SizeFlags.ExpandFill;
- var toolBarHBox = new HBoxContainer { SizeFlagsHorizontal = (int)SizeFlags.ExpandFill };
+ var toolBarHBox = new HBoxContainer { SizeFlagsHorizontal = SizeFlags.ExpandFill };
AddChild(toolBarHBox);
_buildMenuBtn = new MenuButton { Text = "Build", Icon = GetThemeIcon("Play", "EditorIcons") };
@@ -171,11 +177,27 @@ namespace GodotTools.Build
_viewLogBtn.Toggled += ViewLogToggled;
toolBarHBox.AddChild(_viewLogBtn);
+ // Horizontal spacer, push everything to the right.
+ toolBarHBox.AddChild(new Control
+ {
+ SizeFlagsHorizontal = SizeFlags.ExpandFill,
+ });
+
+ _openLogsFolderBtn = new Button
+ {
+ Text = "Show Logs in File Manager".TTR(),
+ Icon = GetThemeIcon("Filesystem", "EditorIcons"),
+ ExpandIcon = false,
+ FocusMode = FocusModeEnum.None,
+ };
+ _openLogsFolderBtn.Pressed += OpenLogsFolderPressed;
+ toolBarHBox.AddChild(_openLogsFolderBtn);
+
BuildOutputView = new BuildOutputView();
AddChild(BuildOutputView);
}
- public override void _Notification(long what)
+ public override void _Notification(int what)
{
base._Notification(what);
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/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index 745a8b73f8..a284451a35 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -17,24 +17,14 @@ namespace GodotTools.Export
{
public partial class ExportPlugin : EditorExportPlugin
{
+ public override string _GetName() => "C#";
+
private List<string> _tempFolders = new List<string>();
public void RegisterExportSettings()
{
// TODO: These would be better as export preset options, but that doesn't seem to be supported yet
-
- GlobalDef("mono/export/include_scripts_content", false);
-
- GlobalDef("mono/export/aot/enabled", false);
- GlobalDef("mono/export/aot/full_aot", false);
- GlobalDef("mono/export/aot/use_interpreter", true);
-
- // --aot or --aot=opt1,opt2 (use 'mono --aot=help AuxAssembly.dll' to list AOT options)
- GlobalDef("mono/export/aot/extra_aot_options", Array.Empty<string>());
- // --optimize/-O=opt1,opt2 (use 'mono --list-opt'' to list optimize options)
- GlobalDef("mono/export/aot/extra_optimizer_options", Array.Empty<string>());
-
- GlobalDef("mono/export/aot/android_toolchain_path", "");
+ GlobalDef("dotnet/export/include_scripts_content", false);
}
private string _maybeLastExportError;
@@ -54,7 +44,7 @@ namespace GodotTools.Export
// TODO What if the source file is not part of the game's C# project
- bool includeScriptsContent = (bool)ProjectSettings.GetSetting("mono/export/include_scripts_content");
+ bool includeScriptsContent = (bool)ProjectSettings.GetSetting("dotnet/export/include_scripts_content");
if (!includeScriptsContent)
{
@@ -69,7 +59,7 @@ namespace GodotTools.Export
}
}
- public override void _ExportBegin(string[] features, bool isDebug, string path, long flags)
+ public override void _ExportBegin(string[] features, bool isDebug, string path, uint flags)
{
base._ExportBegin(features, isDebug, path, flags);
@@ -183,7 +173,9 @@ namespace GodotTools.Export
foreach (string file in Directory.GetFiles(publishOutputTempDir, "*", SearchOption.AllDirectories))
{
- AddSharedObject(file, tags: null, projectDataDirName);
+ AddSharedObject(file, tags: null,
+ Path.Join(projectDataDirName,
+ Path.GetRelativePath(publishOutputTempDir, Path.GetDirectoryName(file))));
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 89364d1c02..43ead4af69 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -22,6 +22,14 @@ namespace GodotTools
{
public partial class GodotSharpEditor : EditorPlugin, ISerializationListener
{
+ public static class Settings
+ {
+ public const string ExternalEditor = "dotnet/editor/external_editor";
+ public const string VerbosityLevel = "dotnet/build/verbosity_level";
+ public const string NoConsoleLogging = "dotnet/build/no_console_logging";
+ public const string CreateBinaryLog = "dotnet/build/create_binary_log";
+ }
+
private EditorSettings _editorSettings;
private PopupMenu _menuPopup;
@@ -57,24 +65,22 @@ namespace GodotTools
{
pr.Step("Generating C# project...".TTR());
- string resourceDir = ProjectSettings.GlobalizePath("res://");
-
- string path = resourceDir;
+ string csprojDir = Path.GetDirectoryName(GodotSharpDirs.ProjectCsProjPath);
+ string slnDir = Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath);
string name = GodotSharpDirs.ProjectAssemblyName;
-
- string guid = CsProjOperations.GenerateGameProject(path, name);
+ string guid = CsProjOperations.GenerateGameProject(csprojDir, name);
if (guid.Length > 0)
{
var solution = new DotNetSolution(name)
{
- DirectoryPath = path
+ DirectoryPath = slnDir
};
var projectInfo = new DotNetSolution.ProjectInfo
{
Guid = guid,
- PathRelativeToSolution = name + ".csproj",
+ PathRelativeToSolution = Path.GetRelativePath(slnDir, GodotSharpDirs.ProjectCsProjPath),
Configs = new List<string> { "Debug", "ExportDebug", "ExportRelease" }
};
@@ -173,7 +179,7 @@ namespace GodotTools
[UsedImplicitly]
public Error OpenInExternalEditor(Script script, int line, int col)
{
- var editorId = (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor");
+ var editorId = _editorSettings.GetSetting(Settings.ExternalEditor).As<ExternalEditorId>();
switch (editorId)
{
@@ -194,7 +200,7 @@ namespace GodotTools
try
{
- if (Godot.OS.IsStdoutVerbose())
+ if (Godot.OS.IsStdOutVerbose())
Console.WriteLine(
$"Running: \"{command}\" {string.Join(" ", args.Select(a => $"\"{a}\""))}");
@@ -325,8 +331,7 @@ namespace GodotTools
[UsedImplicitly]
public bool OverridesExternalEditor()
{
- return (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor") !=
- ExternalEditorId.None;
+ return _editorSettings.GetSetting(Settings.ExternalEditor).As<ExternalEditorId>() != ExternalEditorId.None;
}
public override bool _Build()
@@ -375,6 +380,8 @@ namespace GodotTools
{
base._EnablePlugin();
+ ProjectSettingsChanged += GodotSharpDirs.DetermineProjectLocation;
+
if (Instance != null)
throw new InvalidOperationException();
Instance = this;
@@ -385,7 +392,7 @@ namespace GodotTools
// correct version first (`RegisterDefaults` always picks the latest).
if (DotNetFinder.TryFindDotNetSdk(dotNetSdkSearchVersion, out var sdkVersion, out string sdkPath))
{
- if (Godot.OS.IsStdoutVerbose())
+ if (Godot.OS.IsStdOutVerbose())
Console.WriteLine($"Found .NET Sdk version '{sdkVersion}': {sdkPath}");
ProjectUtils.MSBuildLocatorRegisterMSBuildPath(sdkPath);
@@ -395,12 +402,12 @@ namespace GodotTools
try
{
ProjectUtils.MSBuildLocatorRegisterDefaults(out sdkVersion, out sdkPath);
- if (Godot.OS.IsStdoutVerbose())
+ if (Godot.OS.IsStdOutVerbose())
Console.WriteLine($"Found .NET Sdk version '{sdkVersion}': {sdkPath}");
}
catch (InvalidOperationException e)
{
- if (Godot.OS.IsStdoutVerbose())
+ if (Godot.OS.IsStdOutVerbose())
GD.PrintErr(e.ToString());
GD.PushError($".NET Sdk not found. The required version is '{dotNetSdkSearchVersion}'.");
}
@@ -411,8 +418,6 @@ namespace GodotTools
_editorSettings = editorInterface.GetEditorSettings();
- GodotSharpDirs.RegisterProjectSettings();
-
_errorDialog = new AcceptDialog();
editorBaseControl.AddChild(_errorDialog);
@@ -455,7 +460,10 @@ namespace GodotTools
_menuPopup.IdPressed += _MenuOptionPressed;
// External editor settings
- EditorDef("mono/editor/external_editor", ExternalEditorId.None);
+ EditorDef(Settings.ExternalEditor, Variant.From(ExternalEditorId.None));
+ EditorDef(Settings.VerbosityLevel, Variant.From(VerbosityLevelId.Normal));
+ EditorDef(Settings.NoConsoleLogging, false);
+ EditorDef(Settings.CreateBinaryLog, false);
string settingsHintStr = "Disabled";
@@ -483,11 +491,23 @@ namespace GodotTools
_editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
{
["type"] = (int)Variant.Type.Int,
- ["name"] = "mono/editor/external_editor",
+ ["name"] = Settings.ExternalEditor,
["hint"] = (int)PropertyHint.Enum,
["hint_string"] = settingsHintStr
});
+ var verbosityLevels = Enum.GetValues<VerbosityLevelId>().Select(level => $"{Enum.GetName(level)}:{(int)level}");
+ _editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
+ {
+ ["type"] = (int)Variant.Type.Int,
+ ["name"] = Settings.VerbosityLevel,
+ ["hint"] = (int)PropertyHint.Enum,
+ ["hint_string"] = string.Join(",", verbosityLevels),
+ });
+
+ OnSettingsChanged();
+ _editorSettings.SettingsChanged += OnSettingsChanged;
+
// Export plugin
var exportPlugin = new ExportPlugin();
AddExportPlugin(exportPlugin);
@@ -512,6 +532,24 @@ namespace GodotTools
AddChild(GodotIdeManager);
}
+ public override void _DisablePlugin()
+ {
+ base._DisablePlugin();
+
+ _editorSettings.SettingsChanged -= OnSettingsChanged;
+ }
+
+ private void OnSettingsChanged()
+ {
+ // We want to force NoConsoleLogging to true when the VerbosityLevel is at Detailed or above.
+ // At that point, there's so much info logged that it doesn't make sense to display it in
+ // the tiny editor window, and it'd make the editor hang or crash anyway.
+ var verbosityLevel = _editorSettings.GetSetting(Settings.VerbosityLevel).As<VerbosityLevelId>();
+ var hideConsoleLog = (bool)_editorSettings.GetSetting(Settings.NoConsoleLogging);
+ if (verbosityLevel >= VerbosityLevelId.Detailed && !hideConsoleLog)
+ _editorSettings.SetSetting(Settings.NoConsoleLogging, Variant.From(true));
+ }
+
protected override void Dispose(bool disposing)
{
if (disposing)
diff --git a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
index 89ac8058b9..eb42f01b3a 100644
--- a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
@@ -9,9 +9,9 @@ namespace GodotTools
{
private Timer _watchTimer;
- public override void _Notification(long what)
+ public override void _Notification(int what)
{
- if (what == Node.NotificationWmWindowFocusIn)
+ if (what == Node.NotificationWMWindowFocusIn)
{
RestartTimer();
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
index 9df90ac608..83621ce5af 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
@@ -21,7 +21,8 @@ namespace GodotTools.Ides
return _messagingServer;
_messagingServer?.Dispose();
- _messagingServer = new MessagingServer(OS.GetExecutablePath(), ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir), new GodotLogger());
+ _messagingServer = new MessagingServer(OS.GetExecutablePath(),
+ ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir), new GodotLogger());
_ = _messagingServer.Listen();
@@ -76,8 +77,8 @@ namespace GodotTools.Ides
public async Task<EditorPick?> LaunchIdeAsync(int millisecondsTimeout = 10000)
{
- var editorId = (ExternalEditorId)(int)GodotSharpEditor.Instance.GetEditorInterface()
- .GetEditorSettings().GetSetting("mono/editor/external_editor");
+ var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
+ var editorId = editorSettings.GetSetting(GodotSharpEditor.Settings.ExternalEditor).As<ExternalEditorId>();
string editorIdentity = GetExternalEditorIdentity(editorId);
var runningServer = GetRunningOrNewServer();
@@ -200,13 +201,13 @@ namespace GodotTools.Ides
{
public void LogDebug(string message)
{
- if (OS.IsStdoutVerbose())
+ if (OS.IsStdOutVerbose())
Console.WriteLine(message);
}
public void LogInfo(string message)
{
- if (OS.IsStdoutVerbose())
+ if (OS.IsStdOutVerbose())
Console.WriteLine(message);
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
index 60602a5847..f55ca4c7d7 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
@@ -9,7 +9,7 @@ namespace GodotTools.Ides.Rider
{
public static class RiderPathManager
{
- public static readonly string EditorPathSettingName = "mono/editor/editor_path_optional";
+ public static readonly string EditorPathSettingName = "dotnet/editor/editor_path_optional";
private static string GetRiderPathFromSettings()
{
@@ -22,7 +22,7 @@ namespace GodotTools.Ides.Rider
public static void Initialize()
{
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
- var editor = (ExternalEditorId)(int)editorSettings.GetSetting("mono/editor/external_editor");
+ var editor = editorSettings.GetSetting(GodotSharpEditor.Settings.ExternalEditor).As<ExternalEditorId>();
if (editor == ExternalEditorId.Rider)
{
if (!editorSettings.HasSetting(EditorPathSettingName))
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
index acb7cc3ab0..45ae7eb86b 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
@@ -1,3 +1,4 @@
+using Godot;
using Godot.NativeInterop;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
@@ -8,30 +9,31 @@ namespace GodotTools.Internals
{
public static float EditorScale => Internal.godot_icall_Globals_EditorScale();
- public static unsafe object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false)
+ // ReSharper disable once UnusedMethodReturnValue.Global
+ public static Variant GlobalDef(string setting, Variant defaultValue, bool restartIfChanged = false)
{
using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
- using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue);
- Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
- using (result)
- return Marshaling.ConvertVariantToManagedObject(result);
+ using godot_variant defaultValueIn = defaultValue.CopyNativeVariant();
+ Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged,
+ out godot_variant result);
+ return Variant.CreateTakingOwnershipOfDisposableValue(result);
}
- public static unsafe object EditorDef(string setting, object defaultValue, bool restartIfChanged = false)
+ // ReSharper disable once UnusedMethodReturnValue.Global
+ public static Variant EditorDef(string setting, Variant defaultValue, bool restartIfChanged = false)
{
using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
- using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue);
- Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
- using (result)
- return Marshaling.ConvertVariantToManagedObject(result);
+ using godot_variant defaultValueIn = defaultValue.CopyNativeVariant();
+ Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged,
+ out godot_variant result);
+ return Variant.CreateTakingOwnershipOfDisposableValue(result);
}
- public static object EditorShortcut(string setting)
+ public static Variant EditorShortcut(string setting)
{
using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
Internal.godot_icall_Globals_EditorShortcut(settingIn, out godot_variant result);
- using (result)
- return Marshaling.ConvertVariantToManagedObject(result);
+ return Variant.CreateTakingOwnershipOfDisposableValue(result);
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
index 14285cc0f1..fb68fcbae6 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
@@ -48,14 +48,7 @@ namespace GodotTools.Internals
}
}
- public static void RegisterProjectSettings()
- {
- GlobalDef("dotnet/project/assembly_name", "");
- GlobalDef("dotnet/project/solution_directory", "");
- GlobalDef("dotnet/project/c#_project_directory", "");
- }
-
- private static void DetermineProjectLocation()
+ public static void DetermineProjectLocation()
{
static string DetermineProjectName()
{
@@ -76,10 +69,11 @@ namespace GodotTools.Internals
string slnParentDir = (string)ProjectSettings.GetSetting("dotnet/project/solution_directory");
if (string.IsNullOrEmpty(slnParentDir))
slnParentDir = "res://";
+ else if (!slnParentDir.StartsWith("res://"))
+ slnParentDir = "res://" + slnParentDir;
- string csprojParentDir = (string)ProjectSettings.GetSetting("dotnet/project/c#_project_directory");
- if (string.IsNullOrEmpty(csprojParentDir))
- csprojParentDir = "res://";
+ // The csproj should be in the same folder as project.godot.
+ string csprojParentDir = "res://";
_projectSlnPath = Path.Combine(ProjectSettings.GlobalizePath(slnParentDir),
string.Concat(_projectAssemblyName, ".sln"));
@@ -121,5 +115,11 @@ namespace GodotTools.Internals
return _projectCsProjPath;
}
}
+
+ public static string LogsDirPathFor(string solution, string configuration)
+ => Path.Combine(BuildLogsDirs, $"{solution.Md5Text()}_{configuration}");
+
+ public static string LogsDirPathFor(string configuration)
+ => LogsDirPathFor(ProjectSlnPath, configuration);
}
}
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/editor/GodotTools/GodotTools/VerbosityLevelId.cs b/modules/mono/editor/GodotTools/GodotTools/VerbosityLevelId.cs
new file mode 100644
index 0000000000..0e1afe6bbf
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/VerbosityLevelId.cs
@@ -0,0 +1,11 @@
+namespace GodotTools
+{
+ public enum VerbosityLevelId : long
+ {
+ Quiet,
+ Minimal,
+ Normal,
+ Detailed,
+ Diagnostic,
+ }
+}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index b90321b586..ad6306bb41 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* bindings_generator.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* bindings_generator.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "bindings_generator.h"
@@ -38,10 +38,10 @@
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/os/os.h"
-#include "core/string/ucaps.h"
#include "main/main.h"
#include "../godotsharp_defs.h"
+#include "../utils/naming_utils.h"
#include "../utils/path_utils.h"
#include "../utils/string_utils.h"
@@ -84,10 +84,12 @@ StringBuilder &operator<<(StringBuilder &r_sb, const char *p_cstring) {
#define CS_PROPERTY_SINGLETON "Singleton"
#define CS_METHOD_INVOKE_GODOT_CLASS_METHOD "InvokeGodotClassMethod"
#define CS_METHOD_HAS_GODOT_CLASS_METHOD "HasGodotClassMethod"
+#define CS_METHOD_HAS_GODOT_CLASS_SIGNAL "HasGodotClassSignal"
#define CS_STATIC_FIELD_NATIVE_CTOR "NativeCtor"
#define CS_STATIC_FIELD_METHOD_BIND_PREFIX "MethodBind"
#define CS_STATIC_FIELD_METHOD_PROXY_NAME_PREFIX "MethodProxyName_"
+#define CS_STATIC_FIELD_SIGNAL_PROXY_NAME_PREFIX "SignalProxyName_"
#define ICALL_PREFIX "godot_icall_"
#define ICALL_CLASSDB_GET_METHOD "ClassDB_get_method"
@@ -144,74 +146,6 @@ static String fix_doc_description(const String &p_bbcode) {
.strip_edges();
}
-static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper = false) {
- String ret;
- Vector<String> parts = p_identifier.split("_", true);
-
- for (int i = 0; i < parts.size(); i++) {
- String part = parts[i];
-
- if (part.length()) {
- part[0] = _find_upper(part[0]);
- if (p_input_is_upper) {
- for (int j = 1; j < part.length(); j++) {
- part[j] = _find_lower(part[j]);
- }
- }
- ret += part;
- } else {
- if (i == 0 || i == (parts.size() - 1)) {
- // Preserve underscores at the beginning and end
- ret += "_";
- } else {
- // Preserve contiguous underscores
- if (parts[i - 1].length()) {
- ret += "__";
- } else {
- ret += "_";
- }
- }
- }
- }
-
- return ret;
-}
-
-static String snake_to_camel_case(const String &p_identifier, bool p_input_is_upper = false) {
- String ret;
- Vector<String> parts = p_identifier.split("_", true);
-
- for (int i = 0; i < parts.size(); i++) {
- String part = parts[i];
-
- if (part.length()) {
- if (i != 0) {
- part[0] = _find_upper(part[0]);
- }
- if (p_input_is_upper) {
- for (int j = i != 0 ? 1 : 0; j < part.length(); j++) {
- part[j] = _find_lower(part[j]);
- }
- }
- ret += part;
- } else {
- if (i == 0 || i == (parts.size() - 1)) {
- // Preserve underscores at the beginning and end
- ret += "_";
- } else {
- // Preserve contiguous underscores
- if (parts[i - 1].length()) {
- ret += "__";
- } else {
- ret += "_";
- }
- }
- }
- }
-
- return ret;
-}
-
String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype) {
// Based on the version in EditorHelp
@@ -229,6 +163,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
List<String> tag_stack;
bool code_tag = false;
+ bool line_del = false;
int pos = 0;
while (pos < bbcode.length()) {
@@ -239,20 +174,22 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
}
if (brk_pos > pos) {
- String text = bbcode.substr(pos, brk_pos - pos);
- if (code_tag || tag_stack.size() > 0) {
- xml_output.append(text.xml_escape());
- } else {
- Vector<String> lines = text.split("\n");
- for (int i = 0; i < lines.size(); i++) {
- if (i != 0) {
- xml_output.append("<para>");
- }
+ if (!line_del) {
+ String text = bbcode.substr(pos, brk_pos - pos);
+ if (code_tag || tag_stack.size() > 0) {
+ xml_output.append(text.xml_escape());
+ } else {
+ Vector<String> lines = text.split("\n");
+ for (int i = 0; i < lines.size(); i++) {
+ if (i != 0) {
+ xml_output.append("<para>");
+ }
- xml_output.append(lines[i].xml_escape());
+ xml_output.append(lines[i].xml_escape());
- if (i != lines.size() - 1) {
- xml_output.append("</para>\n");
+ if (i != lines.size() - 1) {
+ xml_output.append("</para>\n");
+ }
}
}
}
@@ -265,20 +202,22 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
int brk_end = bbcode.find("]", brk_pos + 1);
if (brk_end == -1) {
- String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos);
- if (code_tag || tag_stack.size() > 0) {
- xml_output.append(text.xml_escape());
- } else {
- Vector<String> lines = text.split("\n");
- for (int i = 0; i < lines.size(); i++) {
- if (i != 0) {
- xml_output.append("<para>");
- }
+ if (!line_del) {
+ String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos);
+ if (code_tag || tag_stack.size() > 0) {
+ xml_output.append(text.xml_escape());
+ } else {
+ Vector<String> lines = text.split("\n");
+ for (int i = 0; i < lines.size(); i++) {
+ if (i != 0) {
+ xml_output.append("<para>");
+ }
- xml_output.append(lines[i].xml_escape());
+ xml_output.append(lines[i].xml_escape());
- if (i != lines.size() - 1) {
- xml_output.append("</para>\n");
+ if (i != lines.size() - 1) {
+ xml_output.append("</para>\n");
+ }
}
}
}
@@ -292,7 +231,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
bool tag_ok = tag_stack.size() && tag_stack.front()->get() == tag.substr(1, tag.length());
if (!tag_ok) {
- xml_output.append("[");
+ if (!line_del) {
+ xml_output.append("[");
+ }
pos = brk_pos + 1;
continue;
}
@@ -307,11 +248,20 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
xml_output.append("</c>");
} else if (tag == "/codeblock") {
xml_output.append("</code>");
+ } else if (tag == "/b") {
+ xml_output.append("</b>");
+ } else if (tag == "/i") {
+ xml_output.append("</i>");
+ } else if (tag == "/csharp") {
+ xml_output.append("</code>");
+ line_del = true;
+ } else if (tag == "/codeblocks") {
+ line_del = false;
}
} else if (code_tag) {
xml_output.append("[");
pos = brk_pos + 1;
- } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ")) {
+ } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ") || tag.begins_with("param ")) {
const int tag_end = tag.find(" ");
const String link_tag = tag.substr(0, tag_end);
const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" ");
@@ -356,6 +306,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else if (link_tag == "theme_item") {
// We do not declare theme_items in any way in C#, so there is nothing to reference
_append_xml_undeclared(xml_output, link_target);
+ } else if (link_tag == "param") {
+ _append_xml_undeclared(xml_output, snake_to_camel_case(link_target, false));
}
pos = brk_end + 1;
@@ -377,8 +329,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
#endif
"\"/>");
} else if (tag == "Variant") {
- // We use System.Object for Variant, so there is no Variant type in C#
- xml_output.append("<c>Variant</c>");
+ xml_output.append("<see cref=\"Godot.Variant\"/>");
} else if (tag == "String") {
xml_output.append("<see cref=\"string\"/>");
} else if (tag == "Nil") {
@@ -428,11 +379,13 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
pos = brk_end + 1;
} else if (tag == "b") {
- // bold is not supported in xml comments
+ xml_output.append("<b>");
+
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "i") {
- // italics is not supported in xml comments
+ xml_output.append("<i>");
+
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code") {
@@ -447,6 +400,17 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
code_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
+ } else if (tag == "codeblocks") {
+ line_del = true;
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "csharp") {
+ xml_output.append("<code>");
+
+ line_del = false;
+ code_tag = true;
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
} else if (tag == "kbd") {
// keyboard combinations are not supported in xml comments
pos = brk_end + 1;
@@ -459,7 +423,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
xml_output.append("\n"); // FIXME: Should use <para> instead. Luckily this tag isn't used for now.
pos = brk_end + 1;
} else if (tag == "u") {
- // underline is not supported in xml comments
+ // underline is not supported in Rider xml comments
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "s") {
@@ -510,7 +474,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
pos = brk_end + 1;
tag_stack.push_front("font");
} else {
- xml_output.append("["); // ignore
+ if (!line_del) {
+ xml_output.append("["); // ignore
+ }
pos = brk_pos + 1;
}
}
@@ -531,7 +497,7 @@ void BindingsGenerator::_append_xml_method(StringBuilder &p_xml_output, const Ty
} else if (!p_target_itype || !p_target_itype->is_object_type) {
if (OS::get_singleton()->is_stdout_verbose()) {
if (p_target_itype) {
- OS::get_singleton()->print("Cannot resolve method reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ OS::get_singleton()->print("Cannot resolve method reference for non-GodotObject type in documentation: %s\n", p_link_target.utf8().get_data());
} else {
OS::get_singleton()->print("Cannot resolve type from method reference in documentation: %s\n", p_link_target.utf8().get_data());
}
@@ -571,7 +537,7 @@ void BindingsGenerator::_append_xml_member(StringBuilder &p_xml_output, const Ty
} else if (!p_target_itype || !p_target_itype->is_object_type) {
if (OS::get_singleton()->is_stdout_verbose()) {
if (p_target_itype) {
- OS::get_singleton()->print("Cannot resolve member reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ OS::get_singleton()->print("Cannot resolve member reference for non-GodotObject type in documentation: %s\n", p_link_target.utf8().get_data());
} else {
OS::get_singleton()->print("Cannot resolve type from member reference in documentation: %s\n", p_link_target.utf8().get_data());
}
@@ -607,7 +573,7 @@ void BindingsGenerator::_append_xml_signal(StringBuilder &p_xml_output, const Ty
if (!p_target_itype || !p_target_itype->is_object_type) {
if (OS::get_singleton()->is_stdout_verbose()) {
if (p_target_itype) {
- OS::get_singleton()->print("Cannot resolve signal reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ OS::get_singleton()->print("Cannot resolve signal reference for non-GodotObject type in documentation: %s\n", p_link_target.utf8().get_data());
} else {
OS::get_singleton()->print("Cannot resolve type from signal reference in documentation: %s\n", p_link_target.utf8().get_data());
}
@@ -664,7 +630,7 @@ void BindingsGenerator::_append_xml_constant(StringBuilder &p_xml_output, const
if (OS::get_singleton()->is_stdout_verbose()) {
if (p_target_itype) {
- OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ OS::get_singleton()->print("Cannot resolve constant reference for non-GodotObject type in documentation: %s\n", p_link_target.utf8().get_data());
} else {
OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", p_link_target.utf8().get_data());
}
@@ -933,11 +899,11 @@ void BindingsGenerator::_generate_array_extensions(StringBuilder &p_output) {
ARRAY_ALL(string);
ARRAY_ALL(Color);
ARRAY_ALL(Vector2);
- ARRAY_ALL(Vector2i);
+ ARRAY_ALL(Vector2I);
ARRAY_ALL(Vector3);
- ARRAY_ALL(Vector3i);
+ ARRAY_ALL(Vector3I);
ARRAY_ALL(Vector4);
- ARRAY_ALL(Vector4i);
+ ARRAY_ALL(Vector4I);
#undef ARRAY_ALL
#undef ARRAY_IS_EMPTY
@@ -1007,7 +973,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
_log("Declaring global enum '%s' inside struct '%s'\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data());
p_output.append("\npublic partial struct ");
- p_output.append(enum_class_name);
+ p_output.append(pascal_to_pascal_case(enum_class_name));
p_output.append("\n" OPEN_BLOCK);
}
@@ -1016,7 +982,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
}
p_output.append("\npublic enum ");
- p_output.append(enum_proxy_name);
+ p_output.append(pascal_to_pascal_case(enum_proxy_name));
p_output.append(" : long");
p_output.append("\n" OPEN_BLOCK);
@@ -1351,7 +1317,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
bool is_derived_type = itype.base_name != StringName();
if (!is_derived_type) {
- // Some Godot.Object assertions
+ // Some GodotObject assertions
CRASH_COND(itype.cname != name_cache.type_Object);
CRASH_COND(!itype.is_instantiable);
CRASH_COND(itype.api_type != ClassDB::API_CORE);
@@ -1468,7 +1434,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
output.append(MEMBER_BEGIN "public enum ");
- output.append(ienum.cname.operator String());
+ output.append(pascal_to_pascal_case(ienum.cname.operator String()));
output.append(" : long");
output.append(MEMBER_BEGIN OPEN_BLOCK);
@@ -1513,9 +1479,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
if (itype.is_singleton) {
// Add the type name and the singleton pointer as static fields
- output.append(MEMBER_BEGIN "private static Godot.Object singleton;\n");
+ output.append(MEMBER_BEGIN "private static GodotObject singleton;\n");
- output << MEMBER_BEGIN "public static Godot.Object " CS_PROPERTY_SINGLETON "\n" INDENT1 "{\n"
+ output << MEMBER_BEGIN "public static GodotObject " CS_PROPERTY_SINGLETON "\n" INDENT1 "{\n"
<< INDENT2 "get\n" INDENT2 "{\n" INDENT3 "if (singleton == null)\n"
<< INDENT4 "singleton = " C_METHOD_ENGINE_GET_SINGLETON "(typeof("
<< itype.proxy_name
@@ -1525,8 +1491,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.append(itype.name);
output.append("\";\n");
} else {
- // IMPORTANT: We also generate the static fields for Godot.Object instead of declaring
- // them manually in the `Object.base.cs` partial class declaration, because they're
+ // IMPORTANT: We also generate the static fields for GodotObject instead of declaring
+ // them manually in the `GodotObject.base.cs` partial class declaration, because they're
// required by other static fields in this generated partial class declaration.
// Static fields are initialized in order of declaration, but when they're in different
// partial class declarations then it becomes harder to tell (Rider warns about this).
@@ -1608,6 +1574,16 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
<< " = \"" << imethod.proxy_name << "\";\n";
}
+ // Generate signal names cache fields
+
+ for (const SignalInterface &isignal : itype.signals_) {
+ output << MEMBER_BEGIN "// ReSharper disable once InconsistentNaming\n"
+ << INDENT1 "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
+ << INDENT1 "private static readonly StringName "
+ << CS_STATIC_FIELD_SIGNAL_PROXY_NAME_PREFIX << isignal.name
+ << " = \"" << isignal.proxy_name << "\";\n";
+ }
+
// TODO: Only generate HasGodotClassMethod and InvokeGodotClassMethod if there's any method
// Generate InvokeGodotClassMethod
@@ -1721,6 +1697,34 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
output << INDENT1 "}\n";
+
+ // Generate HasGodotClassSignal
+
+ output << MEMBER_BEGIN "protected internal " << (is_derived_type ? "override" : "virtual")
+ << " bool " CS_METHOD_HAS_GODOT_CLASS_SIGNAL "(in godot_string_name signal)\n"
+ << INDENT1 "{\n";
+
+ for (const SignalInterface &isignal : itype.signals_) {
+ // We check for native names (snake_case). If we detect one, we call HasGodotClassSignal
+ // again, but this time with the respective proxy name (PascalCase). It's the job of
+ // user derived classes to override the method and check for those. Our C# source
+ // generators take care of generating those override methods.
+ output << INDENT2 "if (signal == SignalName." << isignal.proxy_name
+ << ")\n" INDENT2 "{\n"
+ << INDENT3 "if (" CS_METHOD_HAS_GODOT_CLASS_SIGNAL "("
+ << CS_STATIC_FIELD_SIGNAL_PROXY_NAME_PREFIX << isignal.name
+ << ".NativeValue.DangerousSelfRef))\n" INDENT3 "{\n"
+ << INDENT4 "return true;\n"
+ << INDENT3 "}\n" INDENT2 "}\n";
+ }
+
+ if (is_derived_type) {
+ output << INDENT2 "return base." CS_METHOD_HAS_GODOT_CLASS_SIGNAL "(signal);\n";
+ } else {
+ output << INDENT2 "return false;\n";
+ }
+
+ output << INDENT1 "}\n";
}
//Generate StringName for all class members
@@ -1864,12 +1868,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append("\n" OPEN_BLOCK_L1);
if (getter) {
- p_output.append(INDENT2 "get\n"
-
- // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
- "#pragma warning disable CS0618 // Disable warning about obsolete method\n"
-
- OPEN_BLOCK_L2 INDENT3);
+ p_output.append(INDENT2 "get\n" OPEN_BLOCK_L2 INDENT3);
p_output.append("return ");
p_output.append(getter->proxy_name + "(");
@@ -1884,21 +1883,11 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append(itos(p_iprop.index));
}
}
- p_output.append(");\n"
-
- CLOSE_BLOCK_L2
-
- // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
- "#pragma warning restore CS0618\n");
+ p_output.append(");\n" CLOSE_BLOCK_L2);
}
if (setter) {
- p_output.append(INDENT2 "set\n"
-
- // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
- "#pragma warning disable CS0618 // Disable warning about obsolete method\n"
-
- OPEN_BLOCK_L2 INDENT3);
+ p_output.append(INDENT2 "set\n" OPEN_BLOCK_L2 INDENT3);
p_output.append(setter->proxy_name + "(");
if (p_iprop.index != -1) {
@@ -1912,12 +1901,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append(itos(p_iprop.index) + ", ");
}
}
- p_output.append("value);\n"
-
- CLOSE_BLOCK_L2
-
- // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
- "#pragma warning restore CS0618\n");
+ p_output.append("value);\n" CLOSE_BLOCK_L2);
}
p_output.append(CLOSE_BLOCK_L1);
@@ -2078,9 +2062,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
<< INDENT1 "private static readonly IntPtr " << method_bind_field << " = ";
if (p_itype.is_singleton) {
- // Singletons are static classes. They don't derive Godot.Object,
+ // Singletons are static classes. They don't derive GodotObject,
// so we need to specify the type to call the static method.
- p_output << "Object.";
+ p_output << "GodotObject.";
}
p_output << ICALL_CLASSDB_GET_METHOD "(" BINDINGS_NATIVE_NAME_FIELD ", MethodName."
@@ -2274,7 +2258,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
p_output.append(");\n");
// Generate Callable trampoline for the delegate
- p_output << MEMBER_BEGIN "private static unsafe void " << p_isignal.proxy_name << "Trampoline"
+ p_output << MEMBER_BEGIN "private static void " << p_isignal.proxy_name << "Trampoline"
<< "(object delegateObj, NativeVariantPtrArgs args, out godot_variant ret)\n"
<< INDENT1 "{\n"
<< INDENT2 "Callable.ThrowIfArgCountMismatch(args, " << itos(p_isignal.arguments.size()) << ");\n"
@@ -2289,9 +2273,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
p_output << ",";
}
- // TODO: We don't need to use VariantConversionCallbacks. We have the type information so we can use [cs_variant_to_managed] and [cs_managed_to_variant].
- p_output << "\n" INDENT3 "VariantConversionCallbacks.GetToManagedCallback<"
- << arg_type->cs_type << ">()(args[" << itos(idx) << "])";
+ p_output << sformat(arg_type->cs_variant_to_managed,
+ "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name);
idx++;
}
@@ -2490,9 +2473,12 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
if (!ret_void) {
if (return_type->cname != name_cache.type_Variant) {
+ // Usually the return value takes ownership, but in this case the variant is only used
+ // for conversion to another return type. As such, the local variable takes ownership.
r_output << "using godot_variant " << C_LOCAL_VARARG_RET " = ";
} else {
- r_output << "using godot_variant " << C_LOCAL_RET " = ";
+ // Variant's [c_out] takes ownership of the variant value
+ r_output << "godot_variant " << C_LOCAL_RET " = ";
}
}
@@ -2543,15 +2529,13 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
<< INDENT2 "int total_length = " << real_argc_str << " + vararg_length;\n";
r_output << INDENT2 "Span<godot_variant.movable> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n"
- << INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :\n"
+ << INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold] :\n"
<< INDENT3 "new godot_variant.movable[vararg_length];\n";
r_output << INDENT2 "Span<IntPtr> " C_LOCAL_PTRCALL_ARGS "_span = total_length <= VarArgsSpanThreshold ?\n"
<< INDENT3 "stackalloc IntPtr[VarArgsSpanThreshold] :\n"
<< INDENT3 "new IntPtr[total_length];\n";
- r_output << INDENT2 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n";
-
r_output << INDENT2 "fixed (godot_variant.movable* varargs = &MemoryMarshal.GetReference(varargs_span))\n"
<< INDENT2 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = "
"&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n"
@@ -2795,6 +2779,18 @@ bool BindingsGenerator::_arg_default_value_is_assignable_to_type(const Variant &
return false;
}
+bool method_has_ptr_parameter(MethodInfo p_method_info) {
+ if (p_method_info.return_val.type == Variant::INT && p_method_info.return_val.hint == PROPERTY_HINT_INT_IS_POINTER) {
+ return true;
+ }
+ for (PropertyInfo arg : p_method_info.arguments) {
+ if (arg.type == Variant::INT && arg.hint == PROPERTY_HINT_INT_IS_POINTER) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool BindingsGenerator::_populate_object_type_interfaces() {
obj_types.clear();
@@ -2832,7 +2828,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(type_cname);
- TypeInterface itype = TypeInterface::create_object_type(type_cname, api_type);
+ TypeInterface itype = TypeInterface::create_object_type(type_cname, pascal_to_pascal_case(type_cname), api_type);
itype.base_name = ClassDB::get_parent_class(type_cname);
itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name);
@@ -2840,9 +2836,6 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.is_ref_counted = ClassDB::is_parent_class(type_cname, name_cache.type_RefCounted);
itype.memory_own = itype.is_ref_counted;
- itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToGodotObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromGodotObject(%0)";
-
itype.c_out = "%5return ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
itype.c_out += itype.is_ref_counted ? "(%1.Reference);\n" : "(%1);\n";
@@ -2850,9 +2843,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.cs_type = itype.proxy_name;
if (itype.is_singleton) {
- itype.cs_in_expr = "Object." CS_STATIC_METHOD_GETINSTANCE "(" CS_PROPERTY_SINGLETON ")";
+ itype.cs_in_expr = "GodotObject." CS_STATIC_METHOD_GETINSTANCE "(" CS_PROPERTY_SINGLETON ")";
} else {
- itype.cs_in_expr = "Object." CS_STATIC_METHOD_GETINSTANCE "(%0)";
+ itype.cs_in_expr = "GodotObject." CS_STATIC_METHOD_GETINSTANCE "(%0)";
}
itype.cs_out = "%5return (%2)%0(%1);";
@@ -2860,7 +2853,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.c_arg_in = "(void*)%s";
itype.c_type = "IntPtr";
itype.c_type_in = itype.c_type;
- itype.c_type_out = "Object";
+ itype.c_type_out = "GodotObject";
// Populate properties
@@ -2941,6 +2934,11 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
continue;
}
+ if (method_has_ptr_parameter(method_info)) {
+ // Pointers are not supported.
+ continue;
+ }
+
MethodInterface imethod;
imethod.name = method_info.name;
imethod.cname = cname;
@@ -3002,7 +3000,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
} else if (return_info.type == Variant::NIL) {
imethod.return_type.cname = name_cache.type_void;
} else {
- imethod.return_type.cname = _get_type_name_from_meta(return_info.type, m ? m->get_argument_meta(-1) : GodotTypeInfo::METADATA_NONE);
+ imethod.return_type.cname = _get_type_name_from_meta(return_info.type, m ? m->get_argument_meta(-1) : (GodotTypeInfo::Metadata)method_info.return_val_metadata);
}
for (int i = 0; i < argc; i++) {
@@ -3026,7 +3024,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
} else if (arginfo.type == Variant::NIL) {
iarg.type.cname = name_cache.type_Variant;
} else {
- iarg.type.cname = _get_type_name_from_meta(arginfo.type, m ? m->get_argument_meta(i) : GodotTypeInfo::METADATA_NONE);
+ iarg.type.cname = _get_type_name_from_meta(arginfo.type, m ? m->get_argument_meta(i) : (GodotTypeInfo::Metadata)method_info.get_argument_meta(i));
}
iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name));
@@ -3059,12 +3057,10 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
HashMap<StringName, StringName>::Iterator accessor = accessor_methods.find(imethod.cname);
if (accessor) {
- const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value);
-
- // We only deprecate an accessor method if it's in the same class as the property. It's easier this way, but also
- // we don't know if an accessor method in a different class could have other purposes, so better leave those untouched.
- imethod.is_deprecated = true;
- imethod.deprecation_message = imethod.proxy_name + " is deprecated. Use the " + accessor_property->proxy_name + " property instead.";
+ // We only make internal an accessor method if it's in the same class as the property.
+ // It's easier this way, but also we don't know if an accessor method in a different class
+ // could have other purposes, so better leave those untouched.
+ imethod.is_internal = true;
}
if (itype.class_doc) {
@@ -3128,7 +3124,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
} else if (arginfo.type == Variant::NIL) {
iarg.type.cname = name_cache.type_Variant;
} else {
- iarg.type.cname = _get_type_name_from_meta(arginfo.type, GodotTypeInfo::METADATA_NONE);
+ iarg.type.cname = _get_type_name_from_meta(arginfo.type, (GodotTypeInfo::Metadata)method_info.get_argument_meta(i));
}
iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name));
@@ -3177,7 +3173,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &E : enum_map) {
StringName enum_proxy_cname = E.key;
- String enum_proxy_name = enum_proxy_cname.operator String();
+ String enum_proxy_name = pascal_to_pascal_case(enum_proxy_cname.operator String());
if (itype.find_property_by_proxy_name(enum_proxy_name) || itype.find_method_by_proxy_name(enum_proxy_name) || itype.find_signal_by_proxy_name(enum_proxy_name)) {
// In case the enum name conflicts with other PascalCase members,
// we append 'Enum' to the enum name in those cases.
@@ -3221,8 +3217,6 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
enum_itype.cname = StringName(enum_itype.name);
enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name;
TypeInterface::postsetup_enum_type(enum_itype);
- enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
- enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
}
@@ -3307,7 +3301,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
} break;
case Variant::AABB: {
AABB aabb = p_val.operator ::AABB();
- r_iarg.default_argument = "new AABB(new Vector3" + aabb.position.operator String() + ", new Vector3" + aabb.size.operator String() + ")";
+ r_iarg.default_argument = "new Aabb(new Vector3" + aabb.position.operator String() + ", new Vector3" + aabb.size.operator String() + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
case Variant::RECT2: {
@@ -3317,7 +3311,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
} break;
case Variant::RECT2I: {
Rect2i rect = p_val.operator Rect2i();
- r_iarg.default_argument = "new Rect2i(new Vector2i" + rect.position.operator String() + ", new Vector2i" + rect.size.operator String() + ")";
+ r_iarg.default_argument = "new Rect2I(new Vector2I" + rect.position.operator String() + ", new Vector2I" + rect.size.operator String() + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
case Variant::COLOR:
@@ -3451,34 +3445,30 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
TypeInterface itype;
-#define INSERT_STRUCT_TYPE(m_type) \
- { \
- itype = TypeInterface::create_value_type(String(#m_type)); \
- itype.c_type_in = #m_type "*"; \
- itype.c_type_out = itype.cs_type; \
- itype.cs_in_expr = "&%0"; \
- itype.cs_in_expr_is_unsafe = true; \
- itype.cs_variant_to_managed = "VariantUtils.ConvertTo%2(%0)"; \
- itype.cs_managed_to_variant = "VariantUtils.CreateFrom%2(%0)"; \
- builtin_types.insert(itype.cname, itype); \
- }
-
- INSERT_STRUCT_TYPE(Vector2)
- INSERT_STRUCT_TYPE(Vector2i)
- INSERT_STRUCT_TYPE(Rect2)
- INSERT_STRUCT_TYPE(Rect2i)
- INSERT_STRUCT_TYPE(Transform2D)
- INSERT_STRUCT_TYPE(Vector3)
- INSERT_STRUCT_TYPE(Vector3i)
- INSERT_STRUCT_TYPE(Basis)
- INSERT_STRUCT_TYPE(Quaternion)
- INSERT_STRUCT_TYPE(Transform3D)
- INSERT_STRUCT_TYPE(AABB)
- INSERT_STRUCT_TYPE(Color)
- INSERT_STRUCT_TYPE(Plane)
- INSERT_STRUCT_TYPE(Vector4)
- INSERT_STRUCT_TYPE(Vector4i)
- INSERT_STRUCT_TYPE(Projection)
+#define INSERT_STRUCT_TYPE(m_type, m_proxy_name) \
+ { \
+ itype = TypeInterface::create_value_type(String(#m_type), String(#m_proxy_name)); \
+ itype.cs_in_expr = "&%0"; \
+ itype.cs_in_expr_is_unsafe = true; \
+ builtin_types.insert(itype.cname, itype); \
+ }
+
+ INSERT_STRUCT_TYPE(Vector2, Vector2)
+ INSERT_STRUCT_TYPE(Vector2i, Vector2I)
+ INSERT_STRUCT_TYPE(Rect2, Rect2)
+ INSERT_STRUCT_TYPE(Rect2i, Rect2I)
+ INSERT_STRUCT_TYPE(Transform2D, Transform2D)
+ INSERT_STRUCT_TYPE(Vector3, Vector3)
+ INSERT_STRUCT_TYPE(Vector3i, Vector3I)
+ INSERT_STRUCT_TYPE(Basis, Basis)
+ INSERT_STRUCT_TYPE(Quaternion, Quaternion)
+ INSERT_STRUCT_TYPE(Transform3D, Transform3D)
+ INSERT_STRUCT_TYPE(AABB, Aabb)
+ INSERT_STRUCT_TYPE(Color, Color)
+ INSERT_STRUCT_TYPE(Plane, Plane)
+ INSERT_STRUCT_TYPE(Vector4, Vector4)
+ INSERT_STRUCT_TYPE(Vector4i, Vector4I)
+ INSERT_STRUCT_TYPE(Projection, Projection)
#undef INSERT_STRUCT_TYPE
@@ -3491,8 +3481,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.c_type;
itype.c_arg_in = "&%s";
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromBool(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToBool(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromBool(%0)";
builtin_types.insert(itype.cname, itype);
// Integer types
@@ -3513,8 +3501,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.name; \
itype.c_type_out = itype.name; \
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromInt(%1);\n"; \
- itype.cs_variant_to_managed = "VariantUtils.ConvertTo" m_int_struct_name "(%0)"; \
- itype.cs_managed_to_variant = "VariantUtils.CreateFromInt(%0)"; \
builtin_types.insert(itype.cname, itype); \
}
@@ -3550,8 +3536,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name;
itype.c_type_out = itype.proxy_name;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromFloat(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToFloat32(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromFloat(%0)";
builtin_types.insert(itype.cname, itype);
// double
@@ -3565,8 +3549,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name;
itype.c_type_out = itype.proxy_name;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromFloat(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToFloat64(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromFloat(%0)";
builtin_types.insert(itype.cname, itype);
}
@@ -3584,8 +3566,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromString(%1);\n";
- itype.cs_variant_to_managed = "VariantUtils.ConvertToStringObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromString(%0)";
builtin_types.insert(itype.cname, itype);
// StringName
@@ -3604,8 +3584,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringName(%1);\n";
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToStringNameObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromStringName(%0)";
builtin_types.insert(itype.cname, itype);
// NodePath
@@ -3623,22 +3601,18 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToNodePathObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromNodePath(%0)";
builtin_types.insert(itype.cname, itype);
// RID
itype = TypeInterface();
itype.name = "RID";
itype.cname = itype.name;
- itype.proxy_name = "RID";
+ itype.proxy_name = "Rid";
itype.cs_type = itype.proxy_name;
itype.c_arg_in = "&%s";
itype.c_type = itype.cs_type;
itype.c_type_in = itype.c_type;
itype.c_type_out = itype.c_type;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToRID(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromRID(%0)";
builtin_types.insert(itype.cname, itype);
// Variant
@@ -3655,8 +3629,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "Variant.CreateCopyingBorrowed(%0)";
- itype.cs_managed_to_variant = "%0.CopyNativeVariant()";
builtin_types.insert(itype.cname, itype);
// Callable
@@ -3669,26 +3641,22 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = "in " + itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToCallableManaged(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromCallable(%0)";
builtin_types.insert(itype.cname, itype);
// Signal
itype = TypeInterface();
itype.name = "Signal";
itype.cname = itype.name;
- itype.proxy_name = "SignalInfo";
+ itype.proxy_name = "Signal";
itype.cs_type = itype.proxy_name;
itype.cs_in_expr = "%0";
itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(in %1);\n";
- itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(&%1);\n";
+ itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(in %1);\n";
itype.c_arg_in = "&%s_in";
itype.c_type = "godot_signal";
itype.c_type_in = "in " + itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToSignalInfo(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromSignalInfo(%0)";
builtin_types.insert(itype.cname, itype);
// VarArg (fictitious type to represent variable arguments)
@@ -3718,8 +3686,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name; \
itype.c_type_out = itype.proxy_name; \
itype.c_type_is_disposable_struct = true; \
- itype.cs_variant_to_managed = "VariantUtils.ConvertAs%2ToSystemArray(%0)"; \
- itype.cs_managed_to_variant = "VariantUtils.CreateFrom%2(%0)"; \
builtin_types.insert(itype.name, itype); \
}
@@ -3755,8 +3721,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToArrayObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromArray(%0)";
builtin_types.insert(itype.cname, itype);
// Array_@generic
@@ -3764,6 +3728,9 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.name = "Array_@generic";
itype.cname = itype.name;
itype.cs_out = "%5return new %2(%0(%1));";
+ // For generic Godot collections, Variant.From<T>/As<T> is slower, so we need this special case
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToArray(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromArray(%0)";
builtin_types.insert(itype.cname, itype);
// Dictionary
@@ -3781,8 +3748,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
- itype.cs_variant_to_managed = "VariantUtils.ConvertToDictionaryObject(%0)";
- itype.cs_managed_to_variant = "VariantUtils.CreateFromDictionary(%0)";
builtin_types.insert(itype.cname, itype);
// Dictionary_@generic
@@ -3790,6 +3755,9 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.name = "Dictionary_@generic";
itype.cname = itype.name;
itype.cs_out = "%5return new %2(%0(%1));";
+ // For generic Godot collections, Variant.From<T>/As<T> is slower, so we need this special case
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToDictionary(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromDictionary(%0)";
builtin_types.insert(itype.cname, itype);
// void (fictitious type to represent the return type of methods that do not return anything)
@@ -3835,7 +3803,7 @@ void BindingsGenerator::_populate_global_constants() {
if (enum_name != StringName()) {
EnumInterface ienum(enum_name);
- // TODO: ienum.is_flags is always false for core constants since they don't seem to support bitfield enums
+ ienum.is_flags = CoreConstants::is_global_constant_bitfield(i);
List<EnumInterface>::Element *enum_match = global_enums.find(ienum);
if (enum_match) {
enum_match->get().constants.push_back(iconstant);
@@ -3853,10 +3821,8 @@ void BindingsGenerator::_populate_global_constants() {
enum_itype.is_enum = true;
enum_itype.name = ienum.cname.operator String();
enum_itype.cname = ienum.cname;
- enum_itype.proxy_name = enum_itype.name;
+ enum_itype.proxy_name = pascal_to_pascal_case(enum_itype.name);
TypeInterface::postsetup_enum_type(enum_itype);
- enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
- enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
int prefix_length = _determine_enum_prefix(ienum);
@@ -3877,9 +3843,9 @@ void BindingsGenerator::_populate_global_constants() {
// HARDCODED
List<StringName> hardcoded_enums;
hardcoded_enums.push_back("Vector2.Axis");
- hardcoded_enums.push_back("Vector2i.Axis");
+ hardcoded_enums.push_back("Vector2I.Axis");
hardcoded_enums.push_back("Vector3.Axis");
- hardcoded_enums.push_back("Vector3i.Axis");
+ hardcoded_enums.push_back("Vector3I.Axis");
for (const StringName &enum_cname : hardcoded_enums) {
// These enums are not generated and must be written manually (e.g.: Vector3.Axis)
// Here, we assume core types do not begin with underscore
@@ -3887,10 +3853,8 @@ void BindingsGenerator::_populate_global_constants() {
enum_itype.is_enum = true;
enum_itype.name = enum_cname.operator String();
enum_itype.cname = enum_cname;
- enum_itype.proxy_name = enum_itype.name;
+ enum_itype.proxy_name = pascal_to_pascal_case(enum_itype.name);
TypeInterface::postsetup_enum_type(enum_itype);
- enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
- enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
}
}
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index a479c44368..5c266ed31f 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* bindings_generator.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* bindings_generator.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef BINDINGS_GENERATOR_H
#define BINDINGS_GENERATOR_H
@@ -209,7 +209,7 @@ class BindingsGenerator {
String name;
StringName cname;
- int type_parameter_count;
+ int type_parameter_count = 0;
/**
* Identifier name of the base class.
@@ -472,49 +472,99 @@ class BindingsGenerator {
}
private:
+ static DocData::ClassDoc *_get_type_doc(TypeInterface &itype) {
+ String doc_name = itype.name.begins_with("_") ? itype.name.substr(1) : itype.name;
+ return &EditorHelp::get_doc_data()->class_list[doc_name];
+ }
+
static void _init_value_type(TypeInterface &itype) {
- itype.proxy_name = itype.name;
+ if (itype.proxy_name.is_empty()) {
+ itype.proxy_name = itype.name;
+ }
- itype.c_type = itype.name;
itype.cs_type = itype.proxy_name;
- itype.c_type_in = itype.proxy_name + "*";
- itype.c_type_out = itype.proxy_name;
- itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
+ itype.c_type = itype.cs_type;
+ itype.c_type_in = itype.cs_type + "*";
+ itype.c_type_out = itype.cs_type;
+
+ itype.class_doc = _get_type_doc(itype);
+ }
+
+ static void _init_object_type(TypeInterface &itype, ClassDB::APIType p_api_type) {
+ if (itype.proxy_name.is_empty()) {
+ itype.proxy_name = itype.name;
+ }
+
+ if (itype.proxy_name.begins_with("_")) {
+ itype.proxy_name = itype.proxy_name.substr(1);
+ }
+
+ itype.api_type = p_api_type;
+ itype.is_object_type = true;
+
+ itype.class_doc = _get_type_doc(itype);
}
public:
- static TypeInterface create_value_type(const String &p_name) {
+ static TypeInterface create_value_type(const String &p_name, const String &p_proxy_name) {
TypeInterface itype;
itype.name = p_name;
- itype.cname = StringName(p_name);
+ itype.cname = p_name;
+ itype.proxy_name = p_proxy_name;
+ _init_value_type(itype);
+ return itype;
+ }
+
+ static TypeInterface create_value_type(const StringName &p_cname, const String &p_proxy_name) {
+ TypeInterface itype;
+ itype.name = p_cname;
+ itype.cname = p_cname;
+ itype.proxy_name = p_proxy_name;
_init_value_type(itype);
return itype;
}
- static TypeInterface create_value_type(const StringName &p_name) {
+ static TypeInterface create_value_type(const String &p_name) {
TypeInterface itype;
- itype.name = p_name.operator String();
+ itype.name = p_name;
itype.cname = p_name;
_init_value_type(itype);
return itype;
}
- static TypeInterface create_object_type(const StringName &p_cname, ClassDB::APIType p_api_type) {
+ static TypeInterface create_value_type(const StringName &p_cname) {
TypeInterface itype;
+ itype.name = p_cname;
+ itype.cname = p_cname;
+ _init_value_type(itype);
+ return itype;
+ }
+ static TypeInterface create_object_type(const StringName &p_cname, const String &p_proxy_name, ClassDB::APIType p_api_type) {
+ TypeInterface itype;
itype.name = p_cname;
itype.cname = p_cname;
- itype.proxy_name = itype.name.begins_with("_") ? itype.name.substr(1, itype.name.length()) : itype.name;
- itype.api_type = p_api_type;
- itype.is_object_type = true;
- itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
+ itype.proxy_name = p_proxy_name;
+ _init_object_type(itype, p_api_type);
+ return itype;
+ }
+ static TypeInterface create_object_type(const StringName &p_cname, ClassDB::APIType p_api_type) {
+ TypeInterface itype;
+ itype.name = p_cname;
+ itype.cname = p_cname;
+ _init_object_type(itype, p_api_type);
return itype;
}
static void postsetup_enum_type(TypeInterface &r_enum_itype);
- TypeInterface() {}
+ TypeInterface() {
+ static String default_cs_variant_to_managed = "VariantUtils.ConvertTo<%1>(%0)";
+ static String default_cs_managed_to_variant = "VariantUtils.CreateFrom<%1>(%0)";
+ cs_variant_to_managed = default_cs_variant_to_managed;
+ cs_managed_to_variant = default_cs_managed_to_variant;
+ }
};
struct InternalCall {
diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp
index dc69567261..ae02e16256 100644
--- a/modules/mono/editor/code_completion.cpp
+++ b/modules/mono/editor/code_completion.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* code_completion.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* code_completion.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "code_completion.h"
diff --git a/modules/mono/editor/code_completion.h b/modules/mono/editor/code_completion.h
index 82b592003b..89d19b10e0 100644
--- a/modules/mono/editor/code_completion.h
+++ b/modules/mono/editor/code_completion.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* code_completion.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* code_completion.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef CODE_COMPLETION_H
#define CODE_COMPLETION_H
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index 91392c8f79..ad9ab66cc9 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* editor_internal_calls.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* editor_internal_calls.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "editor_internal_calls.h"
diff --git a/modules/mono/editor/editor_internal_calls.h b/modules/mono/editor/editor_internal_calls.h
index 35391f1f04..48da02987a 100644
--- a/modules/mono/editor/editor_internal_calls.h
+++ b/modules/mono/editor/editor_internal_calls.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* editor_internal_calls.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* editor_internal_calls.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef EDITOR_INTERNAL_CALLS_H
#define EDITOR_INTERNAL_CALLS_H
diff --git a/modules/mono/editor/hostfxr_resolver.cpp b/modules/mono/editor/hostfxr_resolver.cpp
index ea5978b2cd..786272b28c 100644
--- a/modules/mono/editor/hostfxr_resolver.cpp
+++ b/modules/mono/editor/hostfxr_resolver.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* hostfxr_resolver.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* hostfxr_resolver.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
/*
Adapted to Godot from the nethost library: https://github.com/dotnet/runtime/tree/main/src/native/corehost
diff --git a/modules/mono/editor/hostfxr_resolver.h b/modules/mono/editor/hostfxr_resolver.h
index 0f029ab7ae..398a58c730 100644
--- a/modules/mono/editor/hostfxr_resolver.h
+++ b/modules/mono/editor/hostfxr_resolver.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* hostfxr_resolver.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* hostfxr_resolver.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef HOSTFXR_RESOLVER_H
#define HOSTFXR_RESOLVER_H
diff --git a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs
index fbad482cf6..87468fb433 100644
--- a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs
+++ b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs
@@ -17,22 +17,22 @@ public partial class _CLASS_ : _BASE_
// Add the gravity.
if (!IsOnFloor())
- velocity.y += gravity * (float)delta;
+ velocity.Y += gravity * (float)delta;
// Handle Jump.
if (Input.IsActionJustPressed("ui_accept") && IsOnFloor())
- velocity.y = JumpVelocity;
+ velocity.Y = JumpVelocity;
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 direction = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
if (direction != Vector2.Zero)
{
- velocity.x = direction.x * Speed;
+ velocity.X = direction.X * Speed;
}
else
{
- velocity.x = Mathf.MoveToward(Velocity.x, 0, Speed);
+ velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
}
Velocity = velocity;
diff --git a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs
index abed246a1e..ddeb9d7e00 100644
--- a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs
+++ b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs
@@ -17,25 +17,25 @@ public partial class _CLASS_ : _BASE_
// Add the gravity.
if (!IsOnFloor())
- velocity.y -= gravity * (float)delta;
+ velocity.Y -= gravity * (float)delta;
// Handle Jump.
if (Input.IsActionJustPressed("ui_accept") && IsOnFloor())
- velocity.y = JumpVelocity;
+ velocity.Y = JumpVelocity;
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 inputDir = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
- Vector3 direction = (Transform.basis * new Vector3(inputDir.x, 0, inputDir.y)).Normalized();
+ Vector3 direction = (Transform.Basis * new Vector3(inputDir.X, 0, inputDir.Y)).Normalized();
if (direction != Vector3.Zero)
{
- velocity.x = direction.x * Speed;
- velocity.z = direction.z * Speed;
+ velocity.X = direction.X * Speed;
+ velocity.Z = direction.Z * Speed;
}
else
{
- velocity.x = Mathf.MoveToward(Velocity.x, 0, Speed);
- velocity.z = Mathf.MoveToward(Velocity.z, 0, Speed);
+ velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
+ velocity.Z = Mathf.MoveToward(Velocity.Z, 0, Speed);
}
Velocity = velocity;
diff --git a/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs b/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs
index 9e1b7ef580..fa2ff30a09 100644
--- a/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs
+++ b/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs
@@ -7,7 +7,7 @@ using System;
[Tool]
public partial class _CLASS_ : _BASE_
{
- public override Godot.Object _PostImport(Node scene)
+ public override GodotObject _PostImport(Node scene)
{
// Modify the contents of the scene upon import.
return scene; // Return the modified root node when you're done.
diff --git a/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs b/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs
index bf2c9434e4..4365ba5a04 100644
--- a/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs
+++ b/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs
@@ -7,7 +7,7 @@ using System;
[Tool]
public partial class _CLASS_ : _BASE_
{
- public override Godot.Object _PostImport(Node scene)
+ public override GodotObject _PostImport(Node scene)
{
return scene;
}
diff --git a/modules/mono/editor/semver.cpp b/modules/mono/editor/semver.cpp
index 1656d0932f..1ca3005420 100644
--- a/modules/mono/editor/semver.cpp
+++ b/modules/mono/editor/semver.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* semver.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* semver.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "semver.h"
diff --git a/modules/mono/editor/semver.h b/modules/mono/editor/semver.h
index 48ea8b043e..2f65e99ef5 100644
--- a/modules/mono/editor/semver.h
+++ b/modules/mono/editor/semver.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* semver.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* semver.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef SEMVER_H
#define SEMVER_H
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/Godot.SourceGenerators.Internal/Common.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs
index 16e96c725a..d3726d69f0 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Common.cs
@@ -12,7 +12,7 @@ internal static class Common
{
string message =
"Missing partial modifier on declaration of type '" +
- $"{symbol.FullQualifiedName()}' which has attribute '{GeneratorClasses.GenerateUnmanagedCallbacksAttr}'";
+ $"{symbol.FullQualifiedNameOmitGlobal()}' which has attribute '{GeneratorClasses.GenerateUnmanagedCallbacksAttr}'";
string description = $"{message}. Classes with attribute '{GeneratorClasses.GenerateUnmanagedCallbacksAttr}' " +
"must be declared with the partial modifier.";
@@ -39,7 +39,7 @@ internal static class Common
.GetDeclaredSymbol(outerTypeDeclSyntax);
string fullQualifiedName = outerSymbol is INamedTypeSymbol namedTypeSymbol ?
- namedTypeSymbol.FullQualifiedName() :
+ namedTypeSymbol.FullQualifiedNameOmitGlobal() :
"type not found";
string message =
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs
index fac362479a..37f7005d01 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/ExtensionMethods.cs
@@ -94,13 +94,6 @@ internal static class ExtensionMethods
};
}
- private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
- SymbolDisplayFormat.FullyQualifiedFormat
- .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
-
- public static string FullQualifiedName(this ITypeSymbol symbol)
- => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
-
public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
{
return symbol.IsGenericType ?
@@ -108,8 +101,25 @@ internal static class ExtensionMethods
symbol.Name;
}
- public static string FullQualifiedName(this INamespaceSymbol symbol)
- => symbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+ private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
+
+ private static SymbolDisplayFormat FullyQualifiedFormatIncludeGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Included);
+
+ public static string FullQualifiedNameOmitGlobal(this ITypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedNameOmitGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this ITypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatIncludeGlobal);
+
+ public static string FullQualifiedNameIncludeGlobal(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatIncludeGlobal);
public static string SanitizeQualifiedNameForUniqueHint(this string qualifiedName)
=> qualifiedName
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
index da578309bc..3226ca79e5 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
@@ -96,7 +96,7 @@ internal class GenerateUnmanagedCallbacksAttribute : Attribute
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
@@ -144,7 +144,7 @@ using Godot.NativeInterop;
source.Append("[System.Runtime.CompilerServices.SkipLocalsInit]\n");
source.Append($"unsafe partial class {symbol.Name}\n");
source.Append("{\n");
- source.Append($" private static {data.FuncStructSymbol.FullQualifiedName()} _unmanagedCallbacks;\n\n");
+ source.Append($" private static {data.FuncStructSymbol.FullQualifiedNameIncludeGlobal()} _unmanagedCallbacks;\n\n");
foreach (var callback in data.Methods)
{
@@ -159,7 +159,7 @@ using Godot.NativeInterop;
source.Append("static ");
source.Append("partial ");
- source.Append(callback.ReturnType.FullQualifiedName());
+ source.Append(callback.ReturnType.FullQualifiedNameIncludeGlobal());
source.Append(' ');
source.Append(callback.Name);
source.Append('(');
@@ -228,7 +228,7 @@ using Godot.NativeInterop;
if (!callback.ReturnsVoid)
{
if (methodSourceAfterCall.Length != 0)
- source.Append($"{callback.ReturnType.FullQualifiedName()} ret = ");
+ source.Append($"{callback.ReturnType.FullQualifiedNameIncludeGlobal()} ret = ");
else
source.Append("return ");
}
@@ -267,7 +267,7 @@ using Godot.NativeInterop;
source.Append("\n\n#pragma warning restore CA1707\n");
- context.AddSource($"{data.NativeTypeSymbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()}.generated",
+ context.AddSource($"{data.NativeTypeSymbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()}.generated",
SourceText.From(source.ToString(), Encoding.UTF8));
}
@@ -277,7 +277,7 @@ using Godot.NativeInterop;
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
- namespaceSymbol.FullQualifiedName() :
+ namespaceSymbol.FullQualifiedNameOmitGlobal() :
string.Empty;
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
@@ -338,18 +338,18 @@ using Godot.NativeInterop;
// just pass it by-ref and let it be pinned.
AppendRefKind(source, parameter.RefKind)
.Append(' ')
- .Append(parameter.Type.FullQualifiedName());
+ .Append(parameter.Type.FullQualifiedNameIncludeGlobal());
}
}
else
{
- source.Append(parameter.Type.FullQualifiedName());
+ source.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
}
source.Append(", ");
}
- source.Append(callback.ReturnType.FullQualifiedName());
+ source.Append(callback.ReturnType.FullQualifiedNameIncludeGlobal());
source.Append($"> {callback.Name};\n");
}
@@ -372,12 +372,12 @@ using Godot.NativeInterop;
source.Append("\n#pragma warning restore CA1707\n");
- context.AddSource($"{symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint()}.generated",
+ context.AddSource($"{symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()}.generated",
SourceText.From(source.ToString(), Encoding.UTF8));
}
private static bool IsGodotInteropStruct(ITypeSymbol type) =>
- GodotInteropStructs.Contains(type.FullQualifiedName());
+ GodotInteropStructs.Contains(type.FullQualifiedNameOmitGlobal());
private static bool IsByRefParameter(IParameterSymbol parameter) =>
parameter.RefKind is RefKind.In or RefKind.Out or RefKind.Ref;
@@ -393,7 +393,7 @@ using Godot.NativeInterop;
private static void AppendPointerType(StringBuilder source, ITypeSymbol type)
{
- source.Append(type.FullQualifiedName());
+ source.Append(type.FullQualifiedNameIncludeGlobal());
source.Append('*');
}
@@ -426,7 +426,7 @@ using Godot.NativeInterop;
{
varName = $"{parameter.Name}_copy";
- source.Append(parameter.Type.FullQualifiedName());
+ source.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
source.Append(' ');
source.Append(varName);
if (parameter.RefKind is RefKind.In or RefKind.Ref)
diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj b/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj
index e720d3878c..e58d730ee3 100644
--- a/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj
+++ b/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj
@@ -8,6 +8,7 @@
<!-- To generate the .runtimeconfig.json file-->
<EnableDynamicLoading>true</EnableDynamicLoading>
+ <RollForward>LatestMajor</RollForward>
</PropertyGroup>
<ItemGroup>
diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
index 8308bada24..2a72b7c53e 100644
--- a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
+++ b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
@@ -28,17 +28,24 @@ namespace GodotPlugins
get => _pluginLoadContext?.AssemblyLoadedPath;
}
+ public bool IsCollectible
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ get => _pluginLoadContext?.IsCollectible ?? false;
+ }
+
[MethodImpl(MethodImplOptions.NoInlining)]
public static (Assembly, PluginLoadContextWrapper) CreateAndLoadFromAssemblyName(
AssemblyName assemblyName,
string pluginPath,
ICollection<string> sharedAssemblies,
- AssemblyLoadContext mainLoadContext
+ AssemblyLoadContext mainLoadContext,
+ bool isCollectible
)
{
var wrapper = new PluginLoadContextWrapper();
wrapper._pluginLoadContext = new PluginLoadContext(
- pluginPath, sharedAssemblies, mainLoadContext);
+ pluginPath, sharedAssemblies, mainLoadContext, isCollectible);
var assembly = wrapper._pluginLoadContext.LoadFromAssemblyName(assemblyName);
return (assembly, wrapper);
}
@@ -58,9 +65,10 @@ namespace GodotPlugins
}
private static readonly List<AssemblyName> SharedAssemblies = new();
- private static readonly Assembly CoreApiAssembly = typeof(Godot.Object).Assembly;
+ private static readonly Assembly CoreApiAssembly = typeof(global::Godot.GodotObject).Assembly;
private static Assembly? _editorApiAssembly;
private static PluginLoadContextWrapper? _projectLoadContext;
+ private static bool _editorHint = false;
private static readonly AssemblyLoadContext MainLoadContext =
AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()) ??
@@ -77,15 +85,17 @@ namespace GodotPlugins
{
try
{
+ _editorHint = editorHint.ToBool();
+
_dllImportResolver = new GodotDllImportResolver(godotDllHandle).OnResolveDllImport;
SharedAssemblies.Add(CoreApiAssembly.GetName());
NativeLibrary.SetDllImportResolver(CoreApiAssembly, _dllImportResolver);
- AlcReloadCfg.Configure(alcReloadEnabled: editorHint.ToBool());
+ AlcReloadCfg.Configure(alcReloadEnabled: _editorHint);
NativeFuncs.Initialize(unmanagedCallbacks, unmanagedCallbacksSize);
- if (editorHint.ToBool())
+ if (_editorHint)
{
_editorApiAssembly = Assembly.Load("GodotSharpEditor");
SharedAssemblies.Add(_editorApiAssembly.GetName());
@@ -128,7 +138,7 @@ namespace GodotPlugins
string assemblyPath = new(nAssemblyPath);
- (var projectAssembly, _projectLoadContext) = LoadPlugin(assemblyPath);
+ (var projectAssembly, _projectLoadContext) = LoadPlugin(assemblyPath, isCollectible: _editorHint);
string loadedAssemblyPath = _projectLoadContext.AssemblyLoadedPath ?? assemblyPath;
*outLoadedAssemblyPath = Marshaling.ConvertStringToNative(loadedAssemblyPath);
@@ -155,7 +165,7 @@ namespace GodotPlugins
if (_editorApiAssembly == null)
throw new InvalidOperationException("The Godot editor API assembly is not loaded.");
- var (assembly, _) = LoadPlugin(assemblyPath);
+ var (assembly, _) = LoadPlugin(assemblyPath, isCollectible: _editorHint);
NativeLibrary.SetDllImportResolver(assembly, _dllImportResolver!);
@@ -180,7 +190,7 @@ namespace GodotPlugins
}
}
- private static (Assembly, PluginLoadContextWrapper) LoadPlugin(string assemblyPath)
+ private static (Assembly, PluginLoadContextWrapper) LoadPlugin(string assemblyPath, bool isCollectible)
{
string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
@@ -194,7 +204,7 @@ namespace GodotPlugins
}
return PluginLoadContextWrapper.CreateAndLoadFromAssemblyName(
- new AssemblyName(assemblyName), assemblyPath, sharedAssemblies, MainLoadContext);
+ new AssemblyName(assemblyName), assemblyPath, sharedAssemblies, MainLoadContext, isCollectible);
}
[UnmanagedCallersOnly]
@@ -218,6 +228,12 @@ namespace GodotPlugins
if (pluginLoadContext == null)
return true;
+ if (!pluginLoadContext.IsCollectible)
+ {
+ Console.Error.WriteLine("Cannot unload a non-collectible assembly load context.");
+ return false;
+ }
+
Console.WriteLine("Unloading assembly load context...");
var alcWeakReference = pluginLoadContext.CreateWeakReference();
diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs b/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs
index dcd572c65e..93baf4e51c 100644
--- a/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs
+++ b/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs
@@ -15,12 +15,32 @@ namespace GodotPlugins
public string? AssemblyLoadedPath { get; private set; }
public PluginLoadContext(string pluginPath, ICollection<string> sharedAssemblies,
- AssemblyLoadContext mainLoadContext)
- : base(isCollectible: true)
+ AssemblyLoadContext mainLoadContext, bool isCollectible)
+ : base(isCollectible)
{
_resolver = new AssemblyDependencyResolver(pluginPath);
_sharedAssemblies = sharedAssemblies;
_mainLoadContext = mainLoadContext;
+
+ if (string.IsNullOrEmpty(AppContext.BaseDirectory))
+ {
+ // See https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs#L17-L35
+ // but Assembly.Location is unavailable, because we load assemblies from memory.
+ string? baseDirectory = Path.GetDirectoryName(pluginPath);
+ if (baseDirectory != null)
+ {
+ if (!Path.EndsInDirectorySeparator(baseDirectory))
+ baseDirectory += Path.DirectorySeparatorChar;
+ // This SetData call effectively sets AppContext.BaseDirectory
+ // See https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Private.CoreLib/src/System/AppContext.cs#L21-L25
+ AppDomain.CurrentDomain.SetData("APP_CONTEXT_BASE_DIRECTORY", baseDirectory);
+ }
+ else
+ {
+ // TODO: How to log from GodotPlugins? (delegate pointer?)
+ Console.Error.WriteLine("Failed to set AppContext.BaseDirectory. Dynamic loading of libraries may fail.");
+ }
+ }
}
protected override Assembly? Load(AssemblyName assemblyName)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
index ba65b61e95..65f33e43a8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
+++ b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
@@ -1,7 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=alcs/@EntryIndexedValue">True</s:Boolean>
- <s:Boolean x:Key="/Default/UserDictionary/Words/=gdnative/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/UserDictionary/Words/=gdextension/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=godotsharp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=icall/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quat/@EntryIndexedValue">True</s:Boolean>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs
index d8a6644a66..af83cc24bf 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs
@@ -9,7 +9,7 @@ namespace Godot
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- public struct AABB : IEquatable<AABB>
+ public struct Aabb : IEquatable<Aabb>
{
private Vector3 _position;
private Vector3 _size;
@@ -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,121 +45,130 @@ namespace Godot
/// </value>
public Vector3 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
/// <summary>
- /// Returns an <see cref="AABB"/> with equivalent position and size, modified so that
+ /// The volume of this <see cref="Aabb"/>.
+ /// See also <see cref="HasVolume"/>.
+ /// </summary>
+ public readonly real_t Volume
+ {
+ get { return _size.X * _size.Y * _size.Z; }
+ }
+
+ /// <summary>
+ /// Returns an <see cref="Aabb"/> with equivalent position and size, modified so that
/// the most-negative corner is the origin and the size is positive.
/// </summary>
- /// <returns>The modified <see cref="AABB"/>.</returns>
- public AABB Abs()
+ /// <returns>The modified <see cref="Aabb"/>.</returns>
+ 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));
- return new AABB(topLeft, _size.Abs());
+ Vector3 topLeft = new Vector3(Mathf.Min(_position.X, end.X), Mathf.Min(_position.Y, end.Y), Mathf.Min(_position.Z, end.Z));
+ return new Aabb(topLeft, _size.Abs());
}
/// <summary>
- /// Returns the center of the <see cref="AABB"/>, which is equal
+ /// Returns the center of the <see cref="Aabb"/>, which is equal
/// 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);
}
/// <summary>
- /// Returns <see langword="true"/> if this <see cref="AABB"/> completely encloses another one.
+ /// Returns <see langword="true"/> if this <see cref="Aabb"/> completely encloses another one.
/// </summary>
- /// <param name="with">The other <see cref="AABB"/> that may be enclosed.</param>
+ /// <param name="with">The other <see cref="Aabb"/> that may be enclosed.</param>
/// <returns>
- /// A <see langword="bool"/> for whether or not this <see cref="AABB"/> encloses <paramref name="with"/>.
+ /// 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;
Vector3 dstMin = with._position;
Vector3 dstMax = with._position + with._size;
- return srcMin.x <= dstMin.x &&
- srcMax.x > dstMax.x &&
- srcMin.y <= dstMin.y &&
- srcMax.y > dstMax.y &&
- srcMin.z <= dstMin.z &&
- srcMax.z > dstMax.z;
+ return srcMin.X <= dstMin.X &&
+ srcMax.X > dstMax.X &&
+ srcMin.Y <= dstMin.Y &&
+ srcMax.Y > dstMax.Y &&
+ srcMin.Z <= dstMin.Z &&
+ srcMax.Z > dstMax.Z;
}
/// <summary>
- /// Returns this <see cref="AABB"/> expanded to include a given point.
+ /// Returns this <see cref="Aabb"/> expanded to include a given point.
/// </summary>
/// <param name="point">The point to include.</param>
- /// <returns>The expanded <see cref="AABB"/>.</returns>
- public AABB Expand(Vector3 point)
+ /// <returns>The expanded <see cref="Aabb"/>.</returns>
+ public readonly Aabb Expand(Vector3 point)
{
Vector3 begin = _position;
Vector3 end = _position + _size;
- if (point.x < begin.x)
+ if (point.X < begin.X)
{
- begin.x = point.x;
+ begin.X = point.X;
}
- if (point.y < begin.y)
+ if (point.Y < begin.Y)
{
- begin.y = point.y;
+ begin.Y = point.Y;
}
- if (point.z < begin.z)
+ if (point.Z < begin.Z)
{
- begin.z = point.z;
+ begin.Z = point.Z;
}
- if (point.x > end.x)
+ if (point.X > end.X)
{
- end.x = point.x;
+ end.X = point.X;
}
- if (point.y > end.y)
+ if (point.Y > end.Y)
{
- end.y = point.y;
+ end.Y = point.Y;
}
- if (point.z > end.z)
+ if (point.Z > end.Z)
{
- end.z = point.z;
+ end.Z = point.Z;
}
- return new AABB(begin, end - begin);
+ return new Aabb(begin, end - begin);
}
/// <summary>
- /// Gets the position of one of the 8 endpoints of the <see cref="AABB"/>.
+ /// Gets the position of one of the 8 endpoints of the <see cref="Aabb"/>.
/// </summary>
/// <param name="idx">Which endpoint to get.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// <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)
+ /// <returns>An endpoint of the <see cref="Aabb"/>.</returns>
+ public readonly Vector3 GetEndpoint(int idx)
{
switch (idx)
{
case 0:
- return new Vector3(_position.x, _position.y, _position.z);
+ return new Vector3(_position.X, _position.Y, _position.Z);
case 1:
- return new Vector3(_position.x, _position.y, _position.z + _size.z);
+ return new Vector3(_position.X, _position.Y, _position.Z + _size.Z);
case 2:
- return new Vector3(_position.x, _position.y + _size.y, _position.z);
+ return new Vector3(_position.X, _position.Y + _size.Y, _position.Z);
case 3:
- return new Vector3(_position.x, _position.y + _size.y, _position.z + _size.z);
+ return new Vector3(_position.X, _position.Y + _size.Y, _position.Z + _size.Z);
case 4:
- return new Vector3(_position.x + _size.x, _position.y, _position.z);
+ return new Vector3(_position.X + _size.X, _position.Y, _position.Z);
case 5:
- return new Vector3(_position.x + _size.x, _position.y, _position.z + _size.z);
+ return new Vector3(_position.X + _size.X, _position.Y, _position.Z + _size.Z);
case 6:
- return new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z);
+ return new Vector3(_position.X + _size.X, _position.Y + _size.Y, _position.Z);
case 7:
- return new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z + _size.z);
+ return new Vector3(_position.X + _size.X, _position.Y + _size.Y, _position.Z + _size.Z);
default:
{
throw new ArgumentOutOfRangeException(nameof(idx),
@@ -169,21 +178,21 @@ namespace Godot
}
/// <summary>
- /// Returns the normalized longest axis of the <see cref="AABB"/>.
+ /// 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()
+ /// <returns>A vector representing the normalized longest axis of the <see cref="Aabb"/>.</returns>
+ public readonly Vector3 GetLongestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
- real_t maxSize = _size.x;
+ real_t maxSize = _size.X;
- if (_size.y > maxSize)
+ if (_size.Y > maxSize)
{
axis = new Vector3(0f, 1f, 0f);
- maxSize = _size.y;
+ maxSize = _size.Y;
}
- if (_size.z > maxSize)
+ if (_size.Z > maxSize)
{
axis = new Vector3(0f, 0f, 1f);
}
@@ -192,21 +201,21 @@ namespace Godot
}
/// <summary>
- /// Returns the <see cref="Vector3.Axis"/> index of the longest axis of the <see cref="AABB"/>.
+ /// 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;
+ real_t maxSize = _size.X;
- if (_size.y > maxSize)
+ if (_size.Y > maxSize)
{
axis = Vector3.Axis.Y;
- maxSize = _size.y;
+ maxSize = _size.Y;
}
- if (_size.z > maxSize)
+ if (_size.Z > maxSize)
{
axis = Vector3.Axis.Z;
}
@@ -215,38 +224,38 @@ namespace Godot
}
/// <summary>
- /// Returns the scalar length of the longest axis of the <see cref="AABB"/>.
+ /// 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()
+ /// <returns>The scalar length of the longest axis of the <see cref="Aabb"/>.</returns>
+ public readonly real_t GetLongestAxisSize()
{
- real_t maxSize = _size.x;
+ real_t maxSize = _size.X;
- if (_size.y > maxSize)
- maxSize = _size.y;
+ if (_size.Y > maxSize)
+ maxSize = _size.Y;
- if (_size.z > maxSize)
- maxSize = _size.z;
+ if (_size.Z > maxSize)
+ maxSize = _size.Z;
return maxSize;
}
/// <summary>
- /// Returns the normalized shortest axis of the <see cref="AABB"/>.
+ /// 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()
+ /// <returns>A vector representing the normalized shortest axis of the <see cref="Aabb"/>.</returns>
+ public readonly Vector3 GetShortestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
- real_t maxSize = _size.x;
+ real_t maxSize = _size.X;
- if (_size.y < maxSize)
+ if (_size.Y < maxSize)
{
axis = new Vector3(0f, 1f, 0f);
- maxSize = _size.y;
+ maxSize = _size.Y;
}
- if (_size.z < maxSize)
+ if (_size.Z < maxSize)
{
axis = new Vector3(0f, 0f, 1f);
}
@@ -255,21 +264,21 @@ namespace Godot
}
/// <summary>
- /// Returns the <see cref="Vector3.Axis"/> index of the shortest axis of the <see cref="AABB"/>.
+ /// 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;
+ real_t maxSize = _size.X;
- if (_size.y < maxSize)
+ if (_size.Y < maxSize)
{
axis = Vector3.Axis.Y;
- maxSize = _size.y;
+ maxSize = _size.Y;
}
- if (_size.z < maxSize)
+ if (_size.Z < maxSize)
{
axis = Vector3.Axis.Z;
}
@@ -278,18 +287,18 @@ namespace Godot
}
/// <summary>
- /// Returns the scalar length of the shortest axis of the <see cref="AABB"/>.
+ /// 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()
+ /// <returns>The scalar length of the shortest axis of the <see cref="Aabb"/>.</returns>
+ public readonly real_t GetShortestAxisSize()
{
- real_t maxSize = _size.x;
+ real_t maxSize = _size.X;
- if (_size.y < maxSize)
- maxSize = _size.y;
+ if (_size.Y < maxSize)
+ maxSize = _size.Y;
- if (_size.z < maxSize)
- maxSize = _size.z;
+ if (_size.Z < maxSize)
+ maxSize = _size.Z;
return maxSize;
}
@@ -300,105 +309,96 @@ 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;
return ofs + new Vector3(
- dir.x > 0f ? -halfExtents.x : halfExtents.x,
- dir.y > 0f ? -halfExtents.y : halfExtents.y,
- dir.z > 0f ? -halfExtents.z : halfExtents.z);
- }
-
- /// <summary>
- /// Returns the volume of the <see cref="AABB"/>.
- /// </summary>
- /// <returns>The volume.</returns>
- public real_t GetVolume()
- {
- return _size.x * _size.y * _size.z;
+ dir.X > 0f ? -halfExtents.X : halfExtents.X,
+ dir.Y > 0f ? -halfExtents.Y : halfExtents.Y,
+ dir.Z > 0f ? -halfExtents.Z : halfExtents.Z);
}
/// <summary>
- /// Returns a copy of the <see cref="AABB"/> grown a given amount of units towards all the sides.
+ /// Returns a copy of the <see cref="Aabb"/> grown a given amount of units towards all the sides.
/// </summary>
/// <param name="by">The amount to grow by.</param>
- /// <returns>The grown <see cref="AABB"/>.</returns>
- public AABB Grow(real_t by)
+ /// <returns>The grown <see cref="Aabb"/>.</returns>
+ public readonly Aabb Grow(real_t by)
{
- AABB res = this;
+ Aabb res = this;
- res._position.x -= by;
- res._position.y -= by;
- res._position.z -= by;
- res._size.x += 2.0f * by;
- res._size.y += 2.0f * by;
- res._size.z += 2.0f * by;
+ res._position.X -= by;
+ res._position.Y -= by;
+ res._position.Z -= by;
+ res._size.X += 2.0f * by;
+ res._size.Y += 2.0f * by;
+ res._size.Z += 2.0f * by;
return res;
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/> contains a point,
+ /// Returns <see langword="true"/> if the <see cref="Aabb"/> contains a point,
/// or <see langword="false"/> otherwise.
/// </summary>
/// <param name="point">The point to check.</param>
/// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> contains <paramref name="point"/>.
+ /// 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)
+ if (point.X < _position.X)
return false;
- if (point.y < _position.y)
+ if (point.Y < _position.Y)
return false;
- if (point.z < _position.z)
+ if (point.Z < _position.Z)
return false;
- if (point.x > _position.x + _size.x)
+ if (point.X > _position.X + _size.X)
return false;
- if (point.y > _position.y + _size.y)
+ if (point.Y > _position.Y + _size.Y)
return false;
- if (point.z > _position.z + _size.z)
+ if (point.Z > _position.Z + _size.Z)
return false;
return true;
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/>
+ /// Returns <see langword="true"/> if the <see cref="Aabb"/>
/// has a surface or a length, and <see langword="false"/>
- /// if the <see cref="AABB"/> is empty (all components
+ /// if the <see cref="Aabb"/> is empty (all components
/// of <see cref="Size"/> are zero or negative).
/// </summary>
/// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has surface.
+ /// 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;
+ return _size.X > 0.0f || _size.Y > 0.0f || _size.Z > 0.0f;
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/> has
- /// area, and <see langword="false"/> if the <see cref="AABB"/>
+ /// Returns <see langword="true"/> if the <see cref="Aabb"/> has
+ /// area, and <see langword="false"/> if the <see cref="Aabb"/>
/// is linear, empty, or has a negative <see cref="Size"/>.
- /// See also <see cref="GetVolume"/>.
+ /// See also <see cref="Volume"/>.
/// </summary>
/// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has volume.
+ /// 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;
+ return _size.X > 0.0f && _size.Y > 0.0f && _size.Z > 0.0f;
}
/// <summary>
- /// Returns the intersection of this <see cref="AABB"/> and <paramref name="with"/>.
+ /// Returns the intersection of this <see cref="Aabb"/> and <paramref name="with"/>.
/// </summary>
- /// <param name="with">The other <see cref="AABB"/>.</param>
- /// <returns>The clipped <see cref="AABB"/>.</returns>
- public AABB Intersection(AABB with)
+ /// <param name="with">The other <see cref="Aabb"/>.</param>
+ /// <returns>The clipped <see cref="Aabb"/>.</returns>
+ public readonly Aabb Intersection(Aabb with)
{
Vector3 srcMin = _position;
Vector3 srcMax = _position + _size;
@@ -407,101 +407,78 @@ namespace Godot
Vector3 min, max;
- if (srcMin.x > dstMax.x || srcMax.x < dstMin.x)
+ if (srcMin.X > dstMax.X || srcMax.X < dstMin.X)
{
- return new AABB();
+ return new Aabb();
}
- min.x = srcMin.x > dstMin.x ? srcMin.x : dstMin.x;
- max.x = srcMax.x < dstMax.x ? srcMax.x : dstMax.x;
+ min.X = srcMin.X > dstMin.X ? srcMin.X : dstMin.X;
+ max.X = srcMax.X < dstMax.X ? srcMax.X : dstMax.X;
- if (srcMin.y > dstMax.y || srcMax.y < dstMin.y)
+ if (srcMin.Y > dstMax.Y || srcMax.Y < dstMin.Y)
{
- return new AABB();
+ return new Aabb();
}
- min.y = srcMin.y > dstMin.y ? srcMin.y : dstMin.y;
- max.y = srcMax.y < dstMax.y ? srcMax.y : dstMax.y;
+ min.Y = srcMin.Y > dstMin.Y ? srcMin.Y : dstMin.Y;
+ max.Y = srcMax.Y < dstMax.Y ? srcMax.Y : dstMax.Y;
- if (srcMin.z > dstMax.z || srcMax.z < dstMin.z)
+ if (srcMin.Z > dstMax.Z || srcMax.Z < dstMin.Z)
{
- return new AABB();
+ return new Aabb();
}
- min.z = srcMin.z > dstMin.z ? srcMin.z : dstMin.z;
- max.z = srcMax.z < dstMax.z ? srcMax.z : dstMax.z;
+ min.Z = srcMin.Z > dstMin.Z ? srcMin.Z : dstMin.Z;
+ max.Z = srcMax.Z < dstMax.Z ? srcMax.Z : dstMax.Z;
- return new AABB(min, max - min);
+ return new Aabb(min, max - min);
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/> overlaps with <paramref name="with"/>
+ /// Returns <see langword="true"/> if the <see cref="Aabb"/> overlaps with <paramref name="with"/>
/// (i.e. they have at least one point in common).
- ///
- /// If <paramref name="includeBorders"/> is <see langword="true"/>,
- /// they will also be considered overlapping if their borders touch,
- /// even without intersection.
/// </summary>
- /// <param name="with">The other <see cref="AABB"/> to check for intersections with.</param>
- /// <param name="includeBorders">Whether or not to consider borders.</param>
+ /// <param name="with">The other <see cref="Aabb"/> to check for intersections with.</param>
/// <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)
{
- if (includeBorders)
- {
- if (_position.x > with._position.x + with._size.x)
- return false;
- if (_position.x + _size.x < with._position.x)
- return false;
- if (_position.y > with._position.y + with._size.y)
- return false;
- if (_position.y + _size.y < with._position.y)
- return false;
- if (_position.z > with._position.z + with._size.z)
- return false;
- if (_position.z + _size.z < with._position.z)
- return false;
- }
- else
- {
- if (_position.x >= with._position.x + with._size.x)
- return false;
- if (_position.x + _size.x <= with._position.x)
- return false;
- if (_position.y >= with._position.y + with._size.y)
- return false;
- if (_position.y + _size.y <= with._position.y)
- return false;
- if (_position.z >= with._position.z + with._size.z)
- return false;
- if (_position.z + _size.z <= with._position.z)
- return false;
- }
+ if (_position.X >= with._position.X + with._size.X)
+ return false;
+ if (_position.X + _size.X <= with._position.X)
+ return false;
+ if (_position.Y >= with._position.Y + with._size.Y)
+ return false;
+ if (_position.Y + _size.Y <= with._position.Y)
+ return false;
+ if (_position.Z >= with._position.Z + with._size.Z)
+ return false;
+ if (_position.Z + _size.Z <= with._position.Z)
+ return false;
return true;
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/> is on both sides of <paramref name="plane"/>.
+ /// Returns <see langword="true"/> if the <see cref="Aabb"/> is on both sides of <paramref name="plane"/>.
/// </summary>
/// <param name="plane">The <see cref="Plane"/> to check for intersection.</param>
/// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the <see cref="Plane"/>.
+ /// 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 =
{
- new Vector3(_position.x, _position.y, _position.z),
- new Vector3(_position.x, _position.y, _position.z + _size.z),
- new Vector3(_position.x, _position.y + _size.y, _position.z),
- new Vector3(_position.x, _position.y + _size.y, _position.z + _size.z),
- new Vector3(_position.x + _size.x, _position.y, _position.z),
- new Vector3(_position.x + _size.x, _position.y, _position.z + _size.z),
- new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z),
- new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z + _size.z)
+ new Vector3(_position.X, _position.Y, _position.Z),
+ new Vector3(_position.X, _position.Y, _position.Z + _size.Z),
+ new Vector3(_position.X, _position.Y + _size.Y, _position.Z),
+ new Vector3(_position.X, _position.Y + _size.Y, _position.Z + _size.Z),
+ new Vector3(_position.X + _size.X, _position.Y, _position.Z),
+ new Vector3(_position.X + _size.X, _position.Y, _position.Z + _size.Z),
+ new Vector3(_position.X + _size.X, _position.Y + _size.Y, _position.Z),
+ new Vector3(_position.X + _size.X, _position.Y + _size.Y, _position.Z + _size.Z)
};
bool over = false;
@@ -523,15 +500,15 @@ namespace Godot
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/> intersects
+ /// Returns <see langword="true"/> if the <see cref="Aabb"/> intersects
/// the line segment between <paramref name="from"/> and <paramref name="to"/>.
/// </summary>
/// <param name="from">The start of the line segment.</param>
/// <param name="to">The end of the line segment.</param>
/// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the line segment.
+ /// 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;
@@ -586,73 +563,83 @@ namespace Godot
}
/// <summary>
- /// Returns a larger <see cref="AABB"/> that contains this <see cref="AABB"/> and <paramref name="with"/>.
+ /// Returns <see langword="true"/> if this <see cref="Aabb"/> is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return _position.IsFinite() && _size.IsFinite();
+ }
+
+ /// <summary>
+ /// Returns a larger <see cref="Aabb"/> that contains this <see cref="Aabb"/> and <paramref name="with"/>.
/// </summary>
- /// <param name="with">The other <see cref="AABB"/>.</param>
- /// <returns>The merged <see cref="AABB"/>.</returns>
- public AABB Merge(AABB with)
+ /// <param name="with">The other <see cref="Aabb"/>.</param>
+ /// <returns>The merged <see cref="Aabb"/>.</returns>
+ public readonly Aabb Merge(Aabb with)
{
Vector3 beg1 = _position;
Vector3 beg2 = with._position;
- var end1 = new Vector3(_size.x, _size.y, _size.z) + beg1;
- var end2 = new Vector3(with._size.x, with._size.y, with._size.z) + beg2;
+ var end1 = new Vector3(_size.X, _size.Y, _size.Z) + beg1;
+ var end2 = new Vector3(with._size.X, with._size.Y, with._size.Z) + beg2;
var min = new Vector3(
- beg1.x < beg2.x ? beg1.x : beg2.x,
- beg1.y < beg2.y ? beg1.y : beg2.y,
- beg1.z < beg2.z ? beg1.z : beg2.z
+ beg1.X < beg2.X ? beg1.X : beg2.X,
+ beg1.Y < beg2.Y ? beg1.Y : beg2.Y,
+ beg1.Z < beg2.Z ? beg1.Z : beg2.Z
);
var max = new Vector3(
- end1.x > end2.x ? end1.x : end2.x,
- end1.y > end2.y ? end1.y : end2.y,
- end1.z > end2.z ? end1.z : end2.z
+ end1.X > end2.X ? end1.X : end2.X,
+ end1.Y > end2.Y ? end1.Y : end2.Y,
+ end1.Z > end2.Z ? end1.Z : end2.Z
);
- return new AABB(min, max - min);
+ return new Aabb(min, max - min);
}
/// <summary>
- /// Constructs an <see cref="AABB"/> from a position and size.
+ /// Constructs an <see cref="Aabb"/> from a position and size.
/// </summary>
/// <param name="position">The position.</param>
/// <param name="size">The size, typically positive.</param>
- public AABB(Vector3 position, Vector3 size)
+ public Aabb(Vector3 position, Vector3 size)
{
_position = position;
_size = size;
}
/// <summary>
- /// Constructs an <see cref="AABB"/> from a <paramref name="position"/>,
+ /// Constructs an <see cref="Aabb"/> from a <paramref name="position"/>,
/// <paramref name="width"/>, <paramref name="height"/>, and <paramref name="depth"/>.
/// </summary>
/// <param name="position">The position.</param>
/// <param name="width">The width, typically positive.</param>
/// <param name="height">The height, typically positive.</param>
/// <param name="depth">The depth, typically positive.</param>
- public AABB(Vector3 position, real_t width, real_t height, real_t depth)
+ public Aabb(Vector3 position, real_t width, real_t height, real_t depth)
{
_position = position;
_size = new Vector3(width, height, depth);
}
/// <summary>
- /// Constructs an <see cref="AABB"/> from <paramref name="x"/>,
+ /// Constructs an <see cref="Aabb"/> from <paramref name="x"/>,
/// <paramref name="y"/>, <paramref name="z"/>, and <paramref name="size"/>.
/// </summary>
/// <param name="x">The position's X coordinate.</param>
/// <param name="y">The position's Y coordinate.</param>
/// <param name="z">The position's Z coordinate.</param>
/// <param name="size">The size, typically positive.</param>
- public AABB(real_t x, real_t y, real_t z, Vector3 size)
+ public Aabb(real_t x, real_t y, real_t z, Vector3 size)
{
_position = new Vector3(x, y, z);
_size = size;
}
/// <summary>
- /// Constructs an <see cref="AABB"/> from <paramref name="x"/>,
+ /// Constructs an <see cref="Aabb"/> from <paramref name="x"/>,
/// <paramref name="y"/>, <paramref name="z"/>, <paramref name="width"/>,
/// <paramref name="height"/>, and <paramref name="depth"/>.
/// </summary>
@@ -662,7 +649,7 @@ namespace Godot
/// <param name="width">The width, typically positive.</param>
/// <param name="height">The height, typically positive.</param>
/// <param name="depth">The depth, typically positive.</param>
- public AABB(real_t x, real_t y, real_t z, real_t width, real_t height, real_t depth)
+ public Aabb(real_t x, real_t y, real_t z, real_t width, real_t height, real_t depth)
{
_position = new Vector3(x, y, z);
_size = new Vector3(width, height, depth);
@@ -676,7 +663,7 @@ namespace Godot
/// <param name="left">The left AABB.</param>
/// <param name="right">The right AABB.</param>
/// <returns>Whether or not the AABBs are exactly equal.</returns>
- public static bool operator ==(AABB left, AABB right)
+ public static bool operator ==(Aabb left, Aabb right)
{
return left.Equals(right);
}
@@ -689,7 +676,7 @@ namespace Godot
/// <param name="left">The left AABB.</param>
/// <param name="right">The right AABB.</param>
/// <returns>Whether or not the AABBs are not equal.</returns>
- public static bool operator !=(AABB left, AABB right)
+ public static bool operator !=(Aabb left, Aabb right)
{
return !left.Equals(right);
}
@@ -702,9 +689,9 @@ 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);
+ return obj is Aabb other && Equals(other);
}
/// <summary>
@@ -714,7 +701,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,34 +712,34 @@ 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);
}
/// <summary>
- /// Serves as the hash function for <see cref="AABB"/>.
+ /// 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();
}
/// <summary>
- /// Converts this <see cref="AABB"/> to a string.
+ /// 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}";
}
/// <summary>
- /// Converts this <see cref="AABB"/> to a string with the given <paramref name="format"/>.
+ /// 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/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index f1b46e293b..8598c32760 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using System.Runtime.CompilerServices;
using Godot.NativeInterop;
@@ -99,7 +100,7 @@ namespace Godot.Collections
this[i] = array[i];
}
- public Array(Span<RID> array) : this()
+ public Array(Span<Rid> array) : this()
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -120,7 +121,7 @@ namespace Godot.Collections
// fine as long as the array is not mutated. However, Span does this type checking at
// instantiation, so it's not possible to use it even when not mutating anything.
// ReSharper disable once RedundantNameQualifier
- public Array(ReadOnlySpan<Godot.Object> array) : this()
+ public Array(ReadOnlySpan<GodotObject> array) : this()
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -174,7 +175,15 @@ namespace Godot.Collections
}
/// <summary>
- /// Duplicates this <see cref="Array"/>.
+ /// Returns a copy of the <see cref="Array"/>.
+ /// If <paramref name="deep"/> is <see langword="true"/>, a deep copy if performed:
+ /// all nested arrays and dictionaries are duplicated and will not be shared with
+ /// the original array. If <see langword="false"/>, a shallow copy is made and
+ /// references to the original nested arrays and dictionaries are kept, so that
+ /// modifying a sub-array or dictionary in the copy will also impact those
+ /// referenced in the source array. Note that any <see cref="GodotObject"/> derived
+ /// elements will be shallow copied regardless of the <paramref name="deep"/>
+ /// setting.
/// </summary>
/// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
/// <returns>A new Godot Array.</returns>
@@ -187,27 +196,247 @@ namespace Godot.Collections
}
/// <summary>
- /// Resizes this <see cref="Array"/> to the given size.
+ /// Assigns the given value to all elements in the array. This can typically be
+ /// used together with <see cref="Resize(int)"/> to create an array with a given
+ /// size and initialized elements.
+ /// Note: If <paramref name="value"/> is of a reference type (<see cref="GodotObject"/>
+ /// derived, <see cref="Array"/> or <see cref="Dictionary"/>, etc.) then the array
+ /// is filled with the references to the same object, i.e. no duplicates are
+ /// created.
/// </summary>
+ /// <example>
+ /// <code>
+ /// var array = new Godot.Collections.Array();
+ /// array.Resize(10);
+ /// array.Fill(0); // Initialize the 10 elements to 0.
+ /// </code>
+ /// </example>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <param name="value">The value to fill the array with.</param>
+ public void Fill(Variant value)
+ {
+ ThrowIfReadOnly();
+
+ godot_variant variantValue = (godot_variant)value.NativeVar;
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_fill(ref self, variantValue);
+ }
+
+ /// <summary>
+ /// Returns the maximum value contained in the array if all elements are of
+ /// comparable types. If the elements can't be compared, <see langword="null"/>
+ /// is returned.
+ /// </summary>
+ /// <returns>The maximum value contained in the array.</returns>
+ public Variant Max()
+ {
+ godot_variant resVariant;
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_max(ref self, out resVariant);
+ return Variant.CreateTakingOwnershipOfDisposableValue(resVariant);
+ }
+
+ /// <summary>
+ /// Returns the minimum value contained in the array if all elements are of
+ /// comparable types. If the elements can't be compared, <see langword="null"/>
+ /// is returned.
+ /// </summary>
+ /// <returns>The minimum value contained in the array.</returns>
+ public Variant Min()
+ {
+ godot_variant resVariant;
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_min(ref self, out resVariant);
+ return Variant.CreateTakingOwnershipOfDisposableValue(resVariant);
+ }
+
+ /// <summary>
+ /// Returns a random value from the target array.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var array = new Godot.Collections.Array { 1, 2, 3, 4 };
+ /// GD.Print(array.PickRandom()); // Prints either of the four numbers.
+ /// </code>
+ /// </example>
+ /// <returns>A random element from the array.</returns>
+ public Variant PickRandom()
+ {
+ godot_variant resVariant;
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_pick_random(ref self, out resVariant);
+ return Variant.CreateTakingOwnershipOfDisposableValue(resVariant);
+ }
+
+ /// <summary>
+ /// Compares this <see cref="Array"/> against the <paramref name="other"/>
+ /// <see cref="Array"/> recursively. Returns <see langword="true"/> if the
+ /// sizes and contents of the arrays are equal, <see langword="false"/>
+ /// otherwise.
+ /// </summary>
+ /// <param name="other">The other array to compare against.</param>
+ /// <returns>
+ /// <see langword="true"/> if the sizes and contents of the arrays are equal,
+ /// <see langword="false"/> otherwise.
+ /// </returns>
+ public bool RecursiveEqual(Array other)
+ {
+ var self = (godot_array)NativeValue;
+ var otherVariant = (godot_array)other.NativeValue;
+ return NativeFuncs.godotsharp_array_recursive_equal(ref self, otherVariant).ToBool();
+ }
+
+ /// <summary>
+ /// Resizes the array to contain a different number of elements. If the array
+ /// size is smaller, elements are cleared, if bigger, new elements are
+ /// <see langword="null"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
/// <param name="newSize">The new size of the array.</param>
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
public Error Resize(int newSize)
{
+ ThrowIfReadOnly();
+
var self = (godot_array)NativeValue;
return NativeFuncs.godotsharp_array_resize(ref self, newSize);
}
/// <summary>
- /// Shuffles the contents of this <see cref="Array"/> into a random order.
+ /// Reverses the order of the elements in the array.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ public void Reverse()
+ {
+ ThrowIfReadOnly();
+
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_reverse(ref self);
+ }
+
+ /// <summary>
+ /// Shuffles the array such that the items will have a random order.
+ /// This method uses the global random number generator common to methods
+ /// such as <see cref="GD.Randi"/>. Call <see cref="GD.Randomize"/> to
+ /// ensure that a new seed will be used each time if you want
+ /// non-reproducible shuffling.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
public void Shuffle()
{
+ ThrowIfReadOnly();
+
var self = (godot_array)NativeValue;
NativeFuncs.godotsharp_array_shuffle(ref self);
}
/// <summary>
- /// Concatenates these two <see cref="Array"/>s.
+ /// Creates a shallow copy of a range of elements in the source <see cref="Array"/>.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="start"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="start">The zero-based index at which the range starts.</param>
+ /// <returns>A new array that contains the elements inside the slice range.</returns>
+ public Array Slice(int start)
+ {
+ if (start < 0 || start > Count)
+ throw new ArgumentOutOfRangeException(nameof(start));
+
+ return GetSliceRange(start, Count, step: 1, deep: false);
+ }
+
+ /// <summary>
+ /// Creates a shallow copy of a range of elements in the source <see cref="Array"/>.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="start"/> is less than 0 or greater than the array's size.
+ /// -or-
+ /// <paramref name="length"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="start">The zero-based index at which the range starts.</param>
+ /// <param name="length">The length of the range.</param>
+ /// <returns>A new array that contains the elements inside the slice range.</returns>
+ // The Slice method must have this signature to get implicit Range support.
+ public Array Slice(int start, int length)
+ {
+ if (start < 0 || start > Count)
+ throw new ArgumentOutOfRangeException(nameof(start));
+
+ if (length < 0 || length > Count)
+ throw new ArgumentOutOfRangeException(nameof(start));
+
+ return GetSliceRange(start, start + length, step: 1, deep: false);
+ }
+
+ /// <summary>
+ /// Returns the slice of the <see cref="Array"/>, from <paramref name="start"/>
+ /// (inclusive) to <paramref name="end"/> (exclusive), as a new <see cref="Array"/>.
+ /// The absolute value of <paramref name="start"/> and <paramref name="end"/>
+ /// will be clamped to the array size.
+ /// If either <paramref name="start"/> or <paramref name="end"/> are negative, they
+ /// will be relative to the end of the array (i.e. <c>arr.GetSliceRange(0, -2)</c>
+ /// is a shorthand for <c>arr.GetSliceRange(0, arr.Count - 2)</c>).
+ /// If specified, <paramref name="step"/> is the relative index between source
+ /// elements. It can be negative, then <paramref name="start"/> must be higher than
+ /// <paramref name="end"/>. For example, <c>[0, 1, 2, 3, 4, 5].GetSliceRange(5, 1, -2)</c>
+ /// returns <c>[5, 3]</c>.
+ /// If <paramref name="deep"/> is true, each element will be copied by value
+ /// rather than by reference.
+ /// </summary>
+ /// <param name="start">The zero-based index at which the range starts.</param>
+ /// <param name="end">The zero-based index at which the range ends.</param>
+ /// <param name="step">The relative index between source elements to take.</param>
+ /// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
+ /// <returns>A new array that contains the elements inside the slice range.</returns>
+ public Array GetSliceRange(int start, int end, int step = 1, bool deep = false)
+ {
+ godot_array newArray;
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_slice(ref self, start, end, step, deep.ToGodotBool(), out newArray);
+ return CreateTakingOwnershipOfDisposableValue(newArray);
+ }
+
+ /// <summary>
+ /// Sorts the array.
+ /// Note: The sorting algorithm used is not stable. This means that values
+ /// considered equal may have their order changed when using <see cref="Sort"/>.
+ /// Note: Strings are sorted in alphabetical order (as opposed to natural order).
+ /// This may lead to unexpected behavior when sorting an array of strings ending
+ /// with a sequence of numbers.
+ /// To sort with a custom predicate use
+ /// <see cref="Enumerable.OrderBy{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/>.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var strings = new Godot.Collections.Array { "string1", "string2", "string10", "string11" };
+ /// strings.Sort();
+ /// GD.Print(strings); // Prints [string1, string10, string11, string2]
+ /// </code>
+ /// </example>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ public void Sort()
+ {
+ ThrowIfReadOnly();
+
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_sort(ref self);
+ }
+
+ /// <summary>
+ /// Concatenates two <see cref="Array"/>s together, with the <paramref name="right"/>
+ /// being added to the end of the <see cref="Array"/> specified in <paramref name="left"/>.
+ /// For example, <c>[1, 2] + [3, 4]</c> results in <c>[1, 2, 3, 4]</c>.
/// </summary>
/// <param name="left">The first array.</param>
/// <param name="right">The second array.</param>
@@ -240,6 +469,12 @@ namespace Godot.Collections
/// <summary>
/// Returns the item at the given <paramref name="index"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The property is assigned and the array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
/// <value>The <see cref="Variant"/> item at the given <paramref name="index"/>.</value>
public unsafe Variant this[int index]
{
@@ -250,8 +485,11 @@ namespace Godot.Collections
}
set
{
+ ThrowIfReadOnly();
+
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException(nameof(index));
+
var self = (godot_array)NativeValue;
godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref self);
godot_variant* itemPtr = &ptrw[index];
@@ -264,49 +502,271 @@ namespace Godot.Collections
/// Adds an item to the end of this <see cref="Array"/>.
/// This is the same as <c>append</c> or <c>push_back</c> in GDScript.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
/// <param name="item">The <see cref="Variant"/> item to add.</param>
public void Add(Variant item)
{
+ ThrowIfReadOnly();
+
godot_variant variantValue = (godot_variant)item.NativeVar;
var self = (godot_array)NativeValue;
_ = NativeFuncs.godotsharp_array_add(ref self, variantValue);
}
/// <summary>
- /// Checks if this <see cref="Array"/> contains the given item.
+ /// Adds the elements of the specified collection to the end of this <see cref="Array"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentNullException">
+ /// The <paramref name="collection"/> is <see langword="null"/>.
+ /// </exception>
+ /// <param name="collection">Collection of <see cref="Variant"/> items to add.</param>
+ public void AddRange<[MustBeVariant] T>(IEnumerable<T> collection)
+ {
+ ThrowIfReadOnly();
+
+ if (collection == null)
+ throw new ArgumentNullException(nameof(collection), "Value cannot be null.");
+
+ // If the collection is another Godot Array, we can add the items
+ // with a single interop call.
+ if (collection is Array array)
+ {
+ var self = (godot_array)NativeValue;
+ var collectionNative = (godot_array)array.NativeValue;
+ _ = NativeFuncs.godotsharp_array_add_range(ref self, collectionNative);
+ return;
+ }
+ if (collection is Array<T> typedArray)
+ {
+ var self = (godot_array)NativeValue;
+ var collectionNative = (godot_array)typedArray.NativeValue;
+ _ = NativeFuncs.godotsharp_array_add_range(ref self, collectionNative);
+ return;
+ }
+
+ // If we can retrieve the count of the collection without enumerating it
+ // (e.g.: the collections is a List<T>), use it to resize the array once
+ // instead of growing it as we add items.
+ if (collection.TryGetNonEnumeratedCount(out int count))
+ {
+ Resize(Count + count);
+
+ using var enumerator = collection.GetEnumerator();
+
+ for (int i = 0; i < count; i++)
+ {
+ enumerator.MoveNext();
+ this[count + i] = Variant.From(enumerator.Current);
+ }
+
+ return;
+ }
+
+ foreach (var item in collection)
+ {
+ Add(Variant.From(item));
+ }
+ }
+
+ /// <summary>
+ /// Finds the index of an existing value using binary search.
+ /// If the value is not present in the array, it returns the bitwise
+ /// complement of the insertion index that maintains sorting order.
+ /// Note: Calling <see cref="BinarySearch(int, int, Variant)"/> on an
+ /// unsorted array results in unexpected behavior.
/// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0.
+ /// -or-
+ /// <paramref name="count"/> is less than 0.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="index"/> and <paramref name="count"/> do not denote
+ /// a valid range in the <see cref="Array"/>.
+ /// </exception>
+ /// <param name="index">The starting index of the range to search.</param>
+ /// <param name="count">The length of the range to search.</param>
+ /// <param name="item">The object to locate.</param>
+ /// <returns>
+ /// The index of the item in the array, if <paramref name="item"/> is found;
+ /// otherwise, a negative number that is the bitwise complement of the index
+ /// of the next element that is larger than <paramref name="item"/> or, if
+ /// there is no larger element, the bitwise complement of <see cref="Count"/>.
+ /// </returns>
+ public int BinarySearch(int index, int count, Variant item)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), "index cannot be negative.");
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), "count cannot be negative.");
+ if (Count - index < count)
+ throw new ArgumentException("length is out of bounds or count is greater than the number of elements.");
+
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ godot_variant variantValue = (godot_variant)item.NativeVar;
+ var self = (godot_array)NativeValue;
+ return NativeFuncs.godotsharp_array_binary_search(ref self, index, count, variantValue);
+ }
+
+ /// <summary>
+ /// Finds the index of an existing value using binary search.
+ /// If the value is not present in the array, it returns the bitwise
+ /// complement of the insertion index that maintains sorting order.
+ /// Note: Calling <see cref="BinarySearch(Variant)"/> on an unsorted
+ /// array results in unexpected behavior.
+ /// </summary>
+ /// <param name="item">The object to locate.</param>
+ /// <returns>
+ /// The index of the item in the array, if <paramref name="item"/> is found;
+ /// otherwise, a negative number that is the bitwise complement of the index
+ /// of the next element that is larger than <paramref name="item"/> or, if
+ /// there is no larger element, the bitwise complement of <see cref="Count"/>.
+ /// </returns>
+ public int BinarySearch(Variant item)
+ {
+ return BinarySearch(0, Count, item);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the array contains the given value.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var arr = new Godot.Collections.Array { "inside", 7 };
+ /// GD.Print(arr.Contains("inside")); // True
+ /// GD.Print(arr.Contains("outside")); // False
+ /// GD.Print(arr.Contains(7)); // True
+ /// GD.Print(arr.Contains("7")); // False
+ /// </code>
+ /// </example>
/// <param name="item">The <see cref="Variant"/> item to look for.</param>
/// <returns>Whether or not this array contains the given item.</returns>
public bool Contains(Variant item) => IndexOf(item) != -1;
/// <summary>
- /// Erases all items from this <see cref="Array"/>.
+ /// Clears the array. This is the equivalent to using <see cref="Resize(int)"/>
+ /// with a size of <c>0</c>
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
public void Clear() => Resize(0);
/// <summary>
- /// Searches this <see cref="Array"/> for an item
- /// and returns its index or -1 if not found.
+ /// Searches the array for a value and returns its index or <c>-1</c> if not found.
/// </summary>
/// <param name="item">The <see cref="Variant"/> item to search for.</param>
/// <returns>The index of the item, or -1 if not found.</returns>
public int IndexOf(Variant item)
{
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
godot_variant variantValue = (godot_variant)item.NativeVar;
var self = (godot_array)NativeValue;
return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);
}
/// <summary>
- /// Inserts a new item at a given position in the array.
- /// The position must be a valid position of an existing item,
- /// or the position at the end of the array.
+ /// Searches the array for a value and returns its index or <c>-1</c> if not found.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="item">The <see cref="Variant"/> item to search for.</param>
+ /// <param name="index">The initial search index to start from.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
+ public int IndexOf(Variant item, int index)
+ {
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ godot_variant variantValue = (godot_variant)item.NativeVar;
+ var self = (godot_array)NativeValue;
+ return NativeFuncs.godotsharp_array_index_of(ref self, variantValue, index);
+ }
+
+ /// <summary>
+ /// Searches the array for a value in reverse order and returns its index
+ /// or <c>-1</c> if not found.
+ /// </summary>
+ /// <param name="item">The <see cref="Variant"/> item to search for.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
+ public int LastIndexOf(Variant item)
+ {
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ godot_variant variantValue = (godot_variant)item.NativeVar;
+ var self = (godot_array)NativeValue;
+ return NativeFuncs.godotsharp_array_last_index_of(ref self, variantValue, Count - 1);
+ }
+
+ /// <summary>
+ /// Searches the array for a value in reverse order and returns its index
+ /// or <c>-1</c> if not found.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="item">The <see cref="Variant"/> item to search for.</param>
+ /// <param name="index">The initial search index to start from.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
+ public int LastIndexOf(Variant item, int index)
+ {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ godot_variant variantValue = (godot_variant)item.NativeVar;
+ var self = (godot_array)NativeValue;
+ return NativeFuncs.godotsharp_array_last_index_of(ref self, variantValue, index);
+ }
+
+ /// <summary>
+ /// Inserts a new element at a given position in the array. The position
+ /// must be valid, or at the end of the array (<c>pos == Count - 1</c>).
/// Existing items will be moved to the right.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
/// <param name="index">The index to insert at.</param>
/// <param name="item">The <see cref="Variant"/> item to insert.</param>
public void Insert(int index, Variant item)
{
+ ThrowIfReadOnly();
+
if (index < 0 || index > Count)
throw new ArgumentOutOfRangeException(nameof(index));
@@ -319,9 +779,14 @@ namespace Godot.Collections
/// Removes the first occurrence of the specified <paramref name="item"/>
/// from this <see cref="Array"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
/// <param name="item">The value to remove.</param>
public bool Remove(Variant item)
{
+ ThrowIfReadOnly();
+
int index = IndexOf(item);
if (index >= 0)
{
@@ -333,11 +798,21 @@ namespace Godot.Collections
}
/// <summary>
- /// Removes an element from this <see cref="Array"/> by index.
+ /// Removes an element from the array by index.
+ /// To remove an element by searching for its value, use
+ /// <see cref="Remove(Variant)"/> instead.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
/// <param name="index">The index of the element to remove.</param>
public void RemoveAt(int index)
{
+ ThrowIfReadOnly();
+
if (index < 0 || index > Count)
throw new ArgumentOutOfRangeException(nameof(index));
@@ -358,12 +833,36 @@ namespace Godot.Collections
object ICollection.SyncRoot => false;
- bool ICollection<Variant>.IsReadOnly => false;
+ /// <summary>
+ /// Returns <see langword="true"/> if the array is read-only.
+ /// See <see cref="MakeReadOnly"/>.
+ /// </summary>
+ public bool IsReadOnly => NativeValue.DangerousSelfRef.IsReadOnly;
+
+ /// <summary>
+ /// Makes the <see cref="Array"/> read-only, i.e. disabled modying of the
+ /// array's elements. Does not apply to nested content, e.g. content of
+ /// nested arrays.
+ /// </summary>
+ public void MakeReadOnly()
+ {
+ if (IsReadOnly)
+ {
+ // Avoid interop call when the array is already read-only.
+ return;
+ }
+
+ var self = (godot_array)NativeValue;
+ NativeFuncs.godotsharp_array_make_read_only(ref self);
+ }
/// <summary>
/// Copies the elements of this <see cref="Array"/> to the given
/// <see cref="Variant"/> C# array, starting at the given index.
/// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="arrayIndex"/> is less than 0 or greater than the array's size.
+ /// </exception>
/// <param name="array">The array to copy to.</param>
/// <param name="arrayIndex">The index to start at.</param>
public void CopyTo(Variant[] array, int arrayIndex)
@@ -418,8 +917,8 @@ namespace Godot.Collections
{
for (int i = 0; i < count; i++)
{
- object obj = Marshaling.ConvertVariantToManagedObject(NativeValue.DangerousSelfRef.Elements[i]);
- array.SetValue(obj, index);
+ object boxedVariant = Variant.CreateCopyingBorrowed(NativeValue.DangerousSelfRef.Elements[i]);
+ array.SetValue(boxedVariant, index);
index++;
}
}
@@ -458,6 +957,9 @@ namespace Godot.Collections
/// <summary>
/// The variant returned via the <paramref name="elem"/> parameter is owned by the Array and must not be disposed.
/// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
internal void GetVariantBorrowElementAt(int index, out godot_variant elem)
{
if (index < 0 || index >= Count)
@@ -472,6 +974,19 @@ namespace Godot.Collections
{
elem = NativeValue.DangerousSelfRef.Elements[index];
}
+
+ private void ThrowIfReadOnly()
+ {
+ if (IsReadOnly)
+ {
+ throw new InvalidOperationException("Array instance is read-only.");
+ }
+ }
+ }
+
+ internal interface IGenericGodotArray
+ {
+ public Array UnderlyingArray { get; }
}
/// <summary>
@@ -487,47 +1002,25 @@ namespace Godot.Collections
IList<T>,
IReadOnlyList<T>,
ICollection<T>,
- IEnumerable<T>
+ IEnumerable<T>,
+ IGenericGodotArray
{
private static godot_variant ToVariantFunc(in Array<T> godotArray) =>
VariantUtils.CreateFromArray(godotArray);
private static Array<T> FromVariantFunc(in godot_variant variant) =>
- VariantUtils.ConvertToArrayObject<T>(variant);
-
- // ReSharper disable StaticMemberInGenericType
- // Warning is about unique static fields being created for each generic type combination:
- // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
- // In our case this is exactly what we want.
-
- private static readonly unsafe delegate* managed<in T, godot_variant> ConvertToVariantCallback;
- private static readonly unsafe delegate* managed<in godot_variant, T> ConvertToManagedCallback;
-
- // ReSharper restore StaticMemberInGenericType
+ VariantUtils.ConvertToArray<T>(variant);
static unsafe Array()
{
- VariantConversionCallbacks.GenericConversionCallbacks[typeof(Array<T>)] =
- (
- (IntPtr)(delegate* managed<in Array<T>, godot_variant>)&ToVariantFunc,
- (IntPtr)(delegate* managed<in godot_variant, Array<T>>)&FromVariantFunc
- );
-
- ConvertToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<T>();
- ConvertToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<T>();
- }
-
- private static unsafe void ValidateVariantConversionCallbacks()
- {
- if (ConvertToVariantCallback == null || ConvertToManagedCallback == null)
- {
- throw new InvalidOperationException(
- $"The array element type is not supported for conversion to Variant: '{typeof(T).FullName}'.");
- }
+ VariantUtils.GenericConversion<Array<T>>.ToVariantCb = &ToVariantFunc;
+ VariantUtils.GenericConversion<Array<T>>.FromVariantCb = &FromVariantFunc;
}
private readonly Array _underlyingArray;
+ Array IGenericGodotArray.UnderlyingArray => _underlyingArray;
+
internal ref godot_array.movable NativeValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -539,8 +1032,6 @@ namespace Godot.Collections
/// </summary>
public Array()
{
- ValidateVariantConversionCallbacks();
-
_underlyingArray = new Array();
}
@@ -551,8 +1042,6 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(IEnumerable<T> collection)
{
- ValidateVariantConversionCallbacks();
-
if (collection == null)
throw new ArgumentNullException(nameof(collection));
@@ -569,8 +1058,6 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(T[] array) : this()
{
- ValidateVariantConversionCallbacks();
-
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -586,8 +1073,6 @@ namespace Godot.Collections
/// <param name="array">The untyped array to construct from.</param>
public Array(Array array)
{
- ValidateVariantConversionCallbacks();
-
_underlyingArray = array;
}
@@ -615,8 +1100,102 @@ namespace Godot.Collections
}
/// <summary>
+ /// Assigns the given value to all elements in the array. This can typically be
+ /// used together with <see cref="Resize(int)"/> to create an array with a given
+ /// size and initialized elements.
+ /// Note: If <paramref name="value"/> is of a reference type (<see cref="GodotObject"/>
+ /// derived, <see cref="Array"/> or <see cref="Dictionary"/>, etc.) then the array
+ /// is filled with the references to the same object, i.e. no duplicates are
+ /// created.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var array = new Godot.Collections.Array&lt;int&gt;();
+ /// array.Resize(10);
+ /// array.Fill(0); // Initialize the 10 elements to 0.
+ /// </code>
+ /// </example>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <param name="value">The value to fill the array with.</param>
+ public void Fill(T value)
+ {
+ ThrowIfReadOnly();
+
+ godot_variant variantValue = VariantUtils.CreateFrom(value);
+ var self = (godot_array)_underlyingArray.NativeValue;
+ NativeFuncs.godotsharp_array_fill(ref self, variantValue);
+ }
+
+ /// <summary>
+ /// Returns the maximum value contained in the array if all elements are of
+ /// comparable types. If the elements can't be compared, <see langword="default"/>
+ /// is returned.
+ /// </summary>
+ /// <returns>The maximum value contained in the array.</returns>
+ public T Max()
+ {
+ godot_variant resVariant;
+ var self = (godot_array)_underlyingArray.NativeValue;
+ NativeFuncs.godotsharp_array_max(ref self, out resVariant);
+ return VariantUtils.ConvertTo<T>(resVariant);
+ }
+
+ /// <summary>
+ /// Returns the minimum value contained in the array if all elements are of
+ /// comparable types. If the elements can't be compared, <see langword="default"/>
+ /// is returned.
+ /// </summary>
+ /// <returns>The minimum value contained in the array.</returns>
+ public T Min()
+ {
+ godot_variant resVariant;
+ var self = (godot_array)_underlyingArray.NativeValue;
+ NativeFuncs.godotsharp_array_min(ref self, out resVariant);
+ return VariantUtils.ConvertTo<T>(resVariant);
+ }
+
+ /// <summary>
+ /// Returns a random value from the target array.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var array = new Godot.Collections.Array&lt;int&gt; { 1, 2, 3, 4 };
+ /// GD.Print(array.PickRandom()); // Prints either of the four numbers.
+ /// </code>
+ /// </example>
+ /// <returns>A random element from the array.</returns>
+ public T PickRandom()
+ {
+ godot_variant resVariant;
+ var self = (godot_array)_underlyingArray.NativeValue;
+ NativeFuncs.godotsharp_array_pick_random(ref self, out resVariant);
+ return VariantUtils.ConvertTo<T>(resVariant);
+ }
+
+ /// <summary>
+ /// Compares this <see cref="Array{T}"/> against the <paramref name="other"/>
+ /// <see cref="Array{T}"/> recursively. Returns <see langword="true"/> if the
+ /// sizes and contents of the arrays are equal, <see langword="false"/>
+ /// otherwise.
+ /// </summary>
+ /// <param name="other">The other array to compare against.</param>
+ /// <returns>
+ /// <see langword="true"/> if the sizes and contents of the arrays are equal,
+ /// <see langword="false"/> otherwise.
+ /// </returns>
+ public bool RecursiveEqual(Array<T> other)
+ {
+ return _underlyingArray.RecursiveEqual(other._underlyingArray);
+ }
+
+ /// <summary>
/// Resizes this <see cref="Array{T}"/> to the given size.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
/// <param name="newSize">The new size of the array.</param>
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
public Error Resize(int newSize)
@@ -625,15 +1204,115 @@ namespace Godot.Collections
}
/// <summary>
- /// Shuffles the contents of this <see cref="Array{T}"/> into a random order.
+ /// Reverses the order of the elements in the array.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ public void Reverse()
+ {
+ _underlyingArray.Reverse();
+ }
+
+ /// <summary>
+ /// Shuffles the array such that the items will have a random order.
+ /// This method uses the global random number generator common to methods
+ /// such as <see cref="GD.Randi"/>. Call <see cref="GD.Randomize"/> to
+ /// ensure that a new seed will be used each time if you want
+ /// non-reproducible shuffling.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
public void Shuffle()
{
_underlyingArray.Shuffle();
}
/// <summary>
- /// Concatenates these two <see cref="Array{T}"/>s.
+ /// Creates a shallow copy of a range of elements in the source <see cref="Array{T}"/>.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="start"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="start">The zero-based index at which the range starts.</param>
+ /// <returns>A new array that contains the elements inside the slice range.</returns>
+ public Array<T> Slice(int start)
+ {
+ return GetSliceRange(start, Count, step: 1, deep: false);
+ }
+
+ /// <summary>
+ /// Creates a shallow copy of a range of elements in the source <see cref="Array{T}"/>.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="start"/> is less than 0 or greater than the array's size.
+ /// -or-
+ /// <paramref name="length"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="start">The zero-based index at which the range starts.</param>
+ /// <param name="length">The length of the range.</param>
+ /// <returns>A new array that contains the elements inside the slice range.</returns>
+ // The Slice method must have this signature to get implicit Range support.
+ public Array<T> Slice(int start, int length)
+ {
+ return GetSliceRange(start, start + length, step: 1, deep: false);
+ }
+
+ /// <summary>
+ /// Returns the slice of the <see cref="Array{T}"/>, from <paramref name="start"/>
+ /// (inclusive) to <paramref name="end"/> (exclusive), as a new <see cref="Array{T}"/>.
+ /// The absolute value of <paramref name="start"/> and <paramref name="end"/>
+ /// will be clamped to the array size.
+ /// If either <paramref name="start"/> or <paramref name="end"/> are negative, they
+ /// will be relative to the end of the array (i.e. <c>arr.GetSliceRange(0, -2)</c>
+ /// is a shorthand for <c>arr.GetSliceRange(0, arr.Count - 2)</c>).
+ /// If specified, <paramref name="step"/> is the relative index between source
+ /// elements. It can be negative, then <paramref name="start"/> must be higher than
+ /// <paramref name="end"/>. For example, <c>[0, 1, 2, 3, 4, 5].GetSliceRange(5, 1, -2)</c>
+ /// returns <c>[5, 3]</c>.
+ /// If <paramref name="deep"/> is true, each element will be copied by value
+ /// rather than by reference.
+ /// </summary>
+ /// <param name="start">The zero-based index at which the range starts.</param>
+ /// <param name="end">The zero-based index at which the range ends.</param>
+ /// <param name="step">The relative index between source elements to take.</param>
+ /// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
+ /// <returns>A new array that contains the elements inside the slice range.</returns>
+ public Array<T> GetSliceRange(int start, int end, int step = 1, bool deep = false)
+ {
+ return new Array<T>(_underlyingArray.GetSliceRange(start, end, step, deep));
+ }
+
+ /// <summary>
+ /// Sorts the array.
+ /// Note: The sorting algorithm used is not stable. This means that values
+ /// considered equal may have their order changed when using <see cref="Sort"/>.
+ /// Note: Strings are sorted in alphabetical order (as opposed to natural order).
+ /// This may lead to unexpected behavior when sorting an array of strings ending
+ /// with a sequence of numbers.
+ /// To sort with a custom predicate use
+ /// <see cref="Enumerable.OrderBy{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/>.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var strings = new Godot.Collections.Array&lt;string&gt; { "string1", "string2", "string10", "string11" };
+ /// strings.Sort();
+ /// GD.Print(strings); // Prints [string1, string10, string11, string2]
+ /// </code>
+ /// </example>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ public void Sort()
+ {
+ _underlyingArray.Sort();
+ }
+
+ /// <summary>
+ /// Concatenates two <see cref="Array{T}"/>s together, with the <paramref name="right"/>
+ /// being added to the end of the <see cref="Array{T}"/> specified in <paramref name="left"/>.
+ /// For example, <c>[1, 2] + [3, 4]</c> results in <c>[1, 2, 3, 4]</c>.
/// </summary>
/// <param name="left">The first array.</param>
/// <param name="right">The second array.</param>
@@ -657,62 +1336,161 @@ namespace Godot.Collections
// IList<T>
/// <summary>
- /// Returns the value at the given <paramref name="index"/>.
+ /// Returns the item at the given <paramref name="index"/>.
/// </summary>
- /// <value>The value at the given <paramref name="index"/>.</value>
+ /// <exception cref="InvalidOperationException">
+ /// The property is assigned and the array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <value>The <see cref="Variant"/> item at the given <paramref name="index"/>.</value>
public unsafe T this[int index]
{
get
{
_underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem);
- return ConvertToManagedCallback(borrowElem);
+ return VariantUtils.ConvertTo<T>(borrowElem);
}
set
{
+ ThrowIfReadOnly();
+
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException(nameof(index));
+
var self = (godot_array)_underlyingArray.NativeValue;
godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref self);
godot_variant* itemPtr = &ptrw[index];
(*itemPtr).Dispose();
- *itemPtr = ConvertToVariantCallback(value);
+ *itemPtr = VariantUtils.CreateFrom(value);
}
}
/// <summary>
- /// Searches this <see cref="Array{T}"/> for an item
- /// and returns its index or -1 if not found.
+ /// Searches the array for a value and returns its index or <c>-1</c> if not found.
/// </summary>
- /// <param name="item">The item to search for.</param>
+ /// <param name="item">The <see cref="Variant"/> item to search for.</param>
/// <returns>The index of the item, or -1 if not found.</returns>
- public unsafe int IndexOf(T item)
+ public int IndexOf(T item)
{
- using var variantValue = ConvertToVariantCallback(item);
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ using var variantValue = VariantUtils.CreateFrom(item);
var self = (godot_array)_underlyingArray.NativeValue;
return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);
}
/// <summary>
- /// Inserts a new item at a given position in the <see cref="Array{T}"/>.
- /// The position must be a valid position of an existing item,
- /// or the position at the end of the array.
+ /// Searches the array for a value and returns its index or <c>-1</c> if not found.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="item">The <see cref="Variant"/> item to search for.</param>
+ /// <param name="index">The initial search index to start from.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
+ public int IndexOf(T item, int index)
+ {
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ godot_variant variantValue = VariantUtils.CreateFrom(item);
+ var self = (godot_array)_underlyingArray.NativeValue;
+ return NativeFuncs.godotsharp_array_index_of(ref self, variantValue, index);
+ }
+
+ /// <summary>
+ /// Searches the array for a value in reverse order and returns its index
+ /// or <c>-1</c> if not found.
+ /// </summary>
+ /// <param name="item">The <see cref="Variant"/> item to search for.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
+ public int LastIndexOf(Variant item)
+ {
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ godot_variant variantValue = VariantUtils.CreateFrom(item);
+ var self = (godot_array)_underlyingArray.NativeValue;
+ return NativeFuncs.godotsharp_array_last_index_of(ref self, variantValue, Count - 1);
+ }
+
+ /// <summary>
+ /// Searches the array for a value in reverse order and returns its index
+ /// or <c>-1</c> if not found.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
+ /// <param name="item">The <see cref="Variant"/> item to search for.</param>
+ /// <param name="index">The initial search index to start from.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
+ public int LastIndexOf(Variant item, int index)
+ {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ godot_variant variantValue = VariantUtils.CreateFrom(item);
+ var self = (godot_array)_underlyingArray.NativeValue;
+ return NativeFuncs.godotsharp_array_last_index_of(ref self, variantValue, index);
+ }
+
+ /// <summary>
+ /// Inserts a new element at a given position in the array. The position
+ /// must be valid, or at the end of the array (<c>pos == Count - 1</c>).
/// Existing items will be moved to the right.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
/// <param name="index">The index to insert at.</param>
- /// <param name="item">The item to insert.</param>
- public unsafe void Insert(int index, T item)
+ /// <param name="item">The <see cref="Variant"/> item to insert.</param>
+ public void Insert(int index, T item)
{
+ ThrowIfReadOnly();
+
if (index < 0 || index > Count)
throw new ArgumentOutOfRangeException(nameof(index));
- using var variantValue = ConvertToVariantCallback(item);
+ using var variantValue = VariantUtils.CreateFrom(item);
var self = (godot_array)_underlyingArray.NativeValue;
NativeFuncs.godotsharp_array_insert(ref self, index, variantValue);
}
/// <summary>
- /// Removes an element from this <see cref="Array{T}"/> by index.
+ /// Removes an element from the array by index.
+ /// To remove an element by searching for its value, use
+ /// <see cref="Remove(T)"/> instead.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0 or greater than the array's size.
+ /// </exception>
/// <param name="index">The index of the element to remove.</param>
public void RemoveAt(int index)
{
@@ -728,32 +1506,185 @@ namespace Godot.Collections
/// <returns>The number of elements.</returns>
public int Count => _underlyingArray.Count;
- bool ICollection<T>.IsReadOnly => false;
+ /// <summary>
+ /// Returns <see langword="true"/> if the array is read-only.
+ /// See <see cref="MakeReadOnly"/>.
+ /// </summary>
+ public bool IsReadOnly => _underlyingArray.IsReadOnly;
+
+ /// <summary>
+ /// Makes the <see cref="Array{T}"/> read-only, i.e. disabled modying of the
+ /// array's elements. Does not apply to nested content, e.g. content of
+ /// nested arrays.
+ /// </summary>
+ public void MakeReadOnly()
+ {
+ _underlyingArray.MakeReadOnly();
+ }
/// <summary>
/// Adds an item to the end of this <see cref="Array{T}"/>.
/// This is the same as <c>append</c> or <c>push_back</c> in GDScript.
/// </summary>
- /// <param name="item">The item to add.</param>
- /// <returns>The new size after adding the item.</returns>
- public unsafe void Add(T item)
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <param name="item">The <see cref="Variant"/> item to add.</param>
+ public void Add(T item)
{
- using var variantValue = ConvertToVariantCallback(item);
+ ThrowIfReadOnly();
+
+ using var variantValue = VariantUtils.CreateFrom(item);
var self = (godot_array)_underlyingArray.NativeValue;
_ = NativeFuncs.godotsharp_array_add(ref self, variantValue);
}
/// <summary>
- /// Erases all items from this <see cref="Array{T}"/>.
+ /// Adds the elements of the specified collection to the end of this <see cref="Array{T}"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentNullException">
+ /// The <paramref name="collection"/> is <see langword="null"/>.
+ /// </exception>
+ /// <param name="collection">Collection of <see cref="Variant"/> items to add.</param>
+ public void AddRange(IEnumerable<T> collection)
+ {
+ ThrowIfReadOnly();
+
+ if (collection == null)
+ throw new ArgumentNullException(nameof(collection), "Value cannot be null.");
+
+ // If the collection is another Godot Array, we can add the items
+ // with a single interop call.
+ if (collection is Array array)
+ {
+ var self = (godot_array)_underlyingArray.NativeValue;
+ var collectionNative = (godot_array)array.NativeValue;
+ _ = NativeFuncs.godotsharp_array_add_range(ref self, collectionNative);
+ return;
+ }
+ if (collection is Array<T> typedArray)
+ {
+ var self = (godot_array)_underlyingArray.NativeValue;
+ var collectionNative = (godot_array)typedArray._underlyingArray.NativeValue;
+ _ = NativeFuncs.godotsharp_array_add_range(ref self, collectionNative);
+ return;
+ }
+
+ // If we can retrieve the count of the collection without enumerating it
+ // (e.g.: the collections is a List<T>), use it to resize the array once
+ // instead of growing it as we add items.
+ if (collection.TryGetNonEnumeratedCount(out int count))
+ {
+ Resize(Count + count);
+
+ using var enumerator = collection.GetEnumerator();
+
+ for (int i = 0; i < count; i++)
+ {
+ enumerator.MoveNext();
+ this[count + i] = enumerator.Current;
+ }
+
+ return;
+ }
+
+ foreach (var item in collection)
+ {
+ Add(item);
+ }
+ }
+
+ /// <summary>
+ /// Finds the index of an existing value using binary search.
+ /// If the value is not present in the array, it returns the bitwise
+ /// complement of the insertion index that maintains sorting order.
+ /// Note: Calling <see cref="BinarySearch(int, int, T)"/> on an unsorted
+ /// array results in unexpected behavior.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is less than 0.
+ /// -or-
+ /// <paramref name="count"/> is less than 0.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="index"/> and <paramref name="count"/> do not denote
+ /// a valid range in the <see cref="Array{T}"/>.
+ /// </exception>
+ /// <param name="index">The starting index of the range to search.</param>
+ /// <param name="count">The length of the range to search.</param>
+ /// <param name="item">The object to locate.</param>
+ /// <returns>
+ /// The index of the item in the array, if <paramref name="item"/> is found;
+ /// otherwise, a negative number that is the bitwise complement of the index
+ /// of the next element that is larger than <paramref name="item"/> or, if
+ /// there is no larger element, the bitwise complement of <see cref="Count"/>.
+ /// </returns>
+ public int BinarySearch(int index, int count, T item)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), "index cannot be negative.");
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), "count cannot be negative.");
+ if (Count - index < count)
+ throw new ArgumentException("length is out of bounds or count is greater than the number of elements.");
+
+ if (Count == 0)
+ {
+ // Special case for empty array to avoid an interop call.
+ return -1;
+ }
+
+ using var variantValue = VariantUtils.CreateFrom(item);
+ var self = (godot_array)_underlyingArray.NativeValue;
+ return NativeFuncs.godotsharp_array_binary_search(ref self, index, count, variantValue);
+ }
+
+ /// <summary>
+ /// Finds the index of an existing value using binary search.
+ /// If the value is not present in the array, it returns the bitwise
+ /// complement of the insertion index that maintains sorting order.
+ /// Note: Calling <see cref="BinarySearch(T)"/> on an unsorted
+ /// array results in unexpected behavior.
+ /// </summary>
+ /// <param name="item">The object to locate.</param>
+ /// <returns>
+ /// The index of the item in the array, if <paramref name="item"/> is found;
+ /// otherwise, a negative number that is the bitwise complement of the index
+ /// of the next element that is larger than <paramref name="item"/> or, if
+ /// there is no larger element, the bitwise complement of <see cref="Count"/>.
+ /// </returns>
+ public int BinarySearch(T item)
+ {
+ return BinarySearch(0, Count, item);
+ }
+
+ /// <summary>
+ /// Clears the array. This is the equivalent to using <see cref="Resize(int)"/>
+ /// with a size of <c>0</c>
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
public void Clear()
{
_underlyingArray.Clear();
}
/// <summary>
- /// Checks if this <see cref="Array{T}"/> contains the given item.
+ /// Returns <see langword="true"/> if the array contains the given value.
/// </summary>
+ /// <example>
+ /// <code>
+ /// var arr = new Godot.Collections.Array&lt;string&gt; { "inside", "7" };
+ /// GD.Print(arr.Contains("inside")); // True
+ /// GD.Print(arr.Contains("outside")); // False
+ /// GD.Print(arr.Contains(7)); // False
+ /// GD.Print(arr.Contains("7")); // True
+ /// </code>
+ /// </example>
/// <param name="item">The item to look for.</param>
/// <returns>Whether or not this array contains the given item.</returns>
public bool Contains(T item) => IndexOf(item) != -1;
@@ -762,6 +1693,9 @@ namespace Godot.Collections
/// Copies the elements of this <see cref="Array{T}"/> to the given
/// C# array, starting at the given index.
/// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="arrayIndex"/> is less than 0 or greater than the array's size.
+ /// </exception>
/// <param name="array">The C# array to copy to.</param>
/// <param name="arrayIndex">The index to start at.</param>
public void CopyTo(T[] array, int arrayIndex)
@@ -791,13 +1725,18 @@ namespace Godot.Collections
}
/// <summary>
- /// Removes the first occurrence of the specified value
+ /// Removes the first occurrence of the specified <paramref name="item"/>
/// from this <see cref="Array{T}"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The array is read-only.
+ /// </exception>
/// <param name="item">The value to remove.</param>
/// <returns>A <see langword="bool"/> indicating success or failure.</returns>
public bool Remove(T item)
{
+ ThrowIfReadOnly();
+
int index = IndexOf(item);
if (index >= 0)
{
@@ -837,5 +1776,13 @@ namespace Godot.Collections
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Array<T>(Variant from) => from.AsGodotArray<T>();
+
+ private void ThrowIfReadOnly()
+ {
+ if (IsReadOnly)
+ {
+ throw new InvalidOperationException("Array instance is read-only.");
+ }
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
index b7d633517a..81659f74de 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
@@ -1,20 +1,32 @@
using System;
+using System.Diagnostics.CodeAnalysis;
#nullable enable
namespace Godot
{
/// <summary>
- /// An attribute that determines if an assembly has scripts. If so, what types of scripts the assembly has.
+ /// Attribute that determines that the assembly contains Godot scripts and, optionally, the
+ /// collection of types that implement scripts; otherwise, retrieving the types requires lookup.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly)]
- public class AssemblyHasScriptsAttribute : Attribute
+ public sealed class AssemblyHasScriptsAttribute : Attribute
{
+ /// <summary>
+ /// If the Godot scripts contained in the assembly require lookup
+ /// and can't rely on <see cref="ScriptTypes"/>.
+ /// </summary>
+ [MemberNotNullWhen(false, nameof(ScriptTypes))]
public bool RequiresLookup { get; }
+
+ /// <summary>
+ /// The collection of types that implement a Godot script.
+ /// </summary>
public Type[]? ScriptTypes { get; }
/// <summary>
- /// Constructs a new AssemblyHasScriptsAttribute instance.
+ /// Constructs a new AssemblyHasScriptsAttribute instance
+ /// that requires lookup to get the Godot scripts.
/// </summary>
public AssemblyHasScriptsAttribute()
{
@@ -23,9 +35,10 @@ namespace Godot
}
/// <summary>
- /// Constructs a new AssemblyHasScriptsAttribute instance.
+ /// Constructs a new AssemblyHasScriptsAttribute instance
+ /// that includes the Godot script types and requires no lookup.
/// </summary>
- /// <param name="scriptTypes">The specified type(s) of scripts.</param>
+ /// <param name="scriptTypes">The collection of types that implement a Godot script.</param>
public AssemblyHasScriptsAttribute(Type[] scriptTypes)
{
RequiresLookup = false;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
index 3d204bdf9f..a48d79091f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs
@@ -3,23 +3,30 @@ using System;
namespace Godot
{
/// <summary>
- /// An attribute used to export objects.
+ /// Exports the annotated member as a property of the Godot Object.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportAttribute : Attribute
{
- private PropertyHint hint;
- private string hintString;
+ /// <summary>
+ /// Optional hint that determines how the property should be handled by the editor.
+ /// </summary>
+ public PropertyHint Hint { get; }
+
+ /// <summary>
+ /// Optional string that can contain additional metadata for the <see cref="Hint"/>.
+ /// </summary>
+ public string HintString { get; }
/// <summary>
/// Constructs a new ExportAttribute Instance.
/// </summary>
- /// <param name="hint">A hint to the exported object.</param>
- /// <param name="hintString">A string representing the exported object.</param>
+ /// <param name="hint">The hint for the exported property.</param>
+ /// <param name="hintString">A string that may contain additional metadata for the hint.</param>
public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "")
{
- this.hint = hint;
- this.hintString = hintString;
+ Hint = hint;
+ HintString = hintString;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs
index 101e56f8d3..2ae55acd3e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs
@@ -8,7 +8,10 @@ namespace Godot
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportCategoryAttribute : Attribute
{
- private string name;
+ /// <summary>
+ /// Name of the category.
+ /// </summary>
+ public string Name { get; }
/// <summary>
/// Define a new category for the following exported properties.
@@ -16,7 +19,7 @@ namespace Godot
/// <param name="name">The name of the category.</param>
public ExportCategoryAttribute(string name)
{
- this.name = name;
+ Name = name;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs
index 3bd532cec1..82bd446640 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs
@@ -1,5 +1,7 @@
using System;
+#nullable enable
+
namespace Godot
{
/// <summary>
@@ -8,8 +10,15 @@ namespace Godot
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportGroupAttribute : Attribute
{
- private string name;
- private string prefix;
+ /// <summary>
+ /// Name of the group.
+ /// </summary>
+ public string Name { get; }
+
+ /// <summary>
+ /// If provided, the prefix that all properties must have to be considered part of the group.
+ /// </summary>
+ public string? Prefix { get; }
/// <summary>
/// Define a new group for the following exported properties.
@@ -18,8 +27,8 @@ namespace Godot
/// <param name="prefix">If provided, the group would make group to only consider properties that have this prefix.</param>
public ExportGroupAttribute(string name, string prefix = "")
{
- this.name = name;
- this.prefix = prefix;
+ Name = name;
+ Prefix = prefix;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs
index 2ae6eb0b68..3282b466f6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs
@@ -1,5 +1,7 @@
using System;
+#nullable enable
+
namespace Godot
{
/// <summary>
@@ -8,8 +10,15 @@ namespace Godot
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ExportSubgroupAttribute : Attribute
{
- private string name;
- private string prefix;
+ /// <summary>
+ /// Name of the subgroup.
+ /// </summary>
+ public string Name { get; }
+
+ /// <summary>
+ /// If provided, the prefix that all properties must have to be considered part of the subgroup.
+ /// </summary>
+ public string? Prefix { get; }
/// <summary>
/// Define a new subgroup for the following exported properties. This helps to organize properties in the Inspector dock.
@@ -18,8 +27,8 @@ namespace Godot
/// <param name="prefix">If provided, the subgroup would make group to only consider properties that have this prefix.</param>
public ExportSubgroupAttribute(string name, string prefix = "")
{
- this.name = name;
- this.prefix = prefix;
+ Name = name;
+ Prefix = prefix;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotClassNameAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotClassNameAttribute.cs
new file mode 100644
index 0000000000..b19427f60d
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotClassNameAttribute.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Godot
+{
+ /// <summary>
+ /// Attribute that specifies the engine class name when it's not the same
+ /// as the generated C# class name. This allows introspection code to find
+ /// the name associated with the class. If the attribute is not present,
+ /// the C# class name can be used instead.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class)]
+ public class GodotClassNameAttribute : Attribute
+ {
+ /// <summary>
+ /// Original engine class name.
+ /// </summary>
+ public string Name { get; }
+
+ public GodotClassNameAttribute(string name)
+ {
+ Name = name;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs
index 23088378d1..0070223c95 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs
@@ -7,5 +7,5 @@ namespace Godot
/// that can be marshaled from/to a <see cref="Variant"/>.
/// </summary>
[AttributeUsage(AttributeTargets.GenericParameter)]
- public class MustBeVariantAttribute : Attribute { }
+ public sealed class MustBeVariantAttribute : Attribute { }
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs
index fb37838ffa..6a73d6f70c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs
@@ -5,37 +5,37 @@ namespace Godot
/// <summary>
/// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>,
/// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers).
- /// See <see cref="MultiplayerAPI.RPCMode"/> and <see cref="MultiplayerPeer.TransferModeEnum"/>.
+ /// See <see cref="MultiplayerApi.RpcMode"/> and <see cref="MultiplayerPeer.TransferModeEnum"/>.
/// By default, methods are not exposed to networking (and RPCs).
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
- public class RPCAttribute : Attribute
+ public sealed class RpcAttribute : Attribute
{
/// <summary>
/// RPC mode for the annotated method.
/// </summary>
- public MultiplayerAPI.RPCMode Mode { get; } = MultiplayerAPI.RPCMode.Disabled;
+ public MultiplayerApi.RpcMode Mode { get; } = MultiplayerApi.RpcMode.Disabled;
/// <summary>
/// If the method will also be called locally; otherwise, it is only called remotely.
/// </summary>
- public bool CallLocal { get; set; } = false;
+ public bool CallLocal { get; init; } = false;
/// <summary>
/// Transfer mode for the annotated method.
/// </summary>
- public MultiplayerPeer.TransferModeEnum TransferMode { get; set; } = MultiplayerPeer.TransferModeEnum.Reliable;
+ public MultiplayerPeer.TransferModeEnum TransferMode { get; init; } = MultiplayerPeer.TransferModeEnum.Reliable;
/// <summary>
/// Transfer channel for the annotated mode.
/// </summary>
- public int TransferChannel { get; set; } = 0;
+ public int TransferChannel { get; init; } = 0;
/// <summary>
- /// Constructs a <see cref="RPCAttribute"/> instance.
+ /// Constructs a <see cref="RpcAttribute"/> instance.
/// </summary>
/// <param name="mode">The RPC mode to use.</param>
- public RPCAttribute(MultiplayerAPI.RPCMode mode = MultiplayerAPI.RPCMode.Authority)
+ public RpcAttribute(MultiplayerApi.RpcMode mode = MultiplayerApi.RpcMode.Authority)
{
Mode = mode;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
index 2c8a53ae1c..d363e14c5d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
@@ -6,8 +6,11 @@ namespace Godot
/// An attribute that contains the path to the object's script.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
- public class ScriptPathAttribute : Attribute
+ public sealed class ScriptPathAttribute : Attribute
{
+ /// <summary>
+ /// File path to the script.
+ /// </summary>
public string Path { get; }
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs
index 38e68a89d5..0a08bb5df8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs
@@ -3,5 +3,5 @@ using System;
namespace Godot
{
[AttributeUsage(AttributeTargets.Delegate)]
- public class SignalAttribute : Attribute { }
+ public sealed class SignalAttribute : Attribute { }
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ToolAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ToolAttribute.cs
index d2344389f4..4c56201727 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ToolAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ToolAttribute.cs
@@ -3,5 +3,5 @@ using System;
namespace Godot
{
[AttributeUsage(AttributeTargets.Class)]
- public class ToolAttribute : Attribute { }
+ public sealed class ToolAttribute : Attribute { }
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index bb1d6e1661..ca963cbf4f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -27,9 +27,9 @@ namespace Godot
/// The basis matrix's X vector (column 0).
/// </summary>
/// <value>Equivalent to <see cref="Column0"/> and array index <c>[0]</c>.</value>
- public Vector3 x
+ public Vector3 X
{
- get => Column0;
+ readonly get => Column0;
set => Column0 = value;
}
@@ -37,9 +37,9 @@ namespace Godot
/// The basis matrix's Y vector (column 1).
/// </summary>
/// <value>Equivalent to <see cref="Column1"/> and array index <c>[1]</c>.</value>
- public Vector3 y
+ public Vector3 Y
{
- get => Column1;
+ readonly get => Column1;
set => Column1 = value;
}
@@ -47,9 +47,9 @@ namespace Godot
/// The basis matrix's Z vector (column 2).
/// </summary>
/// <value>Equivalent to <see cref="Column2"/> and array index <c>[2]</c>.</value>
- public Vector3 z
+ public Vector3 Z
{
- get => Column2;
+ readonly get => Column2;
set => Column2 = value;
}
@@ -77,53 +77,53 @@ namespace Godot
/// <summary>
/// Column 0 of the basis matrix (the X vector).
/// </summary>
- /// <value>Equivalent to <see cref="x"/> and array index <c>[0]</c>.</value>
+ /// <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;
- Row1.x = value.y;
- Row2.x = value.z;
+ Row0.X = value.X;
+ Row1.X = value.Y;
+ Row2.X = value.Z;
}
}
/// <summary>
/// Column 1 of the basis matrix (the Y vector).
/// </summary>
- /// <value>Equivalent to <see cref="y"/> and array index <c>[1]</c>.</value>
+ /// <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;
- Row1.y = value.y;
- Row2.y = value.z;
+ Row0.Y = value.X;
+ Row1.Y = value.Y;
+ Row2.Y = value.Z;
}
}
/// <summary>
/// Column 2 of the basis matrix (the Z vector).
/// </summary>
- /// <value>Equivalent to <see cref="z"/> and array index <c>[2]</c>.</value>
+ /// <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;
- Row1.z = value.y;
- Row2.z = value.z;
+ Row0.Z = value.X;
+ Row1.Z = value.Y;
+ Row2.Z = value.Z;
}
}
/// <summary>
- /// The scale of this basis.
+ /// Assuming that the matrix is the combination of a rotation and scaling,
+ /// return the absolute value of scaling factors along each axis.
/// </summary>
- /// <value>Equivalent to the lengths of each column vector, but negative if the determinant is negative.</value>
- public Vector3 Scale
+ public readonly Vector3 Scale
{
get
{
@@ -135,13 +135,6 @@ namespace Godot
Column2.Length()
);
}
- set
- {
- value /= Scale; // Value becomes what's called "delta_scale" in core.
- Column0 *= value.x;
- Column1 *= value.y;
- Column2 *= value.z;
- }
}
/// <summary>
@@ -154,7 +147,7 @@ namespace Godot
/// <value>The basis column.</value>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -195,7 +188,7 @@ namespace Godot
/// <value>The matrix element.</value>
public real_t this[int column, int row]
{
- get
+ readonly get
{
return this[column][row];
}
@@ -220,9 +213,9 @@ namespace Godot
private void SetDiagonal(Vector3 diagonal)
{
- Row0 = new Vector3(diagonal.x, 0, 0);
- Row1 = new Vector3(0, diagonal.y, 0);
- Row2 = new Vector3(0, 0, diagonal.z);
+ Row0 = new Vector3(diagonal.X, 0, 0);
+ Row1 = new Vector3(0, diagonal.Y, 0);
+ Row2 = new Vector3(0, 0, diagonal.Z);
}
/// <summary>
@@ -234,7 +227,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 +248,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)
{
@@ -277,29 +270,29 @@ namespace Godot
if (Row1[0] == 0 && Row0[1] == 0 && Row1[2] == 0 && Row2[1] == 0 && Row1[1] == 1)
{
// return the simplest form (human friendlier in editor and scripts)
- euler.x = 0;
- euler.y = Mathf.Atan2(Row0[2], Row0[0]);
- euler.z = 0;
+ euler.X = 0;
+ euler.Y = Mathf.Atan2(Row0[2], Row0[0]);
+ euler.Z = 0;
}
else
{
- euler.x = Mathf.Atan2(-Row1[2], Row2[2]);
- euler.y = Mathf.Asin(sy);
- euler.z = Mathf.Atan2(-Row0[1], Row0[0]);
+ euler.X = Mathf.Atan2(-Row1[2], Row2[2]);
+ euler.Y = Mathf.Asin(sy);
+ euler.Z = Mathf.Atan2(-Row0[1], Row0[0]);
}
}
else
{
- euler.x = Mathf.Atan2(Row2[1], Row1[1]);
- euler.y = -Mathf.Tau / 4.0f;
- euler.z = 0.0f;
+ euler.X = Mathf.Atan2(Row2[1], Row1[1]);
+ euler.Y = -Mathf.Tau / 4.0f;
+ euler.Z = 0.0f;
}
}
else
{
- euler.x = Mathf.Atan2(Row2[1], Row1[1]);
- euler.y = Mathf.Tau / 4.0f;
- euler.z = 0.0f;
+ euler.X = Mathf.Atan2(Row2[1], Row1[1]);
+ euler.Y = Mathf.Tau / 4.0f;
+ euler.Z = 0.0f;
}
return euler;
}
@@ -317,24 +310,24 @@ namespace Godot
{
if (sz > -(1.0f - Mathf.Epsilon))
{
- euler.x = Mathf.Atan2(Row2[1], Row1[1]);
- euler.y = Mathf.Atan2(Row0[2], Row0[0]);
- euler.z = Mathf.Asin(-sz);
+ euler.X = Mathf.Atan2(Row2[1], Row1[1]);
+ euler.Y = Mathf.Atan2(Row0[2], Row0[0]);
+ euler.Z = Mathf.Asin(-sz);
}
else
{
// It's -1
- euler.x = -Mathf.Atan2(Row1[2], Row2[2]);
- euler.y = 0.0f;
- euler.z = Mathf.Tau / 4.0f;
+ euler.X = -Mathf.Atan2(Row1[2], Row2[2]);
+ euler.Y = 0.0f;
+ euler.Z = Mathf.Tau / 4.0f;
}
}
else
{
// It's 1
- euler.x = -Mathf.Atan2(Row1[2], Row2[2]);
- euler.y = 0.0f;
- euler.z = -Mathf.Tau / 4.0f;
+ euler.X = -Mathf.Atan2(Row1[2], Row2[2]);
+ euler.Y = 0.0f;
+ euler.Z = -Mathf.Tau / 4.0f;
}
return euler;
}
@@ -356,29 +349,29 @@ namespace Godot
if (Row1[0] == 0 && Row0[1] == 0 && Row0[2] == 0 && Row2[0] == 0 && Row0[0] == 1)
{
// return the simplest form (human friendlier in editor and scripts)
- euler.x = Mathf.Atan2(-m12, Row1[1]);
- euler.y = 0;
- euler.z = 0;
+ euler.X = Mathf.Atan2(-m12, Row1[1]);
+ euler.Y = 0;
+ euler.Z = 0;
}
else
{
- euler.x = Mathf.Asin(-m12);
- euler.y = Mathf.Atan2(Row0[2], Row2[2]);
- euler.z = Mathf.Atan2(Row1[0], Row1[1]);
+ euler.X = Mathf.Asin(-m12);
+ euler.Y = Mathf.Atan2(Row0[2], Row2[2]);
+ euler.Z = Mathf.Atan2(Row1[0], Row1[1]);
}
}
else
{ // m12 == -1
- euler.x = Mathf.Tau / 4.0f;
- euler.y = Mathf.Atan2(Row0[1], Row0[0]);
- euler.z = 0;
+ euler.X = Mathf.Tau / 4.0f;
+ euler.Y = Mathf.Atan2(Row0[1], Row0[0]);
+ euler.Z = 0;
}
}
else
{ // m12 == 1
- euler.x = -Mathf.Tau / 4.0f;
- euler.y = -Mathf.Atan2(Row0[1], Row0[0]);
- euler.z = 0;
+ euler.X = -Mathf.Tau / 4.0f;
+ euler.Y = -Mathf.Atan2(Row0[1], Row0[0]);
+ euler.Z = 0;
}
return euler;
@@ -397,24 +390,24 @@ namespace Godot
{
if (sz > -(1.0f - Mathf.Epsilon))
{
- euler.x = Mathf.Atan2(-Row1[2], Row1[1]);
- euler.y = Mathf.Atan2(-Row2[0], Row0[0]);
- euler.z = Mathf.Asin(sz);
+ euler.X = Mathf.Atan2(-Row1[2], Row1[1]);
+ euler.Y = Mathf.Atan2(-Row2[0], Row0[0]);
+ euler.Z = Mathf.Asin(sz);
}
else
{
// It's -1
- euler.x = Mathf.Atan2(Row2[1], Row2[2]);
- euler.y = 0.0f;
- euler.z = -Mathf.Tau / 4.0f;
+ euler.X = Mathf.Atan2(Row2[1], Row2[2]);
+ euler.Y = 0.0f;
+ euler.Z = -Mathf.Tau / 4.0f;
}
}
else
{
// It's 1
- euler.x = Mathf.Atan2(Row2[1], Row2[2]);
- euler.y = 0.0f;
- euler.z = Mathf.Tau / 4.0f;
+ euler.X = Mathf.Atan2(Row2[1], Row2[2]);
+ euler.Y = 0.0f;
+ euler.Z = Mathf.Tau / 4.0f;
}
return euler;
}
@@ -432,24 +425,24 @@ namespace Godot
{
if (sx > -(1.0f - Mathf.Epsilon))
{
- euler.x = Mathf.Asin(sx);
- euler.y = Mathf.Atan2(-Row2[0], Row2[2]);
- euler.z = Mathf.Atan2(-Row0[1], Row1[1]);
+ euler.X = Mathf.Asin(sx);
+ euler.Y = Mathf.Atan2(-Row2[0], Row2[2]);
+ euler.Z = Mathf.Atan2(-Row0[1], Row1[1]);
}
else
{
// It's -1
- euler.x = -Mathf.Tau / 4.0f;
- euler.y = Mathf.Atan2(Row0[2], Row0[0]);
- euler.z = 0;
+ euler.X = -Mathf.Tau / 4.0f;
+ euler.Y = Mathf.Atan2(Row0[2], Row0[0]);
+ euler.Z = 0;
}
}
else
{
// It's 1
- euler.x = Mathf.Tau / 4.0f;
- euler.y = Mathf.Atan2(Row0[2], Row0[0]);
- euler.z = 0;
+ euler.X = Mathf.Tau / 4.0f;
+ euler.Y = Mathf.Atan2(Row0[2], Row0[0]);
+ euler.Z = 0;
}
return euler;
}
@@ -467,24 +460,24 @@ namespace Godot
{
if (sy > -(1.0f - Mathf.Epsilon))
{
- euler.x = Mathf.Atan2(Row2[1], Row2[2]);
- euler.y = Mathf.Asin(-sy);
- euler.z = Mathf.Atan2(Row1[0], Row0[0]);
+ euler.X = Mathf.Atan2(Row2[1], Row2[2]);
+ euler.Y = Mathf.Asin(-sy);
+ euler.Z = Mathf.Atan2(Row1[0], Row0[0]);
}
else
{
// It's -1
- euler.x = 0;
- euler.y = Mathf.Tau / 4.0f;
- euler.z = -Mathf.Atan2(Row0[1], Row1[1]);
+ euler.X = 0;
+ euler.Y = Mathf.Tau / 4.0f;
+ euler.Z = -Mathf.Atan2(Row0[1], Row1[1]);
}
}
else
{
// It's 1
- euler.x = 0;
- euler.y = -Mathf.Tau / 4.0f;
- euler.z = -Mathf.Atan2(Row0[1], Row1[1]);
+ euler.X = 0;
+ euler.Y = -Mathf.Tau / 4.0f;
+ euler.Z = -Mathf.Atan2(Row0[1], Row1[1]);
}
return euler;
}
@@ -493,13 +486,7 @@ namespace Godot
}
}
- /// <summary>
- /// Returns the basis's rotation in the form of a quaternion.
- /// See <see cref="GetEuler"/> if you need Euler angles, but keep in
- /// 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 +545,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();
@@ -573,113 +560,10 @@ namespace Godot
}
/// <summary>
- /// Get rows by index. Rows are not very useful for user code,
- /// but are more efficient for some internal calculations.
- /// </summary>
- /// <param name="index">Which row.</param>
- /// <exception cref="ArgumentOutOfRangeException">
- /// <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)
- {
- switch (index)
- {
- case 0:
- return Row0;
- case 1:
- return Row1;
- case 2:
- return Row2;
- default:
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- }
-
- /// <summary>
- /// Sets rows by index. Rows are not very useful for user code,
- /// but are more efficient for some internal calculations.
- /// </summary>
- /// <param name="index">Which row.</param>
- /// <param name="value">The vector to set the row to.</param>
- /// <exception cref="ArgumentOutOfRangeException">
- /// <paramref name="index"/> is not 0, 1 or 2.
- /// </exception>
- public void SetRow(int index, Vector3 value)
- {
- switch (index)
- {
- case 0:
- Row0 = value;
- return;
- case 1:
- Row1 = value;
- return;
- case 2:
- Row2 = value;
- return;
- default:
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- }
-
- /// <summary>
- /// This function considers a discretization of rotations into
- /// 24 points on unit sphere, lying along the vectors (x, y, z) with
- /// each component being either -1, 0, or 1, and returns the index
- /// of the point best representing the orientation of the object.
- /// It is mainly used by the <see cref="GridMap"/> editor.
- ///
- /// For further details, refer to the Godot source code.
- /// </summary>
- /// <returns>The orthogonal index.</returns>
- public int GetOrthogonalIndex()
- {
- var orth = this;
-
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- var row = orth.GetRow(i);
-
- real_t v = row[j];
-
- if (v > 0.5f)
- {
- v = 1.0f;
- }
- else if (v < -0.5f)
- {
- v = -1.0f;
- }
- else
- {
- v = 0f;
- }
-
- row[j] = v;
-
- orth.SetRow(i, row);
- }
- }
-
- for (int i = 0; i < 24; i++)
- {
- if (orth == _orthoBases[i])
- {
- return i;
- }
- }
-
- return 0;
- }
-
- /// <summary>
/// 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 +593,17 @@ namespace Godot
);
}
- internal Basis Lerp(Basis to, real_t weight)
+ /// <summary>
+ /// Returns <see langword="true"/> if this basis is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return Row0.IsFinite() && Row1.IsFinite() && Row2.IsFinite();
+ }
+
+ internal readonly Basis Lerp(Basis to, real_t weight)
{
Basis b = this;
b.Row0 = Row0.Lerp(to.Row0, weight);
@@ -724,7 +618,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 +640,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,12 +650,12 @@ 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;
- b.Row1 *= scale.y;
- b.Row2 *= scale.z;
+ b.Row0 *= scale.X;
+ b.Row1 *= scale.Y;
+ b.Row2 *= scale.Z;
return b;
}
@@ -772,7 +666,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 +684,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 +694,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 +704,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 +713,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;
}
@@ -899,20 +790,20 @@ namespace Godot
/// <param name="quaternion">The quaternion to create the basis from.</param>
public Basis(Quaternion quaternion)
{
- real_t s = 2.0f / quaternion.LengthSquared;
-
- real_t xs = quaternion.x * s;
- real_t ys = quaternion.y * s;
- real_t zs = quaternion.z * s;
- real_t wx = quaternion.w * xs;
- real_t wy = quaternion.w * ys;
- real_t wz = quaternion.w * zs;
- real_t xx = quaternion.x * xs;
- real_t xy = quaternion.x * ys;
- real_t xz = quaternion.x * zs;
- real_t yy = quaternion.y * ys;
- real_t yz = quaternion.y * zs;
- real_t zz = quaternion.z * zs;
+ real_t s = 2.0f / quaternion.LengthSquared();
+
+ real_t xs = quaternion.X * s;
+ real_t ys = quaternion.Y * s;
+ real_t zs = quaternion.Z * s;
+ real_t wx = quaternion.W * xs;
+ real_t wy = quaternion.W * ys;
+ real_t wz = quaternion.W * zs;
+ real_t xx = quaternion.X * xs;
+ real_t xy = quaternion.X * ys;
+ real_t xz = quaternion.X * zs;
+ real_t yy = quaternion.Y * ys;
+ real_t yz = quaternion.Y * zs;
+ real_t zz = quaternion.Z * zs;
Row0 = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy);
Row1 = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx);
@@ -927,29 +818,29 @@ namespace Godot
/// <param name="angle">The angle to rotate, in radians.</param>
public Basis(Vector3 axis, real_t angle)
{
- Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
- real_t cosine = Mathf.Cos(angle);
- Row0.x = axisSq.x + cosine * (1.0f - axisSq.x);
- Row1.y = axisSq.y + cosine * (1.0f - axisSq.y);
- Row2.z = axisSq.z + cosine * (1.0f - axisSq.z);
-
- real_t sine = Mathf.Sin(angle);
- real_t t = 1.0f - cosine;
-
- real_t xyzt = axis.x * axis.y * t;
- real_t zyxs = axis.z * sine;
- Row0.y = xyzt - zyxs;
- Row1.x = xyzt + zyxs;
-
- xyzt = axis.x * axis.z * t;
- zyxs = axis.y * sine;
- Row0.z = xyzt + zyxs;
- Row2.x = xyzt - zyxs;
-
- xyzt = axis.y * axis.z * t;
- zyxs = axis.x * sine;
- Row1.z = xyzt - zyxs;
- Row2.y = xyzt + zyxs;
+ Vector3 axisSq = new Vector3(axis.X * axis.X, axis.Y * axis.Y, axis.Z * axis.Z);
+ (real_t sin, real_t cos) = Mathf.SinCos(angle);
+
+ Row0.X = axisSq.X + cos * (1.0f - axisSq.X);
+ Row1.Y = axisSq.Y + cos * (1.0f - axisSq.Y);
+ Row2.Z = axisSq.Z + cos * (1.0f - axisSq.Z);
+
+ real_t t = 1.0f - cos;
+
+ real_t xyzt = axis.X * axis.Y * t;
+ real_t zyxs = axis.Z * sin;
+ Row0.Y = xyzt - zyxs;
+ Row1.X = xyzt + zyxs;
+
+ xyzt = axis.X * axis.Z * t;
+ zyxs = axis.Y * sin;
+ Row0.Z = xyzt + zyxs;
+ Row2.X = xyzt - zyxs;
+
+ xyzt = axis.Y * axis.Z * t;
+ zyxs = axis.X * sin;
+ Row1.Z = xyzt - zyxs;
+ Row2.Y = xyzt + zyxs;
}
/// <summary>
@@ -960,9 +851,9 @@ namespace Godot
/// <param name="column2">The Z vector, or Column2.</param>
public Basis(Vector3 column0, Vector3 column1, Vector3 column2)
{
- Row0 = new Vector3(column0.x, column1.x, column2.x);
- Row1 = new Vector3(column0.y, column1.y, column2.y);
- Row2 = new Vector3(column0.z, column1.z, column2.z);
+ Row0 = new Vector3(column0.X, column1.X, column2.X);
+ Row1 = new Vector3(column0.Y, column1.Y, column2.Y);
+ Row2 = new Vector3(column0.Z, column1.Z, column2.Z);
// Same as:
// Column0 = column0;
// Column1 = column1;
@@ -970,8 +861,20 @@ namespace Godot
// We need to assign the struct fields here first so we can't do it that way...
}
- // Arguments are named such that xy is equal to calling x.y
- internal Basis(real_t xx, real_t yx, real_t zx, real_t xy, real_t yy, real_t zy, real_t xz, real_t yz, real_t zz)
+ /// <summary>
+ /// Constructs a transformation matrix from the given components.
+ /// Arguments are named such that xy is equal to calling <c>X.Y</c>.
+ /// </summary>
+ /// <param name="xx">The X component of the X column vector, accessed via <c>b.X.X</c> or <c>[0][0]</c>.</param>
+ /// <param name="yx">The X component of the Y column vector, accessed via <c>b.Y.X</c> or <c>[1][0]</c>.</param>
+ /// <param name="zx">The X component of the Z column vector, accessed via <c>b.Z.X</c> or <c>[2][0]</c>.</param>
+ /// <param name="xy">The Y component of the X column vector, accessed via <c>b.X.Y</c> or <c>[0][1]</c>.</param>
+ /// <param name="yy">The Y component of the Y column vector, accessed via <c>b.Y.Y</c> or <c>[1][1]</c>.</param>
+ /// <param name="zy">The Y component of the Z column vector, accessed via <c>b.Y.Y</c> or <c>[2][1]</c>.</param>
+ /// <param name="xz">The Z component of the X column vector, accessed via <c>b.X.Y</c> or <c>[0][2]</c>.</param>
+ /// <param name="yz">The Z component of the Y column vector, accessed via <c>b.Y.Y</c> or <c>[1][2]</c>.</param>
+ /// <param name="zz">The Z component of the Z column vector, accessed via <c>b.Y.Y</c> or <c>[2][2]</c>.</param>
+ public Basis(real_t xx, real_t yx, real_t zx, real_t xy, real_t yy, real_t zy, real_t xz, real_t yz, real_t zz)
{
Row0 = new Vector3(xx, yx, zx);
Row1 = new Vector3(xy, yy, zy);
@@ -985,19 +888,29 @@ namespace Godot
/// <param name="order">The order to compose the Euler angles.</param>
public static Basis FromEuler(Vector3 euler, EulerOrder order = EulerOrder.Yxz)
{
- real_t c, s;
-
- c = Mathf.Cos(euler.x);
- s = Mathf.Sin(euler.x);
- Basis xmat = new Basis(new Vector3(1, 0, 0), new Vector3(0, c, s), new Vector3(0, -s, c));
+ (real_t sin, real_t cos) = Mathf.SinCos(euler.X);
+ Basis xmat = new Basis
+ (
+ new Vector3(1, 0, 0),
+ new Vector3(0, cos, sin),
+ new Vector3(0, -sin, cos)
+ );
- c = Mathf.Cos(euler.y);
- s = Mathf.Sin(euler.y);
- Basis ymat = new Basis(new Vector3(c, 0, -s), new Vector3(0, 1, 0), new Vector3(s, 0, c));
+ (sin, cos) = Mathf.SinCos(euler.Y);
+ Basis ymat = new Basis
+ (
+ new Vector3(cos, 0, -sin),
+ new Vector3(0, 1, 0),
+ new Vector3(sin, 0, cos)
+ );
- c = Mathf.Cos(euler.z);
- s = Mathf.Sin(euler.z);
- Basis zmat = new Basis(new Vector3(c, s, 0), new Vector3(-s, c, 0), new Vector3(0, 0, 1));
+ (sin, cos) = Mathf.SinCos(euler.Z);
+ Basis zmat = new Basis
+ (
+ new Vector3(cos, sin, 0),
+ new Vector3(-sin, cos, 0),
+ new Vector3(0, 0, 1)
+ );
switch (order)
{
@@ -1028,9 +941,9 @@ namespace Godot
public static Basis FromScale(Vector3 scale)
{
return new Basis(
- scale.x, 0, 0,
- 0, scale.y, 0,
- 0, 0, scale.z
+ scale.X, 0, 0,
+ 0, scale.Y, 0,
+ 0, 0, scale.Z
);
}
@@ -1081,9 +994,9 @@ namespace Godot
{
return new Vector3
(
- basis.Row0[0] * vector.x + basis.Row1[0] * vector.y + basis.Row2[0] * vector.z,
- basis.Row0[1] * vector.x + basis.Row1[1] * vector.y + basis.Row2[1] * vector.z,
- basis.Row0[2] * vector.x + basis.Row1[2] * vector.y + basis.Row2[2] * vector.z
+ basis.Row0[0] * vector.X + basis.Row1[0] * vector.Y + basis.Row2[0] * vector.Z,
+ basis.Row0[1] * vector.X + basis.Row1[1] * vector.Y + basis.Row2[1] * vector.Z,
+ basis.Row0[2] * vector.X + basis.Row1[2] * vector.Y + basis.Row2[2] * vector.Z
);
}
@@ -1121,7 +1034,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 +1046,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 +1057,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 +1066,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,18 +1075,18 @@ 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}]";
+ return $"[X: {X}, Y: {Y}, Z: {Z}]";
}
/// <summary>
/// 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)}]";
+ return $"[X: {X.ToString(format)}, Y: {Y.ToString(format)}, Z: {Z.ToString(format)}]";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs
index 354212da1b..16be494d99 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs
@@ -12,7 +12,7 @@ namespace Godot.Bridge
{
try
{
- var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var godotObject = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (godotObject == null)
{
@@ -49,7 +49,7 @@ namespace Godot.Bridge
{
try
{
- var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var godotObject = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (godotObject == null)
throw new InvalidOperationException();
@@ -79,17 +79,34 @@ namespace Godot.Bridge
{
try
{
- var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var godotObject = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (godotObject == null)
throw new InvalidOperationException();
+ // Properties
if (godotObject.GetGodotClassPropertyValue(CustomUnsafe.AsRef(name), out godot_variant outRetValue))
{
*outRet = outRetValue;
return godot_bool.True;
}
+ // Signals
+ if (godotObject.HasGodotClassSignal(CustomUnsafe.AsRef(name)))
+ {
+ godot_signal signal = new godot_signal(*name, godotObject.GetInstanceId());
+ *outRet = VariantUtils.CreateFromSignalTakingOwnershipOfDisposableValue(signal);
+ return godot_bool.True;
+ }
+
+ // Methods
+ if (godotObject.HasGodotClassMethod(CustomUnsafe.AsRef(name)))
+ {
+ godot_callable method = new godot_callable(*name, godotObject.GetInstanceId());
+ *outRet = VariantUtils.CreateFromCallableTakingOwnershipOfDisposableValue(method);
+ return godot_bool.True;
+ }
+
var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(name)));
@@ -117,7 +134,7 @@ namespace Godot.Bridge
{
try
{
- var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var godotObject = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (okIfNull.ToBool())
godotObject?.Dispose();
@@ -135,7 +152,7 @@ namespace Godot.Bridge
{
try
{
- var self = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var self = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (self == null)
{
@@ -169,7 +186,7 @@ namespace Godot.Bridge
{
try
{
- var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var godotObject = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (godotObject == null)
return godot_bool.False;
@@ -192,7 +209,7 @@ namespace Godot.Bridge
{
try
{
- var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var godotObject = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (godotObject == null)
return;
@@ -225,7 +242,7 @@ namespace Godot.Bridge
{
try
{
- var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
+ var godotObject = (GodotObject)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
if (godotObject == null)
return;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/GodotSerializationInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/GodotSerializationInfo.cs
index 6d20f95007..47feb1902f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/GodotSerializationInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/GodotSerializationInfo.cs
@@ -48,7 +48,7 @@ public sealed class GodotSerializationInfo : IDisposable
{
_signalEvents[name] = serializedData;
}
- else if (OS.IsStdoutVerbose())
+ else if (OS.IsStdOutVerbose())
{
Console.WriteLine($"Failed to serialize event signal delegate: {name}");
}
@@ -72,7 +72,7 @@ public sealed class GodotSerializationInfo : IDisposable
return true;
}
- else if (OS.IsStdoutVerbose())
+ else if (OS.IsStdOutVerbose())
{
Console.WriteLine($"Failed to deserialize event signal delegate: {name}");
}
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/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
index d83cf43eb2..ec2728140e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
@@ -100,7 +100,7 @@ namespace Godot.Bridge
Type nativeType = TypeGetProxyClass(nativeTypeNameStr) ?? throw new InvalidOperationException(
"Wrapper class not found for type: " + nativeTypeNameStr);
- var obj = (Object)FormatterServices.GetUninitializedObject(nativeType);
+ var obj = (GodotObject)FormatterServices.GetUninitializedObject(nativeType);
var ctor = nativeType.GetConstructor(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
@@ -150,7 +150,7 @@ namespace Godot.Bridge
}
}
- var obj = (Object)FormatterServices.GetUninitializedObject(scriptType);
+ var obj = (GodotObject)FormatterServices.GetUninitializedObject(scriptType);
var parameters = ctor.GetParameters();
int paramCount = parameters.Length;
@@ -159,7 +159,7 @@ namespace Godot.Bridge
for (int i = 0; i < paramCount; i++)
{
- invokeParams[i] = Marshaling.ConvertVariantToManagedObjectOfType(
+ invokeParams[i] = DelegateUtils.RuntimeTypeConversionHelper.ConvertToObjectOfType(
*args[i], parameters[i].ParameterType);
}
@@ -189,7 +189,7 @@ namespace Godot.Bridge
return;
}
- var native = Object.InternalGetClassNativeBase(scriptType);
+ var native = GodotObject.InternalGetClassNativeBase(scriptType);
var field = native?.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static |
BindingFlags.Public | BindingFlags.NonPublic);
@@ -222,7 +222,7 @@ namespace Godot.Bridge
{
try
{
- var target = (Object?)GCHandle.FromIntPtr(gcHandlePtr).Target;
+ var target = (GodotObject?)GCHandle.FromIntPtr(gcHandlePtr).Target;
if (target != null)
target.NativePtr = newPtr;
}
@@ -239,21 +239,45 @@ namespace Godot.Bridge
if (nativeTypeNameStr[0] == '_')
nativeTypeNameStr = nativeTypeNameStr.Substring(1);
- Type? wrapperType = typeof(Object).Assembly.GetType("Godot." + nativeTypeNameStr);
+ Type? wrapperType = typeof(GodotObject).Assembly.GetType("Godot." + nativeTypeNameStr);
if (wrapperType == null)
{
- wrapperType = AppDomain.CurrentDomain.GetAssemblies()
- .FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor")?
- .GetType("Godot." + nativeTypeNameStr);
+ wrapperType = GetTypeByGodotClassAttr(typeof(GodotObject).Assembly, nativeTypeNameStr);
+ }
+
+ if (wrapperType == null)
+ {
+ var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
+ .FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor");
+ wrapperType = editorAssembly?.GetType("Godot." + nativeTypeNameStr);
+
+ if (wrapperType == null)
+ {
+ wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr);
+ }
+ }
+
+ static Type? GetTypeByGodotClassAttr(Assembly assembly, string nativeTypeNameStr)
+ {
+ var types = assembly.GetTypes();
+ foreach (var type in types)
+ {
+ var attr = type.GetCustomAttribute<GodotClassNameAttribute>();
+ if (attr?.Name == nativeTypeNameStr)
+ {
+ return type;
+ }
+ }
+ return null;
}
static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed;
if (wrapperType != null && IsStatic(wrapperType))
{
- // A static class means this is a Godot singleton class. If an instance is needed we use Godot.Object.
- return typeof(Object);
+ // A static class means this is a Godot singleton class. If an instance is needed we use GodotObject.
+ return typeof(GodotObject);
}
return wrapperType;
@@ -293,11 +317,11 @@ namespace Godot.Bridge
// such as when disabling C# source generators (for whatever reason) or when using a
// language other than C# that has nothing similar to source generators to automate it.
- var typeOfGodotObject = typeof(Object);
+ var typeOfGodotObject = typeof(GodotObject);
foreach (var type in assembly.GetTypes())
{
- if (type.IsNested)
+ if (type.IsNested || type.IsGenericType)
continue;
if (!typeOfGodotObject.IsAssignableFrom(type))
@@ -314,9 +338,12 @@ namespace Godot.Bridge
if (scriptTypes != null)
{
- for (int i = 0; i < scriptTypes.Length; i++)
+ foreach (var type in scriptTypes)
{
- LookupScriptForClass(scriptTypes[i]);
+ if (type.IsGenericType)
+ continue;
+
+ LookupScriptForClass(type);
}
}
}
@@ -328,7 +355,7 @@ namespace Godot.Bridge
{
try
{
- var owner = (Object?)GCHandle.FromIntPtr(ownerGCHandlePtr).Target;
+ var owner = (GodotObject?)GCHandle.FromIntPtr(ownerGCHandlePtr).Target;
if (owner == null)
{
@@ -536,9 +563,9 @@ namespace Godot.Bridge
}
// ReSharper disable once RedundantNameQualifier
- if (!typeof(Godot.Object).IsAssignableFrom(scriptType))
+ if (!typeof(GodotObject).IsAssignableFrom(scriptType))
{
- // The class no longer inherits Godot.Object, can't reload
+ // The class no longer inherits GodotObject, can't reload
return godot_bool.False;
}
@@ -586,7 +613,7 @@ namespace Godot.Bridge
using var methods = new Collections.Array();
Type? top = scriptType;
- Type native = Object.InternalGetClassNativeBase(top);
+ Type native = GodotObject.InternalGetClassNativeBase(top);
while (top != null && top != native)
{
@@ -647,7 +674,7 @@ namespace Godot.Bridge
continue;
var rpcAttr = method.GetCustomAttributes(inherit: false)
- .OfType<RPCAttribute>().FirstOrDefault();
+ .OfType<RpcAttribute>().FirstOrDefault();
if (rpcAttr == null)
continue;
@@ -729,6 +756,7 @@ namespace Godot.Bridge
{
ExceptionUtils.LogException(e);
*outTool = godot_bool.False;
+ *outMethodsDest = NativeFuncs.godotsharp_array_new();
*outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new();
*outEventSignalsDest = NativeFuncs.godotsharp_dictionary_new();
*outBaseScript = default;
@@ -827,12 +855,13 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
- var aux = stackalloc godotsharp_property_info[length];
+ var aux = stackalloc godotsharp_property_info[stackMaxLength];
interopProperties = aux;
}
else
{
- interopProperties = ((godotsharp_property_info*)NativeMemory.Alloc((nuint)length, (nuint)sizeof(godotsharp_property_info)))!;
+ interopProperties = ((godotsharp_property_info*)NativeMemory.Alloc(
+ (nuint)length, (nuint)sizeof(godotsharp_property_info)))!;
}
try
@@ -858,8 +887,8 @@ namespace Godot.Bridge
addPropInfoFunc(scriptPtr, &currentClassName, interopProperties, length);
- // We're borrowing the StringName's without making an owning copy, so the
- // managed collection needs to be kept alive until `addPropInfoFunc` returns.
+ // We're borrowing the native value of the StringName entries.
+ // The dictionary needs to be kept alive until `addPropInfoFunc` returns.
GC.KeepAlive(properties);
}
finally
@@ -884,12 +913,7 @@ namespace Godot.Bridge
{
// Careful with padding...
public godot_string_name Name; // Not owned
- public godot_variant Value;
-
- public void Dispose()
- {
- Value.Dispose();
- }
+ public godot_variant Value; // Not owned
}
[UnmanagedCallersOnly]
@@ -899,7 +923,7 @@ namespace Godot.Bridge
try
{
Type? top = _scriptTypeBiMap.GetScriptType(scriptPtr);
- Type native = Object.InternalGetClassNativeBase(top);
+ Type native = GodotObject.InternalGetClassNativeBase(top);
while (top != null && top != native)
{
@@ -928,10 +952,35 @@ namespace Godot.Bridge
if (getGodotPropertyDefaultValuesMethod == null)
return;
- var defaultValues = (Dictionary<StringName, object>?)
- getGodotPropertyDefaultValuesMethod.Invoke(null, null);
+ var defaultValuesObj = getGodotPropertyDefaultValuesMethod.Invoke(null, null);
+
+ if (defaultValuesObj == null)
+ return;
+
+ Dictionary<StringName, Variant> defaultValues;
+
+ if (defaultValuesObj is Dictionary<StringName, object> defaultValuesLegacy)
+ {
+ // We have to support this for some time, otherwise this could cause data loss for projects
+ // built with previous releases. Ideally, we should remove this before Godot 4.0 stable.
+
+ if (defaultValuesLegacy.Count <= 0)
+ return;
+
+ defaultValues = new();
- if (defaultValues == null || defaultValues.Count <= 0)
+ foreach (var pair in defaultValuesLegacy)
+ {
+ defaultValues[pair.Key] = Variant.CreateTakingOwnershipOfDisposableValue(
+ DelegateUtils.RuntimeTypeConversionHelper.ConvertToVariant(pair.Value));
+ }
+ }
+ else
+ {
+ defaultValues = (Dictionary<StringName, Variant>)defaultValuesObj;
+ }
+
+ if (defaultValues.Count <= 0)
return;
int length = defaultValues.Count;
@@ -947,12 +996,13 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
- var aux = stackalloc godotsharp_property_def_val_pair[length];
+ var aux = stackalloc godotsharp_property_def_val_pair[stackMaxLength];
interopDefaultValues = aux;
}
else
{
- interopDefaultValues = ((godotsharp_property_def_val_pair*)NativeMemory.Alloc((nuint)length, (nuint)sizeof(godotsharp_property_def_val_pair)))!;
+ interopDefaultValues = ((godotsharp_property_def_val_pair*)NativeMemory.Alloc(
+ (nuint)length, (nuint)sizeof(godotsharp_property_def_val_pair)))!;
}
try
@@ -963,7 +1013,7 @@ namespace Godot.Bridge
godotsharp_property_def_val_pair interopProperty = new()
{
Name = (godot_string_name)defaultValuePair.Key.NativeValue, // Not owned
- Value = Marshaling.ConvertManagedObjectToVariant(defaultValuePair.Value)
+ Value = (godot_variant)defaultValuePair.Value.NativeVar // Not owned
};
interopDefaultValues[i] = interopProperty;
@@ -973,15 +1023,12 @@ namespace Godot.Bridge
addDefValFunc(scriptPtr, interopDefaultValues, length);
- // We're borrowing the StringName's without making an owning copy, so the
- // managed collection needs to be kept alive until `addDefValFunc` returns.
+ // We're borrowing the native value of the StringName and Variant entries.
+ // The dictionary needs to be kept alive until `addDefValFunc` returns.
GC.KeepAlive(defaultValues);
}
finally
{
- for (int i = 0; i < length; i++)
- interopDefaultValues[i].Dispose();
-
if (!useStack)
NativeMemory.Free(interopDefaultValues);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
index f9309ca13e..219a9a8c15 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
@@ -28,7 +28,7 @@ namespace Godot
/// </example>
public readonly partial struct Callable
{
- private readonly Object _target;
+ private readonly GodotObject _target;
private readonly StringName _method;
private readonly Delegate _delegate;
private readonly unsafe delegate* managed<object, NativeVariantPtrArgs, out godot_variant, void> _trampoline;
@@ -36,7 +36,7 @@ namespace Godot
/// <summary>
/// Object that contains the method.
/// </summary>
- public Object Target => _target;
+ public GodotObject Target => _target;
/// <summary>
/// Name of the method that will be called.
@@ -60,7 +60,7 @@ namespace Godot
/// </summary>
/// <param name="target">Object that contains the method.</param>
/// <param name="method">Name of the method that will be called.</param>
- public unsafe Callable(Object target, StringName method)
+ public unsafe Callable(GodotObject target, StringName method)
{
_target = target;
_method = method;
@@ -71,13 +71,13 @@ namespace Godot
private unsafe Callable(Delegate @delegate,
delegate* managed<object, NativeVariantPtrArgs, out godot_variant, void> trampoline)
{
- _target = @delegate?.Target as Object;
+ _target = @delegate?.Target as GodotObject;
_method = null;
_delegate = @delegate;
_trampoline = trampoline;
}
- private const int VarArgsSpanThreshold = 5;
+ private const int VarArgsSpanThreshold = 10;
/// <summary>
/// Calls the method represented by this <see cref="Callable"/>.
@@ -92,15 +92,13 @@ namespace Godot
int argc = args.Length;
Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
- stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
+ stackalloc godot_variant.movable[VarArgsSpanThreshold] :
new godot_variant.movable[argc];
- Span<IntPtr> argsSpan = argc <= 10 ?
- stackalloc IntPtr[argc] :
+ Span<IntPtr> argsSpan = argc <= VarArgsSpanThreshold ?
+ stackalloc IntPtr[VarArgsSpanThreshold] :
new IntPtr[argc];
- using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
-
fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
{
@@ -128,15 +126,13 @@ namespace Godot
int argc = args.Length;
Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
- stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
+ stackalloc godot_variant.movable[VarArgsSpanThreshold] :
new godot_variant.movable[argc];
- Span<IntPtr> argsSpan = argc <= 10 ?
- stackalloc IntPtr[argc] :
+ Span<IntPtr> argsSpan = argc <= VarArgsSpanThreshold ?
+ stackalloc IntPtr[VarArgsSpanThreshold] :
new IntPtr[argc];
- using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
-
fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs
index 6c6a104019..3005582bea 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs
@@ -45,7 +45,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0>(
+ public static unsafe Callable From<[MustBeVariant] T0>(
Action<T0> action
)
{
@@ -54,7 +54,7 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 1);
((Action<T0>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0])
+ VariantUtils.ConvertTo<T0>(args[0])
);
ret = default;
@@ -64,7 +64,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1>(
Action<T0, T1> action
)
{
@@ -73,8 +73,8 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 2);
((Action<T0, T1>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1])
);
ret = default;
@@ -84,7 +84,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1, T2>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2>(
Action<T0, T1, T2> action
)
{
@@ -93,9 +93,9 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 3);
((Action<T0, T1, T2>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2])
);
ret = default;
@@ -105,7 +105,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1, T2, T3>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3>(
Action<T0, T1, T2, T3> action
)
{
@@ -114,10 +114,10 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 4);
((Action<T0, T1, T2, T3>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3])
);
ret = default;
@@ -127,7 +127,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4>(
Action<T0, T1, T2, T3, T4> action
)
{
@@ -136,11 +136,11 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 5);
((Action<T0, T1, T2, T3, T4>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4])
);
ret = default;
@@ -150,7 +150,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5>(
Action<T0, T1, T2, T3, T4, T5> action
)
{
@@ -159,12 +159,12 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 6);
((Action<T0, T1, T2, T3, T4, T5>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5])
);
ret = default;
@@ -174,7 +174,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5, T6>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5, [MustBeVariant] T6>(
Action<T0, T1, T2, T3, T4, T5, T6> action
)
{
@@ -183,13 +183,13 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 7);
((Action<T0, T1, T2, T3, T4, T5, T6>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6])
);
ret = default;
@@ -199,7 +199,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5, T6, T7>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5, [MustBeVariant] T6, [MustBeVariant] T7>(
Action<T0, T1, T2, T3, T4, T5, T6, T7> action
)
{
@@ -208,14 +208,14 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 8);
((Action<T0, T1, T2, T3, T4, T5, T6, T7>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7])
);
ret = default;
@@ -225,7 +225,7 @@ public readonly partial struct Callable
}
/// <inheritdoc cref="From(Action)"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5, T6, T7, T8>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5, [MustBeVariant] T6, [MustBeVariant] T7, [MustBeVariant] T8>(
Action<T0, T1, T2, T3, T4, T5, T6, T7, T8> action
)
{
@@ -234,15 +234,15 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 9);
((Action<T0, T1, T2, T3, T4, T5, T6, T7, T8>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]),
- VariantConversionCallbacks.GetToManagedCallback<T8>()(args[8])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7]),
+ VariantUtils.ConvertTo<T8>(args[8])
);
ret = default;
@@ -255,7 +255,7 @@ public readonly partial struct Callable
/// Constructs a new <see cref="Callable"/> for the given <paramref name="func"/>.
/// </summary>
/// <param name="func">Action method that will be called.</param>
- public static unsafe Callable From<TResult>(
+ public static unsafe Callable From<[MustBeVariant] TResult>(
Func<TResult> func
)
{
@@ -265,14 +265,14 @@ public readonly partial struct Callable
TResult res = ((Func<TResult>)delegateObj)();
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] TResult>(
Func<T0, TResult> func
)
{
@@ -281,17 +281,17 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 1);
TResult res = ((Func<T0, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0])
+ VariantUtils.ConvertTo<T0>(args[0])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] TResult>(
Func<T0, T1, TResult> func
)
{
@@ -300,18 +300,18 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 2);
TResult res = ((Func<T0, T1, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, T2, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] TResult>(
Func<T0, T1, T2, TResult> func
)
{
@@ -320,19 +320,19 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 3);
TResult res = ((Func<T0, T1, T2, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, T2, T3, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] TResult>(
Func<T0, T1, T2, T3, TResult> func
)
{
@@ -341,20 +341,20 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 4);
TResult res = ((Func<T0, T1, T2, T3, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] TResult>(
Func<T0, T1, T2, T3, T4, TResult> func
)
{
@@ -363,21 +363,21 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 5);
TResult res = ((Func<T0, T1, T2, T3, T4, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5, [MustBeVariant] TResult>(
Func<T0, T1, T2, T3, T4, T5, TResult> func
)
{
@@ -386,22 +386,22 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 6);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5, T6, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5, [MustBeVariant] T6, [MustBeVariant] TResult>(
Func<T0, T1, T2, T3, T4, T5, T6, TResult> func
)
{
@@ -410,23 +410,23 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 7);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5, T6, T7, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5, [MustBeVariant] T6, [MustBeVariant] T7, [MustBeVariant] TResult>(
Func<T0, T1, T2, T3, T4, T5, T6, T7, TResult> func
)
{
@@ -435,24 +435,24 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 8);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, T7, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
}
/// <inheritdoc cref="From{TResult}(Func{TResult})"/>
- public static unsafe Callable From<T0, T1, T2, T3, T4, T5, T6, T7, T8, TResult>(
+ public static unsafe Callable From<[MustBeVariant] T0, [MustBeVariant] T1, [MustBeVariant] T2, [MustBeVariant] T3, [MustBeVariant] T4, [MustBeVariant] T5, [MustBeVariant] T6, [MustBeVariant] T7, [MustBeVariant] T8, [MustBeVariant] TResult>(
Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TResult> func
)
{
@@ -461,18 +461,18 @@ public readonly partial struct Callable
ThrowIfArgCountMismatch(args, 9);
TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TResult>)delegateObj)(
- VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]),
- VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]),
- VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]),
- VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]),
- VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]),
- VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]),
- VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]),
- VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]),
- VariantConversionCallbacks.GetToManagedCallback<T8>()(args[8])
+ VariantUtils.ConvertTo<T0>(args[0]),
+ VariantUtils.ConvertTo<T1>(args[1]),
+ VariantUtils.ConvertTo<T2>(args[2]),
+ VariantUtils.ConvertTo<T3>(args[3]),
+ VariantUtils.ConvertTo<T4>(args[4]),
+ VariantUtils.ConvertTo<T5>(args[5]),
+ VariantUtils.ConvertTo<T6>(args[6]),
+ VariantUtils.ConvertTo<T7>(args[7]),
+ VariantUtils.ConvertTo<T8>(args[8])
);
- ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res);
+ ret = VariantUtils.CreateFrom(res);
}
return CreateWithUnsafeTrampoline(func, &Trampoline);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index ee9e59f9fa..555811bab2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -20,97 +21,97 @@ namespace Godot
/// <summary>
/// The color's red component, typically on the range of 0 to 1.
/// </summary>
- public float r;
+ public float R;
/// <summary>
/// The color's green component, typically on the range of 0 to 1.
/// </summary>
- public float g;
+ public float G;
/// <summary>
/// The color's blue component, typically on the range of 0 to 1.
/// </summary>
- public float b;
+ public float B;
/// <summary>
/// The color's alpha (transparency) component, typically on the range of 0 to 1.
/// </summary>
- public float a;
+ public float A;
/// <summary>
- /// Wrapper for <see cref="r"/> that uses the range 0 to 255 instead of 0 to 1.
+ /// Wrapper for <see cref="R"/> that uses the range 0 to 255 instead of 0 to 1.
/// </summary>
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
- public int r8
+ public int R8
{
- get
+ readonly get
{
- return (int)Math.Round(r * 255.0f);
+ return (int)Math.Round(R * 255.0f);
}
set
{
- r = value / 255.0f;
+ R = value / 255.0f;
}
}
/// <summary>
- /// Wrapper for <see cref="g"/> that uses the range 0 to 255 instead of 0 to 1.
+ /// Wrapper for <see cref="G"/> that uses the range 0 to 255 instead of 0 to 1.
/// </summary>
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
- public int g8
+ public int G8
{
- get
+ readonly get
{
- return (int)Math.Round(g * 255.0f);
+ return (int)Math.Round(G * 255.0f);
}
set
{
- g = value / 255.0f;
+ G = value / 255.0f;
}
}
/// <summary>
- /// Wrapper for <see cref="b"/> that uses the range 0 to 255 instead of 0 to 1.
+ /// Wrapper for <see cref="B"/> that uses the range 0 to 255 instead of 0 to 1.
/// </summary>
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
- public int b8
+ public int B8
{
- get
+ readonly get
{
- return (int)Math.Round(b * 255.0f);
+ return (int)Math.Round(B * 255.0f);
}
set
{
- b = value / 255.0f;
+ B = value / 255.0f;
}
}
/// <summary>
- /// Wrapper for <see cref="a"/> that uses the range 0 to 255 instead of 0 to 1.
+ /// Wrapper for <see cref="A"/> that uses the range 0 to 255 instead of 0 to 1.
/// </summary>
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
- public int a8
+ public int A8
{
- get
+ readonly get
{
- return (int)Math.Round(a * 255.0f);
+ return (int)Math.Round(A * 255.0f);
}
set
{
- a = value / 255.0f;
+ A = value / 255.0f;
}
}
/// <summary>
/// The HSV hue of this color, on the range 0 to 1.
/// </summary>
- /// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHSV"/>.</value>
- public float h
+ /// <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));
+ float max = Math.Max(R, Math.Max(G, B));
+ float min = Math.Min(R, Math.Min(G, B));
float delta = max - min;
@@ -121,17 +122,17 @@ namespace Godot
float h;
- if (r == max)
+ if (R == max)
{
- h = (g - b) / delta; // Between yellow & magenta
+ h = (G - B) / delta; // Between yellow & magenta
}
- else if (g == max)
+ else if (G == max)
{
- h = 2 + ((b - r) / delta); // Between cyan & yellow
+ h = 2 + ((B - R) / delta); // Between cyan & yellow
}
else
{
- h = 4 + ((r - g) / delta); // Between magenta & cyan
+ h = 4 + ((R - G) / delta); // Between magenta & cyan
}
h /= 6.0f;
@@ -145,20 +146,20 @@ namespace Godot
}
set
{
- this = FromHSV(value, s, v, a);
+ this = FromHsv(value, S, V, A);
}
}
/// <summary>
/// The HSV saturation of this color, on the range 0 to 1.
/// </summary>
- /// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHSV"/>.</value>
- public float s
+ /// <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));
+ float max = Math.Max(R, Math.Max(G, B));
+ float min = Math.Min(R, Math.Min(G, B));
float delta = max - min;
@@ -166,49 +167,62 @@ namespace Godot
}
set
{
- this = FromHSV(h, value, v, a);
+ this = FromHsv(H, value, V, A);
}
}
/// <summary>
/// The HSV value (brightness) of this color, on the range 0 to 1.
/// </summary>
- /// <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
+ /// <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));
+ return Math.Max(R, Math.Max(G, B));
}
set
{
- this = FromHSV(h, s, value, a);
+ this = FromHsv(H, S, value, A);
}
}
/// <summary>
+ /// Returns the light intensity of the color, as a value between 0.0 and 1.0 (inclusive).
+ /// This is useful when determining light or dark color. Colors with a luminance smaller
+ /// than 0.5 can be generally considered dark.
+ /// Note: <see cref="Luminance"/> relies on the color being in the linear color space to
+ /// return an accurate relative luminance value. If the color is in the sRGB color space
+ /// use <see cref="SrgbToLinear"/> to convert it to the linear color space first.
+ /// </summary>
+ public readonly float Luminance
+ {
+ get { return 0.2126f * R + 0.7152f * G + 0.0722f * B; }
+ }
+
+ /// <summary>
/// Access color components using their index.
/// </summary>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="r"/>,
- /// <c>[1]</c> is equivalent to <see cref="g"/>,
- /// <c>[2]</c> is equivalent to <see cref="b"/>,
- /// <c>[3]</c> is equivalent to <see cref="a"/>.
+ /// <c>[0]</c> is equivalent to <see cref="R"/>,
+ /// <c>[1]</c> is equivalent to <see cref="G"/>,
+ /// <c>[2]</c> is equivalent to <see cref="B"/>,
+ /// <c>[3]</c> is equivalent to <see cref="A"/>.
/// </value>
public float this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return r;
+ return R;
case 1:
- return g;
+ return G;
case 2:
- return b;
+ return B;
case 3:
- return a;
+ return A;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -218,16 +232,16 @@ namespace Godot
switch (index)
{
case 0:
- r = value;
+ R = value;
return;
case 1:
- g = value;
+ G = value;
return;
case 2:
- b = value;
+ B = value;
return;
case 3:
- a = value;
+ A = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -242,21 +256,21 @@ 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;
- float sa = 1.0f - over.a;
- res.a = (a * sa) + over.a;
+ float sa = 1.0f - over.A;
+ res.A = (A * sa) + over.A;
- if (res.a == 0)
+ if (res.A == 0)
{
return new Color(0, 0, 0, 0);
}
- res.r = ((r * a * sa) + (over.r * over.a)) / res.a;
- res.g = ((g * a * sa) + (over.g * over.a)) / res.a;
- res.b = ((b * a * sa) + (over.b * over.a)) / res.a;
+ res.R = ((R * A * sa) + (over.R * over.A)) / res.A;
+ res.G = ((G * A * sa) + (over.G * over.A)) / res.A;
+ res.B = ((B * A * sa) + (over.B * over.A)) / res.A;
return res;
}
@@ -269,16 +283,16 @@ 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);
return new Color
(
- (float)Mathf.Clamp(r, minimum.r, maximum.r),
- (float)Mathf.Clamp(g, minimum.g, maximum.g),
- (float)Mathf.Clamp(b, minimum.b, maximum.b),
- (float)Mathf.Clamp(a, minimum.a, maximum.a)
+ (float)Mathf.Clamp(R, minimum.R, maximum.R),
+ (float)Mathf.Clamp(G, minimum.G, maximum.G),
+ (float)Mathf.Clamp(B, minimum.B, maximum.B),
+ (float)Mathf.Clamp(A, minimum.A, maximum.A)
);
}
@@ -288,12 +302,12 @@ 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;
- res.g *= 1.0f - amount;
- res.b *= 1.0f - amount;
+ res.R *= 1.0f - amount;
+ res.G *= 1.0f - amount;
+ res.B *= 1.0f - amount;
return res;
}
@@ -301,13 +315,13 @@ 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,
- 1.0f - g,
- 1.0f - b,
- a
+ 1.0f - R,
+ 1.0f - G,
+ 1.0f - B,
+ A
);
}
@@ -317,12 +331,12 @@ 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;
- res.g += (1.0f - res.g) * amount;
- res.b += (1.0f - res.b) * amount;
+ res.R += (1.0f - res.R) * amount;
+ res.G += (1.0f - res.G) * amount;
+ res.B += (1.0f - res.B) * amount;
return res;
}
@@ -333,33 +347,44 @@ 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
(
- (float)Mathf.Lerp(r, to.r, weight),
- (float)Mathf.Lerp(g, to.g, weight),
- (float)Mathf.Lerp(b, to.b, weight),
- (float)Mathf.Lerp(a, to.a, weight)
+ (float)Mathf.Lerp(R, to.R, weight),
+ (float)Mathf.Lerp(G, to.G, weight),
+ (float)Mathf.Lerp(B, to.B, weight),
+ (float)Mathf.Lerp(A, to.A, weight)
);
}
/// <summary>
- /// Returns the result of the linear interpolation between
- /// this color and <paramref name="to"/> by color amount <paramref name="weight"/>.
+ /// Returns the color converted to the sRGB color space.
+ /// This method assumes the original color is in the linear color space.
+ /// See also <see cref="SrgbToLinear"/> which performs the opposite operation.
/// </summary>
- /// <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)
+ /// <returns>The sRGB color.</returns>
+ public readonly Color LinearToSrgb()
{
- return new Color
- (
- (float)Mathf.Lerp(r, to.r, weight.r),
- (float)Mathf.Lerp(g, to.g, weight.g),
- (float)Mathf.Lerp(b, to.b, weight.b),
- (float)Mathf.Lerp(a, to.a, weight.a)
- );
+ return new Color(
+ R < 0.0031308f ? 12.92f * R : (1.0f + 0.055f) * (float)Mathf.Pow(R, 1.0f / 2.4f) - 0.055f,
+ G < 0.0031308f ? 12.92f * G : (1.0f + 0.055f) * (float)Mathf.Pow(G, 1.0f / 2.4f) - 0.055f,
+ B < 0.0031308f ? 12.92f * B : (1.0f + 0.055f) * (float)Mathf.Pow(B, 1.0f / 2.4f) - 0.055f, A);
+ }
+
+ /// <summary>
+ /// Returns the color converted to linear color space.
+ /// This method assumes the original color already is in sRGB color space.
+ /// See also <see cref="LinearToSrgb"/> which performs the opposite operation.
+ /// </summary>
+ /// <returns>The color in linear color space.</returns>
+ public readonly Color SrgbToLinear()
+ {
+ return new Color(
+ R < 0.04045f ? R * (1.0f / 12.92f) : (float)Mathf.Pow((R + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
+ G < 0.04045f ? G * (1.0f / 12.92f) : (float)Mathf.Pow((G + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
+ B < 0.04045f ? B * (1.0f / 12.92f) : (float)Mathf.Pow((B + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
+ A);
}
/// <summary>
@@ -368,15 +393,15 @@ 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);
+ uint c = (byte)Math.Round(A * 255);
c <<= 8;
- c |= (byte)Math.Round(b * 255);
+ c |= (byte)Math.Round(B * 255);
c <<= 8;
- c |= (byte)Math.Round(g * 255);
+ c |= (byte)Math.Round(G * 255);
c <<= 8;
- c |= (byte)Math.Round(r * 255);
+ c |= (byte)Math.Round(R * 255);
return c;
}
@@ -387,15 +412,15 @@ 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);
+ ulong c = (ushort)Math.Round(A * 65535);
c <<= 16;
- c |= (ushort)Math.Round(b * 65535);
+ c |= (ushort)Math.Round(B * 65535);
c <<= 16;
- c |= (ushort)Math.Round(g * 65535);
+ c |= (ushort)Math.Round(G * 65535);
c <<= 16;
- c |= (ushort)Math.Round(r * 65535);
+ c |= (ushort)Math.Round(R * 65535);
return c;
}
@@ -406,15 +431,15 @@ 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);
+ uint c = (byte)Math.Round(A * 255);
c <<= 8;
- c |= (byte)Math.Round(r * 255);
+ c |= (byte)Math.Round(R * 255);
c <<= 8;
- c |= (byte)Math.Round(g * 255);
+ c |= (byte)Math.Round(G * 255);
c <<= 8;
- c |= (byte)Math.Round(b * 255);
+ c |= (byte)Math.Round(B * 255);
return c;
}
@@ -425,15 +450,15 @@ 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);
+ ulong c = (ushort)Math.Round(A * 65535);
c <<= 16;
- c |= (ushort)Math.Round(r * 65535);
+ c |= (ushort)Math.Round(R * 65535);
c <<= 16;
- c |= (ushort)Math.Round(g * 65535);
+ c |= (ushort)Math.Round(G * 65535);
c <<= 16;
- c |= (ushort)Math.Round(b * 65535);
+ c |= (ushort)Math.Round(B * 65535);
return c;
}
@@ -444,15 +469,15 @@ 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);
+ uint c = (byte)Math.Round(R * 255);
c <<= 8;
- c |= (byte)Math.Round(g * 255);
+ c |= (byte)Math.Round(G * 255);
c <<= 8;
- c |= (byte)Math.Round(b * 255);
+ c |= (byte)Math.Round(B * 255);
c <<= 8;
- c |= (byte)Math.Round(a * 255);
+ c |= (byte)Math.Round(A * 255);
return c;
}
@@ -463,15 +488,15 @@ 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);
+ ulong c = (ushort)Math.Round(R * 65535);
c <<= 16;
- c |= (ushort)Math.Round(g * 65535);
+ c |= (ushort)Math.Round(G * 65535);
c <<= 16;
- c |= (ushort)Math.Round(b * 65535);
+ c |= (ushort)Math.Round(B * 65535);
c <<= 16;
- c |= (ushort)Math.Round(a * 65535);
+ c |= (ushort)Math.Round(A * 65535);
return c;
}
@@ -483,17 +508,17 @@ 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;
- txt += ToHex32(r);
- txt += ToHex32(g);
- txt += ToHex32(b);
+ txt += ToHex32(R);
+ txt += ToHex32(G);
+ txt += ToHex32(B);
if (includeAlpha)
{
- txt += ToHex32(a);
+ txt += ToHex32(A);
}
return txt;
@@ -508,10 +533,10 @@ namespace Godot
/// <param name="a">The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1.</param>
public Color(float r, float g, float b, float a = 1.0f)
{
- this.r = r;
- this.g = g;
- this.b = b;
- this.a = a;
+ R = r;
+ G = g;
+ B = b;
+ A = a;
}
/// <summary>
@@ -521,10 +546,10 @@ namespace Godot
/// <param name="a">The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1.</param>
public Color(Color c, float a = 1.0f)
{
- r = c.r;
- g = c.g;
- b = c.b;
- this.a = a;
+ R = c.R;
+ G = c.G;
+ B = c.B;
+ A = a;
}
/// <summary>
@@ -534,13 +559,13 @@ namespace Godot
/// <param name="rgba">The <see langword="uint"/> representing the color.</param>
public Color(uint rgba)
{
- a = (rgba & 0xFF) / 255.0f;
+ A = (rgba & 0xFF) / 255.0f;
rgba >>= 8;
- b = (rgba & 0xFF) / 255.0f;
+ B = (rgba & 0xFF) / 255.0f;
rgba >>= 8;
- g = (rgba & 0xFF) / 255.0f;
+ G = (rgba & 0xFF) / 255.0f;
rgba >>= 8;
- r = (rgba & 0xFF) / 255.0f;
+ R = (rgba & 0xFF) / 255.0f;
}
/// <summary>
@@ -550,13 +575,13 @@ namespace Godot
/// <param name="rgba">The <see langword="ulong"/> representing the color.</param>
public Color(ulong rgba)
{
- a = (rgba & 0xFFFF) / 65535.0f;
+ A = (rgba & 0xFFFF) / 65535.0f;
rgba >>= 16;
- b = (rgba & 0xFFFF) / 65535.0f;
+ B = (rgba & 0xFFFF) / 65535.0f;
rgba >>= 16;
- g = (rgba & 0xFFFF) / 65535.0f;
+ G = (rgba & 0xFFFF) / 65535.0f;
rgba >>= 16;
- r = (rgba & 0xFFFF) / 65535.0f;
+ R = (rgba & 0xFFFF) / 65535.0f;
}
/// <summary>
@@ -565,11 +590,15 @@ namespace Godot
/// <see cref="Colors"/> constants.
/// </summary>
/// <param name="code">The HTML color code or color name to construct from.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// A color cannot be inferred from the given <paramref name="code"/>.
+ /// It was invalid HTML and a color with that name was not found.
+ /// </exception>
public Color(string code)
{
if (HtmlIsValid(code))
{
- this = FromHTML(code);
+ this = FromHtml(code);
}
else
{
@@ -587,7 +616,7 @@ namespace Godot
public Color(string code, float alpha)
{
this = new Color(code);
- a = alpha;
+ A = alpha;
}
/// <summary>
@@ -597,15 +626,15 @@ namespace Godot
/// <exception name="ArgumentOutOfRangeException">
/// <paramref name="rgba"/> color code is invalid.
/// </exception>
- private static Color FromHTML(ReadOnlySpan<char> rgba)
+ public static Color FromHtml(ReadOnlySpan<char> rgba)
{
Color c;
if (rgba.Length == 0)
{
- c.r = 0f;
- c.g = 0f;
- c.b = 0f;
- c.a = 1.0f;
+ c.R = 0f;
+ c.G = 0f;
+ c.B = 0f;
+ c.A = 1.0f;
return c;
}
@@ -641,44 +670,44 @@ namespace Godot
$"Invalid color code. Length is {rgba.Length}, but a length of 6 or 8 is expected: {rgba}");
}
- c.a = 1.0f;
+ c.A = 1.0f;
if (isShorthand)
{
- c.r = ParseCol4(rgba, 0) / 15f;
- c.g = ParseCol4(rgba, 1) / 15f;
- c.b = ParseCol4(rgba, 2) / 15f;
+ c.R = ParseCol4(rgba, 0) / 15f;
+ c.G = ParseCol4(rgba, 1) / 15f;
+ c.B = ParseCol4(rgba, 2) / 15f;
if (alpha)
{
- c.a = ParseCol4(rgba, 3) / 15f;
+ c.A = ParseCol4(rgba, 3) / 15f;
}
}
else
{
- c.r = ParseCol8(rgba, 0) / 255f;
- c.g = ParseCol8(rgba, 2) / 255f;
- c.b = ParseCol8(rgba, 4) / 255f;
+ c.R = ParseCol8(rgba, 0) / 255f;
+ c.G = ParseCol8(rgba, 2) / 255f;
+ c.B = ParseCol8(rgba, 4) / 255f;
if (alpha)
{
- c.a = ParseCol8(rgba, 6) / 255f;
+ c.A = ParseCol8(rgba, 6) / 255f;
}
}
- if (c.r < 0)
+ if (c.R < 0)
{
throw new ArgumentOutOfRangeException($"Invalid color code. Red part is not valid hexadecimal: {rgba}");
}
- if (c.g < 0)
+ if (c.G < 0)
{
throw new ArgumentOutOfRangeException($"Invalid color code. Green part is not valid hexadecimal: {rgba}");
}
- if (c.b < 0)
+ if (c.B < 0)
{
throw new ArgumentOutOfRangeException($"Invalid color code. Blue part is not valid hexadecimal: {rgba}");
}
- if (c.a < 0)
+ if (c.A < 0)
{
throw new ArgumentOutOfRangeException($"Invalid color code. Alpha part is not valid hexadecimal: {rgba}");
}
@@ -705,39 +734,70 @@ namespace Godot
/// the constants defined in <see cref="Colors"/>.
/// </summary>
/// <param name="name">The name of the color.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// A color with the given name is not found.
+ /// </exception>
/// <returns>The constructed color.</returns>
private static Color Named(string name)
{
+ if (!FindNamedColor(name, out Color color))
+ {
+ throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}");
+ }
+
+ return color;
+ }
+
+ /// <summary>
+ /// Returns a color according to the standardized name, with the
+ /// specified alpha value. Supported color names are the same as
+ /// the constants defined in <see cref="Colors"/>.
+ /// If a color with the given name is not found, it returns
+ /// <paramref name="default"/>.
+ /// </summary>
+ /// <param name="name">The name of the color.</param>
+ /// <param name="default">
+ /// The default color to return when a color with the given name
+ /// is not found.
+ /// </param>
+ /// <returns>The constructed color.</returns>
+ private static Color Named(string name, Color @default)
+ {
+ if (!FindNamedColor(name, out Color color))
+ {
+ return @default;
+ }
+
+ return color;
+ }
+
+ private static bool FindNamedColor(string name, out Color color)
+ {
name = name.Replace(" ", string.Empty);
name = name.Replace("-", string.Empty);
name = name.Replace("_", string.Empty);
name = name.Replace("'", string.Empty);
name = name.Replace(".", string.Empty);
- name = name.ToUpper();
-
- if (!Colors.namedColors.ContainsKey(name))
- {
- throw new ArgumentOutOfRangeException($"Invalid Color Name: {name}");
- }
+ name = name.ToUpperInvariant();
- return Colors.namedColors[name];
+ return Colors.namedColors.TryGetValue(name, out color);
}
/// <summary>
- /// Constructs a color from an HSV profile, with values on the
- /// range of 0 to 1. This is equivalent to using each of
- /// the <c>h</c>/<c>s</c>/<c>v</c> properties, but much more efficient.
+ /// Constructs a color from an HSV profile. The <paramref name="hue"/>,
+ /// <paramref name="saturation"/>, and <paramref name="value"/> are typically
+ /// between 0.0 and 1.0.
/// </summary>
/// <param name="hue">The HSV hue, typically on the range of 0 to 1.</param>
/// <param name="saturation">The HSV saturation, typically on the range of 0 to 1.</param>
/// <param name="value">The HSV value (brightness), typically on the range of 0 to 1.</param>
/// <param name="alpha">The alpha (transparency) value, typically on the range of 0 to 1.</param>
/// <returns>The constructed color.</returns>
- public static Color FromHSV(float hue, float saturation, float value, float alpha = 1.0f)
+ public static Color FromHsv(float hue, float saturation, float value, float alpha = 1.0f)
{
if (saturation == 0)
{
- // Achromatic (grey)
+ // Achromatic (gray)
return new Color(value, value, value, alpha);
}
@@ -777,10 +837,10 @@ 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));
+ float max = (float)Mathf.Max(R, Mathf.Max(G, B));
+ float min = (float)Mathf.Min(R, Mathf.Min(G, B));
float delta = max - min;
@@ -790,17 +850,17 @@ namespace Godot
}
else
{
- if (r == max)
+ if (R == max)
{
- hue = (g - b) / delta; // Between yellow & magenta
+ hue = (G - B) / delta; // Between yellow & magenta
}
- else if (g == max)
+ else if (G == max)
{
- hue = 2 + ((b - r) / delta); // Between cyan & yellow
+ hue = 2 + ((B - R) / delta); // Between cyan & yellow
}
else
{
- hue = 4 + ((r - g) / delta); // Between magenta & cyan
+ hue = 4 + ((R - G) / delta); // Between magenta & cyan
}
hue /= 6.0f;
@@ -841,13 +901,78 @@ namespace Godot
return ParseCol4(str, index) * 16 + ParseCol4(str, index + 1);
}
+ /// <summary>
+ /// Constructs a color from an OK HSL profile. The <paramref name="hue"/>,
+ /// <paramref name="saturation"/>, and <paramref name="lightness"/> are typically
+ /// between 0.0 and 1.0.
+ /// </summary>
+ /// <param name="hue">The OK HSL hue, typically on the range of 0 to 1.</param>
+ /// <param name="saturation">The OK HSL saturation, typically on the range of 0 to 1.</param>
+ /// <param name="lightness">The OK HSL lightness, typically on the range of 0 to 1.</param>
+ /// <param name="alpha">The alpha (transparency) value, typically on the range of 0 to 1.</param>
+ /// <returns>The constructed color.</returns>
+ public static Color FromOkHsl(float hue, float saturation, float lightness, float alpha = 1.0f)
+ {
+ return NativeFuncs.godotsharp_color_from_ok_hsl(hue, saturation, lightness, alpha);
+ }
+
+ /// <summary>
+ /// Encodes a <see cref="Color"/> from a RGBE9995 format integer.
+ /// See <see cref="Image.Format.Rgbe9995"/>.
+ /// </summary>
+ /// <param name="rgbe">The RGBE9995 encoded color.</param>
+ /// <returns>The constructed color.</returns>
+ public static Color FromRgbe9995(uint rgbe)
+ {
+ float r = rgbe & 0x1ff;
+ float g = (rgbe >> 9) & 0x1ff;
+ float b = (rgbe >> 18) & 0x1ff;
+ float e = rgbe >> 27;
+ float m = (float)Mathf.Pow(2.0f, e - 15.0f - 9.0f);
+
+ float rd = r * m;
+ float gd = g * m;
+ float bd = b * m;
+
+ return new Color(rd, gd, bd, 1.0f);
+ }
+
+ /// <summary>
+ /// Constructs a color from the given string, which can be either an HTML color
+ /// code or a named color. Returns <paramref name="default"/> if the color cannot
+ /// be inferred from the string. Supported color names are the same as the
+ /// <see cref="Colors"/> constants.
+ /// </summary>
+ /// <param name="str">The HTML color code or color name.</param>
+ /// <param name="default">The fallback color to return if the color cannot be inferred.</param>
+ /// <returns>The constructed color.</returns>
+ public static Color FromString(string str, Color @default)
+ {
+ if (HtmlIsValid(str))
+ {
+ return FromHtml(str);
+ }
+ else
+ {
+ return Named(str, @default);
+ }
+ }
+
private static string ToHex32(float val)
{
byte b = (byte)Mathf.RoundToInt(Mathf.Clamp(val * 255, 0, 255));
return b.HexEncode();
}
- internal static bool HtmlIsValid(ReadOnlySpan<char> color)
+ /// <summary>
+ /// Returns <see langword="true"/> if <paramref name="color"/> is a valid HTML hexadecimal
+ /// color string. The string must be a hexadecimal value (case-insensitive) of either 3,
+ /// 4, 6 or 8 digits, and may be prefixed by a hash sign (<c>#</c>). This method is
+ /// identical to <see cref="StringExtensions.IsValidHtmlColor(string)"/>.
+ /// </summary>
+ /// <param name="color">The HTML hexadecimal color string.</param>
+ /// <returns>Whether or not the string was a valid HTML hexadecimal color string.</returns>
+ public static bool HtmlIsValid(ReadOnlySpan<char> color)
{
if (color.IsEmpty)
{
@@ -887,10 +1012,10 @@ namespace Godot
/// <returns>The added color.</returns>
public static Color operator +(Color left, Color right)
{
- left.r += right.r;
- left.g += right.g;
- left.b += right.b;
- left.a += right.a;
+ left.R += right.R;
+ left.G += right.G;
+ left.B += right.B;
+ left.A += right.A;
return left;
}
@@ -903,17 +1028,17 @@ namespace Godot
/// <returns>The subtracted color.</returns>
public static Color operator -(Color left, Color right)
{
- left.r -= right.r;
- left.g -= right.g;
- left.b -= right.b;
- left.a -= right.a;
+ left.R -= right.R;
+ left.G -= right.G;
+ left.B -= right.B;
+ left.A -= right.A;
return left;
}
/// <summary>
/// Inverts the given color. This is equivalent to
/// <c>Colors.White - c</c> or
- /// <c>new Color(1 - c.r, 1 - c.g, 1 - c.b, 1 - c.a)</c>.
+ /// <c>new Color(1 - c.R, 1 - c.G, 1 - c.B, 1 - c.A)</c>.
/// </summary>
/// <param name="color">The color to invert.</param>
/// <returns>The inverted color.</returns>
@@ -931,10 +1056,10 @@ namespace Godot
/// <returns>The multiplied color.</returns>
public static Color operator *(Color color, float scale)
{
- color.r *= scale;
- color.g *= scale;
- color.b *= scale;
- color.a *= scale;
+ color.R *= scale;
+ color.G *= scale;
+ color.B *= scale;
+ color.A *= scale;
return color;
}
@@ -947,10 +1072,10 @@ namespace Godot
/// <returns>The multiplied color.</returns>
public static Color operator *(float scale, Color color)
{
- color.r *= scale;
- color.g *= scale;
- color.b *= scale;
- color.a *= scale;
+ color.R *= scale;
+ color.G *= scale;
+ color.B *= scale;
+ color.A *= scale;
return color;
}
@@ -963,10 +1088,10 @@ namespace Godot
/// <returns>The multiplied color.</returns>
public static Color operator *(Color left, Color right)
{
- left.r *= right.r;
- left.g *= right.g;
- left.b *= right.b;
- left.a *= right.a;
+ left.R *= right.R;
+ left.G *= right.G;
+ left.B *= right.B;
+ left.A *= right.A;
return left;
}
@@ -979,10 +1104,10 @@ namespace Godot
/// <returns>The divided color.</returns>
public static Color operator /(Color color, float scale)
{
- color.r /= scale;
- color.g /= scale;
- color.b /= scale;
- color.a /= scale;
+ color.R /= scale;
+ color.G /= scale;
+ color.B /= scale;
+ color.A /= scale;
return color;
}
@@ -995,10 +1120,10 @@ namespace Godot
/// <returns>The divided color.</returns>
public static Color operator /(Color left, Color right)
{
- left.r /= right.r;
- left.g /= right.g;
- left.b /= right.b;
- left.a /= right.a;
+ left.R /= right.R;
+ left.G /= right.G;
+ left.B /= right.B;
+ left.A /= right.A;
return left;
}
@@ -1042,19 +1167,19 @@ namespace Godot
/// <returns>Whether or not the left is less than the right.</returns>
public static bool operator <(Color left, Color right)
{
- if (left.r == right.r)
+ if (left.R == right.R)
{
- if (left.g == right.g)
+ if (left.G == right.G)
{
- if (left.b == right.b)
+ if (left.B == right.B)
{
- return left.a < right.a;
+ return left.A < right.A;
}
- return left.b < right.b;
+ return left.B < right.B;
}
- return left.g < right.g;
+ return left.G < right.G;
}
- return left.r < right.r;
+ return left.R < right.R;
}
/// <summary>
@@ -1071,19 +1196,19 @@ namespace Godot
/// <returns>Whether or not the left is greater than the right.</returns>
public static bool operator >(Color left, Color right)
{
- if (left.r == right.r)
+ if (left.R == right.R)
{
- if (left.g == right.g)
+ if (left.G == right.G)
{
- if (left.b == right.b)
+ if (left.B == right.B)
{
- return left.a > right.a;
+ return left.A > right.A;
}
- return left.b > right.b;
+ return left.B > right.B;
}
- return left.g > right.g;
+ return left.G > right.G;
}
- return left.r > right.r;
+ return left.R > right.R;
}
/// <summary>
@@ -1100,19 +1225,19 @@ namespace Godot
/// <returns>Whether or not the left is less than or equal to the right.</returns>
public static bool operator <=(Color left, Color right)
{
- if (left.r == right.r)
+ if (left.R == right.R)
{
- if (left.g == right.g)
+ if (left.G == right.G)
{
- if (left.b == right.b)
+ if (left.B == right.B)
{
- return left.a <= right.a;
+ return left.A <= right.A;
}
- return left.b < right.b;
+ return left.B < right.B;
}
- return left.g < right.g;
+ return left.G < right.G;
}
- return left.r < right.r;
+ return left.R < right.R;
}
/// <summary>
@@ -1129,19 +1254,19 @@ namespace Godot
/// <returns>Whether or not the left is greater than or equal to the right.</returns>
public static bool operator >=(Color left, Color right)
{
- if (left.r == right.r)
+ if (left.R == right.R)
{
- if (left.g == right.g)
+ if (left.G == right.G)
{
- if (left.b == right.b)
+ if (left.B == right.B)
{
- return left.a >= right.a;
+ return left.A >= right.A;
}
- return left.b > right.b;
+ return left.B > right.B;
}
- return left.g > right.g;
+ return left.G > right.G;
}
- return left.r > right.r;
+ return left.R > right.R;
}
/// <summary>
@@ -1149,7 +1274,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,9 +1286,9 @@ 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;
+ return R == other.R && G == other.G && B == other.B && A == other.A;
}
/// <summary>
@@ -1172,36 +1297,36 @@ 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);
+ return Mathf.IsEqualApprox(R, other.R) && Mathf.IsEqualApprox(G, other.G) && Mathf.IsEqualApprox(B, other.B) && Mathf.IsEqualApprox(A, other.A);
}
/// <summary>
/// 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();
+ return R.GetHashCode() ^ G.GetHashCode() ^ B.GetHashCode() ^ A.GetHashCode();
}
/// <summary>
/// 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})";
+ return $"({R}, {G}, {B}, {A})";
}
/// <summary>
/// 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)})";
+ return $"({R.ToString(format)}, {G.ToString(format)}, {B.ToString(format)}, {A.ToString(format)})";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
index d19e0c08f2..4a54f67cc9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
@@ -126,7 +126,7 @@ namespace Godot
}
}
// ReSharper disable once RedundantNameQualifier
- case Godot.Object godotObject:
+ case GodotObject godotObject:
{
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
@@ -186,7 +186,7 @@ namespace Godot
writer.Write(field.Name);
var fieldValue = field.GetValue(target);
- using var fieldValueVariant = Marshaling.ConvertManagedObjectToVariant(fieldValue);
+ using var fieldValueVariant = RuntimeTypeConversionHelper.ConvertToVariant(fieldValue);
byte[] valueBuffer = VarToBytes(fieldValueVariant);
writer.Write(valueBuffer.Length);
writer.Write(valueBuffer);
@@ -399,7 +399,7 @@ namespace Godot
{
ulong objectId = reader.ReadUInt64();
// ReSharper disable once RedundantNameQualifier
- Godot.Object godotObject = GD.InstanceFromId(objectId);
+ GodotObject godotObject = GodotObject.InstanceFromId(objectId);
if (godotObject == null)
return false;
@@ -443,7 +443,14 @@ namespace Godot
FieldInfo? fieldInfo = targetType.GetField(name,
BindingFlags.Instance | BindingFlags.Public);
- fieldInfo?.SetValue(recreatedTarget, GD.BytesToVar(valueBuffer));
+
+ if (fieldInfo != null)
+ {
+ var variantValue = GD.BytesToVar(valueBuffer);
+ object? managedValue = RuntimeTypeConversionHelper.ConvertToObjectOfType(
+ (godot_variant)variantValue.NativeVar, fieldInfo.FieldType);
+ fieldInfo.SetValue(recreatedTarget, managedValue);
+ }
}
@delegate = Delegate.CreateDelegate(delegateType, recreatedTarget, methodInfo,
@@ -537,5 +544,289 @@ namespace Godot
return type;
}
+
+ internal static class RuntimeTypeConversionHelper
+ {
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static godot_variant ConvertToVariant(object? obj)
+ {
+ if (obj == null)
+ return default;
+
+ switch (obj)
+ {
+ case bool @bool:
+ return VariantUtils.CreateFrom(@bool);
+ case char @char:
+ return VariantUtils.CreateFrom(@char);
+ case sbyte int8:
+ return VariantUtils.CreateFrom(int8);
+ case short int16:
+ return VariantUtils.CreateFrom(int16);
+ case int int32:
+ return VariantUtils.CreateFrom(int32);
+ case long int64:
+ return VariantUtils.CreateFrom(int64);
+ case byte uint8:
+ return VariantUtils.CreateFrom(uint8);
+ case ushort uint16:
+ return VariantUtils.CreateFrom(uint16);
+ case uint uint32:
+ return VariantUtils.CreateFrom(uint32);
+ case ulong uint64:
+ return VariantUtils.CreateFrom(uint64);
+ case float @float:
+ return VariantUtils.CreateFrom(@float);
+ case double @double:
+ return VariantUtils.CreateFrom(@double);
+ case Vector2 vector2:
+ return VariantUtils.CreateFrom(vector2);
+ case Vector2I vector2I:
+ return VariantUtils.CreateFrom(vector2I);
+ case Rect2 rect2:
+ return VariantUtils.CreateFrom(rect2);
+ case Rect2I rect2I:
+ return VariantUtils.CreateFrom(rect2I);
+ case Transform2D transform2D:
+ return VariantUtils.CreateFrom(transform2D);
+ case Vector3 vector3:
+ return VariantUtils.CreateFrom(vector3);
+ case Vector3I vector3I:
+ return VariantUtils.CreateFrom(vector3I);
+ case Vector4 vector4:
+ return VariantUtils.CreateFrom(vector4);
+ case Vector4I vector4I:
+ return VariantUtils.CreateFrom(vector4I);
+ case Basis basis:
+ return VariantUtils.CreateFrom(basis);
+ case Quaternion quaternion:
+ return VariantUtils.CreateFrom(quaternion);
+ case Transform3D transform3D:
+ return VariantUtils.CreateFrom(transform3D);
+ case Projection projection:
+ return VariantUtils.CreateFrom(projection);
+ case Aabb aabb:
+ return VariantUtils.CreateFrom(aabb);
+ case Color color:
+ return VariantUtils.CreateFrom(color);
+ case Plane plane:
+ return VariantUtils.CreateFrom(plane);
+ case Callable callable:
+ return VariantUtils.CreateFrom(callable);
+ case Signal signal:
+ return VariantUtils.CreateFrom(signal);
+ case string @string:
+ return VariantUtils.CreateFrom(@string);
+ case byte[] byteArray:
+ return VariantUtils.CreateFrom(byteArray);
+ case int[] int32Array:
+ return VariantUtils.CreateFrom(int32Array);
+ case long[] int64Array:
+ return VariantUtils.CreateFrom(int64Array);
+ case float[] floatArray:
+ return VariantUtils.CreateFrom(floatArray);
+ case double[] doubleArray:
+ return VariantUtils.CreateFrom(doubleArray);
+ case string[] stringArray:
+ return VariantUtils.CreateFrom(stringArray);
+ case Vector2[] vector2Array:
+ return VariantUtils.CreateFrom(vector2Array);
+ case Vector3[] vector3Array:
+ return VariantUtils.CreateFrom(vector3Array);
+ case Color[] colorArray:
+ return VariantUtils.CreateFrom(colorArray);
+ case StringName[] stringNameArray:
+ return VariantUtils.CreateFrom(stringNameArray);
+ case NodePath[] nodePathArray:
+ return VariantUtils.CreateFrom(nodePathArray);
+ case Rid[] ridArray:
+ return VariantUtils.CreateFrom(ridArray);
+ case GodotObject[] godotObjectArray:
+ return VariantUtils.CreateFrom(godotObjectArray);
+ case StringName stringName:
+ return VariantUtils.CreateFrom(stringName);
+ case NodePath nodePath:
+ return VariantUtils.CreateFrom(nodePath);
+ case Rid rid:
+ return VariantUtils.CreateFrom(rid);
+ case Collections.Dictionary godotDictionary:
+ return VariantUtils.CreateFrom(godotDictionary);
+ case Collections.Array godotArray:
+ return VariantUtils.CreateFrom(godotArray);
+ case Variant variant:
+ return VariantUtils.CreateFrom(variant);
+ case GodotObject godotObject:
+ return VariantUtils.CreateFrom(godotObject);
+ case Enum @enum:
+ return VariantUtils.CreateFrom(Convert.ToInt64(@enum));
+ case Collections.IGenericGodotDictionary godotDictionary:
+ return VariantUtils.CreateFrom(godotDictionary.UnderlyingDictionary);
+ case Collections.IGenericGodotArray godotArray:
+ return VariantUtils.CreateFrom(godotArray.UnderlyingArray);
+ }
+
+ GD.PushError("Attempted to convert an unmarshallable managed type to Variant. Name: '" +
+ obj.GetType().FullName + ".");
+ return new godot_variant();
+ }
+
+ private delegate object? ConvertToSystemObjectFunc(in godot_variant managed);
+
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ // ReSharper disable once RedundantNameQualifier
+ private static readonly System.Collections.Generic.Dictionary<Type, ConvertToSystemObjectFunc>
+ ToSystemObjectFuncByType = new()
+ {
+ [typeof(bool)] = (in godot_variant variant) => VariantUtils.ConvertTo<bool>(variant),
+ [typeof(char)] = (in godot_variant variant) => VariantUtils.ConvertTo<char>(variant),
+ [typeof(sbyte)] = (in godot_variant variant) => VariantUtils.ConvertTo<sbyte>(variant),
+ [typeof(short)] = (in godot_variant variant) => VariantUtils.ConvertTo<short>(variant),
+ [typeof(int)] = (in godot_variant variant) => VariantUtils.ConvertTo<int>(variant),
+ [typeof(long)] = (in godot_variant variant) => VariantUtils.ConvertTo<long>(variant),
+ [typeof(byte)] = (in godot_variant variant) => VariantUtils.ConvertTo<byte>(variant),
+ [typeof(ushort)] = (in godot_variant variant) => VariantUtils.ConvertTo<ushort>(variant),
+ [typeof(uint)] = (in godot_variant variant) => VariantUtils.ConvertTo<uint>(variant),
+ [typeof(ulong)] = (in godot_variant variant) => VariantUtils.ConvertTo<ulong>(variant),
+ [typeof(float)] = (in godot_variant variant) => VariantUtils.ConvertTo<float>(variant),
+ [typeof(double)] = (in godot_variant variant) => VariantUtils.ConvertTo<double>(variant),
+ [typeof(Vector2)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector2>(variant),
+ [typeof(Vector2I)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector2I>(variant),
+ [typeof(Rect2)] = (in godot_variant variant) => VariantUtils.ConvertTo<Rect2>(variant),
+ [typeof(Rect2I)] = (in godot_variant variant) => VariantUtils.ConvertTo<Rect2I>(variant),
+ [typeof(Transform2D)] = (in godot_variant variant) => VariantUtils.ConvertTo<Transform2D>(variant),
+ [typeof(Vector3)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector3>(variant),
+ [typeof(Vector3I)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector3I>(variant),
+ [typeof(Basis)] = (in godot_variant variant) => VariantUtils.ConvertTo<Basis>(variant),
+ [typeof(Quaternion)] = (in godot_variant variant) => VariantUtils.ConvertTo<Quaternion>(variant),
+ [typeof(Transform3D)] = (in godot_variant variant) => VariantUtils.ConvertTo<Transform3D>(variant),
+ [typeof(Vector4)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector4>(variant),
+ [typeof(Vector4I)] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector4I>(variant),
+ [typeof(Aabb)] = (in godot_variant variant) => VariantUtils.ConvertTo<Aabb>(variant),
+ [typeof(Color)] = (in godot_variant variant) => VariantUtils.ConvertTo<Color>(variant),
+ [typeof(Plane)] = (in godot_variant variant) => VariantUtils.ConvertTo<Plane>(variant),
+ [typeof(Callable)] = (in godot_variant variant) => VariantUtils.ConvertTo<Callable>(variant),
+ [typeof(Signal)] = (in godot_variant variant) => VariantUtils.ConvertTo<Signal>(variant),
+ [typeof(string)] = (in godot_variant variant) => VariantUtils.ConvertTo<string>(variant),
+ [typeof(byte[])] = (in godot_variant variant) => VariantUtils.ConvertTo<byte[]>(variant),
+ [typeof(int[])] = (in godot_variant variant) => VariantUtils.ConvertTo<int[]>(variant),
+ [typeof(long[])] = (in godot_variant variant) => VariantUtils.ConvertTo<long[]>(variant),
+ [typeof(float[])] = (in godot_variant variant) => VariantUtils.ConvertTo<float[]>(variant),
+ [typeof(double[])] = (in godot_variant variant) => VariantUtils.ConvertTo<double[]>(variant),
+ [typeof(string[])] = (in godot_variant variant) => VariantUtils.ConvertTo<string[]>(variant),
+ [typeof(Vector2[])] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector2[]>(variant),
+ [typeof(Vector3[])] = (in godot_variant variant) => VariantUtils.ConvertTo<Vector3[]>(variant),
+ [typeof(Color[])] = (in godot_variant variant) => VariantUtils.ConvertTo<Color[]>(variant),
+ [typeof(StringName[])] =
+ (in godot_variant variant) => VariantUtils.ConvertTo<StringName[]>(variant),
+ [typeof(NodePath[])] = (in godot_variant variant) => VariantUtils.ConvertTo<NodePath[]>(variant),
+ [typeof(Rid[])] = (in godot_variant variant) => VariantUtils.ConvertTo<Rid[]>(variant),
+ [typeof(StringName)] = (in godot_variant variant) => VariantUtils.ConvertTo<StringName>(variant),
+ [typeof(NodePath)] = (in godot_variant variant) => VariantUtils.ConvertTo<NodePath>(variant),
+ [typeof(Rid)] = (in godot_variant variant) => VariantUtils.ConvertTo<Rid>(variant),
+ [typeof(Godot.Collections.Dictionary)] = (in godot_variant variant) =>
+ VariantUtils.ConvertTo<Godot.Collections.Dictionary>(variant),
+ [typeof(Godot.Collections.Array)] =
+ (in godot_variant variant) => VariantUtils.ConvertTo<Godot.Collections.Array>(variant),
+ [typeof(Variant)] = (in godot_variant variant) => VariantUtils.ConvertTo<Variant>(variant),
+ };
+
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static object? ConvertToObjectOfType(in godot_variant variant, Type type)
+ {
+ if (ToSystemObjectFuncByType.TryGetValue(type, out var func))
+ return func(variant);
+
+ if (typeof(GodotObject).IsAssignableFrom(type))
+ return Convert.ChangeType(VariantUtils.ConvertTo<GodotObject>(variant), type);
+
+ if (typeof(GodotObject[]).IsAssignableFrom(type))
+ {
+ static GodotObject[] ConvertToSystemArrayOfGodotObject(in godot_array nativeArray, Type type)
+ {
+ var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_array_new_copy(nativeArray));
+
+ int length = array.Count;
+ var ret = (GodotObject[])Activator.CreateInstance(type, length)!;
+
+ for (int i = 0; i < length; i++)
+ ret[i] = array[i].AsGodotObject();
+
+ return ret;
+ }
+
+ using var godotArray = NativeFuncs.godotsharp_variant_as_array(variant);
+ return Convert.ChangeType(ConvertToSystemArrayOfGodotObject(godotArray, type), type);
+ }
+
+ if (type.IsEnum)
+ {
+ var enumUnderlyingType = type.GetEnumUnderlyingType();
+
+ switch (Type.GetTypeCode(enumUnderlyingType))
+ {
+ case TypeCode.SByte:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt8(variant));
+ case TypeCode.Int16:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt16(variant));
+ case TypeCode.Int32:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt32(variant));
+ case TypeCode.Int64:
+ return Enum.ToObject(type, VariantUtils.ConvertToInt64(variant));
+ case TypeCode.Byte:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt8(variant));
+ case TypeCode.UInt16:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt16(variant));
+ case TypeCode.UInt32:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt32(variant));
+ case TypeCode.UInt64:
+ return Enum.ToObject(type, VariantUtils.ConvertToUInt64(variant));
+ default:
+ {
+ GD.PushError(
+ "Attempted to convert Variant to enum value of unsupported underlying type. Name: " +
+ type.FullName + " : " + enumUnderlyingType.FullName + ".");
+ return null;
+ }
+ }
+ }
+
+ if (type.IsGenericType)
+ {
+ var genericTypeDef = type.GetGenericTypeDefinition();
+
+ if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>))
+ {
+ var ctor = type.GetConstructor(BindingFlags.Default,
+ new[] { typeof(Godot.Collections.Dictionary) });
+
+ if (ctor == null)
+ throw new InvalidOperationException("Dictionary constructor not found");
+
+ return ctor.Invoke(new object?[]
+ {
+ VariantUtils.ConvertTo<Godot.Collections.Dictionary>(variant)
+ });
+ }
+
+ if (genericTypeDef == typeof(Godot.Collections.Array<>))
+ {
+ var ctor = type.GetConstructor(BindingFlags.Default,
+ new[] { typeof(Godot.Collections.Array) });
+
+ if (ctor == null)
+ throw new InvalidOperationException("Array constructor not found");
+
+ return ctor.Invoke(new object?[]
+ {
+ VariantUtils.ConvertTo<Godot.Collections.Array>(variant)
+ });
+ }
+ }
+
+ GD.PushError($"Attempted to convert Variant to unsupported type. Name: {type.FullName}.");
+ return null;
+ }
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index f8793332a0..923b2adafd 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -68,7 +68,15 @@ namespace Godot.Collections
}
/// <summary>
- /// Duplicates this <see cref="Dictionary"/>.
+ /// Returns a copy of the <see cref="Dictionary"/>.
+ /// If <paramref name="deep"/> is <see langword="true"/>, a deep copy is performed:
+ /// all nested arrays and dictionaries are duplicated and will not be shared with
+ /// the original dictionary. If <see langword="false"/>, a shallow copy is made and
+ /// references to the original nested arrays and dictionaries are kept, so that
+ /// modifying a sub-array or dictionary in the copy will also impact those
+ /// referenced in the source dictionary. Note that any <see cref="GodotObject"/> derived
+ /// elements will be shallow copied regardless of the <paramref name="deep"/>
+ /// setting.
/// </summary>
/// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
/// <returns>A new Godot Dictionary.</returns>
@@ -80,6 +88,44 @@ namespace Godot.Collections
return CreateTakingOwnershipOfDisposableValue(newDictionary);
}
+ /// <summary>
+ /// Adds entries from <paramref name="dictionary"/> to this dictionary.
+ /// By default, duplicate keys are not copied over, unless <paramref name="overwrite"/>
+ /// is <see langword="true"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
+ /// <param name="dictionary">Dictionary to copy entries from.</param>
+ /// <param name="overwrite">If duplicate keys should be copied over as well.</param>
+ public void Merge(Dictionary dictionary, bool overwrite = false)
+ {
+ ThrowIfReadOnly();
+
+ var self = (godot_dictionary)NativeValue;
+ var other = (godot_dictionary)dictionary.NativeValue;
+ NativeFuncs.godotsharp_dictionary_merge(ref self, in other, overwrite.ToGodotBool());
+ }
+
+ /// <summary>
+ /// Compares this <see cref="Dictionary"/> against the <paramref name="other"/>
+ /// <see cref="Dictionary"/> recursively. Returns <see langword="true"/> if the
+ /// two dictionaries contain the same keys and values. The order of the entries
+ /// does not matter.
+ /// otherwise.
+ /// </summary>
+ /// <param name="other">The other dictionary to compare against.</param>
+ /// <returns>
+ /// <see langword="true"/> if the dictionaries contain the same keys and values,
+ /// <see langword="false"/> otherwise.
+ /// </returns>
+ public bool RecursiveEqual(Dictionary other)
+ {
+ var self = (godot_dictionary)NativeValue;
+ var otherVariant = (godot_dictionary)other.NativeValue;
+ return NativeFuncs.godotsharp_dictionary_recursive_equal(ref self, otherVariant).ToBool();
+ }
+
// IDictionary
/// <summary>
@@ -134,6 +180,13 @@ namespace Godot.Collections
/// <summary>
/// Returns the value at the given <paramref name="key"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The property is assigned and the dictionary is read-only.
+ /// </exception>
+ /// <exception cref="KeyNotFoundException">
+ /// The property is retrieved and an entry for <paramref name="key"/>
+ /// does not exist in the dictionary.
+ /// </exception>
/// <value>The value at the given <paramref name="key"/>.</value>
public Variant this[Variant key]
{
@@ -153,6 +206,8 @@ namespace Godot.Collections
}
set
{
+ ThrowIfReadOnly();
+
var self = (godot_dictionary)NativeValue;
NativeFuncs.godotsharp_dictionary_set_value(ref self,
(godot_variant)key.NativeVar, (godot_variant)value.NativeVar);
@@ -163,10 +218,18 @@ namespace Godot.Collections
/// Adds an value <paramref name="value"/> at key <paramref name="key"/>
/// to this <see cref="Dictionary"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// An entry for <paramref name="key"/> already exists in the dictionary.
+ /// </exception>
/// <param name="key">The key at which to add the value.</param>
/// <param name="value">The value to add.</param>
public void Add(Variant key, Variant value)
{
+ ThrowIfReadOnly();
+
var variantKey = (godot_variant)key.NativeVar;
var self = (godot_dictionary)NativeValue;
@@ -181,10 +244,15 @@ namespace Godot.Collections
=> Add(item.Key, item.Value);
/// <summary>
- /// Erases all items from this <see cref="Dictionary"/>.
+ /// Clears the dictionary, removing all entries from it.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
public void Clear()
{
+ ThrowIfReadOnly();
+
var self = (godot_dictionary)NativeValue;
NativeFuncs.godotsharp_dictionary_clear(ref self);
}
@@ -200,7 +268,7 @@ namespace Godot.Collections
return NativeFuncs.godotsharp_dictionary_contains_key(ref self, (godot_variant)key.NativeVar).ToBool();
}
- public bool Contains(KeyValuePair<Variant, Variant> item)
+ bool ICollection<KeyValuePair<Variant, Variant>>.Contains(KeyValuePair<Variant, Variant> item)
{
godot_variant variantKey = (godot_variant)item.Key.NativeVar;
var self = (godot_dictionary)NativeValue;
@@ -220,15 +288,22 @@ namespace Godot.Collections
/// <summary>
/// Removes an element from this <see cref="Dictionary"/> by key.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
/// <param name="key">The key of the element to remove.</param>
public bool Remove(Variant key)
{
+ ThrowIfReadOnly();
+
var self = (godot_dictionary)NativeValue;
return NativeFuncs.godotsharp_dictionary_remove_key(ref self, (godot_variant)key.NativeVar).ToBool();
}
- public bool Remove(KeyValuePair<Variant, Variant> item)
+ bool ICollection<KeyValuePair<Variant, Variant>>.Remove(KeyValuePair<Variant, Variant> item)
{
+ ThrowIfReadOnly();
+
godot_variant variantKey = (godot_variant)item.Key.NativeVar;
var self = (godot_dictionary)NativeValue;
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
@@ -264,8 +339,37 @@ namespace Godot.Collections
}
}
- bool ICollection<KeyValuePair<Variant, Variant>>.IsReadOnly => false;
+ /// <summary>
+ /// Returns <see langword="true"/> if the dictionary is read-only.
+ /// See <see cref="MakeReadOnly"/>.
+ /// </summary>
+ public bool IsReadOnly => NativeValue.DangerousSelfRef.IsReadOnly;
+ /// <summary>
+ /// Makes the <see cref="Dictionary"/> read-only, i.e. disabled modying of the
+ /// dictionary's elements. Does not apply to nested content, e.g. content of
+ /// nested dictionaries.
+ /// </summary>
+ public void MakeReadOnly()
+ {
+ if (IsReadOnly)
+ {
+ // Avoid interop call when the dictionary is already read-only.
+ return;
+ }
+
+ var self = (godot_dictionary)NativeValue;
+ NativeFuncs.godotsharp_dictionary_make_read_only(ref self);
+ }
+
+ /// <summary>
+ /// Gets the value for the given <paramref name="key"/> in the dictionary.
+ /// Returns <see langword="true"/> if an entry for the given key exists in
+ /// the dictionary; otherwise, returns <see langword="false"/>.
+ /// </summary>
+ /// <param name="key">The key of the element to get.</param>
+ /// <param name="value">The value at the given <paramref name="key"/>.</param>
+ /// <returns>If an entry was found for the given <paramref name="key"/>.</returns>
public bool TryGetValue(Variant key, out Variant value)
{
var self = (godot_dictionary)NativeValue;
@@ -283,7 +387,7 @@ namespace Godot.Collections
/// </summary>
/// <param name="array">The array to copy to.</param>
/// <param name="arrayIndex">The index to start at.</param>
- public void CopyTo(KeyValuePair<Variant, Variant>[] array, int arrayIndex)
+ void ICollection<KeyValuePair<Variant, Variant>>.CopyTo(KeyValuePair<Variant, Variant>[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
@@ -342,6 +446,19 @@ namespace Godot.Collections
using (str)
return Marshaling.ConvertStringToManaged(str);
}
+
+ private void ThrowIfReadOnly()
+ {
+ if (IsReadOnly)
+ {
+ throw new InvalidOperationException("Dictionary instance is read-only.");
+ }
+ }
+ }
+
+ internal interface IGenericGodotDictionary
+ {
+ public Dictionary UnderlyingDictionary { get; }
}
/// <summary>
@@ -354,57 +471,25 @@ namespace Godot.Collections
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
public class Dictionary<[MustBeVariant] TKey, [MustBeVariant] TValue> :
IDictionary<TKey, TValue>,
- IReadOnlyDictionary<TKey, TValue>
+ IReadOnlyDictionary<TKey, TValue>,
+ IGenericGodotDictionary
{
private static godot_variant ToVariantFunc(in Dictionary<TKey, TValue> godotDictionary) =>
VariantUtils.CreateFromDictionary(godotDictionary);
private static Dictionary<TKey, TValue> FromVariantFunc(in godot_variant variant) =>
- VariantUtils.ConvertToDictionaryObject<TKey, TValue>(variant);
-
- // ReSharper disable StaticMemberInGenericType
- // Warning is about unique static fields being created for each generic type combination:
- // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
- // In our case this is exactly what we want.
-
- private static readonly unsafe delegate* managed<in TKey, godot_variant> ConvertKeyToVariantCallback;
- private static readonly unsafe delegate* managed<in godot_variant, TKey> ConvertKeyToManagedCallback;
- private static readonly unsafe delegate* managed<in TValue, godot_variant> ConvertValueToVariantCallback;
- private static readonly unsafe delegate* managed<in godot_variant, TValue> ConvertValueToManagedCallback;
-
- // ReSharper restore StaticMemberInGenericType
+ VariantUtils.ConvertToDictionary<TKey, TValue>(variant);
static unsafe Dictionary()
{
- VariantConversionCallbacks.GenericConversionCallbacks[typeof(Dictionary<TKey, TValue>)] =
- (
- (IntPtr)(delegate* managed<in Dictionary<TKey, TValue>, godot_variant>)&ToVariantFunc,
- (IntPtr)(delegate* managed<in godot_variant, Dictionary<TKey, TValue>>)&FromVariantFunc
- );
-
- ConvertKeyToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<TKey>();
- ConvertKeyToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<TKey>();
- ConvertValueToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<TValue>();
- ConvertValueToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<TValue>();
- }
-
- private static unsafe void ValidateVariantConversionCallbacks()
- {
- if (ConvertKeyToVariantCallback == null || ConvertKeyToManagedCallback == null)
- {
- throw new InvalidOperationException(
- $"The dictionary key type is not supported for conversion to Variant: '{typeof(TKey).FullName}'.");
- }
-
- if (ConvertValueToVariantCallback == null || ConvertValueToManagedCallback == null)
- {
- throw new InvalidOperationException(
- $"The dictionary value type is not supported for conversion to Variant: '{typeof(TValue).FullName}'.");
- }
+ VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.ToVariantCb = &ToVariantFunc;
+ VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.FromVariantCb = &FromVariantFunc;
}
private readonly Dictionary _underlyingDict;
+ Dictionary IGenericGodotDictionary.UnderlyingDictionary => _underlyingDict;
+
internal ref godot_dictionary.movable NativeValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -416,8 +501,6 @@ namespace Godot.Collections
/// </summary>
public Dictionary()
{
- ValidateVariantConversionCallbacks();
-
_underlyingDict = new Dictionary();
}
@@ -428,8 +511,6 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(IDictionary<TKey, TValue> dictionary)
{
- ValidateVariantConversionCallbacks();
-
if (dictionary == null)
throw new ArgumentNullException(nameof(dictionary));
@@ -446,8 +527,6 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(Dictionary dictionary)
{
- ValidateVariantConversionCallbacks();
-
_underlyingDict = dictionary;
}
@@ -466,33 +545,77 @@ namespace Godot.Collections
}
/// <summary>
- /// Duplicates this <see cref="Dictionary{TKey, TValue}"/>.
+ /// Returns a copy of the <see cref="Dictionary{TKey, TValue}"/>.
+ /// If <paramref name="deep"/> is <see langword="true"/>, a deep copy is performed:
+ /// all nested arrays and dictionaries are duplicated and will not be shared with
+ /// the original dictionary. If <see langword="false"/>, a shallow copy is made and
+ /// references to the original nested arrays and dictionaries are kept, so that
+ /// modifying a sub-array or dictionary in the copy will also impact those
+ /// referenced in the source dictionary. Note that any <see cref="GodotObject"/> derived
+ /// elements will be shallow copied regardless of the <paramref name="deep"/>
+ /// setting.
/// </summary>
- /// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
- /// <returns>A new Godot Dictionary.</returns>
public Dictionary<TKey, TValue> Duplicate(bool deep = false)
{
return new Dictionary<TKey, TValue>(_underlyingDict.Duplicate(deep));
}
+ /// <summary>
+ /// Adds entries from <paramref name="dictionary"/> to this dictionary.
+ /// By default, duplicate keys are not copied over, unless <paramref name="overwrite"/>
+ /// is <see langword="true"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
+ /// <param name="dictionary">Dictionary to copy entries from.</param>
+ /// <param name="overwrite">If duplicate keys should be copied over as well.</param>
+ public void Merge(Dictionary<TKey, TValue> dictionary, bool overwrite = false)
+ {
+ _underlyingDict.Merge(dictionary._underlyingDict, overwrite);
+ }
+
+ /// <summary>
+ /// Compares this <see cref="Dictionary{TKey, TValue}"/> against the <paramref name="other"/>
+ /// <see cref="Dictionary{TKey, TValue}"/> recursively. Returns <see langword="true"/> if the
+ /// two dictionaries contain the same keys and values. The order of the entries does not matter.
+ /// otherwise.
+ /// </summary>
+ /// <param name="other">The other dictionary to compare against.</param>
+ /// <returns>
+ /// <see langword="true"/> if the dictionaries contain the same keys and values,
+ /// <see langword="false"/> otherwise.
+ /// </returns>
+ public bool RecursiveEqual(Dictionary<TKey, TValue> other)
+ {
+ return _underlyingDict.RecursiveEqual(other._underlyingDict);
+ }
+
// IDictionary<TKey, TValue>
/// <summary>
/// Returns the value at the given <paramref name="key"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The property is assigned and the dictionary is read-only.
+ /// </exception>
+ /// <exception cref="KeyNotFoundException">
+ /// The property is retrieved and an entry for <paramref name="key"/>
+ /// does not exist in the dictionary.
+ /// </exception>
/// <value>The value at the given <paramref name="key"/>.</value>
- public unsafe TValue this[TKey key]
+ public TValue this[TKey key]
{
get
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant value).ToBool())
{
using (value)
- return ConvertValueToManagedCallback(value);
+ return VariantUtils.ConvertTo<TValue>(value);
}
else
{
@@ -501,8 +624,10 @@ namespace Godot.Collections
}
set
{
- using var variantKey = ConvertKeyToVariantCallback(key);
- using var variantValue = ConvertValueToVariantCallback(value);
+ ThrowIfReadOnly();
+
+ using var variantKey = VariantUtils.CreateFrom(key);
+ using var variantValue = VariantUtils.CreateFrom(value);
var self = (godot_dictionary)_underlyingDict.NativeValue;
NativeFuncs.godotsharp_dictionary_set_value(ref self,
variantKey, variantValue);
@@ -541,7 +666,7 @@ namespace Godot.Collections
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
- private unsafe KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
+ private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
{
var self = (godot_dictionary)_underlyingDict.NativeValue;
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index,
@@ -551,8 +676,8 @@ namespace Godot.Collections
using (value)
{
return new KeyValuePair<TKey, TValue>(
- ConvertKeyToManagedCallback(key),
- ConvertValueToManagedCallback(value));
+ VariantUtils.ConvertTo<TKey>(key),
+ VariantUtils.ConvertTo<TValue>(value));
}
}
@@ -560,17 +685,22 @@ namespace Godot.Collections
/// Adds an object <paramref name="value"/> at key <paramref name="key"/>
/// to this <see cref="Dictionary{TKey, TValue}"/>.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
/// <param name="key">The key at which to add the object.</param>
/// <param name="value">The object to add.</param>
- public unsafe void Add(TKey key, TValue value)
+ public void Add(TKey key, TValue value)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ ThrowIfReadOnly();
+
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
if (NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool())
throw new ArgumentException("An element with the same key already exists.", nameof(key));
- using var variantValue = ConvertValueToVariantCallback(value);
+ using var variantValue = VariantUtils.CreateFrom(value);
NativeFuncs.godotsharp_dictionary_add(ref self, variantKey, variantValue);
}
@@ -579,9 +709,9 @@ namespace Godot.Collections
/// </summary>
/// <param name="key">The key to look for.</param>
/// <returns>Whether or not this dictionary contains the given key.</returns>
- public unsafe bool ContainsKey(TKey key)
+ public bool ContainsKey(TKey key)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
return NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool();
}
@@ -589,29 +719,36 @@ namespace Godot.Collections
/// <summary>
/// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
/// <param name="key">The key of the element to remove.</param>
- public unsafe bool Remove(TKey key)
+ public bool Remove(TKey key)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ ThrowIfReadOnly();
+
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
return NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey).ToBool();
}
/// <summary>
- /// Gets the object at the given <paramref name="key"/>.
+ /// Gets the value for the given <paramref name="key"/> in the dictionary.
+ /// Returns <see langword="true"/> if an entry for the given key exists in
+ /// the dictionary; otherwise, returns <see langword="false"/>.
/// </summary>
/// <param name="key">The key of the element to get.</param>
/// <param name="value">The value at the given <paramref name="key"/>.</param>
- /// <returns>If an object was found for the given <paramref name="key"/>.</returns>
- public unsafe bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
+ /// <returns>If an entry was found for the given <paramref name="key"/>.</returns>
+ public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
- using var variantKey = ConvertKeyToVariantCallback(key);
+ using var variantKey = VariantUtils.CreateFrom(key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant retValue).ToBool();
using (retValue)
- value = found ? ConvertValueToManagedCallback(retValue) : default;
+ value = found ? VariantUtils.ConvertTo<TValue>(retValue) : default;
return found;
}
@@ -625,19 +762,36 @@ namespace Godot.Collections
/// <returns>The number of elements.</returns>
public int Count => _underlyingDict.Count;
- bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
+ /// <summary>
+ /// Returns <see langword="true"/> if the dictionary is read-only.
+ /// See <see cref="MakeReadOnly"/>.
+ /// </summary>
+ public bool IsReadOnly => _underlyingDict.IsReadOnly;
+
+ /// <summary>
+ /// Makes the <see cref="Dictionary{TKey, TValue}"/> read-only, i.e. disabled
+ /// modying of the dictionary's elements. Does not apply to nested content,
+ /// e.g. content of nested dictionaries.
+ /// </summary>
+ public void MakeReadOnly()
+ {
+ _underlyingDict.MakeReadOnly();
+ }
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
=> Add(item.Key, item.Value);
/// <summary>
- /// Erases all the items from this <see cref="Dictionary{TKey, TValue}"/>.
+ /// Clears the dictionary, removing all entries from it.
/// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The dictionary is read-only.
+ /// </exception>
public void Clear() => _underlyingDict.Clear();
- unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
- using var variantKey = ConvertKeyToVariantCallback(item.Key);
+ using var variantKey = VariantUtils.CreateFrom(item.Key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant retValue).ToBool();
@@ -647,7 +801,7 @@ namespace Godot.Collections
if (!found)
return false;
- using var variantValue = ConvertValueToVariantCallback(item.Value);
+ using var variantValue = VariantUtils.CreateFrom(item.Value);
return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();
}
}
@@ -658,7 +812,7 @@ namespace Godot.Collections
/// </summary>
/// <param name="array">The array to copy to.</param>
/// <param name="arrayIndex">The index to start at.</param>
- public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
@@ -680,9 +834,11 @@ namespace Godot.Collections
}
}
- unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
- using var variantKey = ConvertKeyToVariantCallback(item.Key);
+ ThrowIfReadOnly();
+
+ using var variantKey = VariantUtils.CreateFrom(item.Key);
var self = (godot_dictionary)_underlyingDict.NativeValue;
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
variantKey, out godot_variant retValue).ToBool();
@@ -692,7 +848,7 @@ namespace Godot.Collections
if (!found)
return false;
- using var variantValue = ConvertValueToVariantCallback(item.Value);
+ using var variantValue = VariantUtils.CreateFrom(item.Value);
if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())
{
return NativeFuncs.godotsharp_dictionary_remove_key(
@@ -731,5 +887,13 @@ namespace Godot.Collections
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Dictionary<TKey, TValue>(Variant from) =>
from.AsGodotDictionary<TKey, TValue>();
+
+ private void ThrowIfReadOnly()
+ {
+ if (IsReadOnly)
+ {
+ throw new InvalidOperationException("Dictionary instance is read-only.");
+ }
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
index e6cb4171a7..e7370b2b05 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
@@ -9,7 +9,10 @@ namespace Godot
internal static GodotTaskScheduler DefaultGodotTaskScheduler;
internal static void InitializeDefaultGodotTaskScheduler()
- => DefaultGodotTaskScheduler = new GodotTaskScheduler();
+ {
+ DefaultGodotTaskScheduler?.Dispose();
+ DefaultGodotTaskScheduler = new GodotTaskScheduler();
+ }
public static GodotSynchronizationContext SynchronizationContext => DefaultGodotTaskScheduler.Context;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs
index 421b588560..53292e10cf 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs
@@ -28,7 +28,7 @@ namespace Godot
try
{
- isStdoutVerbose = OS.IsStdoutVerbose();
+ isStdoutVerbose = OS.IsStdOutVerbose();
}
catch (ObjectDisposedException)
{
@@ -43,9 +43,9 @@ namespace Godot
// like StringName, NodePath, Godot.Collections.Array/Dictionary, etc.
// The Godot Object Dispose() method may need any of the later instances.
- foreach (WeakReference<Object> item in GodotObjectInstances.Keys)
+ foreach (WeakReference<GodotObject> item in GodotObjectInstances.Keys)
{
- if (item.TryGetTarget(out Object? self))
+ if (item.TryGetTarget(out GodotObject? self))
self.Dispose();
}
@@ -60,15 +60,15 @@ namespace Godot
}
// ReSharper disable once RedundantNameQualifier
- private static ConcurrentDictionary<WeakReference<Godot.Object>, byte> GodotObjectInstances { get; } =
+ private static ConcurrentDictionary<WeakReference<GodotObject>, byte> GodotObjectInstances { get; } =
new();
private static ConcurrentDictionary<WeakReference<IDisposable>, byte> OtherInstances { get; } =
new();
- public static WeakReference<Object> RegisterGodotObject(Object godotObject)
+ public static WeakReference<GodotObject> RegisterGodotObject(GodotObject godotObject)
{
- var weakReferenceToSelf = new WeakReference<Object>(godotObject);
+ var weakReferenceToSelf = new WeakReference<GodotObject>(godotObject);
GodotObjectInstances.TryAdd(weakReferenceToSelf, 0);
return weakReferenceToSelf;
}
@@ -80,7 +80,7 @@ namespace Godot
return weakReferenceToSelf;
}
- public static void UnregisterGodotObject(Object godotObject, WeakReference<Object> weakReferenceToSelf)
+ public static void UnregisterGodotObject(GodotObject godotObject, WeakReference<GodotObject> weakReferenceToSelf)
{
if (!GodotObjectInstances.TryRemove(weakReferenceToSelf, out _))
throw new ArgumentException("Godot Object not registered.", nameof(weakReferenceToSelf));
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/GodotObjectExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/GodotObjectExtensions.cs
new file mode 100644
index 0000000000..6c90c17078
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/GodotObjectExtensions.cs
@@ -0,0 +1,86 @@
+using System;
+using Godot.NativeInterop;
+
+namespace Godot
+{
+ public partial class GodotObject
+ {
+ /// <summary>
+ /// Returns the <see cref="GodotObject"/> that corresponds to <paramref name="instanceId"/>.
+ /// All Objects have a unique instance ID. See also <see cref="GetInstanceId"/>.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// public partial class MyNode : Node
+ /// {
+ /// public string Foo { get; set; } = "bar";
+ ///
+ /// public override void _Ready()
+ /// {
+ /// ulong id = GetInstanceId();
+ /// var inst = (MyNode)InstanceFromId(Id);
+ /// GD.Print(inst.Foo); // Prints bar
+ /// }
+ /// }
+ /// </code>
+ /// </example>
+ /// <param name="instanceId">Instance ID of the Object to retrieve.</param>
+ /// <returns>The <see cref="GodotObject"/> instance.</returns>
+ public static GodotObject InstanceFromId(ulong instanceId)
+ {
+ return InteropUtils.UnmanagedGetManaged(NativeFuncs.godotsharp_instance_from_id(instanceId));
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the <see cref="GodotObject"/> that corresponds
+ /// to <paramref name="id"/> is a valid object (e.g. has not been deleted from
+ /// memory). All Objects have a unique instance ID.
+ /// </summary>
+ /// <param name="id">The Object ID to check.</param>
+ /// <returns>If the instance with the given ID is a valid object.</returns>
+ public static bool IsInstanceIdValid(ulong id)
+ {
+ return IsInstanceValid(InstanceFromId(id));
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if <paramref name="instance"/> is a
+ /// valid <see cref="GodotObject"/> (e.g. has not been deleted from memory).
+ /// </summary>
+ /// <param name="instance">The instance to check.</param>
+ /// <returns>If the instance is a valid object.</returns>
+ public static bool IsInstanceValid(GodotObject instance)
+ {
+ return instance != null && instance.NativeInstance != IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Returns a weak reference to an object, or <see langword="null"/>
+ /// if the argument is invalid.
+ /// A weak reference to an object is not enough to keep the object alive:
+ /// when the only remaining references to a referent are weak references,
+ /// garbage collection is free to destroy the referent and reuse its memory
+ /// for something else. However, until the object is actually destroyed the
+ /// weak reference may return the object even if there are no strong references
+ /// to it.
+ /// </summary>
+ /// <param name="obj">The object.</param>
+ /// <returns>
+ /// The <see cref="WeakRef"/> reference to the object or <see langword="null"/>.
+ /// </returns>
+ public static WeakRef WeakRef(GodotObject obj)
+ {
+ if (!IsInstanceValid(obj))
+ return null;
+
+ NativeFuncs.godotsharp_weakref(GetPtr(obj), out godot_ref weakRef);
+ using (weakRef)
+ {
+ if (weakRef.IsNull)
+ return null;
+
+ return (WeakRef)InteropUtils.UnmanagedGetManaged(weakRef.Reference);
+ }
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs
index 03996bafdd..8325af034c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs
@@ -48,13 +48,8 @@ namespace Godot
}
/// <summary>
- /// Fetches a node. The <see cref="NodePath"/> can be either a relative path (from
- /// the current node) or an absolute path (in the scene tree) to a node. If the path
- /// does not exist, a <see langword="null"/> instance is returned and an error
- /// is logged. Attempts to access methods on the return value will result in an
- /// "Attempt to call &lt;method&gt; on a null instance." error.
- /// Note: Fetching absolute paths only works when the node is inside the scene tree
- /// (see <see cref="IsInsideTree"/>).
+ /// Similar to <see cref="GetNode"/>, but does not log an error if <paramref name="path"/>
+ /// does not point to a valid <see cref="Node"/>.
/// </summary>
/// <example>
/// Example: Assume your current node is Character and the following tree:
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
deleted file mode 100644
index 4094ceeb22..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System;
-using Godot.NativeInterop;
-
-namespace Godot
-{
- public partial class Object
- {
- /// <summary>
- /// Returns whether <paramref name="instance"/> is a valid object
- /// (e.g. has not been deleted from memory).
- /// </summary>
- /// <param name="instance">The instance to check.</param>
- /// <returns>If the instance is a valid object.</returns>
- public static bool IsInstanceValid(Object instance)
- {
- return instance != null && instance.NativeInstance != IntPtr.Zero;
- }
-
- /// <summary>
- /// Returns a weak reference to an object, or <see langword="null"/>
- /// if the argument is invalid.
- /// A weak reference to an object is not enough to keep the object alive:
- /// when the only remaining references to a referent are weak references,
- /// garbage collection is free to destroy the referent and reuse its memory
- /// for something else. However, until the object is actually destroyed the
- /// weak reference may return the object even if there are no strong references
- /// to it.
- /// </summary>
- /// <param name="obj">The object.</param>
- /// <returns>
- /// The <see cref="WeakRef"/> reference to the object or <see langword="null"/>.
- /// </returns>
- public static WeakRef WeakRef(Object obj)
- {
- if (!IsInstanceValid(obj))
- return null;
-
- NativeFuncs.godotsharp_weakref(GetPtr(obj), out godot_ref weakRef);
- using (weakRef)
- {
- if (weakRef.IsNull)
- return null;
-
- return (WeakRef)InteropUtils.UnmanagedGetManaged(weakRef.Reference);
- }
- }
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
index 8463403096..4610761bdb 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
@@ -7,7 +7,7 @@ namespace Godot
/// <summary>
/// Instantiates the scene's node hierarchy, erroring on failure.
/// Triggers child scene instantiation(s). Triggers a
- /// <see cref="Node.NotificationInstanced"/> notification on the root node.
+ /// <see cref="Node.NotificationSceneInstantiated"/> notification on the root node.
/// </summary>
/// <seealso cref="InstantiateOrNull{T}(GenEditState)"/>
/// <exception cref="InvalidCastException">
@@ -23,7 +23,7 @@ namespace Godot
/// <summary>
/// Instantiates the scene's node hierarchy, returning <see langword="null"/> on failure.
/// Triggers child scene instantiation(s). Triggers a
- /// <see cref="Node.NotificationInstanced"/> notification on the root node.
+ /// <see cref="Node.NotificationSceneInstantiated"/> notification on the root node.
/// </summary>
/// <seealso cref="Instantiate{T}(GenEditState)"/>
/// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index e4b79e7ec4..9425b7424c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Text;
using Godot.NativeInterop;
namespace Godot
@@ -10,36 +11,45 @@ namespace Godot
public static partial class GD
{
/// <summary>
- /// Decodes a byte array back to a <c>Variant</c> value.
- /// If <paramref name="allowObjects"/> is <see langword="true"/> decoding objects is allowed.
- ///
- /// WARNING: Deserialized object can contain code which gets executed.
- /// Do not set <paramref name="allowObjects"/> to <see langword="true"/>
- /// if the serialized object comes from untrusted sources to avoid
- /// potential security threats (remote code execution).
+ /// Decodes a byte array back to a <see cref="Variant"/> value, without decoding objects.
+ /// Note: If you need object deserialization, see <see cref="BytesToVarWithObjects"/>.
/// </summary>
- /// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param>
- /// <param name="allowObjects">If objects should be decoded.</param>
- /// <returns>The decoded <c>Variant</c>.</returns>
- public static Variant BytesToVar(Span<byte> bytes, bool allowObjects = false)
+ /// <param name="bytes">Byte array that will be decoded to a <see cref="Variant"/>.</param>
+ /// <returns>The decoded <see cref="Variant"/>.</returns>
+ public static Variant BytesToVar(Span<byte> bytes)
{
using var varBytes = Marshaling.ConvertSystemArrayToNativePackedByteArray(bytes);
- NativeFuncs.godotsharp_bytes_to_var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret);
+ NativeFuncs.godotsharp_bytes_to_var(varBytes, godot_bool.False, out godot_variant ret);
return Variant.CreateTakingOwnershipOfDisposableValue(ret);
}
/// <summary>
- /// Converts from a <c>Variant</c> type to another in the best way possible.
+ /// Decodes a byte array back to a <see cref="Variant"/> value. Decoding objects is allowed.
+ /// Warning: Deserialized object can contain code which gets executed. Do not use this
+ /// option if the serialized object comes from untrusted sources to avoid potential security
+ /// threats (remote code execution).
+ /// </summary>
+ /// <param name="bytes">Byte array that will be decoded to a <see cref="Variant"/>.</param>
+ /// <returns>The decoded <see cref="Variant"/>.</returns>
+ public static Variant BytesToVarWithObjects(Span<byte> bytes)
+ {
+ using var varBytes = Marshaling.ConvertSystemArrayToNativePackedByteArray(bytes);
+ NativeFuncs.godotsharp_bytes_to_var(varBytes, godot_bool.True, out godot_variant ret);
+ return Variant.CreateTakingOwnershipOfDisposableValue(ret);
+ }
+
+ /// <summary>
+ /// Converts <paramref name="what"/> to <paramref name="type"/> in the best way possible.
/// The <paramref name="type"/> parameter uses the <see cref="Variant.Type"/> values.
/// </summary>
/// <example>
/// <code>
- /// var a = new Vector2(1, 0);
- /// // Prints 1
- /// GD.Print(a.Length());
- /// var b = GD.Convert(a, Variant.Type.String)
- /// // Prints 6 as "(1, 0)" is 6 characters
- /// GD.Print(b.Length);
+ /// Variant a = new Godot.Collections.Array { 4, 2.5, 1.2 };
+ /// GD.Print(a.VariantType == Variant.Type.Array); // Prints true
+ ///
+ /// var b = GD.Convert(a, Variant.Type.PackedByteArray);
+ /// GD.Print(b); // Prints [4, 2, 1]
+ /// GD.Print(b.VariantType == Variant.Type.Array); // Prints false
/// </code>
/// </example>
/// <returns>The <c>Variant</c> converted to the given <paramref name="type"/>.</returns>
@@ -50,28 +60,7 @@ namespace Godot
}
/// <summary>
- /// Converts from decibels to linear energy (audio).
- /// </summary>
- /// <seealso cref="LinearToDb(real_t)"/>
- /// <param name="db">Decibels to convert.</param>
- /// <returns>Audio volume as linear energy.</returns>
- public static real_t DbToLinear(real_t db)
- {
- return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
- }
-
- private static string[] GetPrintParams(object[] parameters)
- {
- if (parameters == null)
- {
- return new[] { "null" };
- }
-
- return Array.ConvertAll(parameters, x => x?.ToString() ?? "null");
- }
-
- /// <summary>
- /// Returns the integer hash of the variable passed.
+ /// Returns the integer hash of the passed <paramref name="var"/>.
/// </summary>
/// <example>
/// <code>
@@ -86,52 +75,6 @@ namespace Godot
}
/// <summary>
- /// Returns the <see cref="Object"/> that corresponds to <paramref name="instanceId"/>.
- /// All Objects have a unique instance ID.
- /// </summary>
- /// <example>
- /// <code>
- /// public class MyNode : Node
- /// {
- /// public string foo = "bar";
- ///
- /// public override void _Ready()
- /// {
- /// ulong id = GetInstanceId();
- /// var inst = (MyNode)GD.InstanceFromId(Id);
- /// GD.Print(inst.foo); // Prints bar
- /// }
- /// }
- /// </code>
- /// </example>
- /// <param name="instanceId">Instance ID of the Object to retrieve.</param>
- /// <returns>The <see cref="Object"/> instance.</returns>
- public static Object InstanceFromId(ulong instanceId)
- {
- return InteropUtils.UnmanagedGetManaged(NativeFuncs.godotsharp_instance_from_id(instanceId));
- }
-
- /// <summary>
- /// Converts from linear energy to decibels (audio).
- /// This can be used to implement volume sliders that behave as expected (since volume isn't linear).
- /// </summary>
- /// <seealso cref="DbToLinear(real_t)"/>
- /// <example>
- /// <code>
- /// // "slider" refers to a node that inherits Range such as HSlider or VSlider.
- /// // Its range must be configured to go from 0 to 1.
- /// // Change the bus name if you'd like to change the volume of a specific bus only.
- /// AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), GD.LinearToDb(slider.value));
- /// </code>
- /// </example>
- /// <param name="linear">The linear energy to convert.</param>
- /// <returns>Audio as decibels.</returns>
- public static real_t LinearToDb(real_t linear)
- {
- return (real_t)(Math.Log(linear) * 8.6858896380650365530225783783321);
- }
-
- /// <summary>
/// Loads a resource from the filesystem located at <paramref name="path"/>.
/// The resource is loaded on the method call (unless it's referenced already
/// elsewhere, e.g. in another script or in the scene), which might cause slight delay,
@@ -185,57 +128,96 @@ namespace Godot
return ResourceLoader.Load<T>(path);
}
- /// <summary>
- /// Pushes an error message to Godot's built-in debugger and to the OS terminal.
- ///
- /// Note: Errors printed this way will not pause project execution.
- /// </summary>
- /// <example>
- /// <code>
- /// GD.PushError("test_error"); // Prints "test error" to debugger and terminal as error call
- /// </code>
- /// </example>
- /// <param name="message">Error message.</param>
- public static void PushError(string message)
+ private static string AppendPrintParams(object[] parameters)
{
- using var godotStr = Marshaling.ConvertStringToNative(message);
- NativeFuncs.godotsharp_pusherror(godotStr);
+ if (parameters == null)
+ {
+ return "null";
+ }
+
+ var sb = new StringBuilder();
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ sb.Append(parameters[i]?.ToString() ?? "null");
+ }
+ return sb.ToString();
+ }
+
+ private static string AppendPrintParams(char separator, object[] parameters)
+ {
+ if (parameters == null)
+ {
+ return "null";
+ }
+
+ var sb = new StringBuilder();
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ if (i != 0)
+ sb.Append(separator);
+ sb.Append(parameters[i]?.ToString() ?? "null");
+ }
+ return sb.ToString();
}
/// <summary>
- /// Pushes a warning message to Godot's built-in debugger and to the OS terminal.
+ /// Prints a message to the console.
+ ///
+ /// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/>
+ /// to print error and warning messages instead of <see cref="Print(string)"/>.
+ /// This distinguishes them from print messages used for debugging purposes,
+ /// while also displaying a stack trace when an error or warning is printed.
/// </summary>
- /// <example>
- /// GD.PushWarning("test warning"); // Prints "test warning" to debugger and terminal as warning call
- /// </example>
- /// <param name="message">Warning message.</param>
- public static void PushWarning(string message)
+ /// <param name="what">Message that will be printed.</param>
+ public static void Print(string what)
{
- using var godotStr = Marshaling.ConvertStringToNative(message);
- NativeFuncs.godotsharp_pushwarning(godotStr);
+ using var godotStr = Marshaling.ConvertStringToNative(what);
+ NativeFuncs.godotsharp_print(godotStr);
}
/// <summary>
/// Converts one or more arguments of any type to string in the best way possible
/// and prints them to the console.
///
- /// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/>
+ /// Note: Consider using <see cref="PushError(object[])"/> and <see cref="PushWarning(object[])"/>
/// to print error and warning messages instead of <see cref="Print(object[])"/>.
/// This distinguishes them from print messages used for debugging purposes,
/// while also displaying a stack trace when an error or warning is printed.
/// </summary>
/// <example>
/// <code>
- /// var a = new int[] { 1, 2, 3 };
+ /// var a = new Godot.Collections.Array { 1, 2, 3 };
/// GD.Print("a", "b", a); // Prints ab[1, 2, 3]
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
public static void Print(params object[] what)
{
- string str = string.Concat(GetPrintParams(what));
- using var godotStr = Marshaling.ConvertStringToNative(str);
- NativeFuncs.godotsharp_print(godotStr);
+ Print(AppendPrintParams(what));
+ }
+
+ /// <summary>
+ /// Prints a message to the console.
+ /// The following BBCode tags are supported: b, i, u, s, indent, code, url, center,
+ /// right, color, bgcolor, fgcolor.
+ /// Color tags only support named colors such as <c>red</c>, not hexadecimal color codes.
+ /// Unsupported tags will be left as-is in standard output.
+ /// When printing to standard output, the supported subset of BBCode is converted to
+ /// ANSI escape codes for the terminal emulator to display. Displaying ANSI escape codes
+ /// is currently only supported on Linux and macOS. Support for ANSI escape codes may vary
+ /// across terminal emulators, especially for italic and strikethrough.
+ ///
+ /// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/>
+ /// to print error and warning messages instead of <see cref="Print(string)"/> or
+ /// <see cref="PrintRich(string)"/>.
+ /// This distinguishes them from print messages used for debugging purposes,
+ /// while also displaying a stack trace when an error or warning is printed.
+ /// </summary>
+ /// <param name="what">Message that will be printed.</param>
+ public static void PrintRich(string what)
+ {
+ using var godotStr = Marshaling.ConvertStringToNative(what);
+ NativeFuncs.godotsharp_print_rich(godotStr);
}
/// <summary>
@@ -250,7 +232,7 @@ namespace Godot
/// is currently only supported on Linux and macOS. Support for ANSI escape codes may vary
/// across terminal emulators, especially for italic and strikethrough.
///
- /// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/>
+ /// Note: Consider using <see cref="PushError(object[])"/> and <see cref="PushWarning(object[])"/>
/// to print error and warning messages instead of <see cref="Print(object[])"/> or
/// <see cref="PrintRich(object[])"/>.
/// This distinguishes them from print messages used for debugging purposes,
@@ -258,23 +240,23 @@ namespace Godot
/// </summary>
/// <example>
/// <code>
- /// GD.PrintRich("[b]Hello world![/b]"); // Prints out "Hello world!" in bold.
+ /// GD.PrintRich("[code][b]Hello world![/b][/code]"); // Prints out: [b]Hello world![/b]
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
public static void PrintRich(params object[] what)
{
- string str = string.Concat(GetPrintParams(what));
- using var godotStr = Marshaling.ConvertStringToNative(str);
- NativeFuncs.godotsharp_print_rich(godotStr);
+ PrintRich(AppendPrintParams(what));
}
/// <summary>
- /// Prints the current stack trace information to the console.
+ /// Prints a message to standard error line.
/// </summary>
- public static void PrintStack()
+ /// <param name="what">Message that will be printed.</param>
+ public static void PrintErr(string what)
{
- Print(System.Environment.StackTrace);
+ using var godotStr = Marshaling.ConvertStringToNative(what);
+ NativeFuncs.godotsharp_printerr(godotStr);
}
/// <summary>
@@ -288,31 +270,36 @@ namespace Godot
/// <param name="what">Arguments that will be printed.</param>
public static void PrintErr(params object[] what)
{
- string str = string.Concat(GetPrintParams(what));
- using var godotStr = Marshaling.ConvertStringToNative(str);
- NativeFuncs.godotsharp_printerr(godotStr);
+ PrintErr(AppendPrintParams(what));
}
/// <summary>
- /// Prints one or more arguments to strings in the best way possible to console.
- /// No newline is added at the end.
- ///
- /// Note: Due to limitations with Godot's built-in console, this only prints to the terminal.
- /// If you need to print in the editor, use another method, such as <see cref="Print(object[])"/>.
+ /// Prints a message to the OS terminal.
+ /// Unlike <see cref="Print(string)"/>, no newline is added at the end.
+ /// </summary>
+ /// <param name="what">Message that will be printed.</param>
+ public static void PrintRaw(string what)
+ {
+ using var godotStr = Marshaling.ConvertStringToNative(what);
+ NativeFuncs.godotsharp_printraw(godotStr);
+ }
+
+ /// <summary>
+ /// Prints one or more arguments to strings in the best way possible to the OS terminal.
+ /// Unlike <see cref="Print(object[])"/>, no newline is added at the end.
/// </summary>
/// <example>
/// <code>
/// GD.PrintRaw("A");
/// GD.PrintRaw("B");
- /// // Prints AB
+ /// GD.PrintRaw("C");
+ /// // Prints ABC to terminal
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
public static void PrintRaw(params object[] what)
{
- string str = string.Concat(GetPrintParams(what));
- using var godotStr = Marshaling.ConvertStringToNative(str);
- NativeFuncs.godotsharp_printraw(godotStr);
+ PrintRaw(AppendPrintParams(what));
}
/// <summary>
@@ -326,8 +313,8 @@ namespace Godot
/// <param name="what">Arguments that will be printed.</param>
public static void PrintS(params object[] what)
{
- string str = string.Join(' ', GetPrintParams(what));
- using var godotStr = Marshaling.ConvertStringToNative(str);
+ string message = AppendPrintParams(' ', what);
+ using var godotStr = Marshaling.ConvertStringToNative(message);
NativeFuncs.godotsharp_prints(godotStr);
}
@@ -342,12 +329,74 @@ namespace Godot
/// <param name="what">Arguments that will be printed.</param>
public static void PrintT(params object[] what)
{
- string str = string.Join('\t', GetPrintParams(what));
- using var godotStr = Marshaling.ConvertStringToNative(str);
+ string message = AppendPrintParams('\t', what);
+ using var godotStr = Marshaling.ConvertStringToNative(message);
NativeFuncs.godotsharp_printt(godotStr);
}
/// <summary>
+ /// Pushes an error message to Godot's built-in debugger and to the OS terminal.
+ ///
+ /// Note: Errors printed this way will not pause project execution.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PushError("test error"); // Prints "test error" to debugger and terminal as error call
+ /// </code>
+ /// </example>
+ /// <param name="message">Error message.</param>
+ public static void PushError(string message)
+ {
+ using var godotStr = Marshaling.ConvertStringToNative(message);
+ NativeFuncs.godotsharp_pusherror(godotStr);
+ }
+
+ /// <summary>
+ /// Pushes an error message to Godot's built-in debugger and to the OS terminal.
+ ///
+ /// Note: Errors printed this way will not pause project execution.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PushError("test_error"); // Prints "test error" to debugger and terminal as error call
+ /// </code>
+ /// </example>
+ /// <param name="what">Arguments that form the error message.</param>
+ public static void PushError(params object[] what)
+ {
+ PushError(AppendPrintParams(what));
+ }
+
+ /// <summary>
+ /// Pushes a warning message to Godot's built-in debugger and to the OS terminal.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PushWarning("test warning"); // Prints "test warning" to debugger and terminal as warning call
+ /// </code>
+ /// </example>
+ /// <param name="message">Warning message.</param>
+ public static void PushWarning(string message)
+ {
+ using var godotStr = Marshaling.ConvertStringToNative(message);
+ NativeFuncs.godotsharp_pushwarning(godotStr);
+ }
+
+ /// <summary>
+ /// Pushes a warning message to Godot's built-in debugger and to the OS terminal.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PushWarning("test warning"); // Prints "test warning" to debugger and terminal as warning call
+ /// </code>
+ /// </example>
+ /// <param name="what">Arguments that form the warning message.</param>
+ public static void PushWarning(params object[] what)
+ {
+ PushWarning(AppendPrintParams(what));
+ }
+
+ /// <summary>
/// Returns a random floating point value between <c>0.0</c> and <c>1.0</c> (inclusive).
/// </summary>
/// <example>
@@ -362,7 +411,9 @@ namespace Godot
}
/// <summary>
- /// Returns a normally-distributed pseudo-random number, using Box-Muller transform with the specified <c>mean</c> and a standard <c>deviation</c>.
+ /// Returns a normally-distributed pseudo-random floating point value
+ /// using Box-Muller transform with the specified <pararmref name="mean"/>
+ /// and a standard <paramref name="deviation"/>.
/// This is also called Gaussian distribution.
/// </summary>
/// <returns>A random normally-distributed <see langword="float"/> number.</returns>
@@ -373,7 +424,8 @@ namespace Godot
/// <summary>
/// Returns a random unsigned 32-bit integer.
- /// Use remainder to obtain a random value in the interval <c>[0, N - 1]</c> (where N is smaller than 2^32).
+ /// Use remainder to obtain a random value in the interval <c>[0, N - 1]</c>
+ /// (where N is smaller than 2^32).
/// </summary>
/// <example>
/// <code>
@@ -391,11 +443,11 @@ namespace Godot
/// <summary>
/// Randomizes the seed (or the internal state) of the random number generator.
- /// Current implementation reseeds using a number based on time.
+ /// The current implementation uses a number based on the device's time.
///
/// Note: This method is called automatically when the project is run.
- /// If you need to fix the seed to have reproducible results, use <see cref="Seed(ulong)"/>
- /// to initialize the random number generator.
+ /// If you need to fix the seed to have consistent, reproducible results,
+ /// use <see cref="Seed(ulong)"/> to initialize the random number generator.
/// </summary>
public static void Randomize()
{
@@ -403,12 +455,13 @@ namespace Godot
}
/// <summary>
- /// Returns a random floating point value on the interval between <paramref name="from"/>
+ /// Returns a random floating point value between <paramref name="from"/>
/// and <paramref name="to"/> (inclusive).
/// </summary>
/// <example>
/// <code>
- /// GD.PrintS(GD.RandRange(-10.0, 10.0), GD.RandRange(-10.0, 10.0)); // Prints e.g. -3.844535 7.45315
+ /// GD.RandRange(0.0, 20.5); // Returns e.g. 7.45315
+ /// GD.RandRange(-10.0, 10.0); // Returns e.g. -3.844535
/// </code>
/// </example>
/// <returns>A random <see langword="double"/> number inside the given range.</returns>
@@ -424,8 +477,8 @@ namespace Godot
/// </summary>
/// <example>
/// <code>
- /// GD.Print(GD.RandRange(0, 1)); // Prints 0 or 1
- /// GD.Print(GD.RandRange(-10, 1000)); // Prints any number from -10 to 1000
+ /// GD.RandRange(0, 1); // Returns either 0 or 1
+ /// GD.RandRange(-10, 1000); // Returns random integer between -10 and 1000
/// </code>
/// </example>
/// <returns>A random <see langword="int"/> number inside the given range.</returns>
@@ -435,8 +488,18 @@ namespace Godot
}
/// <summary>
- /// Returns a random unsigned 32-bit integer, using the given <paramref name="seed"/>.
+ /// Given a <paramref name="seed"/>, returns a randomized <see langword="uint"/>
+ /// value. The <paramref name="seed"/> may be modified.
+ /// Passing the same <paramref name="seed"/> consistently returns the same value.
+ ///
+ /// Note: "Seed" here refers to the internal state of the pseudo random number
+ /// generator, currently implemented as a 64 bit integer.
/// </summary>
+ /// <example>
+ /// <code>
+ /// var a = GD.RandFromSeed(4);
+ /// </code>
+ /// </example>
/// <param name="seed">
/// Seed to use to generate the random number.
/// If a different seed is used, its value will be modified.
@@ -449,7 +512,8 @@ namespace Godot
/// <summary>
/// Returns a <see cref="IEnumerable{T}"/> that iterates from
- /// <c>0</c> to <paramref name="end"/> in steps of <c>1</c>.
+ /// <c>0</c> (inclusive) to <paramref name="end"/> (exclusive)
+ /// in steps of <c>1</c>.
/// </summary>
/// <param name="end">The last index.</param>
public static IEnumerable<int> Range(int end)
@@ -459,7 +523,8 @@ namespace Godot
/// <summary>
/// Returns a <see cref="IEnumerable{T}"/> that iterates from
- /// <paramref name="start"/> to <paramref name="end"/> in steps of <c>1</c>.
+ /// <paramref name="start"/> (inclusive) to <paramref name="end"/> (exclusive)
+ /// in steps of <c>1</c>.
/// </summary>
/// <param name="start">The first index.</param>
/// <param name="end">The last index.</param>
@@ -470,13 +535,21 @@ namespace Godot
/// <summary>
/// Returns a <see cref="IEnumerable{T}"/> that iterates from
- /// <paramref name="start"/> to <paramref name="end"/> in steps of <paramref name="step"/>.
+ /// <paramref name="start"/> (inclusive) to <paramref name="end"/> (exclusive)
+ /// in steps of <paramref name="step"/>.
+ /// The argument <paramref name="step"/> can be negative, but not <c>0</c>.
/// </summary>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="step"/> is 0.
+ /// </exception>
/// <param name="start">The first index.</param>
/// <param name="end">The last index.</param>
/// <param name="step">The amount by which to increment the index on each iteration.</param>
public static IEnumerable<int> Range(int start, int end, int step)
{
+ if (step == 0)
+ throw new ArgumentException("step cannot be 0.", nameof(step));
+
if (end < start && step > 0)
yield break;
@@ -496,8 +569,20 @@ namespace Godot
}
/// <summary>
- /// Sets seed for the random number generator.
+ /// Sets seed for the random number generator to <paramref name="seed"/>.
+ /// Setting the seed manually can ensure consistent, repeatable results for
+ /// most random functions.
/// </summary>
+ /// <example>
+ /// <code>
+ /// ulong mySeed = (ulong)GD.Hash("Godot Rocks");
+ /// GD.Seed(mySeed);
+ /// var a = GD.Randf() + GD.Randi();
+ /// GD.Seed(mySeed);
+ /// var b = GD.Randf() + GD.Randi();
+ /// // a and b are now identical
+ /// </code>
+ /// </example>
/// <param name="seed">Seed that will be used.</param>
public static void Seed(ulong seed)
{
@@ -505,26 +590,14 @@ namespace Godot
}
/// <summary>
- /// Converts one or more arguments of any type to string in the best way possible.
- /// </summary>
- /// <param name="what">Arguments that will converted to string.</param>
- /// <returns>The string formed by the given arguments.</returns>
- public static string Str(params Variant[] what)
- {
- using var whatGodot = new Godot.Collections.Array(what);
- NativeFuncs.godotsharp_str((godot_array)whatGodot.NativeValue, out godot_string ret);
- using (ret)
- return Marshaling.ConvertStringToManaged(ret);
- }
-
- /// <summary>
- /// Converts a formatted string that was returned by <see cref="VarToStr(Variant)"/> to the original value.
+ /// Converts a formatted string that was returned by <see cref="VarToStr(Variant)"/>
+ /// to the original value.
/// </summary>
/// <example>
/// <code>
- /// string a = "{\"a\": 1, \"b\": 2 }";
- /// var b = (Godot.Collections.Dictionary)GD.StrToVar(a);
- /// GD.Print(b["a"]); // Prints 1
+ /// string a = "{ \"a\": 1, \"b\": 2 }"; // a is a string
+ /// var b = GD.StrToVar(a).AsGodotDictionary(); // b is a Dictionary
+ /// GD.Print(b["a"]); // Prints 1
/// </code>
/// </example>
/// <param name="str">String that will be converted to Variant.</param>
@@ -537,38 +610,49 @@ namespace Godot
}
/// <summary>
- /// Encodes a <c>Variant</c> value to a byte array.
- /// If <paramref name="fullObjects"/> is <see langword="true"/> encoding objects is allowed
- /// (and can potentially include code).
- /// Deserialization can be done with <see cref="BytesToVar(Span{byte}, bool)"/>.
+ /// Encodes a <see cref="Variant"/> value to a byte array, without encoding objects.
+ /// Deserialization can be done with <see cref="BytesToVar"/>.
+ /// Note: If you need object serialization, see <see cref="VarToBytesWithObjects"/>.
+ /// </summary>
+ /// <param name="var"><see cref="Variant"/> that will be encoded.</param>
+ /// <returns>The <see cref="Variant"/> encoded as an array of bytes.</returns>
+ public static byte[] VarToBytes(Variant var)
+ {
+ NativeFuncs.godotsharp_var_to_bytes((godot_variant)var.NativeVar, godot_bool.False, out var varBytes);
+ using (varBytes)
+ return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes);
+ }
+
+ /// <summary>
+ /// Encodes a <see cref="Variant"/>. Encoding objects is allowed (and can potentially
+ /// include executable code). Deserialization can be done with <see cref="BytesToVarWithObjects"/>.
/// </summary>
- /// <param name="var">Variant that will be encoded.</param>
- /// <param name="fullObjects">If objects should be serialized.</param>
- /// <returns>The <c>Variant</c> encoded as an array of bytes.</returns>
- public static byte[] VarToBytes(Variant var, bool fullObjects = false)
+ /// <param name="var"><see cref="Variant"/> that will be encoded.</param>
+ /// <returns>The <see cref="Variant"/> encoded as an array of bytes.</returns>
+ public static byte[] VarToBytesWithObjects(Variant var)
{
- NativeFuncs.godotsharp_var_to_bytes((godot_variant)var.NativeVar, fullObjects.ToGodotBool(), out var varBytes);
+ NativeFuncs.godotsharp_var_to_bytes((godot_variant)var.NativeVar, godot_bool.True, out var varBytes);
using (varBytes)
return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes);
}
/// <summary>
- /// Converts a <c>Variant</c> <paramref name="var"/> to a formatted string that
+ /// Converts a <see cref="Variant"/> <paramref name="var"/> to a formatted string that
/// can later be parsed using <see cref="StrToVar(string)"/>.
/// </summary>
/// <example>
/// <code>
/// var a = new Godot.Collections.Dictionary { ["a"] = 1, ["b"] = 2 };
/// GD.Print(GD.VarToStr(a));
- /// // Prints
+ /// // Prints:
/// // {
- /// // "a": 1,
- /// // "b": 2
+ /// // "a": 1,
+ /// // "b": 2
/// // }
/// </code>
/// </example>
/// <param name="var">Variant that will be converted to string.</param>
- /// <returns>The <c>Variant</c> encoded as a string.</returns>
+ /// <returns>The <see cref="Variant"/> encoded as a string.</returns>
public static string VarToStr(Variant var)
{
NativeFuncs.godotsharp_var_to_str((godot_variant)var.NativeVar, out godot_string ret);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
index 60ee6eb6f4..b9a5ac82d1 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
@@ -5,20 +5,20 @@ using Godot.NativeInterop;
namespace Godot
{
- public partial class Object : IDisposable
+ public partial class GodotObject : IDisposable
{
private bool _disposed = false;
- private static readonly Type CachedType = typeof(Object);
+ private static readonly Type CachedType = typeof(GodotObject);
internal IntPtr NativePtr;
private bool _memoryOwn;
- private WeakReference<Object> _weakReferenceToSelf;
+ private WeakReference<GodotObject> _weakReferenceToSelf;
/// <summary>
- /// Constructs a new <see cref="Object"/>.
+ /// Constructs a new <see cref="GodotObject"/>.
/// </summary>
- public Object() : this(false)
+ public GodotObject() : this(false)
{
unsafe
{
@@ -49,17 +49,17 @@ namespace Godot
_weakReferenceToSelf = DisposablesTracker.RegisterGodotObject(this);
}
- internal Object(bool memoryOwn)
+ internal GodotObject(bool memoryOwn)
{
_memoryOwn = memoryOwn;
}
/// <summary>
- /// The pointer to the native instance of this <see cref="Object"/>.
+ /// The pointer to the native instance of this <see cref="GodotObject"/>.
/// </summary>
public IntPtr NativeInstance => NativePtr;
- internal static IntPtr GetPtr(Object instance)
+ internal static IntPtr GetPtr(GodotObject instance)
{
if (instance == null)
return IntPtr.Zero;
@@ -75,13 +75,13 @@ namespace Godot
return instance.NativePtr;
}
- ~Object()
+ ~GodotObject()
{
Dispose(false);
}
/// <summary>
- /// Disposes of this <see cref="Object"/>.
+ /// Disposes of this <see cref="GodotObject"/>.
/// </summary>
public void Dispose()
{
@@ -90,7 +90,7 @@ namespace Godot
}
/// <summary>
- /// Disposes implementation of this <see cref="Object"/>.
+ /// Disposes implementation of this <see cref="GodotObject"/>.
/// </summary>
protected virtual void Dispose(bool disposing)
{
@@ -129,7 +129,7 @@ namespace Godot
}
/// <summary>
- /// Converts this <see cref="Object"/> to a string.
+ /// Converts this <see cref="GodotObject"/> to a string.
/// </summary>
/// <returns>A string representation of this object.</returns>
public override string ToString()
@@ -166,7 +166,7 @@ namespace Godot
/// A <see cref="SignalAwaiter"/> that completes when
/// <paramref name="source"/> emits the <paramref name="signal"/>.
/// </returns>
- public SignalAwaiter ToSignal(Object source, StringName signal)
+ public SignalAwaiter ToSignal(GodotObject source, StringName signal)
{
return new SignalAwaiter(source, signal, this);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.exceptions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.exceptions.cs
index 0fcc4ee01b..a7640043ce 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.exceptions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.exceptions.cs
@@ -5,7 +5,7 @@ using System.Text;
namespace Godot
{
- public partial class Object
+ public partial class GodotObject
{
public class NativeMemberNotFoundException : Exception
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
index 1b599beab5..79030c79cc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
@@ -1,17 +1,44 @@
+using System;
using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.Threading;
+using System.Threading.Tasks;
namespace Godot
{
- public class GodotSynchronizationContext : SynchronizationContext
+ public sealed class GodotSynchronizationContext : SynchronizationContext, IDisposable
{
- private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> _queue =
- new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
+ private readonly BlockingCollection<(SendOrPostCallback Callback, object State)> _queue = new();
+
+ public override void Send(SendOrPostCallback d, object state)
+ {
+ // Shortcut if we're already on this context
+ // Also necessary to avoid a deadlock, since Send is blocking
+ if (Current == this)
+ {
+ d(state);
+ return;
+ }
+
+ var source = new TaskCompletionSource();
+
+ _queue.Add((st =>
+ {
+ try
+ {
+ d(st);
+ }
+ finally
+ {
+ source.SetResult();
+ }
+ }, state));
+
+ source.Task.Wait();
+ }
public override void Post(SendOrPostCallback d, object state)
{
- _queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
+ _queue.Add((d, state));
}
/// <summary>
@@ -21,8 +48,13 @@ namespace Godot
{
while (_queue.TryTake(out var workItem))
{
- workItem.Key(workItem.Value);
+ workItem.Callback(workItem.State);
}
}
+
+ public void Dispose()
+ {
+ _queue.Dispose();
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs
index 408bed71b2..f6c36455b2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs
@@ -10,7 +10,7 @@ namespace Godot
/// GodotTaskScheduler contains a linked list of tasks to perform as a queue. Methods
/// within the class are used to control the queue and perform the contained tasks.
/// </summary>
- public class GodotTaskScheduler : TaskScheduler
+ public sealed class GodotTaskScheduler : TaskScheduler, IDisposable
{
/// <summary>
/// The current synchronization context.
@@ -108,5 +108,10 @@ namespace Godot
}
}
}
+
+ public void Dispose()
+ {
+ Context.Dispose();
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index f2667c6807..ca0032df73 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -1,4 +1,5 @@
using System;
+using System.Runtime.CompilerServices;
namespace Godot
{
@@ -35,15 +36,18 @@ namespace Godot
public const real_t NaN = real_t.NaN;
// 0.0174532924f and 0.0174532925199433
- private const real_t _degToRadConst = (real_t)0.0174532925199432957692369077M;
+ private const float _degToRadConstF = (float)0.0174532925199432957692369077M;
+ private const double _degToRadConstD = (double)0.0174532925199432957692369077M;
// 57.29578f and 57.2957795130823
- private const real_t _radToDegConst = (real_t)57.295779513082320876798154814M;
+ private const float _radToDegConstF = (float)57.295779513082320876798154814M;
+ private const double _radToDegConstD = (double)57.295779513082320876798154814M;
/// <summary>
/// Returns the absolute value of <paramref name="s"/> (i.e. positive value).
/// </summary>
/// <param name="s">The input number.</param>
/// <returns>The absolute value of <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Abs(int s)
{
return Math.Abs(s);
@@ -54,7 +58,19 @@ namespace Godot
/// </summary>
/// <param name="s">The input number.</param>
/// <returns>The absolute value of <paramref name="s"/>.</returns>
- public static real_t Abs(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Abs(float s)
+ {
+ return Math.Abs(s);
+ }
+
+ /// <summary>
+ /// Returns the absolute value of <paramref name="s"/> (i.e. positive value).
+ /// </summary>
+ /// <param name="s">The input number.</param>
+ /// <returns>The absolute value of <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Abs(double s)
{
return Math.Abs(s);
}
@@ -67,9 +83,38 @@ namespace Godot
/// <returns>
/// An angle that would result in the given cosine value. On the range <c>0</c> to <c>Tau/2</c>.
/// </returns>
- public static real_t Acos(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Acos(float s)
{
- return (real_t)Math.Acos(s);
+ return MathF.Acos(s);
+ }
+
+ /// <summary>
+ /// Returns the arc cosine of <paramref name="s"/> in radians.
+ /// Use to get the angle of cosine <paramref name="s"/>.
+ /// </summary>
+ /// <param name="s">The input cosine value. Must be on the range of -1.0 to 1.0.</param>
+ /// <returns>
+ /// An angle that would result in the given cosine value. On the range <c>0</c> to <c>Tau/2</c>.
+ /// </returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Acos(double s)
+ {
+ return Math.Acos(s);
+ }
+
+ /// <summary>
+ /// Returns the arc sine of <paramref name="s"/> in radians.
+ /// Use to get the angle of sine <paramref name="s"/>.
+ /// </summary>
+ /// <param name="s">The input sine value. Must be on the range of -1.0 to 1.0.</param>
+ /// <returns>
+ /// An angle that would result in the given sine value. On the range <c>-Tau/4</c> to <c>Tau/4</c>.
+ /// </returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Asin(float s)
+ {
+ return MathF.Asin(s);
}
/// <summary>
@@ -80,9 +125,27 @@ namespace Godot
/// <returns>
/// An angle that would result in the given sine value. On the range <c>-Tau/4</c> to <c>Tau/4</c>.
/// </returns>
- public static real_t Asin(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Asin(double s)
+ {
+ return Math.Asin(s);
+ }
+
+ /// <summary>
+ /// Returns the arc tangent of <paramref name="s"/> in radians.
+ /// Use to get the angle of tangent <paramref name="s"/>.
+ ///
+ /// The method cannot know in which quadrant the angle should fall.
+ /// See <see cref="Atan2(float, float)"/> if you have both <c>y</c> and <c>x</c>.
+ /// </summary>
+ /// <param name="s">The input tangent value.</param>
+ /// <returns>
+ /// An angle that would result in the given tangent value. On the range <c>-Tau/4</c> to <c>Tau/4</c>.
+ /// </returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Atan(float s)
{
- return (real_t)Math.Asin(s);
+ return MathF.Atan(s);
}
/// <summary>
@@ -90,15 +153,16 @@ namespace Godot
/// Use to get the angle of tangent <paramref name="s"/>.
///
/// The method cannot know in which quadrant the angle should fall.
- /// See <see cref="Atan2(real_t, real_t)"/> if you have both <c>y</c> and <c>x</c>.
+ /// See <see cref="Atan2(double, double)"/> if you have both <c>y</c> and <c>x</c>.
/// </summary>
/// <param name="s">The input tangent value.</param>
/// <returns>
/// An angle that would result in the given tangent value. On the range <c>-Tau/4</c> to <c>Tau/4</c>.
/// </returns>
- public static real_t Atan(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Atan(double s)
{
- return (real_t)Math.Atan(s);
+ return Math.Atan(s);
}
/// <summary>
@@ -113,9 +177,39 @@ namespace Godot
/// <returns>
/// An angle that would result in the given tangent value. On the range <c>-Tau/2</c> to <c>Tau/2</c>.
/// </returns>
- public static real_t Atan2(real_t y, real_t x)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Atan2(float y, float x)
{
- return (real_t)Math.Atan2(y, x);
+ return MathF.Atan2(y, x);
+ }
+
+ /// <summary>
+ /// Returns the arc tangent of <paramref name="y"/> and <paramref name="x"/> in radians.
+ /// Use to get the angle of the tangent of <c>y/x</c>. To compute the value, the method takes into
+ /// account the sign of both arguments in order to determine the quadrant.
+ ///
+ /// Important note: The Y coordinate comes first, by convention.
+ /// </summary>
+ /// <param name="y">The Y coordinate of the point to find the angle to.</param>
+ /// <param name="x">The X coordinate of the point to find the angle to.</param>
+ /// <returns>
+ /// An angle that would result in the given tangent value. On the range <c>-Tau/2</c> to <c>Tau/2</c>.
+ /// </returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Atan2(double y, double x)
+ {
+ return Math.Atan2(y, x);
+ }
+
+ /// <summary>
+ /// Rounds <paramref name="s"/> upward (towards positive infinity).
+ /// </summary>
+ /// <param name="s">The number to ceil.</param>
+ /// <returns>The smallest whole number that is not less than <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Ceil(float s)
+ {
+ return MathF.Ceiling(s);
}
/// <summary>
@@ -123,9 +217,10 @@ namespace Godot
/// </summary>
/// <param name="s">The number to ceil.</param>
/// <returns>The smallest whole number that is not less than <paramref name="s"/>.</returns>
- public static real_t Ceil(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Ceil(double s)
{
- return (real_t)Math.Ceiling(s);
+ return Math.Ceiling(s);
}
/// <summary>
@@ -136,9 +231,10 @@ namespace Godot
/// <param name="min">The minimum allowed value.</param>
/// <param name="max">The maximum allowed value.</param>
/// <returns>The clamped value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Clamp(int value, int min, int max)
{
- return value < min ? min : value > max ? max : value;
+ return Math.Clamp(value, min, max);
}
/// <summary>
@@ -149,9 +245,24 @@ namespace Godot
/// <param name="min">The minimum allowed value.</param>
/// <param name="max">The maximum allowed value.</param>
/// <returns>The clamped value.</returns>
- public static real_t Clamp(real_t value, real_t min, real_t max)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Clamp(float value, float min, float max)
{
- return value < min ? min : value > max ? max : value;
+ return Math.Clamp(value, min, max);
+ }
+
+ /// <summary>
+ /// Clamps a <paramref name="value"/> so that it is not less than <paramref name="min"/>
+ /// and not more than <paramref name="max"/>.
+ /// </summary>
+ /// <param name="value">The value to clamp.</param>
+ /// <param name="min">The minimum allowed value.</param>
+ /// <param name="max">The maximum allowed value.</param>
+ /// <returns>The clamped value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Clamp(double value, double min, double max)
+ {
+ return Math.Clamp(value, min, max);
}
/// <summary>
@@ -159,9 +270,21 @@ namespace Godot
/// </summary>
/// <param name="s">The angle in radians.</param>
/// <returns>The cosine of that angle.</returns>
- public static real_t Cos(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Cos(float s)
{
- return (real_t)Math.Cos(s);
+ return MathF.Cos(s);
+ }
+
+ /// <summary>
+ /// Returns the cosine of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The cosine of that angle.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Cos(double s)
+ {
+ return Math.Cos(s);
}
/// <summary>
@@ -169,9 +292,21 @@ namespace Godot
/// </summary>
/// <param name="s">The angle in radians.</param>
/// <returns>The hyperbolic cosine of that angle.</returns>
- public static real_t Cosh(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Cosh(float s)
{
- return (real_t)Math.Cosh(s);
+ return MathF.Cosh(s);
+ }
+
+ /// <summary>
+ /// Returns the hyperbolic cosine of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The hyperbolic cosine of that angle.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Cosh(double s)
+ {
+ return Math.Cosh(s);
}
/// <summary>
@@ -184,7 +319,7 @@ namespace Godot
/// <param name="post">The value which after "to" value 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 value of the interpolation.</returns>
- public static real_t CubicInterpolate(real_t from, real_t to, real_t pre, real_t post, real_t weight)
+ public static float CubicInterpolate(float from, float to, float pre, float post, float weight)
{
return 0.5f *
((from * 2.0f) +
@@ -194,9 +329,28 @@ namespace Godot
}
/// <summary>
+ /// Cubic interpolates between two values by the factor defined in <paramref name="weight"/>
+ /// with pre and post values.
+ /// </summary>
+ /// <param name="from">The start value for interpolation.</param>
+ /// <param name="to">The destination value for interpolation.</param>
+ /// <param name="pre">The value which before "from" value for interpolation.</param>
+ /// <param name="post">The value which after "to" value 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 value of the interpolation.</returns>
+ public static double CubicInterpolate(double from, double to, double pre, double post, double weight)
+ {
+ return 0.5 *
+ ((from * 2.0) +
+ (-pre + to) * weight +
+ (2.0 * pre - 5.0 * from + 4.0 * to - post) * (weight * weight) +
+ (-pre + 3.0 * from - 3.0 * to + post) * (weight * weight * weight));
+ }
+
+ /// <summary>
/// Cubic interpolates between two rotation values with shortest path
/// by the factor defined in <paramref name="weight"/> with pre and post values.
- /// See also <see cref="LerpAngle"/>.
+ /// See also <see cref="LerpAngle(float, float, float)"/>.
/// </summary>
/// <param name="from">The start value for interpolation.</param>
/// <param name="to">The destination value for interpolation.</param>
@@ -204,18 +358,45 @@ namespace Godot
/// <param name="post">The value which after "to" value 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 value of the interpolation.</returns>
- public static real_t CubicInterpolateAngle(real_t from, real_t to, real_t pre, real_t post, real_t weight)
+ public static float CubicInterpolateAngle(float from, float to, float pre, float post, float weight)
{
- real_t fromRot = from % Mathf.Tau;
+ float fromRot = from % MathF.Tau;
- real_t preDiff = (pre - fromRot) % Mathf.Tau;
- real_t preRot = fromRot + (2.0f * preDiff) % Mathf.Tau - preDiff;
+ float preDiff = (pre - fromRot) % MathF.Tau;
+ float preRot = fromRot + (2.0f * preDiff) % MathF.Tau - preDiff;
- real_t toDiff = (to - fromRot) % Mathf.Tau;
- real_t toRot = fromRot + (2.0f * toDiff) % Mathf.Tau - toDiff;
+ float toDiff = (to - fromRot) % MathF.Tau;
+ float toRot = fromRot + (2.0f * toDiff) % MathF.Tau - toDiff;
- real_t postDiff = (post - toRot) % Mathf.Tau;
- real_t postRot = toRot + (2.0f * postDiff) % Mathf.Tau - postDiff;
+ float postDiff = (post - toRot) % MathF.Tau;
+ float postRot = toRot + (2.0f * postDiff) % MathF.Tau - postDiff;
+
+ return CubicInterpolate(fromRot, toRot, preRot, postRot, weight);
+ }
+
+ /// <summary>
+ /// Cubic interpolates between two rotation values with shortest path
+ /// by the factor defined in <paramref name="weight"/> with pre and post values.
+ /// See also <see cref="LerpAngle(double, double, double)"/>.
+ /// </summary>
+ /// <param name="from">The start value for interpolation.</param>
+ /// <param name="to">The destination value for interpolation.</param>
+ /// <param name="pre">The value which before "from" value for interpolation.</param>
+ /// <param name="post">The value which after "to" value 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 value of the interpolation.</returns>
+ public static double CubicInterpolateAngle(double from, double to, double pre, double post, double weight)
+ {
+ double fromRot = from % Math.Tau;
+
+ double preDiff = (pre - fromRot) % Math.Tau;
+ double preRot = fromRot + (2.0 * preDiff) % Math.Tau - preDiff;
+
+ double toDiff = (to - fromRot) % Math.Tau;
+ double toRot = fromRot + (2.0 * toDiff) % Math.Tau - toDiff;
+
+ double postDiff = (post - toRot) % Math.Tau;
+ double postRot = toRot + (2.0 * postDiff) % Math.Tau - postDiff;
return CubicInterpolate(fromRot, toRot, preRot, postRot, weight);
}
@@ -223,7 +404,8 @@ namespace Godot
/// <summary>
/// Cubic interpolates between two values by the factor defined in <paramref name="weight"/>
/// with pre and post values.
- /// It can perform smoother interpolation than <see cref="CubicInterpolate"/>
+ /// It can perform smoother interpolation than
+ /// <see cref="CubicInterpolate(float, float, float, float, float)"/>
/// by the time values.
/// </summary>
/// <param name="from">The start value for interpolation.</param>
@@ -235,23 +417,52 @@ namespace Godot
/// <param name="preT"></param>
/// <param name="postT"></param>
/// <returns>The resulting value of the interpolation.</returns>
- public static real_t CubicInterpolateInTime(real_t from, real_t to, real_t pre, real_t post, real_t weight, real_t toT, real_t preT, real_t postT)
+ public static float CubicInterpolateInTime(float from, float to, float pre, float post, float weight, float toT, float preT, float postT)
{
/* Barry-Goldman method */
- real_t t = Lerp(0.0f, toT, weight);
- real_t a1 = Lerp(pre, from, preT == 0 ? 0.0f : (t - preT) / -preT);
- real_t a2 = Lerp(from, to, toT == 0 ? 0.5f : t / toT);
- real_t a3 = Lerp(to, post, postT - toT == 0 ? 1.0f : (t - toT) / (postT - toT));
- real_t b1 = Lerp(a1, a2, toT - preT == 0 ? 0.0f : (t - preT) / (toT - preT));
- real_t b2 = Lerp(a2, a3, postT == 0 ? 1.0f : t / postT);
+ float t = Lerp(0.0f, toT, weight);
+ float a1 = Lerp(pre, from, preT == 0 ? 0.0f : (t - preT) / -preT);
+ float a2 = Lerp(from, to, toT == 0 ? 0.5f : t / toT);
+ float a3 = Lerp(to, post, postT - toT == 0 ? 1.0f : (t - toT) / (postT - toT));
+ float b1 = Lerp(a1, a2, toT - preT == 0 ? 0.0f : (t - preT) / (toT - preT));
+ float b2 = Lerp(a2, a3, postT == 0 ? 1.0f : t / postT);
return Lerp(b1, b2, toT == 0 ? 0.5f : t / toT);
}
/// <summary>
+ /// Cubic interpolates between two values by the factor defined in <paramref name="weight"/>
+ /// with pre and post values.
+ /// It can perform smoother interpolation than
+ /// <see cref="CubicInterpolate(double, double, double, double, double)"/>
+ /// by the time values.
+ /// </summary>
+ /// <param name="from">The start value for interpolation.</param>
+ /// <param name="to">The destination value for interpolation.</param>
+ /// <param name="pre">The value which before "from" value for interpolation.</param>
+ /// <param name="post">The value which after "to" value for interpolation.</param>
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <param name="toT"></param>
+ /// <param name="preT"></param>
+ /// <param name="postT"></param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public static double CubicInterpolateInTime(double from, double to, double pre, double post, double weight, double toT, double preT, double postT)
+ {
+ /* Barry-Goldman method */
+ double t = Lerp(0.0, toT, weight);
+ double a1 = Lerp(pre, from, preT == 0 ? 0.0 : (t - preT) / -preT);
+ double a2 = Lerp(from, to, toT == 0 ? 0.5 : t / toT);
+ double a3 = Lerp(to, post, postT - toT == 0 ? 1.0 : (t - toT) / (postT - toT));
+ double b1 = Lerp(a1, a2, toT - preT == 0 ? 0.0 : (t - preT) / (toT - preT));
+ double b2 = Lerp(a2, a3, postT == 0 ? 1.0 : t / postT);
+ return Lerp(b1, b2, toT == 0 ? 0.5 : t / toT);
+ }
+
+ /// <summary>
/// Cubic interpolates between two rotation values with shortest path
/// by the factor defined in <paramref name="weight"/> with pre and post values.
- /// See also <see cref="LerpAngle"/>.
- /// It can perform smoother interpolation than <see cref="CubicInterpolateAngle"/>
+ /// See also <see cref="LerpAngle(float, float, float)"/>.
+ /// It can perform smoother interpolation than
+ /// <see cref="CubicInterpolateAngle(float, float, float, float, float)"/>
/// by the time values.
/// </summary>
/// <param name="from">The start value for interpolation.</param>
@@ -263,26 +474,58 @@ namespace Godot
/// <param name="preT"></param>
/// <param name="postT"></param>
/// <returns>The resulting value of the interpolation.</returns>
- public static real_t CubicInterpolateAngleInTime(real_t from, real_t to, real_t pre, real_t post, real_t weight,
- real_t toT, real_t preT, real_t postT)
+ public static float CubicInterpolateAngleInTime(float from, float to, float pre, float post, float weight, float toT, float preT, float postT)
{
- real_t fromRot = from % Mathf.Tau;
+ float fromRot = from % MathF.Tau;
- real_t preDiff = (pre - fromRot) % Mathf.Tau;
- real_t preRot = fromRot + (2.0f * preDiff) % Mathf.Tau - preDiff;
+ float preDiff = (pre - fromRot) % MathF.Tau;
+ float preRot = fromRot + (2.0f * preDiff) % MathF.Tau - preDiff;
- real_t toDiff = (to - fromRot) % Mathf.Tau;
- real_t toRot = fromRot + (2.0f * toDiff) % Mathf.Tau - toDiff;
+ float toDiff = (to - fromRot) % MathF.Tau;
+ float toRot = fromRot + (2.0f * toDiff) % MathF.Tau - toDiff;
- real_t postDiff = (post - toRot) % Mathf.Tau;
- real_t postRot = toRot + (2.0f * postDiff) % Mathf.Tau - postDiff;
+ float postDiff = (post - toRot) % MathF.Tau;
+ float postRot = toRot + (2.0f * postDiff) % MathF.Tau - postDiff;
+
+ return CubicInterpolateInTime(fromRot, toRot, preRot, postRot, weight, toT, preT, postT);
+ }
+
+ /// <summary>
+ /// Cubic interpolates between two rotation values with shortest path
+ /// by the factor defined in <paramref name="weight"/> with pre and post values.
+ /// See also <see cref="LerpAngle(double, double, double)"/>.
+ /// It can perform smoother interpolation than
+ /// <see cref="CubicInterpolateAngle(double, double, double, double, double)"/>
+ /// by the time values.
+ /// </summary>
+ /// <param name="from">The start value for interpolation.</param>
+ /// <param name="to">The destination value for interpolation.</param>
+ /// <param name="pre">The value which before "from" value for interpolation.</param>
+ /// <param name="post">The value which after "to" value for interpolation.</param>
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <param name="toT"></param>
+ /// <param name="preT"></param>
+ /// <param name="postT"></param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public static double CubicInterpolateAngleInTime(double from, double to, double pre, double post, double weight, double toT, double preT, double postT)
+ {
+ double fromRot = from % Math.Tau;
+
+ double preDiff = (pre - fromRot) % Math.Tau;
+ double preRot = fromRot + (2.0 * preDiff) % Math.Tau - preDiff;
+
+ double toDiff = (to - fromRot) % Math.Tau;
+ double toRot = fromRot + (2.0 * toDiff) % Math.Tau - toDiff;
+
+ double postDiff = (post - toRot) % Math.Tau;
+ double postRot = toRot + (2.0 * postDiff) % Math.Tau - postDiff;
return CubicInterpolateInTime(fromRot, toRot, preRot, postRot, weight, toT, preT, postT);
}
/// <summary>
/// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by
- /// the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
+ /// the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
/// </summary>
/// <param name="start">The start value for the interpolation.</param>
/// <param name="control1">Control point that defines the bezier curve.</param>
@@ -290,16 +533,112 @@ namespace Godot
/// <param name="end">The destination value for the interpolation.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting value of the interpolation.</returns>
- public static real_t BezierInterpolate(real_t start, real_t control1, real_t control2, real_t end, real_t t)
+ public static float BezierInterpolate(float start, float control1, float control2, float end, float t)
{
// Formula from Wikipedia article on Bezier curves
- real_t omt = 1 - t;
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
+ float omt = 1.0f - t;
+ float omt2 = omt * omt;
+ float omt3 = omt2 * omt;
+ float t2 = t * t;
+ float t3 = t2 * t;
- return start * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ return start * omt3 + control1 * omt2 * t * 3.0f + control2 * omt * t2 * 3.0f + end * t3;
+ }
+
+ /// <summary>
+ /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by
+ /// the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="start">The start value for the interpolation.</param>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination value for the interpolation.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public static double BezierInterpolate(double start, double control1, double control2, double end, double t)
+ {
+ // Formula from Wikipedia article on Bezier curves
+ double omt = 1.0 - t;
+ double omt2 = omt * omt;
+ double omt3 = omt2 * omt;
+ double t2 = t * t;
+ double t3 = t2 * t;
+
+ return start * omt3 + control1 * omt2 * t * 3.0 + control2 * omt * t2 * 3.0 + end * t3;
+ }
+
+ /// <summary>
+ /// Returns the derivative at the given <paramref name="t"/> on a one dimensional Bezier curve defined by
+ /// the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="start">The start value for the interpolation.</param>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination value for the interpolation.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public static float BezierDerivative(float start, float control1, float control2, float end, float t)
+ {
+ // Formula from Wikipedia article on Bezier curves
+ float omt = 1.0f - t;
+ float omt2 = omt * omt;
+ float t2 = t * t;
+
+ float d = (control1 - start) * 3.0f * omt2 + (control2 - control1) * 6.0f * omt * t + (end - control2) * 3.0f * t2;
+ return d;
+ }
+
+ /// <summary>
+ /// Returns the derivative at the given <paramref name="t"/> on a one dimensional Bezier curve defined by
+ /// the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="start">The start value for the interpolation.</param>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination value for the interpolation.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public static double BezierDerivative(double start, double control1, double control2, double end, double t)
+ {
+ // Formula from Wikipedia article on Bezier curves
+ double omt = 1.0 - t;
+ double omt2 = omt * omt;
+ double t2 = t * t;
+
+ double d = (control1 - start) * 3.0 * omt2 + (control2 - control1) * 6.0 * omt * t + (end - control2) * 3.0 * t2;
+ return d;
+ }
+
+ /// <summary>
+ /// Converts from decibels to linear energy (audio).
+ /// </summary>
+ /// <seealso cref="LinearToDb(float)"/>
+ /// <param name="db">Decibels to convert.</param>
+ /// <returns>Audio volume as linear energy.</returns>
+ public static float DbToLinear(float db)
+ {
+ return MathF.Exp(db * 0.11512925464970228420089957273422f);
+ }
+
+ /// <summary>
+ /// Converts from decibels to linear energy (audio).
+ /// </summary>
+ /// <seealso cref="LinearToDb(double)"/>
+ /// <param name="db">Decibels to convert.</param>
+ /// <returns>Audio volume as linear energy.</returns>
+ public static double DbToLinear(double db)
+ {
+ return Math.Exp(db * 0.11512925464970228420089957273422);
+ }
+
+ /// <summary>
+ /// Converts an angle expressed in degrees to radians.
+ /// </summary>
+ /// <param name="deg">An angle expressed in degrees.</param>
+ /// <returns>The same angle expressed in radians.</returns>
+ public static float DegToRad(float deg)
+ {
+ return deg * _degToRadConstF;
}
/// <summary>
@@ -307,9 +646,9 @@ namespace Godot
/// </summary>
/// <param name="deg">An angle expressed in degrees.</param>
/// <returns>The same angle expressed in radians.</returns>
- public static real_t DegToRad(real_t deg)
+ public static double DegToRad(double deg)
{
- return deg * _degToRadConst;
+ return deg * _degToRadConstD;
}
/// <summary>
@@ -322,38 +661,82 @@ namespace Godot
/// <c>0</c> is constant, <c>1</c> is linear, <c>0</c> to <c>1</c> is ease-in, <c>1</c> or more is ease-out.
/// </param>
/// <returns>The eased value.</returns>
- public static real_t Ease(real_t s, real_t curve)
+ public static float Ease(float s, float curve)
{
- if (s < 0f)
+ if (s < 0.0f)
{
- s = 0f;
+ s = 0.0f;
}
else if (s > 1.0f)
{
s = 1.0f;
}
- if (curve > 0f)
+ if (curve > 0.0f)
{
if (curve < 1.0f)
{
- return 1.0f - Pow(1.0f - s, 1.0f / curve);
+ return 1.0f - MathF.Pow(1.0f - s, 1.0f / curve);
}
- return Pow(s, curve);
+ return MathF.Pow(s, curve);
}
- if (curve < 0f)
+ if (curve < 0.0f)
{
if (s < 0.5f)
{
- return Pow(s * 2.0f, -curve) * 0.5f;
+ return MathF.Pow(s * 2.0f, -curve) * 0.5f;
}
- return ((1.0f - Pow(1.0f - ((s - 0.5f) * 2.0f), -curve)) * 0.5f) + 0.5f;
+ return ((1.0f - MathF.Pow(1.0f - ((s - 0.5f) * 2.0f), -curve)) * 0.5f) + 0.5f;
}
- return 0f;
+ return 0.0f;
+ }
+
+ /// <summary>
+ /// Easing function, based on exponent. The <paramref name="curve"/> values are:
+ /// <c>0</c> is constant, <c>1</c> is linear, <c>0</c> to <c>1</c> is ease-in, <c>1</c> or more is ease-out.
+ /// Negative values are in-out/out-in.
+ /// </summary>
+ /// <param name="s">The value to ease.</param>
+ /// <param name="curve">
+ /// <c>0</c> is constant, <c>1</c> is linear, <c>0</c> to <c>1</c> is ease-in, <c>1</c> or more is ease-out.
+ /// </param>
+ /// <returns>The eased value.</returns>
+ public static double Ease(double s, double curve)
+ {
+ if (s < 0.0)
+ {
+ s = 0.0;
+ }
+ else if (s > 1.0)
+ {
+ s = 1.0;
+ }
+
+ if (curve > 0)
+ {
+ if (curve < 1.0)
+ {
+ return 1.0 - Math.Pow(1.0 - s, 1.0 / curve);
+ }
+
+ return Math.Pow(s, curve);
+ }
+
+ if (curve < 0.0)
+ {
+ if (s < 0.5)
+ {
+ return Math.Pow(s * 2.0, -curve) * 0.5;
+ }
+
+ return ((1.0 - Math.Pow(1.0 - ((s - 0.5) * 2.0), -curve)) * 0.5) + 0.5;
+ }
+
+ return 0.0;
}
/// <summary>
@@ -362,9 +745,33 @@ namespace Godot
/// </summary>
/// <param name="s">The exponent to raise <c>e</c> to.</param>
/// <returns><c>e</c> raised to the power of <paramref name="s"/>.</returns>
- public static real_t Exp(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Exp(float s)
{
- return (real_t)Math.Exp(s);
+ return MathF.Exp(s);
+ }
+
+ /// <summary>
+ /// The natural exponential function. It raises the mathematical
+ /// constant <c>e</c> to the power of <paramref name="s"/> and returns it.
+ /// </summary>
+ /// <param name="s">The exponent to raise <c>e</c> to.</param>
+ /// <returns><c>e</c> raised to the power of <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Exp(double s)
+ {
+ return Math.Exp(s);
+ }
+
+ /// <summary>
+ /// Rounds <paramref name="s"/> downward (towards negative infinity).
+ /// </summary>
+ /// <param name="s">The number to floor.</param>
+ /// <returns>The largest whole number that is not more than <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Floor(float s)
+ {
+ return MathF.Floor(s);
}
/// <summary>
@@ -372,14 +779,32 @@ namespace Godot
/// </summary>
/// <param name="s">The number to floor.</param>
/// <returns>The largest whole number that is not more than <paramref name="s"/>.</returns>
- public static real_t Floor(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Floor(double s)
+ {
+ return Math.Floor(s);
+ }
+
+ /// <summary>
+ /// Returns a normalized value considering the given range.
+ /// This is the opposite of <see cref="Lerp(float, float, float)"/>.
+ /// </summary>
+ /// <param name="from">The start value for interpolation.</param>
+ /// <param name="to">The destination value for interpolation.</param>
+ /// <param name="weight">The interpolated value.</param>
+ /// <returns>
+ /// The resulting value of the inverse interpolation.
+ /// The returned value will be between 0.0 and 1.0 if <paramref name="weight"/> is
+ /// between <paramref name="from"/> and <paramref name="to"/> (inclusive).
+ /// </returns>
+ public static float InverseLerp(float from, float to, float weight)
{
- return (real_t)Math.Floor(s);
+ return (weight - from) / (to - from);
}
/// <summary>
/// Returns a normalized value considering the given range.
- /// This is the opposite of <see cref="Lerp(real_t, real_t, real_t)"/>.
+ /// This is the opposite of <see cref="Lerp(double, double, double)"/>.
/// </summary>
/// <param name="from">The start value for interpolation.</param>
/// <param name="to">The destination value for interpolation.</param>
@@ -389,7 +814,7 @@ namespace Godot
/// The returned value will be between 0.0 and 1.0 if <paramref name="weight"/> is
/// between <paramref name="from"/> and <paramref name="to"/> (inclusive).
/// </returns>
- public static real_t InverseLerp(real_t from, real_t to, real_t weight)
+ public static double InverseLerp(double from, double to, double weight)
{
return (weight - from) / (to - from);
}
@@ -402,7 +827,31 @@ namespace Godot
/// <param name="a">One of the values.</param>
/// <param name="b">The other value.</param>
/// <returns>A <see langword="bool"/> for whether or not the two values are approximately equal.</returns>
- public static bool IsEqualApprox(real_t a, real_t b)
+ public static bool IsEqualApprox(float a, float b)
+ {
+ // Check for exact equality first, required to handle "infinity" values.
+ if (a == b)
+ {
+ return true;
+ }
+ // Then check for approximate equality.
+ float tolerance = _epsilonF * Math.Abs(a);
+ if (tolerance < _epsilonF)
+ {
+ tolerance = _epsilonF;
+ }
+ return Math.Abs(a - b) < tolerance;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if <paramref name="a"/> and <paramref name="b"/> are approximately equal
+ /// to each other.
+ /// The comparison is done using a tolerance calculation with <see cref="Epsilon"/>.
+ /// </summary>
+ /// <param name="a">One of the values.</param>
+ /// <param name="b">The other value.</param>
+ /// <returns>A <see langword="bool"/> for whether or not the two values are approximately equal.</returns>
+ public static bool IsEqualApprox(double a, double b)
{
// Check for exact equality first, required to handle "infinity" values.
if (a == b)
@@ -410,12 +859,47 @@ namespace Godot
return true;
}
// Then check for approximate equality.
- real_t tolerance = Epsilon * Abs(a);
- if (tolerance < Epsilon)
+ double tolerance = _epsilonD * Math.Abs(a);
+ if (tolerance < _epsilonD)
{
- tolerance = Epsilon;
+ tolerance = _epsilonD;
}
- return Abs(a - b) < tolerance;
+ return Math.Abs(a - b) < tolerance;
+ }
+
+ /// <summary>
+ /// Returns whether <paramref name="s"/> is a finite value, i.e. it is not
+ /// <see cref="NaN"/>, positive infinite, or negative infinity.
+ /// </summary>
+ /// <param name="s">The value to check.</param>
+ /// <returns>A <see langword="bool"/> for whether or not the value is a finite value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsFinite(float s)
+ {
+ return float.IsFinite(s);
+ }
+
+ /// <summary>
+ /// Returns whether <paramref name="s"/> is a finite value, i.e. it is not
+ /// <see cref="NaN"/>, positive infinite, or negative infinity.
+ /// </summary>
+ /// <param name="s">The value to check.</param>
+ /// <returns>A <see langword="bool"/> for whether or not the value is a finite value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsFinite(double s)
+ {
+ return double.IsFinite(s);
+ }
+
+ /// <summary>
+ /// Returns whether <paramref name="s"/> is an infinity value (either positive infinity or negative infinity).
+ /// </summary>
+ /// <param name="s">The value to check.</param>
+ /// <returns>A <see langword="bool"/> for whether or not the value is an infinity value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsInf(float s)
+ {
+ return float.IsInfinity(s);
}
/// <summary>
@@ -423,9 +907,21 @@ namespace Godot
/// </summary>
/// <param name="s">The value to check.</param>
/// <returns>A <see langword="bool"/> for whether or not the value is an infinity value.</returns>
- public static bool IsInf(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsInf(double s)
+ {
+ return double.IsInfinity(s);
+ }
+
+ /// <summary>
+ /// Returns whether <paramref name="s"/> is a <c>NaN</c> ("Not a Number" or invalid) value.
+ /// </summary>
+ /// <param name="s">The value to check.</param>
+ /// <returns>A <see langword="bool"/> for whether or not the value is a <c>NaN</c> value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsNaN(float s)
{
- return real_t.IsInfinity(s);
+ return float.IsNaN(s);
}
/// <summary>
@@ -433,64 +929,166 @@ namespace Godot
/// </summary>
/// <param name="s">The value to check.</param>
/// <returns>A <see langword="bool"/> for whether or not the value is a <c>NaN</c> value.</returns>
- public static bool IsNaN(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsNaN(double s)
{
- return real_t.IsNaN(s);
+ return double.IsNaN(s);
}
/// <summary>
- /// Returns <see langword="true"/> if <paramref name="s"/> is approximately zero.
+ /// Returns <see langword="true"/> if <paramref name="s"/> is zero or almost zero.
/// The comparison is done using a tolerance calculation with <see cref="Epsilon"/>.
///
- /// This method is faster than using <see cref="IsEqualApprox(real_t, real_t)"/> with one value as zero.
+ /// This method is faster than using <see cref="IsEqualApprox(float, float)"/> with
+ /// one value as zero.
/// </summary>
/// <param name="s">The value to check.</param>
/// <returns>A <see langword="bool"/> for whether or not the value is nearly zero.</returns>
- public static bool IsZeroApprox(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsZeroApprox(float s)
{
- return Abs(s) < Epsilon;
+ return Math.Abs(s) < _epsilonF;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if <paramref name="s"/> is zero or almost zero.
+ /// The comparison is done using a tolerance calculation with <see cref="Epsilon"/>.
+ ///
+ /// This method is faster than using <see cref="IsEqualApprox(double, double)"/> with
+ /// one value as zero.
+ /// </summary>
+ /// <param name="s">The value to check.</param>
+ /// <returns>A <see langword="bool"/> for whether or not the value is nearly zero.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsZeroApprox(double s)
+ {
+ return Math.Abs(s) < _epsilonD;
}
/// <summary>
/// Linearly interpolates between two values by a normalized value.
- /// This is the opposite <see cref="InverseLerp(real_t, real_t, real_t)"/>.
+ /// This is the opposite <see cref="InverseLerp(float, float, float)"/>.
/// </summary>
/// <param name="from">The start value for interpolation.</param>
/// <param name="to">The destination value 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 value of the interpolation.</returns>
- public static real_t Lerp(real_t from, real_t to, real_t weight)
+ public static float Lerp(float from, float to, float weight)
{
return from + ((to - from) * weight);
}
/// <summary>
+ /// Linearly interpolates between two values by a normalized value.
+ /// This is the opposite <see cref="InverseLerp(double, double, double)"/>.
+ /// </summary>
+ /// <param name="from">The start value for interpolation.</param>
+ /// <param name="to">The destination value 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 value of the interpolation.</returns>
+ public static double Lerp(double from, double to, double weight)
+ {
+ return from + ((to - from) * weight);
+ }
+
+ /// <summary>
+ /// Linearly interpolates between two angles (in radians) by a normalized value.
+ ///
+ /// Similar to <see cref="Lerp(float, float, float)"/>,
+ /// but interpolates correctly when the angles wrap around <see cref="Tau"/>.
+ /// </summary>
+ /// <param name="from">The start angle for interpolation.</param>
+ /// <param name="to">The destination angle 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 angle of the interpolation.</returns>
+ public static float LerpAngle(float from, float to, float weight)
+ {
+ float difference = (to - from) % MathF.Tau;
+ float distance = ((2 * difference) % MathF.Tau) - difference;
+ return from + (distance * weight);
+ }
+
+ /// <summary>
/// Linearly interpolates between two angles (in radians) by a normalized value.
///
- /// Similar to <see cref="Lerp(real_t, real_t, real_t)"/>,
+ /// Similar to <see cref="Lerp(double, double, double)"/>,
/// but interpolates correctly when the angles wrap around <see cref="Tau"/>.
/// </summary>
/// <param name="from">The start angle for interpolation.</param>
/// <param name="to">The destination angle 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 angle of the interpolation.</returns>
- public static real_t LerpAngle(real_t from, real_t to, real_t weight)
+ public static double LerpAngle(double from, double to, double weight)
{
- real_t difference = (to - from) % Mathf.Tau;
- real_t distance = ((2 * difference) % Mathf.Tau) - difference;
+ double difference = (to - from) % Math.Tau;
+ double distance = ((2 * difference) % Math.Tau) - difference;
return from + (distance * weight);
}
/// <summary>
+ /// Converts from linear energy to decibels (audio).
+ /// This can be used to implement volume sliders that behave as expected (since volume isn't linear).
+ /// </summary>
+ /// <seealso cref="DbToLinear(float)"/>
+ /// <example>
+ /// <code>
+ /// // "slider" refers to a node that inherits Range such as HSlider or VSlider.
+ /// // Its range must be configured to go from 0 to 1.
+ /// // Change the bus name if you'd like to change the volume of a specific bus only.
+ /// AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), GD.LinearToDb(slider.value));
+ /// </code>
+ /// </example>
+ /// <param name="linear">The linear energy to convert.</param>
+ /// <returns>Audio as decibels.</returns>
+ public static float LinearToDb(float linear)
+ {
+ return MathF.Log(linear) * 8.6858896380650365530225783783321f;
+ }
+
+ /// <summary>
+ /// Converts from linear energy to decibels (audio).
+ /// This can be used to implement volume sliders that behave as expected (since volume isn't linear).
+ /// </summary>
+ /// <seealso cref="DbToLinear(double)"/>
+ /// <example>
+ /// <code>
+ /// // "slider" refers to a node that inherits Range such as HSlider or VSlider.
+ /// // Its range must be configured to go from 0 to 1.
+ /// // Change the bus name if you'd like to change the volume of a specific bus only.
+ /// AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), GD.LinearToDb(slider.value));
+ /// </code>
+ /// </example>
+ /// <param name="linear">The linear energy to convert.</param>
+ /// <returns>Audio as decibels.</returns>
+ public static double LinearToDb(double linear)
+ {
+ return Math.Log(linear) * 8.6858896380650365530225783783321;
+ }
+
+ /// <summary>
+ /// Natural logarithm. The amount of time needed to reach a certain level of continuous growth.
+ ///
+ /// Note: This is not the same as the "log" function on most calculators, which uses a base 10 logarithm.
+ /// </summary>
+ /// <param name="s">The input value.</param>
+ /// <returns>The natural log of <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Log(float s)
+ {
+ return MathF.Log(s);
+ }
+
+ /// <summary>
/// Natural logarithm. The amount of time needed to reach a certain level of continuous growth.
///
/// Note: This is not the same as the "log" function on most calculators, which uses a base 10 logarithm.
/// </summary>
/// <param name="s">The input value.</param>
/// <returns>The natural log of <paramref name="s"/>.</returns>
- public static real_t Log(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Log(double s)
{
- return (real_t)Math.Log(s);
+ return Math.Log(s);
}
/// <summary>
@@ -499,9 +1097,10 @@ namespace Godot
/// <param name="a">One of the values.</param>
/// <param name="b">The other value.</param>
/// <returns>Whichever of the two values is higher.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Max(int a, int b)
{
- return a > b ? a : b;
+ return Math.Max(a, b);
}
/// <summary>
@@ -510,9 +1109,22 @@ namespace Godot
/// <param name="a">One of the values.</param>
/// <param name="b">The other value.</param>
/// <returns>Whichever of the two values is higher.</returns>
- public static real_t Max(real_t a, real_t b)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Max(float a, float b)
{
- return a > b ? a : b;
+ return Math.Max(a, b);
+ }
+
+ /// <summary>
+ /// Returns the maximum of two values.
+ /// </summary>
+ /// <param name="a">One of the values.</param>
+ /// <param name="b">The other value.</param>
+ /// <returns>Whichever of the two values is higher.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Max(double a, double b)
+ {
+ return Math.Max(a, b);
}
/// <summary>
@@ -521,9 +1133,22 @@ namespace Godot
/// <param name="a">One of the values.</param>
/// <param name="b">The other value.</param>
/// <returns>Whichever of the two values is lower.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Min(int a, int b)
{
- return a < b ? a : b;
+ return Math.Min(a, b);
+ }
+
+ /// <summary>
+ /// Returns the minimum of two values.
+ /// </summary>
+ /// <param name="a">One of the values.</param>
+ /// <param name="b">The other value.</param>
+ /// <returns>Whichever of the two values is lower.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Min(float a, float b)
+ {
+ return Math.Min(a, b);
}
/// <summary>
@@ -532,9 +1157,10 @@ namespace Godot
/// <param name="a">One of the values.</param>
/// <param name="b">The other value.</param>
/// <returns>Whichever of the two values is lower.</returns>
- public static real_t Min(real_t a, real_t b)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Min(double a, double b)
{
- return a < b ? a : b;
+ return Math.Min(a, b);
}
/// <summary>
@@ -546,12 +1172,29 @@ namespace Godot
/// <param name="to">The value to move towards.</param>
/// <param name="delta">The amount to move by.</param>
/// <returns>The value after moving.</returns>
- public static real_t MoveToward(real_t from, real_t to, real_t delta)
+ public static float MoveToward(float from, float to, float delta)
{
- if (Abs(to - from) <= delta)
+ if (Math.Abs(to - from) <= delta)
return to;
- return from + (Sign(to - from) * delta);
+ return from + (Math.Sign(to - from) * delta);
+ }
+
+ /// <summary>
+ /// Moves <paramref name="from"/> toward <paramref name="to"/> by the <paramref name="delta"/> value.
+ ///
+ /// Use a negative <paramref name="delta"/> value to move away.
+ /// </summary>
+ /// <param name="from">The start value.</param>
+ /// <param name="to">The value to move towards.</param>
+ /// <param name="delta">The amount to move by.</param>
+ /// <returns>The value after moving.</returns>
+ public static double MoveToward(double from, double to, double delta)
+ {
+ if (Math.Abs(to - from) <= delta)
+ return to;
+
+ return from + (Math.Sign(to - from) * delta);
}
/// <summary>
@@ -593,9 +1236,25 @@ namespace Godot
/// <param name="a">The dividend, the primary input.</param>
/// <param name="b">The divisor. The output is on the range [0, <paramref name="b"/>).</param>
/// <returns>The resulting output.</returns>
- public static real_t PosMod(real_t a, real_t b)
+ public static float PosMod(float a, float b)
+ {
+ float c = a % b;
+ if ((c < 0 && b > 0) || (c > 0 && b < 0))
+ {
+ c += b;
+ }
+ return c;
+ }
+
+ /// <summary>
+ /// Performs a canonical Modulus operation, where the output is on the range [0, <paramref name="b"/>).
+ /// </summary>
+ /// <param name="a">The dividend, the primary input.</param>
+ /// <param name="b">The divisor. The output is on the range [0, <paramref name="b"/>).</param>
+ /// <returns>The resulting output.</returns>
+ public static double PosMod(double a, double b)
{
- real_t c = a % b;
+ double c = a % b;
if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
@@ -609,9 +1268,33 @@ namespace Godot
/// <param name="x">The base.</param>
/// <param name="y">The exponent.</param>
/// <returns><paramref name="x"/> raised to the power of <paramref name="y"/>.</returns>
- public static real_t Pow(real_t x, real_t y)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Pow(float x, float y)
{
- return (real_t)Math.Pow(x, y);
+ return MathF.Pow(x, y);
+ }
+
+ /// <summary>
+ /// Returns the result of <paramref name="x"/> raised to the power of <paramref name="y"/>.
+ /// </summary>
+ /// <param name="x">The base.</param>
+ /// <param name="y">The exponent.</param>
+ /// <returns><paramref name="x"/> raised to the power of <paramref name="y"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Pow(double x, double y)
+ {
+ return Math.Pow(x, y);
+ }
+
+ /// <summary>
+ /// Converts an angle expressed in radians to degrees.
+ /// </summary>
+ /// <param name="rad">An angle expressed in radians.</param>
+ /// <returns>The same angle expressed in degrees.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float RadToDeg(float rad)
+ {
+ return rad * _radToDegConstF;
}
/// <summary>
@@ -619,9 +1302,10 @@ namespace Godot
/// </summary>
/// <param name="rad">An angle expressed in radians.</param>
/// <returns>The same angle expressed in degrees.</returns>
- public static real_t RadToDeg(real_t rad)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double RadToDeg(double rad)
{
- return rad * _radToDegConst;
+ return rad * _radToDegConstD;
}
/// <summary>
@@ -634,20 +1318,48 @@ namespace Godot
/// <param name="outFrom">The start value for the output interpolation.</param>
/// <param name="outTo">The destination value for the output interpolation.</param>
/// <returns>The resulting mapped value mapped.</returns>
- public static real_t Remap(real_t value, real_t inFrom, real_t inTo, real_t outFrom, real_t outTo)
+ public static float Remap(float value, float inFrom, float inTo, float outFrom, float outTo)
{
return Lerp(outFrom, outTo, InverseLerp(inFrom, inTo, value));
}
/// <summary>
+ /// Maps a <paramref name="value"/> from [<paramref name="inFrom"/>, <paramref name="inTo"/>]
+ /// to [<paramref name="outFrom"/>, <paramref name="outTo"/>].
+ /// </summary>
+ /// <param name="value">The value to map.</param>
+ /// <param name="inFrom">The start value for the input interpolation.</param>
+ /// <param name="inTo">The destination value for the input interpolation.</param>
+ /// <param name="outFrom">The start value for the output interpolation.</param>
+ /// <param name="outTo">The destination value for the output interpolation.</param>
+ /// <returns>The resulting mapped value mapped.</returns>
+ public static double Remap(double value, double inFrom, double inTo, double outFrom, double outTo)
+ {
+ return Lerp(outFrom, outTo, InverseLerp(inFrom, inTo, value));
+ }
+
+ /// <summary>
+ /// Rounds <paramref name="s"/> to the nearest whole number,
+ /// with halfway cases rounded towards the nearest multiple of two.
+ /// </summary>
+ /// <param name="s">The number to round.</param>
+ /// <returns>The rounded number.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Round(float s)
+ {
+ return MathF.Round(s);
+ }
+
+ /// <summary>
/// Rounds <paramref name="s"/> to the nearest whole number,
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <param name="s">The number to round.</param>
/// <returns>The rounded number.</returns>
- public static real_t Round(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Round(double s)
{
- return (real_t)Math.Round(s);
+ return Math.Round(s);
}
/// <summary>
@@ -656,11 +1368,10 @@ namespace Godot
/// </summary>
/// <param name="s">The input number.</param>
/// <returns>One of three possible values: <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Sign(int s)
{
- if (s == 0)
- return 0;
- return s < 0 ? -1 : 1;
+ return Math.Sign(s);
}
/// <summary>
@@ -669,11 +1380,33 @@ namespace Godot
/// </summary>
/// <param name="s">The input number.</param>
/// <returns>One of three possible values: <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public static int Sign(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Sign(float s)
{
- if (s == 0)
- return 0;
- return s < 0 ? -1 : 1;
+ return Math.Sign(s);
+ }
+
+ /// <summary>
+ /// Returns the sign of <paramref name="s"/>: <c>-1</c> or <c>1</c>.
+ /// Returns <c>0</c> if <paramref name="s"/> is <c>0</c>.
+ /// </summary>
+ /// <param name="s">The input number.</param>
+ /// <returns>One of three possible values: <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Sign(double s)
+ {
+ return Math.Sign(s);
+ }
+
+ /// <summary>
+ /// Returns the sine of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The sine of that angle.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Sin(float s)
+ {
+ return MathF.Sin(s);
}
/// <summary>
@@ -681,9 +1414,21 @@ namespace Godot
/// </summary>
/// <param name="s">The angle in radians.</param>
/// <returns>The sine of that angle.</returns>
- public static real_t Sin(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Sin(double s)
+ {
+ return Math.Sin(s);
+ }
+
+ /// <summary>
+ /// Returns the hyperbolic sine of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The hyperbolic sine of that angle.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Sinh(float s)
{
- return (real_t)Math.Sin(s);
+ return MathF.Sinh(s);
}
/// <summary>
@@ -691,27 +1436,47 @@ namespace Godot
/// </summary>
/// <param name="s">The angle in radians.</param>
/// <returns>The hyperbolic sine of that angle.</returns>
- public static real_t Sinh(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Sinh(double s)
+ {
+ return Math.Sinh(s);
+ }
+
+ /// <summary>
+ /// Returns a number smoothly interpolated between <paramref name="from"/> and <paramref name="to"/>,
+ /// based on the <paramref name="weight"/>. Similar to <see cref="Lerp(float, float, float)"/>,
+ /// but interpolates faster at the beginning and slower at the end.
+ /// </summary>
+ /// <param name="from">The start value for interpolation.</param>
+ /// <param name="to">The destination value for interpolation.</param>
+ /// <param name="weight">A value representing the amount of interpolation.</param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public static float SmoothStep(float from, float to, float weight)
{
- return (real_t)Math.Sinh(s);
+ if (IsEqualApprox(from, to))
+ {
+ return from;
+ }
+ float x = Math.Clamp((weight - from) / (to - from), 0.0f, 1.0f);
+ return x * x * (3 - (2 * x));
}
/// <summary>
/// Returns a number smoothly interpolated between <paramref name="from"/> and <paramref name="to"/>,
- /// based on the <paramref name="weight"/>. Similar to <see cref="Lerp(real_t, real_t, real_t)"/>,
+ /// based on the <paramref name="weight"/>. Similar to <see cref="Lerp(double, double, double)"/>,
/// but interpolates faster at the beginning and slower at the end.
/// </summary>
/// <param name="from">The start value for interpolation.</param>
/// <param name="to">The destination value for interpolation.</param>
/// <param name="weight">A value representing the amount of interpolation.</param>
/// <returns>The resulting value of the interpolation.</returns>
- public static real_t SmoothStep(real_t from, real_t to, real_t weight)
+ public static double SmoothStep(double from, double to, double weight)
{
if (IsEqualApprox(from, to))
{
return from;
}
- real_t x = Clamp((weight - from) / (to - from), (real_t)0.0, (real_t)1.0);
+ double x = Math.Clamp((weight - from) / (to - from), 0.0, 1.0);
return x * x * (3 - (2 * x));
}
@@ -722,9 +1487,23 @@ namespace Godot
/// </summary>
/// <param name="s">The input number. Must not be negative.</param>
/// <returns>The square root of <paramref name="s"/>.</returns>
- public static real_t Sqrt(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Sqrt(float s)
{
- return (real_t)Math.Sqrt(s);
+ return MathF.Sqrt(s);
+ }
+
+ /// <summary>
+ /// Returns the square root of <paramref name="s"/>, where <paramref name="s"/> is a non-negative number.
+ ///
+ /// If you need negative inputs, use <see cref="System.Numerics.Complex"/>.
+ /// </summary>
+ /// <param name="s">The input number. Must not be negative.</param>
+ /// <returns>The square root of <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Sqrt(double s)
+ {
+ return Math.Sqrt(s);
}
/// <summary>
@@ -734,7 +1513,7 @@ namespace Godot
/// </summary>
/// <param name="step">The input value.</param>
/// <returns>The position of the first non-zero digit.</returns>
- public static int StepDecimals(real_t step)
+ public static int StepDecimals(double step)
{
double[] sd = new double[]
{
@@ -748,7 +1527,7 @@ namespace Godot
0.00000009999,
0.000000009999,
};
- double abs = Abs(step);
+ double abs = Math.Abs(step);
double decs = abs - (int)abs; // Strip away integer part
for (int i = 0; i < sd.Length; i++)
{
@@ -767,24 +1546,53 @@ namespace Godot
/// <param name="s">The value to snap.</param>
/// <param name="step">The step size to snap to.</param>
/// <returns>The snapped value.</returns>
- public static real_t Snapped(real_t s, real_t step)
+ public static float Snapped(float s, float step)
{
if (step != 0f)
{
- return Floor((s / step) + 0.5f) * step;
+ return MathF.Floor((s / step) + 0.5f) * step;
}
return s;
}
/// <summary>
+ /// Snaps float value <paramref name="s"/> to a given <paramref name="step"/>.
+ /// This can also be used to round a floating point number to an arbitrary number of decimals.
+ /// </summary>
+ /// <param name="s">The value to snap.</param>
+ /// <param name="step">The step size to snap to.</param>
+ /// <returns>The snapped value.</returns>
+ public static double Snapped(double s, double step)
+ {
+ if (step != 0f)
+ {
+ return Math.Floor((s / step) + 0.5f) * step;
+ }
+
+ return s;
+ }
+
+ /// <summary>
+ /// Returns the tangent of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The tangent of that angle.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Tan(float s)
+ {
+ return MathF.Tan(s);
+ }
+
+ /// <summary>
/// Returns the tangent of angle <paramref name="s"/> in radians.
/// </summary>
/// <param name="s">The angle in radians.</param>
/// <returns>The tangent of that angle.</returns>
- public static real_t Tan(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Tan(double s)
{
- return (real_t)Math.Tan(s);
+ return Math.Tan(s);
}
/// <summary>
@@ -792,9 +1600,21 @@ namespace Godot
/// </summary>
/// <param name="s">The angle in radians.</param>
/// <returns>The hyperbolic tangent of that angle.</returns>
- public static real_t Tanh(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Tanh(float s)
{
- return (real_t)Math.Tanh(s);
+ return MathF.Tanh(s);
+ }
+
+ /// <summary>
+ /// Returns the hyperbolic tangent of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The hyperbolic tangent of that angle.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Tanh(double s)
+ {
+ return Math.Tanh(s);
}
/// <summary>
@@ -820,15 +1640,35 @@ namespace Godot
/// Wraps <paramref name="value"/> between <paramref name="min"/> and <paramref name="max"/>.
/// Usable for creating loop-alike behavior or infinite surfaces.
/// If <paramref name="min"/> is <c>0</c>, this is equivalent
- /// to <see cref="PosMod(real_t, real_t)"/>, so prefer using that instead.
+ /// to <see cref="PosMod(float, float)"/>, so prefer using that instead.
+ /// </summary>
+ /// <param name="value">The value to wrap.</param>
+ /// <param name="min">The minimum allowed value and lower bound of the range.</param>
+ /// <param name="max">The maximum allowed value and upper bound of the range.</param>
+ /// <returns>The wrapped value.</returns>
+ public static float Wrap(float value, float min, float max)
+ {
+ float range = max - min;
+ if (IsZeroApprox(range))
+ {
+ return min;
+ }
+ return min + ((((value - min) % range) + range) % range);
+ }
+
+ /// <summary>
+ /// Wraps <paramref name="value"/> between <paramref name="min"/> and <paramref name="max"/>.
+ /// Usable for creating loop-alike behavior or infinite surfaces.
+ /// If <paramref name="min"/> is <c>0</c>, this is equivalent
+ /// to <see cref="PosMod(double, double)"/>, so prefer using that instead.
/// </summary>
/// <param name="value">The value to wrap.</param>
/// <param name="min">The minimum allowed value and lower bound of the range.</param>
/// <param name="max">The maximum allowed value and upper bound of the range.</param>
/// <returns>The wrapped value.</returns>
- public static real_t Wrap(real_t value, real_t min, real_t max)
+ public static double Wrap(double value, double min, double max)
{
- real_t range = max - min;
+ double range = max - min;
if (IsZeroApprox(range))
{
return min;
@@ -836,9 +1676,23 @@ namespace Godot
return min + ((((value - min) % range) + range) % range);
}
- private static real_t Fract(real_t value)
+ /// <summary>
+ /// Returns the <paramref name="value"/> wrapped between <c>0</c> and the <paramref name="length"/>.
+ /// If the limit is reached, the next value the function returned is decreased to the <c>0</c> side
+ /// or increased to the <paramref name="length"/> side (like a triangle wave).
+ /// If <paramref name="length"/> is less than zero, it becomes positive.
+ /// </summary>
+ /// <param name="value">The value to pingpong.</param>
+ /// <param name="length">The maximum value of the function.</param>
+ /// <returns>The ping-ponged value.</returns>
+ public static float PingPong(float value, float length)
{
- return value - (real_t)Math.Floor(value);
+ return (length != 0.0f) ? Math.Abs(Fract((value - length) / (length * 2.0f)) * length * 2.0f - length) : 0.0f;
+
+ static float Fract(float value)
+ {
+ return value - MathF.Floor(value);
+ }
}
/// <summary>
@@ -850,9 +1704,14 @@ namespace Godot
/// <param name="value">The value to pingpong.</param>
/// <param name="length">The maximum value of the function.</param>
/// <returns>The ping-ponged value.</returns>
- public static real_t PingPong(real_t value, real_t length)
+ public static double PingPong(double value, double length)
{
- return (length != (real_t)0.0) ? Abs(Fract((value - length) / (length * (real_t)2.0)) * length * (real_t)2.0 - length) : (real_t)0.0;
+ return (length != 0.0) ? Math.Abs(Fract((value - length) / (length * 2.0)) * length * 2.0 - length) : 0.0;
+
+ static double Fract(double value)
+ {
+ return value - Math.Floor(value);
+ }
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
index ea05c1547c..cc2d61f58d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
@@ -1,4 +1,8 @@
using System;
+using System.Runtime.CompilerServices;
+
+// This file contains extra members for the Mathf class that aren't part of Godot's Core API.
+// Math API that is also part of Core should go into Mathf.cs.
namespace Godot
{
@@ -16,14 +20,18 @@ namespace Godot
/// </summary>
public const real_t Sqrt2 = (real_t)1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095
+ // Epsilon size should depend on the precision used.
+ private const float _epsilonF = 1e-06f;
+ private const double _epsilonD = 1e-14;
+
/// <summary>
/// A very small number used for float comparison with error tolerance.
/// 1e-06 with single-precision floats, but 1e-14 if <c>REAL_T_IS_DOUBLE</c>.
/// </summary>
#if REAL_T_IS_DOUBLE
- public const real_t Epsilon = 1e-14; // Epsilon size should depend on the precision used.
+ public const real_t Epsilon = _epsilonD;
#else
- public const real_t Epsilon = 1e-06f;
+ public const real_t Epsilon = _epsilonF;
#endif
/// <summary>
@@ -31,7 +39,8 @@ namespace Godot
/// </summary>
/// <param name="s">The input value.</param>
/// <returns>The amount of digits.</returns>
- public static int DecimalCount(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int DecimalCount(double s)
{
return DecimalCount((decimal)s);
}
@@ -41,6 +50,7 @@ namespace Godot
/// </summary>
/// <param name="s">The input <see langword="decimal"/> value.</param>
/// <returns>The amount of digits.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int DecimalCount(decimal s)
{
return BitConverter.GetBytes(decimal.GetBits(s)[3])[2];
@@ -49,11 +59,25 @@ namespace Godot
/// <summary>
/// Rounds <paramref name="s"/> upward (towards positive infinity).
///
- /// This is the same as <see cref="Ceil(real_t)"/>, but returns an <see langword="int"/>.
+ /// This is the same as <see cref="Ceil(float)"/>, but returns an <see langword="int"/>.
/// </summary>
/// <param name="s">The number to ceil.</param>
/// <returns>The smallest whole number that is not less than <paramref name="s"/>.</returns>
- public static int CeilToInt(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CeilToInt(float s)
+ {
+ return (int)MathF.Ceiling(s);
+ }
+
+ /// <summary>
+ /// Rounds <paramref name="s"/> upward (towards positive infinity).
+ ///
+ /// This is the same as <see cref="Ceil(double)"/>, but returns an <see langword="int"/>.
+ /// </summary>
+ /// <param name="s">The number to ceil.</param>
+ /// <returns>The smallest whole number that is not less than <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CeilToInt(double s)
{
return (int)Math.Ceiling(s);
}
@@ -61,11 +85,25 @@ namespace Godot
/// <summary>
/// Rounds <paramref name="s"/> downward (towards negative infinity).
///
- /// This is the same as <see cref="Floor(real_t)"/>, but returns an <see langword="int"/>.
+ /// This is the same as <see cref="Floor(float)"/>, but returns an <see langword="int"/>.
/// </summary>
/// <param name="s">The number to floor.</param>
/// <returns>The largest whole number that is not more than <paramref name="s"/>.</returns>
- public static int FloorToInt(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int FloorToInt(float s)
+ {
+ return (int)MathF.Floor(s);
+ }
+
+ /// <summary>
+ /// Rounds <paramref name="s"/> downward (towards negative infinity).
+ ///
+ /// This is the same as <see cref="Floor(double)"/>, but returns an <see langword="int"/>.
+ /// </summary>
+ /// <param name="s">The number to floor.</param>
+ /// <returns>The largest whole number that is not more than <paramref name="s"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int FloorToInt(double s)
{
return (int)Math.Floor(s);
}
@@ -73,26 +111,81 @@ namespace Godot
/// <summary>
/// Rounds <paramref name="s"/> to the nearest whole number.
///
- /// This is the same as <see cref="Round(real_t)"/>, but returns an <see langword="int"/>.
+ /// This is the same as <see cref="Round(float)"/>, but returns an <see langword="int"/>.
+ /// </summary>
+ /// <param name="s">The number to round.</param>
+ /// <returns>The rounded number.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int RoundToInt(float s)
+ {
+ return (int)MathF.Round(s);
+ }
+
+ /// <summary>
+ /// Rounds <paramref name="s"/> to the nearest whole number.
+ ///
+ /// This is the same as <see cref="Round(double)"/>, but returns an <see langword="int"/>.
/// </summary>
/// <param name="s">The number to round.</param>
/// <returns>The rounded number.</returns>
- public static int RoundToInt(real_t s)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int RoundToInt(double s)
{
return (int)Math.Round(s);
}
/// <summary>
+ /// Returns the sine and cosine of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The sine and cosine of that angle.</returns>
+ public static (float Sin, float Cos) SinCos(float s)
+ {
+ return MathF.SinCos(s);
+ }
+
+ /// <summary>
+ /// Returns the sine and cosine of angle <paramref name="s"/> in radians.
+ /// </summary>
+ /// <param name="s">The angle in radians.</param>
+ /// <returns>The sine and cosine of that angle.</returns>
+ public static (double Sin, double Cos) SinCos(double s)
+ {
+ return Math.SinCos(s);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if <paramref name="a"/> and <paramref name="b"/> are approximately
+ /// equal to each other.
+ /// The comparison is done using the provided tolerance value.
+ /// If you want the tolerance to be calculated for you, use <see cref="IsEqualApprox(float, float)"/>.
+ /// </summary>
+ /// <param name="a">One of the values.</param>
+ /// <param name="b">The other value.</param>
+ /// <param name="tolerance">The pre-calculated tolerance value.</param>
+ /// <returns>A <see langword="bool"/> for whether or not the two values are equal.</returns>
+ public static bool IsEqualApprox(float a, float b, float tolerance)
+ {
+ // Check for exact equality first, required to handle "infinity" values.
+ if (a == b)
+ {
+ return true;
+ }
+ // Then check for approximate equality.
+ return Math.Abs(a - b) < tolerance;
+ }
+
+ /// <summary>
/// Returns <see langword="true"/> if <paramref name="a"/> and <paramref name="b"/> are approximately
/// equal to each other.
/// The comparison is done using the provided tolerance value.
- /// If you want the tolerance to be calculated for you, use <see cref="IsEqualApprox(real_t, real_t)"/>.
+ /// If you want the tolerance to be calculated for you, use <see cref="IsEqualApprox(double, double)"/>.
/// </summary>
/// <param name="a">One of the values.</param>
/// <param name="b">The other value.</param>
/// <param name="tolerance">The pre-calculated tolerance value.</param>
/// <returns>A <see langword="bool"/> for whether or not the two values are equal.</returns>
- public static bool IsEqualApprox(real_t a, real_t b, real_t tolerance)
+ public static bool IsEqualApprox(double a, double b, double tolerance)
{
// Check for exact equality first, required to handle "infinity" values.
if (a == b)
@@ -100,7 +193,7 @@ namespace Godot
return true;
}
// Then check for approximate equality.
- return Abs(a - b) < tolerance;
+ return Math.Abs(a - b) < tolerance;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs
index 5a0ea2ba13..71a2adadcb 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs
@@ -68,7 +68,7 @@ namespace Godot.NativeInterop
string file = globalFrames.Count > 0 ? globalFrames[0].File ?? "" : "";
string func = globalFrames.Count > 0 ? globalFrames[0].Func : "";
int line = globalFrames.Count > 0 ? globalFrames[0].Line : 0;
- string errorMsg = "Exception";
+ string errorMsg = e.GetType().FullName ?? "";
using godot_string nFile = Marshaling.ConvertStringToNative(file);
using godot_string nFunc = Marshaling.ConvertStringToNative(func);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
index fa79c2efbc..43e7c7eb9a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
@@ -104,7 +104,7 @@ namespace Godot.NativeInterop
}
}
- [StructLayout(LayoutKind.Explicit)]
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
// ReSharper disable once InconsistentNaming
public ref struct godot_variant
{
@@ -113,11 +113,11 @@ namespace Godot.NativeInterop
=> (godot_variant*)Unsafe.AsPointer(ref Unsafe.AsRef(in _typeField));
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
- [FieldOffset(0)] private int _typeField;
+ private int _typeField;
// There's padding here
- [FieldOffset(8)] private godot_variant_data _data;
+ private godot_variant_data _data;
[StructLayout(LayoutKind.Explicit)]
// ReSharper disable once InconsistentNaming
@@ -126,10 +126,10 @@ namespace Godot.NativeInterop
[FieldOffset(0)] public godot_bool _bool;
[FieldOffset(0)] public long _int;
[FieldOffset(0)] public double _float;
- [FieldOffset(0)] public Transform2D* _transform2D;
- [FieldOffset(0)] public AABB* _aabb;
+ [FieldOffset(0)] public Transform2D* _transform2d;
+ [FieldOffset(0)] public Aabb* _aabb;
[FieldOffset(0)] public Basis* _basis;
- [FieldOffset(0)] public Transform3D* _transform3D;
+ [FieldOffset(0)] public Transform3D* _transform3d;
[FieldOffset(0)] public Projection* _projection;
[FieldOffset(0)] private godot_variant_data_mem _mem;
@@ -137,18 +137,18 @@ namespace Godot.NativeInterop
[FieldOffset(0)] public godot_string_name _m_string_name;
[FieldOffset(0)] public godot_string _m_string;
[FieldOffset(0)] public Vector4 _m_vector4;
- [FieldOffset(0)] public Vector4i _m_vector4i;
+ [FieldOffset(0)] public Vector4I _m_vector4i;
[FieldOffset(0)] public Vector3 _m_vector3;
- [FieldOffset(0)] public Vector3i _m_vector3i;
+ [FieldOffset(0)] public Vector3I _m_vector3i;
[FieldOffset(0)] public Vector2 _m_vector2;
- [FieldOffset(0)] public Vector2i _m_vector2i;
+ [FieldOffset(0)] public Vector2I _m_vector2i;
[FieldOffset(0)] public Rect2 _m_rect2;
- [FieldOffset(0)] public Rect2i _m_rect2i;
+ [FieldOffset(0)] public Rect2I _m_rect2i;
[FieldOffset(0)] public Plane _m_plane;
[FieldOffset(0)] public Quaternion _m_quaternion;
[FieldOffset(0)] public Color _m_color;
[FieldOffset(0)] public godot_node_path _m_node_path;
- [FieldOffset(0)] public RID _m_rid;
+ [FieldOffset(0)] public Rid _m_rid;
[FieldOffset(0)] public godot_variant_obj_data _m_obj_data;
[FieldOffset(0)] public godot_callable _m_callable;
[FieldOffset(0)] public godot_signal _m_signal;
@@ -211,10 +211,10 @@ namespace Godot.NativeInterop
public readonly unsafe Transform2D* Transform2D
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _data._transform2D;
+ get => _data._transform2d;
}
- public readonly unsafe AABB* AABB
+ public readonly unsafe Aabb* Aabb
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _data._aabb;
@@ -229,7 +229,7 @@ namespace Godot.NativeInterop
public readonly unsafe Transform3D* Transform3D
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _data._transform3D;
+ get => _data._transform3d;
}
public readonly unsafe Projection* Projection
@@ -262,7 +262,7 @@ namespace Godot.NativeInterop
set => _data._m_vector4 = value;
}
- public Vector4i Vector4i
+ public Vector4I Vector4I
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => _data._m_vector4i;
@@ -278,7 +278,7 @@ namespace Godot.NativeInterop
set => _data._m_vector3 = value;
}
- public Vector3i Vector3i
+ public Vector3I Vector3I
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => _data._m_vector3i;
@@ -294,7 +294,7 @@ namespace Godot.NativeInterop
set => _data._m_vector2 = value;
}
- public Vector2i Vector2i
+ public Vector2I Vector2I
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => _data._m_vector2i;
@@ -310,7 +310,7 @@ namespace Godot.NativeInterop
set => _data._m_rect2 = value;
}
- public Rect2i Rect2i
+ public Rect2I Rect2I
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => _data._m_rect2i;
@@ -350,7 +350,7 @@ namespace Godot.NativeInterop
set => _data._m_node_path = value;
}
- public RID RID
+ public Rid Rid
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => _data._m_rid;
@@ -405,13 +405,13 @@ namespace Godot.NativeInterop
case Variant.Type.Int:
case Variant.Type.Float:
case Variant.Type.Vector2:
- case Variant.Type.Vector2i:
+ case Variant.Type.Vector2I:
case Variant.Type.Rect2:
- case Variant.Type.Rect2i:
+ case Variant.Type.Rect2I:
case Variant.Type.Vector3:
- case Variant.Type.Vector3i:
+ case Variant.Type.Vector3I:
case Variant.Type.Vector4:
- case Variant.Type.Vector4i:
+ case Variant.Type.Vector4I:
case Variant.Type.Plane:
case Variant.Type.Quaternion:
case Variant.Type.Color:
@@ -697,6 +697,9 @@ namespace Godot.NativeInterop
private uint _safeRefCount;
public VariantVector _arrayVector;
+
+ private unsafe godot_variant* _readOnly;
+
// There are more fields here, but we don't care as we never store this in C#
public readonly int Size
@@ -704,6 +707,12 @@ namespace Godot.NativeInterop
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _arrayVector.Size;
}
+
+ public readonly unsafe bool IsReadOnly
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _readOnly != null;
+ }
}
[StructLayout(LayoutKind.Sequential)]
@@ -737,6 +746,12 @@ namespace Godot.NativeInterop
get => _p != null ? _p->Size : 0;
}
+ public readonly unsafe bool IsReadOnly
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _p != null && _p->IsReadOnly;
+ }
+
public unsafe void Dispose()
{
if (_p == null)
@@ -766,35 +781,59 @@ namespace Godot.NativeInterop
// A correctly constructed value needs to call the native default constructor to allocate `_p`.
// Don't pass a C# default constructed `godot_dictionary` to native code, unless it's going to
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
- [StructLayout(LayoutKind.Sequential)]
+ [StructLayout(LayoutKind.Explicit)]
// ReSharper disable once InconsistentNaming
public ref struct godot_dictionary
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal readonly unsafe godot_dictionary* GetUnsafeAddress()
- => (godot_dictionary*)Unsafe.AsPointer(ref Unsafe.AsRef(in _p));
+ => (godot_dictionary*)Unsafe.AsPointer(ref Unsafe.AsRef(in _getUnsafeAddressHelper));
- private IntPtr _p;
+ [FieldOffset(0)] private byte _getUnsafeAddressHelper;
- public readonly bool IsAllocated
+ [FieldOffset(0)] private unsafe DictionaryPrivate* _p;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct DictionaryPrivate
+ {
+ private uint _safeRefCount;
+
+ private unsafe godot_variant* _readOnly;
+
+ // There are more fields here, but we don't care as we never store this in C#
+
+ public readonly unsafe bool IsReadOnly
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _readOnly != null;
+ }
+ }
+
+ public readonly unsafe bool IsAllocated
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _p != IntPtr.Zero;
+ get => _p != null;
}
- public void Dispose()
+ public readonly unsafe bool IsReadOnly
{
- if (_p == IntPtr.Zero)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _p != null && _p->IsReadOnly;
+ }
+
+ public unsafe void Dispose()
+ {
+ if (_p == null)
return;
NativeFuncs.godotsharp_dictionary_destroy(ref this);
- _p = IntPtr.Zero;
+ _p = null;
}
[StructLayout(LayoutKind.Sequential)]
// ReSharper disable once InconsistentNaming
internal struct movable
{
- private IntPtr _p;
+ private unsafe DictionaryPrivate* _p;
public static unsafe explicit operator movable(in godot_dictionary value)
=> *(movable*)CustomUnsafe.AsPointer(ref CustomUnsafe.AsRef(value));
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs
index 82f1c04d40..cc308bfdb3 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs
@@ -8,7 +8,7 @@ namespace Godot.NativeInterop
{
internal static class InteropUtils
{
- public static Object UnmanagedGetManaged(IntPtr unmanaged)
+ public static GodotObject UnmanagedGetManaged(IntPtr unmanaged)
{
// The native pointer may be null
if (unmanaged == IntPtr.Zero)
@@ -23,7 +23,7 @@ namespace Godot.NativeInterop
unmanaged, out hasCsScriptInstance);
if (gcHandlePtr != IntPtr.Zero)
- return (Object)GCHandle.FromIntPtr(gcHandlePtr).Target;
+ return (GodotObject)GCHandle.FromIntPtr(gcHandlePtr).Target;
// Otherwise, if the object has a CSharpInstance script instance, return null
@@ -37,17 +37,17 @@ namespace Godot.NativeInterop
object target = gcHandlePtr != IntPtr.Zero ? GCHandle.FromIntPtr(gcHandlePtr).Target : null;
if (target != null)
- return (Object)target;
+ return (GodotObject)target;
// If the native instance binding GC handle target was collected, create a new one
gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_instance_binding_create_managed(
unmanaged, gcHandlePtr);
- return gcHandlePtr != IntPtr.Zero ? (Object)GCHandle.FromIntPtr(gcHandlePtr).Target : null;
+ return gcHandlePtr != IntPtr.Zero ? (GodotObject)GCHandle.FromIntPtr(gcHandlePtr).Target : null;
}
- public static void TieManagedToUnmanaged(Object managed, IntPtr unmanaged,
+ public static void TieManagedToUnmanaged(GodotObject managed, IntPtr unmanaged,
StringName nativeName, bool refCounted, Type type, Type nativeType)
{
var gcHandle = refCounted ?
@@ -76,7 +76,7 @@ namespace Godot.NativeInterop
}
}
- public static void TieManagedToUnmanagedWithPreSetup(Object managed, IntPtr unmanaged,
+ public static void TieManagedToUnmanagedWithPreSetup(GodotObject managed, IntPtr unmanaged,
Type type, Type nativeType)
{
if (type == nativeType)
@@ -87,7 +87,7 @@ namespace Godot.NativeInterop
GCHandle.ToIntPtr(strongGCHandle), unmanaged);
}
- public static Object EngineGetSingleton(string name)
+ public static GodotObject EngineGetSingleton(string name)
{
using godot_string src = Marshaling.ConvertStringToNative(name);
return UnmanagedGetManaged(NativeFuncs.godotsharp_engine_get_singleton(src));
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index 649661ee06..93a83b701b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -1,5 +1,7 @@
using System;
using System.Runtime.InteropServices;
+using Godot.Collections;
+using Array = System.Array;
// ReSharper disable InconsistentNaming
@@ -49,29 +51,29 @@ namespace Godot.NativeInterop
if (type == typeof(Vector2))
return Variant.Type.Vector2;
- if (type == typeof(Vector2i))
- return Variant.Type.Vector2i;
+ if (type == typeof(Vector2I))
+ return Variant.Type.Vector2I;
if (type == typeof(Rect2))
return Variant.Type.Rect2;
- if (type == typeof(Rect2i))
- return Variant.Type.Rect2i;
+ if (type == typeof(Rect2I))
+ return Variant.Type.Rect2I;
if (type == typeof(Transform2D))
- return Variant.Type.Transform2d;
+ return Variant.Type.Transform2D;
if (type == typeof(Vector3))
return Variant.Type.Vector3;
- if (type == typeof(Vector3i))
- return Variant.Type.Vector3i;
+ if (type == typeof(Vector3I))
+ return Variant.Type.Vector3I;
if (type == typeof(Vector4))
return Variant.Type.Vector4;
- if (type == typeof(Vector4i))
- return Variant.Type.Vector4i;
+ if (type == typeof(Vector4I))
+ return Variant.Type.Vector4I;
if (type == typeof(Basis))
return Variant.Type.Basis;
@@ -80,12 +82,12 @@ namespace Godot.NativeInterop
return Variant.Type.Quaternion;
if (type == typeof(Transform3D))
- return Variant.Type.Transform3d;
+ return Variant.Type.Transform3D;
if (type == typeof(Projection))
return Variant.Type.Projection;
- if (type == typeof(AABB))
+ if (type == typeof(Aabb))
return Variant.Type.Aabb;
if (type == typeof(Color))
@@ -97,7 +99,7 @@ namespace Godot.NativeInterop
if (type == typeof(Callable))
return Variant.Type.Callable;
- if (type == typeof(SignalInfo))
+ if (type == typeof(Signal))
return Variant.Type.Signal;
if (type.IsEnum)
@@ -138,16 +140,25 @@ namespace Godot.NativeInterop
if (type == typeof(NodePath[]))
return Variant.Type.Array;
- if (type == typeof(RID[]))
+ if (type == typeof(Rid[]))
return Variant.Type.Array;
- if (typeof(Godot.Object[]).IsAssignableFrom(type))
+ if (typeof(GodotObject[]).IsAssignableFrom(type))
return Variant.Type.Array;
}
else if (type.IsGenericType)
{
- if (typeof(Godot.Object).IsAssignableFrom(type))
+ if (typeof(GodotObject).IsAssignableFrom(type))
return Variant.Type.Object;
+
+ // We use `IsAssignableFrom` with our helper interfaces to detect generic Godot collections
+ // because `GetGenericTypeDefinition` is not supported in NativeAOT reflection-free mode.
+
+ if (typeof(IGenericGodotDictionary).IsAssignableFrom(type))
+ return Variant.Type.Dictionary;
+
+ if (typeof(IGenericGodotArray).IsAssignableFrom(type))
+ return Variant.Type.Array;
}
else if (type == typeof(Variant))
{
@@ -156,7 +167,7 @@ namespace Godot.NativeInterop
}
else
{
- if (typeof(Godot.Object).IsAssignableFrom(type))
+ if (typeof(GodotObject).IsAssignableFrom(type))
return Variant.Type.Object;
if (typeof(StringName) == type)
@@ -165,7 +176,7 @@ namespace Godot.NativeInterop
if (typeof(NodePath) == type)
return Variant.Type.NodePath;
- if (typeof(RID) == type)
+ if (typeof(Rid) == type)
return Variant.Type.Rid;
if (typeof(Collections.Dictionary) == type)
@@ -183,508 +194,6 @@ namespace Godot.NativeInterop
return Variant.Type.Nil;
}
- /* TODO: Reflection and type checking each time is slow. This will be replaced with source generators. */
- public static godot_variant ConvertManagedObjectToVariant(object? p_obj)
- {
- if (p_obj == null)
- return new godot_variant();
-
- switch (p_obj)
- {
- case bool @bool:
- return VariantUtils.CreateFromBool(@bool);
- case char @char:
- return VariantUtils.CreateFromInt(@char);
- case sbyte @int8:
- return VariantUtils.CreateFromInt(@int8);
- case short @int16:
- return VariantUtils.CreateFromInt(@int16);
- case int @int32:
- return VariantUtils.CreateFromInt(@int32);
- case long @int64:
- return VariantUtils.CreateFromInt(@int64);
- case byte @uint8:
- return VariantUtils.CreateFromInt(@uint8);
- case ushort @uint16:
- return VariantUtils.CreateFromInt(@uint16);
- case uint @uint32:
- return VariantUtils.CreateFromInt(@uint32);
- case ulong @uint64:
- return VariantUtils.CreateFromInt(@uint64);
- case float @float:
- return VariantUtils.CreateFromFloat(@float);
- case double @double:
- return VariantUtils.CreateFromFloat(@double);
- case Vector2 @vector2:
- return VariantUtils.CreateFromVector2(@vector2);
- case Vector2i @vector2i:
- return VariantUtils.CreateFromVector2i(@vector2i);
- case Rect2 @rect2:
- return VariantUtils.CreateFromRect2(@rect2);
- case Rect2i @rect2i:
- return VariantUtils.CreateFromRect2i(@rect2i);
- case Transform2D @transform2D:
- return VariantUtils.CreateFromTransform2D(@transform2D);
- case Vector3 @vector3:
- return VariantUtils.CreateFromVector3(@vector3);
- case Vector3i @vector3i:
- return VariantUtils.CreateFromVector3i(@vector3i);
- case Vector4 @vector4:
- return VariantUtils.CreateFromVector4(@vector4);
- case Vector4i @vector4i:
- return VariantUtils.CreateFromVector4i(@vector4i);
- case Basis @basis:
- return VariantUtils.CreateFromBasis(@basis);
- case Quaternion @quaternion:
- return VariantUtils.CreateFromQuaternion(@quaternion);
- case Transform3D @transform3d:
- return VariantUtils.CreateFromTransform3D(@transform3d);
- case Projection @projection:
- return VariantUtils.CreateFromProjection(@projection);
- case AABB @aabb:
- return VariantUtils.CreateFromAABB(@aabb);
- case Color @color:
- return VariantUtils.CreateFromColor(@color);
- case Plane @plane:
- return VariantUtils.CreateFromPlane(@plane);
- case Callable @callable:
- return VariantUtils.CreateFromCallable(@callable);
- case SignalInfo @signalInfo:
- return VariantUtils.CreateFromSignalInfo(@signalInfo);
- case Enum @enum:
- return VariantUtils.CreateFromInt(Convert.ToInt64(@enum));
- case string @string:
- return VariantUtils.CreateFromString(@string);
- case byte[] byteArray:
- return VariantUtils.CreateFromPackedByteArray(byteArray);
- case int[] int32Array:
- return VariantUtils.CreateFromPackedInt32Array(int32Array);
- case long[] int64Array:
- return VariantUtils.CreateFromPackedInt64Array(int64Array);
- case float[] floatArray:
- return VariantUtils.CreateFromPackedFloat32Array(floatArray);
- case double[] doubleArray:
- return VariantUtils.CreateFromPackedFloat64Array(doubleArray);
- case string[] stringArray:
- return VariantUtils.CreateFromPackedStringArray(stringArray);
- case Vector2[] vector2Array:
- return VariantUtils.CreateFromPackedVector2Array(vector2Array);
- case Vector3[] vector3Array:
- return VariantUtils.CreateFromPackedVector3Array(vector3Array);
- case Color[] colorArray:
- return VariantUtils.CreateFromPackedColorArray(colorArray);
- case StringName[] stringNameArray:
- return VariantUtils.CreateFromSystemArrayOfStringName(stringNameArray);
- case NodePath[] nodePathArray:
- return VariantUtils.CreateFromSystemArrayOfNodePath(nodePathArray);
- case RID[] ridArray:
- return VariantUtils.CreateFromSystemArrayOfRID(ridArray);
- case Godot.Object[] godotObjectArray:
- return VariantUtils.CreateFromSystemArrayOfGodotObject(godotObjectArray);
- case Godot.Object godotObject:
- return VariantUtils.CreateFromGodotObject(godotObject);
- case StringName stringName:
- return VariantUtils.CreateFromStringName(stringName);
- case NodePath nodePath:
- return VariantUtils.CreateFromNodePath(nodePath);
- case RID rid:
- return VariantUtils.CreateFromRID(rid);
- case Collections.Dictionary godotDictionary:
- return VariantUtils.CreateFromDictionary(godotDictionary);
- case Collections.Array godotArray:
- return VariantUtils.CreateFromArray(godotArray);
- case Variant variant:
- return NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar);
- }
-
- GD.PushError("Attempted to convert an unmarshallable managed type to Variant. Name: '" +
- p_obj.GetType().FullName + ".");
- return new godot_variant();
- }
-
- public static object? ConvertVariantToManagedObjectOfType(in godot_variant p_var, Type type)
- {
- // This function is only needed to set the value of properties. Fields have their own implementation, set_value_from_variant.
- switch (Type.GetTypeCode(type))
- {
- case TypeCode.Boolean:
- return VariantUtils.ConvertToBool(p_var);
- case TypeCode.Char:
- return VariantUtils.ConvertToChar(p_var);
- case TypeCode.SByte:
- return VariantUtils.ConvertToInt8(p_var);
- case TypeCode.Int16:
- return VariantUtils.ConvertToInt16(p_var);
- case TypeCode.Int32:
- return VariantUtils.ConvertToInt32(p_var);
- case TypeCode.Int64:
- return VariantUtils.ConvertToInt64(p_var);
- case TypeCode.Byte:
- return VariantUtils.ConvertToUInt8(p_var);
- case TypeCode.UInt16:
- return VariantUtils.ConvertToUInt16(p_var);
- case TypeCode.UInt32:
- return VariantUtils.ConvertToUInt32(p_var);
- case TypeCode.UInt64:
- return VariantUtils.ConvertToUInt64(p_var);
- case TypeCode.Single:
- return VariantUtils.ConvertToFloat32(p_var);
- case TypeCode.Double:
- return VariantUtils.ConvertToFloat64(p_var);
- case TypeCode.String:
- return VariantUtils.ConvertToStringObject(p_var);
- default:
- {
- if (type == typeof(Vector2))
- return VariantUtils.ConvertToVector2(p_var);
-
- if (type == typeof(Vector2i))
- return VariantUtils.ConvertToVector2i(p_var);
-
- if (type == typeof(Rect2))
- return VariantUtils.ConvertToRect2(p_var);
-
- if (type == typeof(Rect2i))
- return VariantUtils.ConvertToRect2i(p_var);
-
- if (type == typeof(Transform2D))
- return VariantUtils.ConvertToTransform2D(p_var);
-
- if (type == typeof(Vector3))
- return VariantUtils.ConvertToVector3(p_var);
-
- if (type == typeof(Vector3i))
- return VariantUtils.ConvertToVector3i(p_var);
-
- if (type == typeof(Vector4))
- return VariantUtils.ConvertToVector4(p_var);
-
- if (type == typeof(Vector4i))
- return VariantUtils.ConvertToVector4i(p_var);
-
- if (type == typeof(Basis))
- return VariantUtils.ConvertToBasis(p_var);
-
- if (type == typeof(Quaternion))
- return VariantUtils.ConvertToQuaternion(p_var);
-
- if (type == typeof(Transform3D))
- return VariantUtils.ConvertToTransform3D(p_var);
-
- if (type == typeof(Projection))
- return VariantUtils.ConvertToProjection(p_var);
-
- if (type == typeof(AABB))
- return VariantUtils.ConvertToAABB(p_var);
-
- if (type == typeof(Color))
- return VariantUtils.ConvertToColor(p_var);
-
- if (type == typeof(Plane))
- return VariantUtils.ConvertToPlane(p_var);
-
- if (type == typeof(Callable))
- return VariantUtils.ConvertToCallableManaged(p_var);
-
- if (type == typeof(SignalInfo))
- return VariantUtils.ConvertToSignalInfo(p_var);
-
- if (type.IsEnum)
- {
- var enumUnderlyingType = type.GetEnumUnderlyingType();
- switch (Type.GetTypeCode(enumUnderlyingType))
- {
- case TypeCode.SByte:
- return VariantUtils.ConvertToInt8(p_var);
- case TypeCode.Int16:
- return VariantUtils.ConvertToInt16(p_var);
- case TypeCode.Int32:
- return VariantUtils.ConvertToInt32(p_var);
- case TypeCode.Int64:
- return VariantUtils.ConvertToInt64(p_var);
- case TypeCode.Byte:
- return VariantUtils.ConvertToUInt8(p_var);
- case TypeCode.UInt16:
- return VariantUtils.ConvertToUInt16(p_var);
- case TypeCode.UInt32:
- return VariantUtils.ConvertToUInt32(p_var);
- case TypeCode.UInt64:
- return VariantUtils.ConvertToUInt64(p_var);
- default:
- {
- GD.PushError(
- "Attempted to convert Variant to enum value of unsupported underlying type. Name: " +
- type.FullName + " : " + enumUnderlyingType.FullName + ".");
- return null;
- }
- }
- }
-
- if (type.IsArray || type.IsSZArray)
- {
- return ConvertVariantToSystemArrayOfType(p_var, type);
- }
- else if (type.IsGenericType)
- {
- if (typeof(Godot.Object).IsAssignableFrom(type))
- {
- var godotObject = VariantUtils.ConvertToGodotObject(p_var);
-
- if (!type.IsInstanceOfType(godotObject))
- {
- GD.PushError("Invalid cast when marshaling Godot.Object type." +
- $" `{godotObject.GetType()}` is not assignable to `{type.FullName}`.");
- return null;
- }
-
- return godotObject;
- }
-
- return null;
- }
- else if (type == typeof(Variant))
- {
- return Variant.CreateCopyingBorrowed(p_var);
- }
-
- if (ConvertVariantToManagedObjectOfClass(p_var, type, out object? res))
- return res;
-
- break;
- }
- }
-
- GD.PushError("Attempted to convert Variant to unsupported type. Name: " +
- type.FullName + ".");
- return null;
- }
-
- private static object? ConvertVariantToSystemArrayOfType(in godot_variant p_var, Type type)
- {
- if (type == typeof(byte[]))
- return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
-
- if (type == typeof(int[]))
- return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
-
- if (type == typeof(long[]))
- return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
-
- if (type == typeof(float[]))
- return VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(p_var);
-
- if (type == typeof(double[]))
- return VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(p_var);
-
- if (type == typeof(string[]))
- return VariantUtils.ConvertAsPackedStringArrayToSystemArray(p_var);
-
- if (type == typeof(Vector2[]))
- return VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(p_var);
-
- if (type == typeof(Vector3[]))
- return VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(p_var);
-
- if (type == typeof(Color[]))
- return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
-
- if (type == typeof(StringName[]))
- return VariantUtils.ConvertToSystemArrayOfStringName(p_var);
-
- if (type == typeof(NodePath[]))
- return VariantUtils.ConvertToSystemArrayOfNodePath(p_var);
-
- if (type == typeof(RID[]))
- return VariantUtils.ConvertToSystemArrayOfRID(p_var);
-
- if (typeof(Godot.Object[]).IsAssignableFrom(type))
- return VariantUtils.ConvertToSystemArrayOfGodotObject(p_var, type);
-
- GD.PushError("Attempted to convert Variant to array of unsupported element type. Name: " +
- type.GetElementType()!.FullName + ".");
- return null;
- }
-
- private static bool ConvertVariantToManagedObjectOfClass(in godot_variant p_var, Type type,
- out object? res)
- {
- if (typeof(Godot.Object).IsAssignableFrom(type))
- {
- if (p_var.Type == Variant.Type.Nil)
- {
- res = null;
- return true;
- }
-
- if (p_var.Type != Variant.Type.Object)
- {
- GD.PushError("Invalid cast when marshaling Godot.Object type." +
- $" Variant type is `{p_var.Type}`; expected `{p_var.Object}`.");
- res = null;
- return true;
- }
-
- var godotObjectPtr = VariantUtils.ConvertToGodotObjectPtr(p_var);
-
- if (godotObjectPtr == IntPtr.Zero)
- {
- res = null;
- return true;
- }
-
- var godotObject = InteropUtils.UnmanagedGetManaged(godotObjectPtr);
-
- if (!type.IsInstanceOfType(godotObject))
- {
- GD.PushError("Invalid cast when marshaling Godot.Object type." +
- $" `{godotObject.GetType()}` is not assignable to `{type.FullName}`.");
- res = null;
- return false;
- }
-
- res = godotObject;
- return true;
- }
-
- if (typeof(StringName) == type)
- {
- res = VariantUtils.ConvertToStringNameObject(p_var);
- return true;
- }
-
- if (typeof(NodePath) == type)
- {
- res = VariantUtils.ConvertToNodePathObject(p_var);
- return true;
- }
-
- if (typeof(RID) == type)
- {
- res = VariantUtils.ConvertToRID(p_var);
- return true;
- }
-
- if (typeof(Collections.Dictionary) == type)
- {
- res = VariantUtils.ConvertToDictionaryObject(p_var);
- return true;
- }
-
- if (typeof(Collections.Array) == type)
- {
- res = VariantUtils.ConvertToArrayObject(p_var);
- return true;
- }
-
- res = null;
- return false;
- }
-
- public static unsafe object? ConvertVariantToManagedObject(in godot_variant p_var)
- {
- switch (p_var.Type)
- {
- case Variant.Type.Bool:
- return p_var.Bool.ToBool();
- case Variant.Type.Int:
- return p_var.Int;
- case Variant.Type.Float:
- {
-#if REAL_T_IS_DOUBLE
- return p_var.Float;
-#else
- return (float)p_var.Float;
-#endif
- }
- case Variant.Type.String:
- return ConvertStringToManaged(p_var.String);
- case Variant.Type.Vector2:
- return p_var.Vector2;
- case Variant.Type.Vector2i:
- return p_var.Vector2i;
- case Variant.Type.Rect2:
- return p_var.Rect2;
- case Variant.Type.Rect2i:
- return p_var.Rect2i;
- case Variant.Type.Vector3:
- return p_var.Vector3;
- case Variant.Type.Vector3i:
- return p_var.Vector3i;
- case Variant.Type.Transform2d:
- return *p_var.Transform2D;
- case Variant.Type.Vector4:
- return p_var.Vector4;
- case Variant.Type.Vector4i:
- return p_var.Vector4i;
- case Variant.Type.Plane:
- return p_var.Plane;
- case Variant.Type.Quaternion:
- return p_var.Quaternion;
- case Variant.Type.Aabb:
- return *p_var.AABB;
- case Variant.Type.Basis:
- return *p_var.Basis;
- case Variant.Type.Transform3d:
- return *p_var.Transform3D;
- case Variant.Type.Projection:
- return *p_var.Projection;
- case Variant.Type.Color:
- return p_var.Color;
- case Variant.Type.StringName:
- {
- // The Variant owns the value, so we need to make a copy
- return StringName.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName));
- }
- case Variant.Type.NodePath:
- {
- // The Variant owns the value, so we need to make a copy
- return NodePath.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath));
- }
- case Variant.Type.Rid:
- return p_var.RID;
- case Variant.Type.Object:
- return InteropUtils.UnmanagedGetManaged(p_var.Object);
- case Variant.Type.Callable:
- return ConvertCallableToManaged(p_var.Callable);
- case Variant.Type.Signal:
- return ConvertSignalToManaged(p_var.Signal);
- case Variant.Type.Dictionary:
- {
- // The Variant owns the value, so we need to make a copy
- return Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary));
- }
- case Variant.Type.Array:
- {
- // The Variant owns the value, so we need to make a copy
- return Collections.Array.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_array_new_copy(p_var.Array));
- }
- case Variant.Type.PackedByteArray:
- return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
- case Variant.Type.PackedInt32Array:
- return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
- case Variant.Type.PackedInt64Array:
- return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
- case Variant.Type.PackedFloat32Array:
- return VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(p_var);
- case Variant.Type.PackedFloat64Array:
- return VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(p_var);
- case Variant.Type.PackedStringArray:
- return VariantUtils.ConvertAsPackedStringArrayToSystemArray(p_var);
- case Variant.Type.PackedVector2Array:
- return VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(p_var);
- case Variant.Type.PackedVector3Array:
- return VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(p_var);
- case Variant.Type.PackedColorArray:
- return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
- default:
- return null;
- }
- }
-
// String
public static unsafe godot_string ConvertStringToNative(string? p_mono_string)
@@ -723,7 +232,7 @@ namespace Godot.NativeInterop
var gcHandle = CustomGCHandle.AllocStrong(p_managed_callable.Delegate);
IntPtr objectPtr = p_managed_callable.Target != null ?
- Object.GetPtr(p_managed_callable.Target) :
+ GodotObject.GetPtr(p_managed_callable.Target) :
IntPtr.Zero;
unsafe
@@ -779,9 +288,9 @@ namespace Godot.NativeInterop
return new Callable();
}
- // SignalInfo
+ // Signal
- public static godot_signal ConvertSignalToNative(in SignalInfo p_managed_signal)
+ public static godot_signal ConvertSignalToNative(in Signal p_managed_signal)
{
ulong ownerId = p_managed_signal.Owner.GetInstanceId();
godot_string_name name;
@@ -799,18 +308,18 @@ namespace Godot.NativeInterop
return new godot_signal(name, ownerId);
}
- public static SignalInfo ConvertSignalToManaged(in godot_signal p_signal)
+ public static Signal ConvertSignalToManaged(in godot_signal p_signal)
{
- var owner = GD.InstanceFromId(p_signal.ObjectId);
+ var owner = GodotObject.InstanceFromId(p_signal.ObjectId);
var name = StringName.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_string_name_new_copy(p_signal.Name));
- return new SignalInfo(owner, name);
+ return new Signal(owner, name);
}
// Array
internal static T[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType<T>(in godot_array p_array)
- where T : Godot.Object
+ where T : GodotObject
{
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_array_new_copy(p_array));
@@ -824,22 +333,6 @@ namespace Godot.NativeInterop
return ret;
}
- // TODO: This needs reflection. Look for an alternative.
- internal static Godot.Object[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(in godot_array p_array,
- Type type)
- {
- var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
- NativeFuncs.godotsharp_array_new_copy(p_array));
-
- int length = array.Count;
- var ret = (Godot.Object[])Activator.CreateInstance(type, length)!;
-
- for (int i = 0; i < length; i++)
- ret[i] = array[i].AsGodotObject();
-
- return ret;
- }
-
internal static StringName[] ConvertNativeGodotArrayToSystemArrayOfStringName(in godot_array p_array)
{
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
@@ -868,16 +361,16 @@ namespace Godot.NativeInterop
return ret;
}
- internal static RID[] ConvertNativeGodotArrayToSystemArrayOfRID(in godot_array p_array)
+ internal static Rid[] ConvertNativeGodotArrayToSystemArrayOfRid(in godot_array p_array)
{
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_array_new_copy(p_array));
int length = array.Count;
- var ret = new RID[length];
+ var ret = new Rid[length];
for (int i = 0; i < length; i++)
- ret[i] = array[i].AsRID();
+ ret[i] = array[i].AsRid();
return ret;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
index b30b6a0752..3d72ee0036 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
@@ -153,6 +153,8 @@ namespace Godot.NativeInterop
internal static partial void godotsharp_callable_call_deferred(in godot_callable p_callable,
godot_variant** p_args, int p_arg_count);
+ internal static partial Color godotsharp_color_from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha);
+
// GDNative functions
// gdnative.h
@@ -182,7 +184,7 @@ namespace Godot.NativeInterop
public static partial void godotsharp_variant_new_projection(out godot_variant r_dest, in Projection p_proj);
- public static partial void godotsharp_variant_new_aabb(out godot_variant r_dest, in AABB p_aabb);
+ public static partial void godotsharp_variant_new_aabb(out godot_variant r_dest, in Aabb p_aabb);
public static partial void godotsharp_variant_new_dictionary(out godot_variant r_dest,
in godot_dictionary p_dict);
@@ -226,27 +228,27 @@ namespace Godot.NativeInterop
public static partial Vector2 godotsharp_variant_as_vector2(in godot_variant p_self);
- public static partial Vector2i godotsharp_variant_as_vector2i(in godot_variant p_self);
+ public static partial Vector2I godotsharp_variant_as_vector2i(in godot_variant p_self);
public static partial Rect2 godotsharp_variant_as_rect2(in godot_variant p_self);
- public static partial Rect2i godotsharp_variant_as_rect2i(in godot_variant p_self);
+ public static partial Rect2I godotsharp_variant_as_rect2i(in godot_variant p_self);
public static partial Vector3 godotsharp_variant_as_vector3(in godot_variant p_self);
- public static partial Vector3i godotsharp_variant_as_vector3i(in godot_variant p_self);
+ public static partial Vector3I godotsharp_variant_as_vector3i(in godot_variant p_self);
public static partial Transform2D godotsharp_variant_as_transform2d(in godot_variant p_self);
public static partial Vector4 godotsharp_variant_as_vector4(in godot_variant p_self);
- public static partial Vector4i godotsharp_variant_as_vector4i(in godot_variant p_self);
+ public static partial Vector4I godotsharp_variant_as_vector4i(in godot_variant p_self);
public static partial Plane godotsharp_variant_as_plane(in godot_variant p_self);
public static partial Quaternion godotsharp_variant_as_quaternion(in godot_variant p_self);
- public static partial AABB godotsharp_variant_as_aabb(in godot_variant p_self);
+ public static partial Aabb godotsharp_variant_as_aabb(in godot_variant p_self);
public static partial Basis godotsharp_variant_as_basis(in godot_variant p_self);
@@ -260,7 +262,7 @@ namespace Godot.NativeInterop
public static partial godot_node_path godotsharp_variant_as_node_path(in godot_variant p_self);
- public static partial RID godotsharp_variant_as_rid(in godot_variant p_self);
+ public static partial Rid godotsharp_variant_as_rid(in godot_variant p_self);
public static partial godot_callable godotsharp_variant_as_callable(in godot_variant p_self);
@@ -363,19 +365,44 @@ namespace Godot.NativeInterop
public static partial int godotsharp_array_add(ref godot_array p_self, in godot_variant p_item);
+ public static partial int godotsharp_array_add_range(ref godot_array p_self, in godot_array p_collection);
+
+ public static partial int godotsharp_array_binary_search(ref godot_array p_self, int p_index, int p_count, in godot_variant p_value);
+
public static partial void
godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
- public static partial int godotsharp_array_index_of(ref godot_array p_self, in godot_variant p_item);
+ public static partial void godotsharp_array_fill(ref godot_array p_self, in godot_variant p_value);
+
+ public static partial int godotsharp_array_index_of(ref godot_array p_self, in godot_variant p_item, int p_index = 0);
public static partial void godotsharp_array_insert(ref godot_array p_self, int p_index, in godot_variant p_item);
+ public static partial int godotsharp_array_last_index_of(ref godot_array p_self, in godot_variant p_item, int p_index);
+
+ public static partial void godotsharp_array_make_read_only(ref godot_array p_self);
+
+ public static partial void godotsharp_array_max(ref godot_array p_self, out godot_variant r_value);
+
+ public static partial void godotsharp_array_min(ref godot_array p_self, out godot_variant r_value);
+
+ public static partial void godotsharp_array_pick_random(ref godot_array p_self, out godot_variant r_value);
+
+ public static partial godot_bool godotsharp_array_recursive_equal(ref godot_array p_self, in godot_array p_other);
+
public static partial void godotsharp_array_remove_at(ref godot_array p_self, int p_index);
public static partial Error godotsharp_array_resize(ref godot_array p_self, int p_new_size);
+ public static partial void godotsharp_array_reverse(ref godot_array p_self);
+
public static partial void godotsharp_array_shuffle(ref godot_array p_self);
+ public static partial void godotsharp_array_slice(ref godot_array p_self, int p_start, int p_end,
+ int p_step, godot_bool p_deep, out godot_array r_dest);
+
+ public static partial void godotsharp_array_sort(ref godot_array p_self);
+
public static partial void godotsharp_array_to_string(ref godot_array p_self, out godot_string r_str);
// Dictionary
@@ -407,28 +434,19 @@ namespace Godot.NativeInterop
public static partial void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep,
out godot_dictionary r_dest);
+ public static partial void godotsharp_dictionary_merge(ref godot_dictionary p_self, in godot_dictionary p_dictionary, godot_bool p_overwrite);
+
+ public static partial godot_bool godotsharp_dictionary_recursive_equal(ref godot_dictionary p_self, in godot_dictionary p_other);
+
public static partial godot_bool godotsharp_dictionary_remove_key(ref godot_dictionary p_self,
in godot_variant p_key);
+ public static partial void godotsharp_dictionary_make_read_only(ref godot_dictionary p_self);
+
public static partial void godotsharp_dictionary_to_string(ref godot_dictionary p_self, out godot_string r_str);
// StringExtensions
- public static partial void godotsharp_string_md5_buffer(in godot_string p_self,
- out godot_packed_byte_array r_md5_buffer);
-
- public static partial void godotsharp_string_md5_text(in godot_string p_self, out godot_string r_md5_text);
-
- public static partial int godotsharp_string_rfind(in godot_string p_self, in godot_string p_what, int p_from);
-
- public static partial int godotsharp_string_rfindn(in godot_string p_self, in godot_string p_what, int p_from);
-
- public static partial void godotsharp_string_sha256_buffer(in godot_string p_self,
- out godot_packed_byte_array r_sha256_buffer);
-
- public static partial void godotsharp_string_sha256_text(in godot_string p_self,
- out godot_string r_sha256_text);
-
public static partial void godotsharp_string_simplify_path(in godot_string p_self,
out godot_string r_simplified_path);
@@ -464,6 +482,10 @@ namespace Godot.NativeInterop
public static partial godot_bool godotsharp_node_path_is_absolute(in godot_node_path p_self);
+ public static partial godot_bool godotsharp_node_path_equals(in godot_node_path p_self, in godot_node_path p_other);
+
+ public static partial int godotsharp_node_path_hash(in godot_node_path p_self);
+
// GD, etc
internal static partial void godotsharp_bytes_to_var(in godot_packed_byte_array p_bytes,
@@ -507,8 +529,6 @@ namespace Godot.NativeInterop
internal static partial void godotsharp_weakref(IntPtr p_obj, out godot_ref r_weak_ref);
- internal static partial void godotsharp_str(in godot_array p_what, out godot_string r_ret);
-
internal static partial void godotsharp_str_to_var(in godot_string p_str, out godot_variant r_ret);
internal static partial void godotsharp_var_to_bytes(in godot_variant p_what, godot_bool p_full_objects,
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
index 9f0b55431b..44ec16dca9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
@@ -18,20 +18,20 @@ namespace Godot.NativeInterop
return new godot_variant() { Float = src.Float, Type = Variant.Type.Float };
case Variant.Type.Vector2:
return new godot_variant() { Vector2 = src.Vector2, Type = Variant.Type.Vector2 };
- case Variant.Type.Vector2i:
- return new godot_variant() { Vector2i = src.Vector2i, Type = Variant.Type.Vector2i };
+ case Variant.Type.Vector2I:
+ return new godot_variant() { Vector2I = src.Vector2I, Type = Variant.Type.Vector2I };
case Variant.Type.Rect2:
return new godot_variant() { Rect2 = src.Rect2, Type = Variant.Type.Rect2 };
- case Variant.Type.Rect2i:
- return new godot_variant() { Rect2i = src.Rect2i, Type = Variant.Type.Rect2i };
+ case Variant.Type.Rect2I:
+ return new godot_variant() { Rect2I = src.Rect2I, Type = Variant.Type.Rect2I };
case Variant.Type.Vector3:
return new godot_variant() { Vector3 = src.Vector3, Type = Variant.Type.Vector3 };
- case Variant.Type.Vector3i:
- return new godot_variant() { Vector3i = src.Vector3i, Type = Variant.Type.Vector3i };
+ case Variant.Type.Vector3I:
+ return new godot_variant() { Vector3I = src.Vector3I, Type = Variant.Type.Vector3I };
case Variant.Type.Vector4:
return new godot_variant() { Vector4 = src.Vector4, Type = Variant.Type.Vector4 };
- case Variant.Type.Vector4i:
- return new godot_variant() { Vector4i = src.Vector4i, Type = Variant.Type.Vector4i };
+ case Variant.Type.Vector4I:
+ return new godot_variant() { Vector4I = src.Vector4I, Type = Variant.Type.Vector4I };
case Variant.Type.Plane:
return new godot_variant() { Plane = src.Plane, Type = Variant.Type.Plane };
case Variant.Type.Quaternion:
@@ -39,7 +39,7 @@ namespace Godot.NativeInterop
case Variant.Type.Color:
return new godot_variant() { Color = src.Color, Type = Variant.Type.Color };
case Variant.Type.Rid:
- return new godot_variant() { RID = src.RID, Type = Variant.Type.Rid };
+ return new godot_variant() { Rid = src.Rid, Type = Variant.Type.Rid };
}
godotsharp_variant_new_copy(out godot_variant ret, src);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs
deleted file mode 100644
index 4b3db0c01a..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs
+++ /dev/null
@@ -1,1057 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
-
-namespace Godot.NativeInterop;
-
-// TODO: Change VariantConversionCallbacks<T>. Store the callback in a static field for quick repeated access, instead of checking every time.
-internal static unsafe class VariantConversionCallbacks
-{
- internal static System.Collections.Generic.Dictionary<Type, (IntPtr ToVariant, IntPtr FromVariant)>
- GenericConversionCallbacks = new();
-
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
- internal static delegate*<in T, godot_variant> GetToVariantCallback<T>()
- {
- static godot_variant FromBool(in bool @bool) =>
- VariantUtils.CreateFromBool(@bool);
-
- static godot_variant FromChar(in char @char) =>
- VariantUtils.CreateFromInt(@char);
-
- static godot_variant FromInt8(in sbyte @int8) =>
- VariantUtils.CreateFromInt(@int8);
-
- static godot_variant FromInt16(in short @int16) =>
- VariantUtils.CreateFromInt(@int16);
-
- static godot_variant FromInt32(in int @int32) =>
- VariantUtils.CreateFromInt(@int32);
-
- static godot_variant FromInt64(in long @int64) =>
- VariantUtils.CreateFromInt(@int64);
-
- static godot_variant FromUInt8(in byte @uint8) =>
- VariantUtils.CreateFromInt(@uint8);
-
- static godot_variant FromUInt16(in ushort @uint16) =>
- VariantUtils.CreateFromInt(@uint16);
-
- static godot_variant FromUInt32(in uint @uint32) =>
- VariantUtils.CreateFromInt(@uint32);
-
- static godot_variant FromUInt64(in ulong @uint64) =>
- VariantUtils.CreateFromInt(@uint64);
-
- static godot_variant FromFloat(in float @float) =>
- VariantUtils.CreateFromFloat(@float);
-
- static godot_variant FromDouble(in double @double) =>
- VariantUtils.CreateFromFloat(@double);
-
- static godot_variant FromVector2(in Vector2 @vector2) =>
- VariantUtils.CreateFromVector2(@vector2);
-
- static godot_variant FromVector2I(in Vector2i vector2I) =>
- VariantUtils.CreateFromVector2i(vector2I);
-
- static godot_variant FromRect2(in Rect2 @rect2) =>
- VariantUtils.CreateFromRect2(@rect2);
-
- static godot_variant FromRect2I(in Rect2i rect2I) =>
- VariantUtils.CreateFromRect2i(rect2I);
-
- static godot_variant FromTransform2D(in Transform2D @transform2D) =>
- VariantUtils.CreateFromTransform2D(@transform2D);
-
- static godot_variant FromVector3(in Vector3 @vector3) =>
- VariantUtils.CreateFromVector3(@vector3);
-
- static godot_variant FromVector3I(in Vector3i vector3I) =>
- VariantUtils.CreateFromVector3i(vector3I);
-
- static godot_variant FromBasis(in Basis @basis) =>
- VariantUtils.CreateFromBasis(@basis);
-
- static godot_variant FromQuaternion(in Quaternion @quaternion) =>
- VariantUtils.CreateFromQuaternion(@quaternion);
-
- static godot_variant FromTransform3D(in Transform3D @transform3d) =>
- VariantUtils.CreateFromTransform3D(@transform3d);
-
- static godot_variant FromVector4(in Vector4 @vector4) =>
- VariantUtils.CreateFromVector4(@vector4);
-
- static godot_variant FromVector4I(in Vector4i vector4I) =>
- VariantUtils.CreateFromVector4i(vector4I);
-
- static godot_variant FromAabb(in AABB @aabb) =>
- VariantUtils.CreateFromAABB(@aabb);
-
- static godot_variant FromColor(in Color @color) =>
- VariantUtils.CreateFromColor(@color);
-
- static godot_variant FromPlane(in Plane @plane) =>
- VariantUtils.CreateFromPlane(@plane);
-
- static godot_variant FromCallable(in Callable @callable) =>
- VariantUtils.CreateFromCallable(@callable);
-
- static godot_variant FromSignalInfo(in SignalInfo @signalInfo) =>
- VariantUtils.CreateFromSignalInfo(@signalInfo);
-
- static godot_variant FromString(in string @string) =>
- VariantUtils.CreateFromString(@string);
-
- static godot_variant FromByteArray(in byte[] byteArray) =>
- VariantUtils.CreateFromPackedByteArray(byteArray);
-
- static godot_variant FromInt32Array(in int[] int32Array) =>
- VariantUtils.CreateFromPackedInt32Array(int32Array);
-
- static godot_variant FromInt64Array(in long[] int64Array) =>
- VariantUtils.CreateFromPackedInt64Array(int64Array);
-
- static godot_variant FromFloatArray(in float[] floatArray) =>
- VariantUtils.CreateFromPackedFloat32Array(floatArray);
-
- static godot_variant FromDoubleArray(in double[] doubleArray) =>
- VariantUtils.CreateFromPackedFloat64Array(doubleArray);
-
- static godot_variant FromStringArray(in string[] stringArray) =>
- VariantUtils.CreateFromPackedStringArray(stringArray);
-
- static godot_variant FromVector2Array(in Vector2[] vector2Array) =>
- VariantUtils.CreateFromPackedVector2Array(vector2Array);
-
- static godot_variant FromVector3Array(in Vector3[] vector3Array) =>
- VariantUtils.CreateFromPackedVector3Array(vector3Array);
-
- static godot_variant FromColorArray(in Color[] colorArray) =>
- VariantUtils.CreateFromPackedColorArray(colorArray);
-
- static godot_variant FromStringNameArray(in StringName[] stringNameArray) =>
- VariantUtils.CreateFromSystemArrayOfStringName(stringNameArray);
-
- static godot_variant FromNodePathArray(in NodePath[] nodePathArray) =>
- VariantUtils.CreateFromSystemArrayOfNodePath(nodePathArray);
-
- static godot_variant FromRidArray(in RID[] ridArray) =>
- VariantUtils.CreateFromSystemArrayOfRID(ridArray);
-
- static godot_variant FromGodotObject(in Godot.Object godotObject) =>
- VariantUtils.CreateFromGodotObject(godotObject);
-
- static godot_variant FromStringName(in StringName stringName) =>
- VariantUtils.CreateFromStringName(stringName);
-
- static godot_variant FromNodePath(in NodePath nodePath) =>
- VariantUtils.CreateFromNodePath(nodePath);
-
- static godot_variant FromRid(in RID rid) =>
- VariantUtils.CreateFromRID(rid);
-
- static godot_variant FromGodotDictionary(in Collections.Dictionary godotDictionary) =>
- VariantUtils.CreateFromDictionary(godotDictionary);
-
- static godot_variant FromGodotArray(in Collections.Array godotArray) =>
- VariantUtils.CreateFromArray(godotArray);
-
- static godot_variant FromVariant(in Variant variant) =>
- NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar);
-
- var typeOfT = typeof(T);
-
- if (typeOfT == typeof(bool))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in bool, godot_variant>)
- &FromBool;
- }
-
- if (typeOfT == typeof(char))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in char, godot_variant>)
- &FromChar;
- }
-
- if (typeOfT == typeof(sbyte))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in sbyte, godot_variant>)
- &FromInt8;
- }
-
- if (typeOfT == typeof(short))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in short, godot_variant>)
- &FromInt16;
- }
-
- if (typeOfT == typeof(int))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in int, godot_variant>)
- &FromInt32;
- }
-
- if (typeOfT == typeof(long))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in long, godot_variant>)
- &FromInt64;
- }
-
- if (typeOfT == typeof(byte))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in byte, godot_variant>)
- &FromUInt8;
- }
-
- if (typeOfT == typeof(ushort))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ushort, godot_variant>)
- &FromUInt16;
- }
-
- if (typeOfT == typeof(uint))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in uint, godot_variant>)
- &FromUInt32;
- }
-
- if (typeOfT == typeof(ulong))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ulong, godot_variant>)
- &FromUInt64;
- }
-
- if (typeOfT == typeof(float))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in float, godot_variant>)
- &FromFloat;
- }
-
- if (typeOfT == typeof(double))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in double, godot_variant>)
- &FromDouble;
- }
-
- if (typeOfT == typeof(Vector2))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector2, godot_variant>)
- &FromVector2;
- }
-
- if (typeOfT == typeof(Vector2i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector2i, godot_variant>)
- &FromVector2I;
- }
-
- if (typeOfT == typeof(Rect2))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Rect2, godot_variant>)
- &FromRect2;
- }
-
- if (typeOfT == typeof(Rect2i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Rect2i, godot_variant>)
- &FromRect2I;
- }
-
- if (typeOfT == typeof(Transform2D))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Transform2D, godot_variant>)
- &FromTransform2D;
- }
-
- if (typeOfT == typeof(Vector3))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector3, godot_variant>)
- &FromVector3;
- }
-
- if (typeOfT == typeof(Vector3i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector3i, godot_variant>)
- &FromVector3I;
- }
-
- if (typeOfT == typeof(Basis))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Basis, godot_variant>)
- &FromBasis;
- }
-
- if (typeOfT == typeof(Quaternion))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Quaternion, godot_variant>)
- &FromQuaternion;
- }
-
- if (typeOfT == typeof(Transform3D))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Transform3D, godot_variant>)
- &FromTransform3D;
- }
-
- if (typeOfT == typeof(Vector4))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector4, godot_variant>)
- &FromVector4;
- }
-
- if (typeOfT == typeof(Vector4i))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector4i, godot_variant>)
- &FromVector4I;
- }
-
- if (typeOfT == typeof(AABB))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in AABB, godot_variant>)
- &FromAabb;
- }
-
- if (typeOfT == typeof(Color))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Color, godot_variant>)
- &FromColor;
- }
-
- if (typeOfT == typeof(Plane))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Plane, godot_variant>)
- &FromPlane;
- }
-
- if (typeOfT == typeof(Callable))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Callable, godot_variant>)
- &FromCallable;
- }
-
- if (typeOfT == typeof(SignalInfo))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in SignalInfo, godot_variant>)
- &FromSignalInfo;
- }
-
- if (typeOfT.IsEnum)
- {
- var enumUnderlyingType = typeOfT.GetEnumUnderlyingType();
-
- switch (Type.GetTypeCode(enumUnderlyingType))
- {
- case TypeCode.SByte:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in sbyte, godot_variant>)
- &FromInt8;
- }
- case TypeCode.Int16:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in short, godot_variant>)
- &FromInt16;
- }
- case TypeCode.Int32:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in int, godot_variant>)
- &FromInt32;
- }
- case TypeCode.Int64:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in long, godot_variant>)
- &FromInt64;
- }
- case TypeCode.Byte:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in byte, godot_variant>)
- &FromUInt8;
- }
- case TypeCode.UInt16:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ushort, godot_variant>)
- &FromUInt16;
- }
- case TypeCode.UInt32:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in uint, godot_variant>)
- &FromUInt32;
- }
- case TypeCode.UInt64:
- {
- return (delegate*<in T, godot_variant>)(delegate*<in ulong, godot_variant>)
- &FromUInt64;
- }
- default:
- return null;
- }
- }
-
- if (typeOfT == typeof(string))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in string, godot_variant>)
- &FromString;
- }
-
- if (typeOfT == typeof(byte[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in byte[], godot_variant>)
- &FromByteArray;
- }
-
- if (typeOfT == typeof(int[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in int[], godot_variant>)
- &FromInt32Array;
- }
-
- if (typeOfT == typeof(long[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in long[], godot_variant>)
- &FromInt64Array;
- }
-
- if (typeOfT == typeof(float[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in float[], godot_variant>)
- &FromFloatArray;
- }
-
- if (typeOfT == typeof(double[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in double[], godot_variant>)
- &FromDoubleArray;
- }
-
- if (typeOfT == typeof(string[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in string[], godot_variant>)
- &FromStringArray;
- }
-
- if (typeOfT == typeof(Vector2[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector2[], godot_variant>)
- &FromVector2Array;
- }
-
- if (typeOfT == typeof(Vector3[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Vector3[], godot_variant>)
- &FromVector3Array;
- }
-
- if (typeOfT == typeof(Color[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Color[], godot_variant>)
- &FromColorArray;
- }
-
- if (typeOfT == typeof(StringName[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in StringName[], godot_variant>)
- &FromStringNameArray;
- }
-
- if (typeOfT == typeof(NodePath[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in NodePath[], godot_variant>)
- &FromNodePathArray;
- }
-
- if (typeOfT == typeof(RID[]))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in RID[], godot_variant>)
- &FromRidArray;
- }
-
- if (typeof(Godot.Object).IsAssignableFrom(typeOfT))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Godot.Object, godot_variant>)
- &FromGodotObject;
- }
-
- if (typeOfT == typeof(StringName))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in StringName, godot_variant>)
- &FromStringName;
- }
-
- if (typeOfT == typeof(NodePath))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in NodePath, godot_variant>)
- &FromNodePath;
- }
-
- if (typeOfT == typeof(RID))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in RID, godot_variant>)
- &FromRid;
- }
-
- if (typeOfT == typeof(Godot.Collections.Dictionary))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Godot.Collections.Dictionary, godot_variant>)
- &FromGodotDictionary;
- }
-
- if (typeOfT == typeof(Godot.Collections.Array))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Godot.Collections.Array, godot_variant>)
- &FromGodotArray;
- }
-
- if (typeOfT == typeof(Variant))
- {
- return (delegate*<in T, godot_variant>)(delegate*<in Variant, godot_variant>)
- &FromVariant;
- }
-
- // TODO:
- // IsGenericType and GetGenericTypeDefinition don't work in NativeAOT's reflection-free mode.
- // We could make the Godot collections implement an interface and use IsAssignableFrom instead.
- // Or we could just skip the check and always look for a conversion callback for the type.
- if (typeOfT.IsGenericType)
- {
- var genericTypeDef = typeOfT.GetGenericTypeDefinition();
-
- if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>) ||
- genericTypeDef == typeof(Godot.Collections.Array<>))
- {
- RuntimeHelpers.RunClassConstructor(typeOfT.TypeHandle);
-
- if (GenericConversionCallbacks.TryGetValue(typeOfT, out var genericConversion))
- {
- return (delegate*<in T, godot_variant>)genericConversion.ToVariant;
- }
- }
- }
-
- return null;
- }
-
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
- internal static delegate*<in godot_variant, T> GetToManagedCallback<T>()
- {
- static bool ToBool(in godot_variant variant) =>
- VariantUtils.ConvertToBool(variant);
-
- static char ToChar(in godot_variant variant) =>
- VariantUtils.ConvertToChar(variant);
-
- static sbyte ToInt8(in godot_variant variant) =>
- VariantUtils.ConvertToInt8(variant);
-
- static short ToInt16(in godot_variant variant) =>
- VariantUtils.ConvertToInt16(variant);
-
- static int ToInt32(in godot_variant variant) =>
- VariantUtils.ConvertToInt32(variant);
-
- static long ToInt64(in godot_variant variant) =>
- VariantUtils.ConvertToInt64(variant);
-
- static byte ToUInt8(in godot_variant variant) =>
- VariantUtils.ConvertToUInt8(variant);
-
- static ushort ToUInt16(in godot_variant variant) =>
- VariantUtils.ConvertToUInt16(variant);
-
- static uint ToUInt32(in godot_variant variant) =>
- VariantUtils.ConvertToUInt32(variant);
-
- static ulong ToUInt64(in godot_variant variant) =>
- VariantUtils.ConvertToUInt64(variant);
-
- static float ToFloat(in godot_variant variant) =>
- VariantUtils.ConvertToFloat32(variant);
-
- static double ToDouble(in godot_variant variant) =>
- VariantUtils.ConvertToFloat64(variant);
-
- static Vector2 ToVector2(in godot_variant variant) =>
- VariantUtils.ConvertToVector2(variant);
-
- static Vector2i ToVector2I(in godot_variant variant) =>
- VariantUtils.ConvertToVector2i(variant);
-
- static Rect2 ToRect2(in godot_variant variant) =>
- VariantUtils.ConvertToRect2(variant);
-
- static Rect2i ToRect2I(in godot_variant variant) =>
- VariantUtils.ConvertToRect2i(variant);
-
- static Transform2D ToTransform2D(in godot_variant variant) =>
- VariantUtils.ConvertToTransform2D(variant);
-
- static Vector3 ToVector3(in godot_variant variant) =>
- VariantUtils.ConvertToVector3(variant);
-
- static Vector3i ToVector3I(in godot_variant variant) =>
- VariantUtils.ConvertToVector3i(variant);
-
- static Basis ToBasis(in godot_variant variant) =>
- VariantUtils.ConvertToBasis(variant);
-
- static Quaternion ToQuaternion(in godot_variant variant) =>
- VariantUtils.ConvertToQuaternion(variant);
-
- static Transform3D ToTransform3D(in godot_variant variant) =>
- VariantUtils.ConvertToTransform3D(variant);
-
- static Vector4 ToVector4(in godot_variant variant) =>
- VariantUtils.ConvertToVector4(variant);
-
- static Vector4i ToVector4I(in godot_variant variant) =>
- VariantUtils.ConvertToVector4i(variant);
-
- static AABB ToAabb(in godot_variant variant) =>
- VariantUtils.ConvertToAABB(variant);
-
- static Color ToColor(in godot_variant variant) =>
- VariantUtils.ConvertToColor(variant);
-
- static Plane ToPlane(in godot_variant variant) =>
- VariantUtils.ConvertToPlane(variant);
-
- static Callable ToCallable(in godot_variant variant) =>
- VariantUtils.ConvertToCallableManaged(variant);
-
- static SignalInfo ToSignalInfo(in godot_variant variant) =>
- VariantUtils.ConvertToSignalInfo(variant);
-
- static string ToString(in godot_variant variant) =>
- VariantUtils.ConvertToStringObject(variant);
-
- static byte[] ToByteArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedByteArrayToSystemArray(variant);
-
- static int[] ToInt32Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(variant);
-
- static long[] ToInt64Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(variant);
-
- static float[] ToFloatArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(variant);
-
- static double[] ToDoubleArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(variant);
-
- static string[] ToStringArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedStringArrayToSystemArray(variant);
-
- static Vector2[] ToVector2Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(variant);
-
- static Vector3[] ToVector3Array(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(variant);
-
- static Color[] ToColorArray(in godot_variant variant) =>
- VariantUtils.ConvertAsPackedColorArrayToSystemArray(variant);
-
- static StringName[] ToStringNameArray(in godot_variant variant) =>
- VariantUtils.ConvertToSystemArrayOfStringName(variant);
-
- static NodePath[] ToNodePathArray(in godot_variant variant) =>
- VariantUtils.ConvertToSystemArrayOfNodePath(variant);
-
- static RID[] ToRidArray(in godot_variant variant) =>
- VariantUtils.ConvertToSystemArrayOfRID(variant);
-
- static Godot.Object ToGodotObject(in godot_variant variant) =>
- VariantUtils.ConvertToGodotObject(variant);
-
- static StringName ToStringName(in godot_variant variant) =>
- VariantUtils.ConvertToStringNameObject(variant);
-
- static NodePath ToNodePath(in godot_variant variant) =>
- VariantUtils.ConvertToNodePathObject(variant);
-
- static RID ToRid(in godot_variant variant) =>
- VariantUtils.ConvertToRID(variant);
-
- static Collections.Dictionary ToGodotDictionary(in godot_variant variant) =>
- VariantUtils.ConvertToDictionaryObject(variant);
-
- static Collections.Array ToGodotArray(in godot_variant variant) =>
- VariantUtils.ConvertToArrayObject(variant);
-
- static Variant ToVariant(in godot_variant variant) =>
- Variant.CreateCopyingBorrowed(variant);
-
- var typeOfT = typeof(T);
-
- // ReSharper disable RedundantCast
- // Rider is being stupid here. These casts are definitely needed. We get build errors without them.
-
- if (typeOfT == typeof(bool))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, bool>)
- &ToBool;
- }
-
- if (typeOfT == typeof(char))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, char>)
- &ToChar;
- }
-
- if (typeOfT == typeof(sbyte))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, sbyte>)
- &ToInt8;
- }
-
- if (typeOfT == typeof(short))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, short>)
- &ToInt16;
- }
-
- if (typeOfT == typeof(int))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int>)
- &ToInt32;
- }
-
- if (typeOfT == typeof(long))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long>)
- &ToInt64;
- }
-
- if (typeOfT == typeof(byte))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte>)
- &ToUInt8;
- }
-
- if (typeOfT == typeof(ushort))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ushort>)
- &ToUInt16;
- }
-
- if (typeOfT == typeof(uint))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, uint>)
- &ToUInt32;
- }
-
- if (typeOfT == typeof(ulong))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ulong>)
- &ToUInt64;
- }
-
- if (typeOfT == typeof(float))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, float>)
- &ToFloat;
- }
-
- if (typeOfT == typeof(double))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, double>)
- &ToDouble;
- }
-
- if (typeOfT == typeof(Vector2))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2>)
- &ToVector2;
- }
-
- if (typeOfT == typeof(Vector2i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2i>)
- &ToVector2I;
- }
-
- if (typeOfT == typeof(Rect2))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Rect2>)
- &ToRect2;
- }
-
- if (typeOfT == typeof(Rect2i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Rect2i>)
- &ToRect2I;
- }
-
- if (typeOfT == typeof(Transform2D))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Transform2D>)
- &ToTransform2D;
- }
-
- if (typeOfT == typeof(Vector3))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3>)
- &ToVector3;
- }
-
- if (typeOfT == typeof(Vector3i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3i>)
- &ToVector3I;
- }
-
- if (typeOfT == typeof(Basis))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Basis>)
- &ToBasis;
- }
-
- if (typeOfT == typeof(Quaternion))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Quaternion>)
- &ToQuaternion;
- }
-
- if (typeOfT == typeof(Transform3D))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Transform3D>)
- &ToTransform3D;
- }
-
- if (typeOfT == typeof(Vector4))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector4>)
- &ToVector4;
- }
-
- if (typeOfT == typeof(Vector4i))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector4i>)
- &ToVector4I;
- }
-
- if (typeOfT == typeof(AABB))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, AABB>)
- &ToAabb;
- }
-
- if (typeOfT == typeof(Color))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Color>)
- &ToColor;
- }
-
- if (typeOfT == typeof(Plane))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Plane>)
- &ToPlane;
- }
-
- if (typeOfT == typeof(Callable))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Callable>)
- &ToCallable;
- }
-
- if (typeOfT == typeof(SignalInfo))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, SignalInfo>)
- &ToSignalInfo;
- }
-
- if (typeOfT.IsEnum)
- {
- var enumUnderlyingType = typeOfT.GetEnumUnderlyingType();
-
- switch (Type.GetTypeCode(enumUnderlyingType))
- {
- case TypeCode.SByte:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, sbyte>)
- &ToInt8;
- }
- case TypeCode.Int16:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, short>)
- &ToInt16;
- }
- case TypeCode.Int32:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int>)
- &ToInt32;
- }
- case TypeCode.Int64:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long>)
- &ToInt64;
- }
- case TypeCode.Byte:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte>)
- &ToUInt8;
- }
- case TypeCode.UInt16:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ushort>)
- &ToUInt16;
- }
- case TypeCode.UInt32:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, uint>)
- &ToUInt32;
- }
- case TypeCode.UInt64:
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ulong>)
- &ToUInt64;
- }
- default:
- return null;
- }
- }
-
- if (typeOfT == typeof(string))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, string>)
- &ToString;
- }
-
- if (typeOfT == typeof(byte[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte[]>)
- &ToByteArray;
- }
-
- if (typeOfT == typeof(int[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int[]>)
- &ToInt32Array;
- }
-
- if (typeOfT == typeof(long[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long[]>)
- &ToInt64Array;
- }
-
- if (typeOfT == typeof(float[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, float[]>)
- &ToFloatArray;
- }
-
- if (typeOfT == typeof(double[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, double[]>)
- &ToDoubleArray;
- }
-
- if (typeOfT == typeof(string[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, string[]>)
- &ToStringArray;
- }
-
- if (typeOfT == typeof(Vector2[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2[]>)
- &ToVector2Array;
- }
-
- if (typeOfT == typeof(Vector3[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3[]>)
- &ToVector3Array;
- }
-
- if (typeOfT == typeof(Color[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Color[]>)
- &ToColorArray;
- }
-
- if (typeOfT == typeof(StringName[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, StringName[]>)
- &ToStringNameArray;
- }
-
- if (typeOfT == typeof(NodePath[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, NodePath[]>)
- &ToNodePathArray;
- }
-
- if (typeOfT == typeof(RID[]))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, RID[]>)
- &ToRidArray;
- }
-
- if (typeof(Godot.Object).IsAssignableFrom(typeOfT))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Object>)
- &ToGodotObject;
- }
-
- if (typeOfT == typeof(StringName))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, StringName>)
- &ToStringName;
- }
-
- if (typeOfT == typeof(NodePath))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, NodePath>)
- &ToNodePath;
- }
-
- if (typeOfT == typeof(RID))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, RID>)
- &ToRid;
- }
-
- if (typeOfT == typeof(Godot.Collections.Dictionary))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Collections.Dictionary>)
- &ToGodotDictionary;
- }
-
- if (typeOfT == typeof(Godot.Collections.Array))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Collections.Array>)
- &ToGodotArray;
- }
-
- if (typeOfT == typeof(Variant))
- {
- return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Variant>)
- &ToVariant;
- }
-
- // TODO:
- // IsGenericType and GetGenericTypeDefinition don't work in NativeAOT's reflection-free mode.
- // We could make the Godot collections implement an interface and use IsAssignableFrom instead.
- // Or we could just skip the check and always look for a conversion callback for the type.
- if (typeOfT.IsGenericType)
- {
- var genericTypeDef = typeOfT.GetGenericTypeDefinition();
-
- if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>) ||
- genericTypeDef == typeof(Godot.Collections.Array<>))
- {
- RuntimeHelpers.RunClassConstructor(typeOfT.TypeHandle);
-
- if (GenericConversionCallbacks.TryGetValue(typeOfT, out var genericConversion))
- {
- return (delegate*<in godot_variant, T>)genericConversion.FromVariant;
- }
- }
- }
-
- // ReSharper restore RedundantCast
-
- return null;
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs
deleted file mode 100644
index 46f31bbf4e..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-
-namespace Godot.NativeInterop
-{
- internal readonly ref struct VariantSpanDisposer
- {
- private readonly Span<godot_variant.movable> _variantSpan;
-
- // IMPORTANT: The span element must be default initialized.
- // Make sure call Clear() on the span if it was created with stackalloc.
- public VariantSpanDisposer(Span<godot_variant.movable> variantSpan)
- {
- _variantSpan = variantSpan;
- }
-
- public void Dispose()
- {
- for (int i = 0; i < _variantSpan.Length; i++)
- _variantSpan[i].DangerousSelfRef.Dispose();
- }
- }
-
- internal static class VariantSpanExtensions
- {
- // Used to make sure we always initialize the span values to the default,
- // as we need that in order to safely dispose all elements after.
- public static Span<godot_variant.movable> Cleared(this Span<godot_variant.movable> span)
- {
- span.Clear();
- return span;
- }
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
index 57f9ec7d95..e6bcd9393d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
@@ -8,10 +8,10 @@ using Godot.Collections;
namespace Godot.NativeInterop
{
- public static class VariantUtils
+ public static partial class VariantUtils
{
- public static godot_variant CreateFromRID(RID from)
- => new() { Type = Variant.Type.Rid, RID = from };
+ public static godot_variant CreateFromRid(Rid from)
+ => new() { Type = Variant.Type.Rid, Rid = from };
public static godot_variant CreateFromBool(bool from)
=> new() { Type = Variant.Type.Bool, Bool = from.ToGodotBool() };
@@ -28,26 +28,26 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromVector2(Vector2 from)
=> new() { Type = Variant.Type.Vector2, Vector2 = from };
- public static godot_variant CreateFromVector2i(Vector2i from)
- => new() { Type = Variant.Type.Vector2i, Vector2i = from };
+ public static godot_variant CreateFromVector2I(Vector2I from)
+ => new() { Type = Variant.Type.Vector2I, Vector2I = from };
public static godot_variant CreateFromVector3(Vector3 from)
=> new() { Type = Variant.Type.Vector3, Vector3 = from };
- public static godot_variant CreateFromVector3i(Vector3i from)
- => new() { Type = Variant.Type.Vector3i, Vector3i = from };
+ public static godot_variant CreateFromVector3I(Vector3I from)
+ => new() { Type = Variant.Type.Vector3I, Vector3I = from };
public static godot_variant CreateFromVector4(Vector4 from)
=> new() { Type = Variant.Type.Vector4, Vector4 = from };
- public static godot_variant CreateFromVector4i(Vector4i from)
- => new() { Type = Variant.Type.Vector4i, Vector4i = from };
+ public static godot_variant CreateFromVector4I(Vector4I from)
+ => new() { Type = Variant.Type.Vector4I, Vector4I = from };
public static godot_variant CreateFromRect2(Rect2 from)
=> new() { Type = Variant.Type.Rect2, Rect2 = from };
- public static godot_variant CreateFromRect2i(Rect2i from)
- => new() { Type = Variant.Type.Rect2i, Rect2i = from };
+ public static godot_variant CreateFromRect2I(Rect2I from)
+ => new() { Type = Variant.Type.Rect2I, Rect2I = from };
public static godot_variant CreateFromQuaternion(Quaternion from)
=> new() { Type = Variant.Type.Quaternion, Quaternion = from };
@@ -82,7 +82,7 @@ namespace Godot.NativeInterop
return ret;
}
- public static godot_variant CreateFromAABB(AABB from)
+ public static godot_variant CreateFromAabb(Aabb from)
{
NativeFuncs.godotsharp_variant_new_aabb(out godot_variant ret, from);
return ret;
@@ -102,7 +102,7 @@ namespace Godot.NativeInterop
=> new() { Type = Variant.Type.Signal, Signal = from };
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_variant CreateFromSignalInfo(SignalInfo from)
+ public static godot_variant CreateFromSignal(Signal from)
=> CreateFromSignalTakingOwnershipOfDisposableValue(
Marshaling.ConvertSignalToNative(from));
@@ -170,39 +170,66 @@ namespace Godot.NativeInterop
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedByteArray(Span<byte> from)
- => CreateFromPackedByteArray(Marshaling.ConvertSystemArrayToNativePackedByteArray(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedByteArray(from);
+ return CreateFromPackedByteArray(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedInt32Array(Span<int> from)
- => CreateFromPackedInt32Array(Marshaling.ConvertSystemArrayToNativePackedInt32Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt32Array(from);
+ return CreateFromPackedInt32Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedInt64Array(Span<long> from)
- => CreateFromPackedInt64Array(Marshaling.ConvertSystemArrayToNativePackedInt64Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt64Array(from);
+ return CreateFromPackedInt64Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedFloat32Array(Span<float> from)
- => CreateFromPackedFloat32Array(Marshaling.ConvertSystemArrayToNativePackedFloat32Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat32Array(from);
+ return CreateFromPackedFloat32Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedFloat64Array(Span<double> from)
- => CreateFromPackedFloat64Array(Marshaling.ConvertSystemArrayToNativePackedFloat64Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat64Array(from);
+ return CreateFromPackedFloat64Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedStringArray(Span<string> from)
- => CreateFromPackedStringArray(Marshaling.ConvertSystemArrayToNativePackedStringArray(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedStringArray(from);
+ return CreateFromPackedStringArray(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedVector2Array(Span<Vector2> from)
- => CreateFromPackedVector2Array(Marshaling.ConvertSystemArrayToNativePackedVector2Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector2Array(from);
+ return CreateFromPackedVector2Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedVector3Array(Span<Vector3> from)
- => CreateFromPackedVector3Array(Marshaling.ConvertSystemArrayToNativePackedVector3Array(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector3Array(from);
+ return CreateFromPackedVector3Array(nativePackedArray);
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedColorArray(Span<Color> from)
- => CreateFromPackedColorArray(Marshaling.ConvertSystemArrayToNativePackedColorArray(from));
+ {
+ using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedColorArray(from);
+ return CreateFromPackedColorArray(nativePackedArray);
+ }
public static godot_variant CreateFromSystemArrayOfStringName(Span<StringName> from)
=> CreateFromArray(new Collections.Array(from));
@@ -210,11 +237,11 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromSystemArrayOfNodePath(Span<NodePath> from)
=> CreateFromArray(new Collections.Array(from));
- public static godot_variant CreateFromSystemArrayOfRID(Span<RID> from)
+ public static godot_variant CreateFromSystemArrayOfRid(Span<Rid> from)
=> CreateFromArray(new Collections.Array(from));
// ReSharper disable once RedundantNameQualifier
- public static godot_variant CreateFromSystemArrayOfGodotObject(Godot.Object[]? from)
+ public static godot_variant CreateFromSystemArrayOfGodotObject(GodotObject[]? from)
{
if (from == null)
return default; // Nil
@@ -233,7 +260,7 @@ namespace Godot.NativeInterop
=> from != null ? CreateFromArray((godot_array)from.NativeValue) : default;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_variant CreateFromArray<T>(Array<T>? from)
+ public static godot_variant CreateFromArray<[MustBeVariant] T>(Array<T>? from)
=> from != null ? CreateFromArray((godot_array)((Collections.Array)from).NativeValue) : default;
public static godot_variant CreateFromDictionary(godot_dictionary from)
@@ -247,7 +274,7 @@ namespace Godot.NativeInterop
=> from != null ? CreateFromDictionary((godot_dictionary)from.NativeValue) : default;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_variant CreateFromDictionary<TKey, TValue>(Dictionary<TKey, TValue>? from)
+ public static godot_variant CreateFromDictionary<[MustBeVariant] TKey, [MustBeVariant] TValue>(Dictionary<TKey, TValue>? from)
=> from != null ? CreateFromDictionary((godot_dictionary)((Dictionary)from).NativeValue) : default;
public static godot_variant CreateFromStringName(godot_string_name from)
@@ -280,8 +307,8 @@ namespace Godot.NativeInterop
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// ReSharper disable once RedundantNameQualifier
- public static godot_variant CreateFromGodotObject(Godot.Object? from)
- => from != null ? CreateFromGodotObjectPtr(Object.GetPtr(from)) : default;
+ public static godot_variant CreateFromGodotObject(GodotObject? from)
+ => from != null ? CreateFromGodotObjectPtr(GodotObject.GetPtr(from)) : default;
// We avoid the internal call if the stored type is the same we want.
@@ -348,9 +375,9 @@ namespace Godot.NativeInterop
p_var.Vector2 :
NativeFuncs.godotsharp_variant_as_vector2(p_var);
- public static Vector2i ConvertToVector2i(in godot_variant p_var)
- => p_var.Type == Variant.Type.Vector2i ?
- p_var.Vector2i :
+ public static Vector2I ConvertToVector2I(in godot_variant p_var)
+ => p_var.Type == Variant.Type.Vector2I ?
+ p_var.Vector2I :
NativeFuncs.godotsharp_variant_as_vector2i(p_var);
public static Rect2 ConvertToRect2(in godot_variant p_var)
@@ -358,13 +385,13 @@ namespace Godot.NativeInterop
p_var.Rect2 :
NativeFuncs.godotsharp_variant_as_rect2(p_var);
- public static Rect2i ConvertToRect2i(in godot_variant p_var)
- => p_var.Type == Variant.Type.Rect2i ?
- p_var.Rect2i :
+ public static Rect2I ConvertToRect2I(in godot_variant p_var)
+ => p_var.Type == Variant.Type.Rect2I ?
+ p_var.Rect2I :
NativeFuncs.godotsharp_variant_as_rect2i(p_var);
public static unsafe Transform2D ConvertToTransform2D(in godot_variant p_var)
- => p_var.Type == Variant.Type.Transform2d ?
+ => p_var.Type == Variant.Type.Transform2D ?
*p_var.Transform2D :
NativeFuncs.godotsharp_variant_as_transform2d(p_var);
@@ -373,9 +400,9 @@ namespace Godot.NativeInterop
p_var.Vector3 :
NativeFuncs.godotsharp_variant_as_vector3(p_var);
- public static Vector3i ConvertToVector3i(in godot_variant p_var)
- => p_var.Type == Variant.Type.Vector3i ?
- p_var.Vector3i :
+ public static Vector3I ConvertToVector3I(in godot_variant p_var)
+ => p_var.Type == Variant.Type.Vector3I ?
+ p_var.Vector3I :
NativeFuncs.godotsharp_variant_as_vector3i(p_var);
public static unsafe Vector4 ConvertToVector4(in godot_variant p_var)
@@ -383,9 +410,9 @@ namespace Godot.NativeInterop
p_var.Vector4 :
NativeFuncs.godotsharp_variant_as_vector4(p_var);
- public static unsafe Vector4i ConvertToVector4i(in godot_variant p_var)
- => p_var.Type == Variant.Type.Vector4i ?
- p_var.Vector4i :
+ public static unsafe Vector4I ConvertToVector4I(in godot_variant p_var)
+ => p_var.Type == Variant.Type.Vector4I ?
+ p_var.Vector4I :
NativeFuncs.godotsharp_variant_as_vector4i(p_var);
public static unsafe Basis ConvertToBasis(in godot_variant p_var)
@@ -399,7 +426,7 @@ namespace Godot.NativeInterop
NativeFuncs.godotsharp_variant_as_quaternion(p_var);
public static unsafe Transform3D ConvertToTransform3D(in godot_variant p_var)
- => p_var.Type == Variant.Type.Transform3d ?
+ => p_var.Type == Variant.Type.Transform3D ?
*p_var.Transform3D :
NativeFuncs.godotsharp_variant_as_transform3d(p_var);
@@ -408,9 +435,9 @@ namespace Godot.NativeInterop
*p_var.Projection :
NativeFuncs.godotsharp_variant_as_projection(p_var);
- public static unsafe AABB ConvertToAABB(in godot_variant p_var)
+ public static unsafe Aabb ConvertToAabb(in godot_variant p_var)
=> p_var.Type == Variant.Type.Aabb ?
- *p_var.AABB :
+ *p_var.Aabb :
NativeFuncs.godotsharp_variant_as_aabb(p_var);
public static Color ConvertToColor(in godot_variant p_var)
@@ -423,9 +450,9 @@ namespace Godot.NativeInterop
p_var.Plane :
NativeFuncs.godotsharp_variant_as_plane(p_var);
- public static RID ConvertToRID(in godot_variant p_var)
+ public static Rid ConvertToRid(in godot_variant p_var)
=> p_var.Type == Variant.Type.Rid ?
- p_var.RID :
+ p_var.Rid :
NativeFuncs.godotsharp_variant_as_rid(p_var);
public static IntPtr ConvertToGodotObjectPtr(in godot_variant p_var)
@@ -433,10 +460,10 @@ namespace Godot.NativeInterop
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// ReSharper disable once RedundantNameQualifier
- public static Godot.Object ConvertToGodotObject(in godot_variant p_var)
+ public static GodotObject ConvertToGodotObject(in godot_variant p_var)
=> InteropUtils.UnmanagedGetManaged(ConvertToGodotObjectPtr(p_var));
- public static string ConvertToStringObject(in godot_variant p_var)
+ public static string ConvertToString(in godot_variant p_var)
{
switch (p_var.Type)
{
@@ -455,65 +482,65 @@ namespace Godot.NativeInterop
}
}
- public static godot_string_name ConvertToStringName(in godot_variant p_var)
+ public static godot_string_name ConvertToNativeStringName(in godot_variant p_var)
=> p_var.Type == Variant.Type.StringName ?
NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName) :
NativeFuncs.godotsharp_variant_as_string_name(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static StringName ConvertToStringNameObject(in godot_variant p_var)
- => StringName.CreateTakingOwnershipOfDisposableValue(ConvertToStringName(p_var));
+ public static StringName ConvertToStringName(in godot_variant p_var)
+ => StringName.CreateTakingOwnershipOfDisposableValue(ConvertToNativeStringName(p_var));
- public static godot_node_path ConvertToNodePath(in godot_variant p_var)
+ public static godot_node_path ConvertToNativeNodePath(in godot_variant p_var)
=> p_var.Type == Variant.Type.NodePath ?
NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath) :
NativeFuncs.godotsharp_variant_as_node_path(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static NodePath ConvertToNodePathObject(in godot_variant p_var)
- => NodePath.CreateTakingOwnershipOfDisposableValue(ConvertToNodePath(p_var));
+ public static NodePath ConvertToNodePath(in godot_variant p_var)
+ => NodePath.CreateTakingOwnershipOfDisposableValue(ConvertToNativeNodePath(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_callable ConvertToCallable(in godot_variant p_var)
+ public static godot_callable ConvertToNativeCallable(in godot_variant p_var)
=> NativeFuncs.godotsharp_variant_as_callable(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Callable ConvertToCallableManaged(in godot_variant p_var)
- => Marshaling.ConvertCallableToManaged(ConvertToCallable(p_var));
+ public static Callable ConvertToCallable(in godot_variant p_var)
+ => Marshaling.ConvertCallableToManaged(ConvertToNativeCallable(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static godot_signal ConvertToSignal(in godot_variant p_var)
+ public static godot_signal ConvertToNativeSignal(in godot_variant p_var)
=> NativeFuncs.godotsharp_variant_as_signal(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static SignalInfo ConvertToSignalInfo(in godot_variant p_var)
- => Marshaling.ConvertSignalToManaged(ConvertToSignal(p_var));
+ public static Signal ConvertToSignal(in godot_variant p_var)
+ => Marshaling.ConvertSignalToManaged(ConvertToNativeSignal(p_var));
- public static godot_array ConvertToArray(in godot_variant p_var)
+ public static godot_array ConvertToNativeArray(in godot_variant p_var)
=> p_var.Type == Variant.Type.Array ?
NativeFuncs.godotsharp_array_new_copy(p_var.Array) :
NativeFuncs.godotsharp_variant_as_array(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Collections.Array ConvertToArrayObject(in godot_variant p_var)
- => Collections.Array.CreateTakingOwnershipOfDisposableValue(ConvertToArray(p_var));
+ public static Collections.Array ConvertToArray(in godot_variant p_var)
+ => Collections.Array.CreateTakingOwnershipOfDisposableValue(ConvertToNativeArray(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Array<T> ConvertToArrayObject<T>(in godot_variant p_var)
- => Array<T>.CreateTakingOwnershipOfDisposableValue(ConvertToArray(p_var));
+ public static Array<T> ConvertToArray<[MustBeVariant] T>(in godot_variant p_var)
+ => Array<T>.CreateTakingOwnershipOfDisposableValue(ConvertToNativeArray(p_var));
- public static godot_dictionary ConvertToDictionary(in godot_variant p_var)
+ public static godot_dictionary ConvertToNativeDictionary(in godot_variant p_var)
=> p_var.Type == Variant.Type.Dictionary ?
NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary) :
NativeFuncs.godotsharp_variant_as_dictionary(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Dictionary ConvertToDictionaryObject(in godot_variant p_var)
- => Dictionary.CreateTakingOwnershipOfDisposableValue(ConvertToDictionary(p_var));
+ public static Dictionary ConvertToDictionary(in godot_variant p_var)
+ => Dictionary.CreateTakingOwnershipOfDisposableValue(ConvertToNativeDictionary(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Dictionary<TKey, TValue> ConvertToDictionaryObject<TKey, TValue>(in godot_variant p_var)
- => Dictionary<TKey, TValue>.CreateTakingOwnershipOfDisposableValue(ConvertToDictionary(p_var));
+ public static Dictionary<TKey, TValue> ConvertToDictionary<[MustBeVariant] TKey, [MustBeVariant] TValue>(in godot_variant p_var)
+ => Dictionary<TKey, TValue>.CreateTakingOwnershipOfDisposableValue(ConvertToNativeDictionary(p_var));
public static byte[] ConvertAsPackedByteArrayToSystemArray(in godot_variant p_var)
{
@@ -581,25 +608,18 @@ namespace Godot.NativeInterop
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfNodePath(godotArray);
}
- public static RID[] ConvertToSystemArrayOfRID(in godot_variant p_var)
+ public static Rid[] ConvertToSystemArrayOfRid(in godot_variant p_var)
{
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return Marshaling.ConvertNativeGodotArrayToSystemArrayOfRID(godotArray);
+ return Marshaling.ConvertNativeGodotArrayToSystemArrayOfRid(godotArray);
}
public static T[] ConvertToSystemArrayOfGodotObject<T>(in godot_variant p_var)
// ReSharper disable once RedundantNameQualifier
- where T : Godot.Object
+ where T : GodotObject
{
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType<T>(godotArray);
}
-
- // ReSharper disable once RedundantNameQualifier
- public static Godot.Object[] ConvertToSystemArrayOfGodotObject(in godot_variant p_var, Type type)
- {
- using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(godotArray, type);
- }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs
new file mode 100644
index 0000000000..12b0a47079
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs
@@ -0,0 +1,414 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace Godot.NativeInterop;
+
+#nullable enable
+
+public partial class VariantUtils
+{
+ private static Exception UnsupportedType<T>() => new InvalidOperationException(
+ $"The type is not supported for conversion to/from Variant: '{typeof(T).FullName}'");
+
+ internal static class GenericConversion<T>
+ {
+ public static unsafe godot_variant ToVariant(in T from) =>
+ ToVariantCb != null ? ToVariantCb(from) : throw UnsupportedType<T>();
+
+ public static unsafe T FromVariant(in godot_variant variant) =>
+ FromVariantCb != null ? FromVariantCb(variant) : throw UnsupportedType<T>();
+
+ // ReSharper disable once StaticMemberInGenericType
+ internal static unsafe delegate*<in T, godot_variant> ToVariantCb;
+
+ // ReSharper disable once StaticMemberInGenericType
+ internal static unsafe delegate*<in godot_variant, T> FromVariantCb;
+
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ static GenericConversion()
+ {
+ RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static godot_variant CreateFrom<[MustBeVariant] T>(in T from)
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static TTo UnsafeAs<TTo>(in T f) => Unsafe.As<T, TTo>(ref Unsafe.AsRef(f));
+
+ // `typeof(T) == typeof(X)` is optimized away. We cannot cache `typeof(T)` in a local variable, as it's not optimized when done like that.
+
+ if (typeof(T) == typeof(bool))
+ return CreateFromBool(UnsafeAs<bool>(from));
+
+ if (typeof(T) == typeof(char))
+ return CreateFromInt(UnsafeAs<char>(from));
+
+ if (typeof(T) == typeof(sbyte))
+ return CreateFromInt(UnsafeAs<sbyte>(from));
+
+ if (typeof(T) == typeof(short))
+ return CreateFromInt(UnsafeAs<short>(from));
+
+ if (typeof(T) == typeof(int))
+ return CreateFromInt(UnsafeAs<int>(from));
+
+ if (typeof(T) == typeof(long))
+ return CreateFromInt(UnsafeAs<long>(from));
+
+ if (typeof(T) == typeof(byte))
+ return CreateFromInt(UnsafeAs<byte>(from));
+
+ if (typeof(T) == typeof(ushort))
+ return CreateFromInt(UnsafeAs<ushort>(from));
+
+ if (typeof(T) == typeof(uint))
+ return CreateFromInt(UnsafeAs<uint>(from));
+
+ if (typeof(T) == typeof(ulong))
+ return CreateFromInt(UnsafeAs<ulong>(from));
+
+ if (typeof(T) == typeof(float))
+ return CreateFromFloat(UnsafeAs<float>(from));
+
+ if (typeof(T) == typeof(double))
+ return CreateFromFloat(UnsafeAs<double>(from));
+
+ if (typeof(T) == typeof(Vector2))
+ return CreateFromVector2(UnsafeAs<Vector2>(from));
+
+ if (typeof(T) == typeof(Vector2I))
+ return CreateFromVector2I(UnsafeAs<Vector2I>(from));
+
+ if (typeof(T) == typeof(Rect2))
+ return CreateFromRect2(UnsafeAs<Rect2>(from));
+
+ if (typeof(T) == typeof(Rect2I))
+ return CreateFromRect2I(UnsafeAs<Rect2I>(from));
+
+ if (typeof(T) == typeof(Transform2D))
+ return CreateFromTransform2D(UnsafeAs<Transform2D>(from));
+
+ if (typeof(T) == typeof(Projection))
+ return CreateFromProjection(UnsafeAs<Projection>(from));
+
+ if (typeof(T) == typeof(Vector3))
+ return CreateFromVector3(UnsafeAs<Vector3>(from));
+
+ if (typeof(T) == typeof(Vector3I))
+ return CreateFromVector3I(UnsafeAs<Vector3I>(from));
+
+ if (typeof(T) == typeof(Basis))
+ return CreateFromBasis(UnsafeAs<Basis>(from));
+
+ if (typeof(T) == typeof(Quaternion))
+ return CreateFromQuaternion(UnsafeAs<Quaternion>(from));
+
+ if (typeof(T) == typeof(Transform3D))
+ return CreateFromTransform3D(UnsafeAs<Transform3D>(from));
+
+ if (typeof(T) == typeof(Vector4))
+ return CreateFromVector4(UnsafeAs<Vector4>(from));
+
+ if (typeof(T) == typeof(Vector4I))
+ return CreateFromVector4I(UnsafeAs<Vector4I>(from));
+
+ if (typeof(T) == typeof(Aabb))
+ return CreateFromAabb(UnsafeAs<Aabb>(from));
+
+ if (typeof(T) == typeof(Color))
+ return CreateFromColor(UnsafeAs<Color>(from));
+
+ if (typeof(T) == typeof(Plane))
+ return CreateFromPlane(UnsafeAs<Plane>(from));
+
+ if (typeof(T) == typeof(Callable))
+ return CreateFromCallable(UnsafeAs<Callable>(from));
+
+ if (typeof(T) == typeof(Signal))
+ return CreateFromSignal(UnsafeAs<Signal>(from));
+
+ if (typeof(T) == typeof(string))
+ return CreateFromString(UnsafeAs<string>(from));
+
+ if (typeof(T) == typeof(byte[]))
+ return CreateFromPackedByteArray(UnsafeAs<byte[]>(from));
+
+ if (typeof(T) == typeof(int[]))
+ return CreateFromPackedInt32Array(UnsafeAs<int[]>(from));
+
+ if (typeof(T) == typeof(long[]))
+ return CreateFromPackedInt64Array(UnsafeAs<long[]>(from));
+
+ if (typeof(T) == typeof(float[]))
+ return CreateFromPackedFloat32Array(UnsafeAs<float[]>(from));
+
+ if (typeof(T) == typeof(double[]))
+ return CreateFromPackedFloat64Array(UnsafeAs<double[]>(from));
+
+ if (typeof(T) == typeof(string[]))
+ return CreateFromPackedStringArray(UnsafeAs<string[]>(from));
+
+ if (typeof(T) == typeof(Vector2[]))
+ return CreateFromPackedVector2Array(UnsafeAs<Vector2[]>(from));
+
+ if (typeof(T) == typeof(Vector3[]))
+ return CreateFromPackedVector3Array(UnsafeAs<Vector3[]>(from));
+
+ if (typeof(T) == typeof(Color[]))
+ return CreateFromPackedColorArray(UnsafeAs<Color[]>(from));
+
+ if (typeof(T) == typeof(StringName[]))
+ return CreateFromSystemArrayOfStringName(UnsafeAs<StringName[]>(from));
+
+ if (typeof(T) == typeof(NodePath[]))
+ return CreateFromSystemArrayOfNodePath(UnsafeAs<NodePath[]>(from));
+
+ if (typeof(T) == typeof(Rid[]))
+ return CreateFromSystemArrayOfRid(UnsafeAs<Rid[]>(from));
+
+ if (typeof(T) == typeof(StringName))
+ return CreateFromStringName(UnsafeAs<StringName>(from));
+
+ if (typeof(T) == typeof(NodePath))
+ return CreateFromNodePath(UnsafeAs<NodePath>(from));
+
+ if (typeof(T) == typeof(Rid))
+ return CreateFromRid(UnsafeAs<Rid>(from));
+
+ if (typeof(T) == typeof(Godot.Collections.Dictionary))
+ return CreateFromDictionary(UnsafeAs<Godot.Collections.Dictionary>(from));
+
+ if (typeof(T) == typeof(Godot.Collections.Array))
+ return CreateFromArray(UnsafeAs<Godot.Collections.Array>(from));
+
+ if (typeof(T) == typeof(Variant))
+ return NativeFuncs.godotsharp_variant_new_copy((godot_variant)UnsafeAs<Variant>(from).NativeVar);
+
+ // More complex checks here at the end, to avoid screwing the simple ones in case they're not optimized away.
+
+ // `typeof(X).IsAssignableFrom(typeof(T))` is optimized away
+
+ if (typeof(GodotObject).IsAssignableFrom(typeof(T)))
+ return CreateFromGodotObject(UnsafeAs<GodotObject>(from));
+
+ // `typeof(T).IsValueType` is optimized away
+ // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113
+ // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job!
+
+ if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T)))
+ {
+ // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away.
+ // Fortunately, `Unsafe.SizeOf<T>()` works and is optimized away.
+ // We don't need to know whether it's signed or unsigned.
+
+ if (Unsafe.SizeOf<T>() == 1)
+ return CreateFromInt(UnsafeAs<sbyte>(from));
+
+ if (Unsafe.SizeOf<T>() == 2)
+ return CreateFromInt(UnsafeAs<short>(from));
+
+ if (Unsafe.SizeOf<T>() == 4)
+ return CreateFromInt(UnsafeAs<int>(from));
+
+ if (Unsafe.SizeOf<T>() == 8)
+ return CreateFromInt(UnsafeAs<long>(from));
+
+ throw UnsupportedType<T>();
+ }
+
+ return GenericConversion<T>.ToVariant(from);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ public static T ConvertTo<[MustBeVariant] T>(in godot_variant variant)
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static T UnsafeAsT<TFrom>(TFrom f) => Unsafe.As<TFrom, T>(ref Unsafe.AsRef(f));
+
+ if (typeof(T) == typeof(bool))
+ return UnsafeAsT(ConvertToBool(variant));
+
+ if (typeof(T) == typeof(char))
+ return UnsafeAsT(ConvertToChar(variant));
+
+ if (typeof(T) == typeof(sbyte))
+ return UnsafeAsT(ConvertToInt8(variant));
+
+ if (typeof(T) == typeof(short))
+ return UnsafeAsT(ConvertToInt16(variant));
+
+ if (typeof(T) == typeof(int))
+ return UnsafeAsT(ConvertToInt32(variant));
+
+ if (typeof(T) == typeof(long))
+ return UnsafeAsT(ConvertToInt64(variant));
+
+ if (typeof(T) == typeof(byte))
+ return UnsafeAsT(ConvertToUInt8(variant));
+
+ if (typeof(T) == typeof(ushort))
+ return UnsafeAsT(ConvertToUInt16(variant));
+
+ if (typeof(T) == typeof(uint))
+ return UnsafeAsT(ConvertToUInt32(variant));
+
+ if (typeof(T) == typeof(ulong))
+ return UnsafeAsT(ConvertToUInt64(variant));
+
+ if (typeof(T) == typeof(float))
+ return UnsafeAsT(ConvertToFloat32(variant));
+
+ if (typeof(T) == typeof(double))
+ return UnsafeAsT(ConvertToFloat64(variant));
+
+ if (typeof(T) == typeof(Vector2))
+ return UnsafeAsT(ConvertToVector2(variant));
+
+ if (typeof(T) == typeof(Vector2I))
+ return UnsafeAsT(ConvertToVector2I(variant));
+
+ if (typeof(T) == typeof(Rect2))
+ return UnsafeAsT(ConvertToRect2(variant));
+
+ if (typeof(T) == typeof(Rect2I))
+ return UnsafeAsT(ConvertToRect2I(variant));
+
+ if (typeof(T) == typeof(Transform2D))
+ return UnsafeAsT(ConvertToTransform2D(variant));
+
+ if (typeof(T) == typeof(Vector3))
+ return UnsafeAsT(ConvertToVector3(variant));
+
+ if (typeof(T) == typeof(Vector3I))
+ return UnsafeAsT(ConvertToVector3I(variant));
+
+ if (typeof(T) == typeof(Basis))
+ return UnsafeAsT(ConvertToBasis(variant));
+
+ if (typeof(T) == typeof(Quaternion))
+ return UnsafeAsT(ConvertToQuaternion(variant));
+
+ if (typeof(T) == typeof(Transform3D))
+ return UnsafeAsT(ConvertToTransform3D(variant));
+
+ if (typeof(T) == typeof(Projection))
+ return UnsafeAsT(ConvertToProjection(variant));
+
+ if (typeof(T) == typeof(Vector4))
+ return UnsafeAsT(ConvertToVector4(variant));
+
+ if (typeof(T) == typeof(Vector4I))
+ return UnsafeAsT(ConvertToVector4I(variant));
+
+ if (typeof(T) == typeof(Aabb))
+ return UnsafeAsT(ConvertToAabb(variant));
+
+ if (typeof(T) == typeof(Color))
+ return UnsafeAsT(ConvertToColor(variant));
+
+ if (typeof(T) == typeof(Plane))
+ return UnsafeAsT(ConvertToPlane(variant));
+
+ if (typeof(T) == typeof(Callable))
+ return UnsafeAsT(ConvertToCallable(variant));
+
+ if (typeof(T) == typeof(Signal))
+ return UnsafeAsT(ConvertToSignal(variant));
+
+ if (typeof(T) == typeof(string))
+ return UnsafeAsT(ConvertToString(variant));
+
+ if (typeof(T) == typeof(byte[]))
+ return UnsafeAsT(ConvertAsPackedByteArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(int[]))
+ return UnsafeAsT(ConvertAsPackedInt32ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(long[]))
+ return UnsafeAsT(ConvertAsPackedInt64ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(float[]))
+ return UnsafeAsT(ConvertAsPackedFloat32ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(double[]))
+ return UnsafeAsT(ConvertAsPackedFloat64ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(string[]))
+ return UnsafeAsT(ConvertAsPackedStringArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(Vector2[]))
+ return UnsafeAsT(ConvertAsPackedVector2ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(Vector3[]))
+ return UnsafeAsT(ConvertAsPackedVector3ArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(Color[]))
+ return UnsafeAsT(ConvertAsPackedColorArrayToSystemArray(variant));
+
+ if (typeof(T) == typeof(StringName[]))
+ return UnsafeAsT(ConvertToSystemArrayOfStringName(variant));
+
+ if (typeof(T) == typeof(NodePath[]))
+ return UnsafeAsT(ConvertToSystemArrayOfNodePath(variant));
+
+ if (typeof(T) == typeof(Rid[]))
+ return UnsafeAsT(ConvertToSystemArrayOfRid(variant));
+
+ if (typeof(T) == typeof(StringName))
+ return UnsafeAsT(ConvertToStringName(variant));
+
+ if (typeof(T) == typeof(NodePath))
+ return UnsafeAsT(ConvertToNodePath(variant));
+
+ if (typeof(T) == typeof(Rid))
+ return UnsafeAsT(ConvertToRid(variant));
+
+ if (typeof(T) == typeof(Godot.Collections.Dictionary))
+ return UnsafeAsT(ConvertToDictionary(variant));
+
+ if (typeof(T) == typeof(Godot.Collections.Array))
+ return UnsafeAsT(ConvertToArray(variant));
+
+ if (typeof(T) == typeof(Variant))
+ return UnsafeAsT(Variant.CreateCopyingBorrowed(variant));
+
+ // More complex checks here at the end, to avoid screwing the simple ones in case they're not optimized away.
+
+ // `typeof(X).IsAssignableFrom(typeof(T))` is optimized away
+
+ if (typeof(GodotObject).IsAssignableFrom(typeof(T)))
+ return (T)(object)ConvertToGodotObject(variant);
+
+ // `typeof(T).IsValueType` is optimized away
+ // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113
+ // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job!
+
+ if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T)))
+ {
+ // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away.
+ // Fortunately, `Unsafe.SizeOf<T>()` works and is optimized away.
+ // We don't need to know whether it's signed or unsigned.
+
+ if (Unsafe.SizeOf<T>() == 1)
+ return UnsafeAsT(ConvertToInt8(variant));
+
+ if (Unsafe.SizeOf<T>() == 2)
+ return UnsafeAsT(ConvertToInt16(variant));
+
+ if (Unsafe.SizeOf<T>() == 4)
+ return UnsafeAsT(ConvertToInt32(variant));
+
+ if (Unsafe.SizeOf<T>() == 8)
+ return UnsafeAsT(ConvertToInt64(variant));
+
+ throw UnsupportedType<T>();
+ }
+
+ return GenericConversion<T>.FromVariant(variant);
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
index b02bd167a1..f216fb7ea3 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
@@ -39,7 +39,7 @@ namespace Godot
/// new NodePath("/root/MyAutoload"); // If you have an autoloaded node or scene.
/// </code>
/// </example>
- public sealed class NodePath : IDisposable
+ public sealed class NodePath : IDisposable, IEquatable<NodePath>
{
internal godot_node_path.movable NativeValue;
@@ -288,5 +288,37 @@ namespace Godot
/// </summary>
/// <returns>If the <see cref="NodePath"/> is empty.</returns>
public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty;
+
+ public static bool operator ==(NodePath left, NodePath right)
+ {
+ if (left is null)
+ return right is null;
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(NodePath left, NodePath right)
+ {
+ return !(left == right);
+ }
+
+ public bool Equals(NodePath other)
+ {
+ if (other is null)
+ return false;
+ var self = (godot_node_path)NativeValue;
+ var otherNative = (godot_node_path)other.NativeValue;
+ return NativeFuncs.godotsharp_node_path_equals(self, otherNative).ToBool();
+ }
+
+ public override bool Equals(object obj)
+ {
+ return ReferenceEquals(this, obj) || (obj is NodePath other && Equals(other));
+ }
+
+ public override int GetHashCode()
+ {
+ var self = (godot_node_path)NativeValue;
+ return NativeFuncs.godotsharp_node_path_hash(self);
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index 664b2e0f34..55b7a83fc2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -13,32 +13,47 @@ namespace Godot
public struct Plane : IEquatable<Plane>
{
private Vector3 _normal;
+ private real_t _d;
/// <summary>
- /// The normal of the plane, which must be normalized.
+ /// The normal of the plane, which must be a unit vector.
/// In the scalar equation of the plane <c>ax + by + cz = d</c>, this is
/// the vector <c>(a, b, c)</c>, where <c>d</c> is the <see cref="D"/> property.
/// </summary>
- /// <value>Equivalent to <see cref="x"/>, <see cref="y"/>, and <see cref="z"/>.</value>
+ /// <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; }
}
/// <summary>
+ /// The distance from the origin to the plane (in the direction of
+ /// <see cref="Normal"/>). This value is typically non-negative.
+ /// In the scalar equation of the plane <c>ax + by + cz = d</c>,
+ /// this is <c>d</c>, while the <c>(a, b, c)</c> coordinates are represented
+ /// by the <see cref="Normal"/> property.
+ /// </summary>
+ /// <value>The plane's distance from the origin.</value>
+ public real_t D
+ {
+ readonly get { return _d; }
+ set { _d = value; }
+ }
+
+ /// <summary>
/// The X component of the plane's normal vector.
/// </summary>
/// <value>Equivalent to <see cref="Normal"/>'s X value.</value>
- public real_t x
+ public real_t X
{
- get
+ readonly get
{
- return _normal.x;
+ return _normal.X;
}
set
{
- _normal.x = value;
+ _normal.X = value;
}
}
@@ -46,15 +61,15 @@ namespace Godot
/// The Y component of the plane's normal vector.
/// </summary>
/// <value>Equivalent to <see cref="Normal"/>'s Y value.</value>
- public real_t y
+ public real_t Y
{
- get
+ readonly get
{
- return _normal.y;
+ return _normal.Y;
}
set
{
- _normal.y = value;
+ _normal.Y = value;
}
}
@@ -62,53 +77,36 @@ namespace Godot
/// The Z component of the plane's normal vector.
/// </summary>
/// <value>Equivalent to <see cref="Normal"/>'s Z value.</value>
- public real_t z
+ public real_t Z
{
- get
+ readonly get
{
- return _normal.z;
+ return _normal.Z;
}
set
{
- _normal.z = value;
+ _normal.Z = value;
}
}
/// <summary>
- /// The distance from the origin to the plane (in the direction of
- /// <see cref="Normal"/>). This value is typically non-negative.
- /// In the scalar equation of the plane <c>ax + by + cz = d</c>,
- /// this is <c>d</c>, while the <c>(a, b, c)</c> coordinates are represented
- /// by the <see cref="Normal"/> property.
- /// </summary>
- /// <value>The plane's distance from the origin.</value>
- public real_t D { get; set; }
-
- /// <summary>
- /// The center of the plane, the point where the normal line intersects the plane.
+ /// Returns the shortest distance from this plane to the position <paramref name="point"/>.
/// </summary>
- /// <value>Equivalent to <see cref="Normal"/> multiplied by <see cref="D"/>.</value>
- public Vector3 Center
+ /// <param name="point">The position to use for the calculation.</param>
+ /// <returns>The shortest distance.</returns>
+ public readonly real_t DistanceTo(Vector3 point)
{
- get
- {
- return _normal * D;
- }
- set
- {
- _normal = value.Normalized();
- D = value.Length();
- }
+ return _normal.Dot(point) - _d;
}
/// <summary>
- /// Returns the shortest distance from this plane to the position <paramref name="point"/>.
+ /// Returns the center of the plane, the point on the plane closest to the origin.
+ /// The point where the normal line going through the origin intersects the plane.
/// </summary>
- /// <param name="point">The position to use for the calculation.</param>
- /// <returns>The shortest distance.</returns>
- public real_t DistanceTo(Vector3 point)
+ /// <value>Equivalent to <see cref="Normal"/> multiplied by <see cref="D"/>.</value>
+ public readonly Vector3 GetCenter()
{
- return _normal.Dot(point) - D;
+ return _normal * _d;
}
/// <summary>
@@ -118,9 +116,9 @@ 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;
+ real_t dist = _normal.Dot(point) - _d;
return Mathf.Abs(dist) <= tolerance;
}
@@ -131,7 +129,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);
@@ -140,9 +138,9 @@ namespace Godot
return null;
}
- Vector3 result = (b._normal.Cross(c._normal) * D) +
- (c._normal.Cross(_normal) * b.D) +
- (_normal.Cross(b._normal) * c.D);
+ Vector3 result = (b._normal.Cross(c._normal) * _d) +
+ (c._normal.Cross(_normal) * b._d) +
+ (_normal.Cross(b._normal) * c._d);
return result / denom;
}
@@ -155,7 +153,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? IntersectsRay(Vector3 from, Vector3 dir)
{
real_t den = _normal.Dot(dir);
@@ -164,7 +162,7 @@ namespace Godot
return null;
}
- real_t dist = (_normal.Dot(from) - D) / den;
+ real_t dist = (_normal.Dot(from) - _d) / den;
// This is a ray, before the emitting pos (from) does not exist
if (dist > Mathf.Epsilon)
@@ -183,7 +181,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? IntersectsSegment(Vector3 begin, Vector3 end)
{
Vector3 segment = begin - end;
real_t den = _normal.Dot(segment);
@@ -193,7 +191,7 @@ namespace Godot
return null;
}
- real_t dist = (_normal.Dot(begin) - D) / den;
+ real_t dist = (_normal.Dot(begin) - _d) / den;
// Only allow dist to be in the range of 0 to 1, with tolerance.
if (dist < -Mathf.Epsilon || dist > 1.0f + Mathf.Epsilon)
@@ -205,20 +203,30 @@ namespace Godot
}
/// <summary>
+ /// Returns <see langword="true"/> if this plane is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return _normal.IsFinite() && Mathf.IsFinite(D);
+ }
+
+ /// <summary>
/// Returns <see langword="true"/> if <paramref name="point"/> is located above the plane.
/// </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;
+ return _normal.Dot(point) > _d;
}
/// <summary>
/// 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();
@@ -227,7 +235,7 @@ namespace Godot
return new Plane(0, 0, 0, 0);
}
- return new Plane(_normal / len, D / len);
+ return new Plane(_normal / len, _d / len);
}
/// <summary>
@@ -235,7 +243,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));
}
@@ -276,31 +284,42 @@ namespace Godot
public Plane(real_t a, real_t b, real_t c, real_t d)
{
_normal = new Vector3(a, b, c);
- D = d;
+ _d = d;
+ }
+
+ /// <summary>
+ /// Constructs a <see cref="Plane"/> from a <paramref name="normal"/> vector.
+ /// The plane will intersect the origin.
+ /// </summary>
+ /// <param name="normal">The normal of the plane, must be a unit vector.</param>
+ public Plane(Vector3 normal)
+ {
+ _normal = normal;
+ _d = 0;
}
/// <summary>
/// Constructs a <see cref="Plane"/> from a <paramref name="normal"/> vector and
/// the plane's distance to the origin <paramref name="d"/>.
/// </summary>
- /// <param name="normal">The normal of the plane, must be normalized.</param>
+ /// <param name="normal">The normal of the plane, must be a unit vector.</param>
/// <param name="d">The plane's distance from the origin. This value is typically non-negative.</param>
public Plane(Vector3 normal, real_t d)
{
_normal = normal;
- D = d;
+ _d = d;
}
/// <summary>
/// Constructs a <see cref="Plane"/> from a <paramref name="normal"/> vector and
/// a <paramref name="point"/> on the plane.
/// </summary>
- /// <param name="normal">The normal of the plane, must be normalized.</param>
+ /// <param name="normal">The normal of the plane, must be a unit vector.</param>
/// <param name="point">The point on the plane.</param>
public Plane(Vector3 normal, Vector3 point)
{
_normal = normal;
- D = _normal.Dot(point);
+ _d = _normal.Dot(point);
}
/// <summary>
@@ -313,7 +332,7 @@ namespace Godot
{
_normal = (v1 - v3).Cross(v1 - v2);
_normal.Normalize();
- D = _normal.Dot(v1);
+ _d = _normal.Dot(v1);
}
/// <summary>
@@ -327,7 +346,7 @@ namespace Godot
/// <returns>The negated/flipped plane.</returns>
public static Plane operator -(Plane plane)
{
- return new Plane(-plane._normal, -plane.D);
+ return new Plane(-plane._normal, -plane._d);
}
/// <summary>
@@ -363,7 +382,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,9 +392,9 @@ 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;
+ return _normal == other._normal && _d == other._d;
}
/// <summary>
@@ -384,36 +403,36 @@ 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);
+ return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(_d, other._d);
}
/// <summary>
/// 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();
+ return _normal.GetHashCode() ^ _d.GetHashCode();
}
/// <summary>
/// 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}";
+ return $"{_normal}, {_d}";
}
/// <summary>
/// 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)}";
+ 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..84fc73b87a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
@@ -3,6 +3,14 @@ using System.Runtime.InteropServices;
namespace Godot
{
+ /// <summary>
+ /// A 4x4 matrix used for 3D projective transformations. It can represent transformations such as
+ /// translation, rotation, scaling, shearing, and perspective division. It consists of four
+ /// <see cref="Vector4"/> columns.
+ /// For purely linear transformations (translation, rotation, and scale), it is recommended to use
+ /// <see cref="Transform3D"/>, as it is more performant and has a lower memory footprint.
+ /// Used internally as <see cref="Camera3D"/>'s projection matrix.
+ /// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Projection : IEquatable<Projection>
@@ -41,66 +49,125 @@ namespace Godot
/// <summary>
/// The projection's X column. Also accessible by using the index position <c>[0]</c>.
/// </summary>
- public Vector4 x;
+ public Vector4 X;
/// <summary>
/// The projection's Y column. Also accessible by using the index position <c>[1]</c>.
/// </summary>
- public Vector4 y;
+ public Vector4 Y;
/// <summary>
/// The projection's Z column. Also accessible by using the index position <c>[2]</c>.
/// </summary>
- public Vector4 z;
+ public Vector4 Z;
/// <summary>
/// The projection's W column. Also accessible by using the index position <c>[3]</c>.
/// </summary>
- public Vector4 w;
+ public Vector4 W;
/// <summary>
- /// Constructs a projection from 4 vectors (matrix columns).
+ /// Access whole columns in the form of <see cref="Vector4"/>.
/// </summary>
- /// <param name="x">The X column, or column index 0.</param>
- /// <param name="y">The Y column, or column index 1.</param>
- /// <param name="z">The Z column, or column index 2.</param>
- /// <param name="w">The W column, or column index 3.</param>
- public Projection(Vector4 x, Vector4 y, Vector4 z, Vector4 w)
+ /// <param name="column">Which column vector.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="column"/> is not 0, 1, 2 or 3.
+ /// </exception>
+ public Vector4 this[int column]
{
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
+ readonly get
+ {
+ switch (column)
+ {
+ case 0:
+ return X;
+ case 1:
+ return Y;
+ case 2:
+ return Z;
+ case 3:
+ return W;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
+ set
+ {
+ switch (column)
+ {
+ case 0:
+ X = value;
+ return;
+ case 1:
+ Y = value;
+ return;
+ case 2:
+ Z = value;
+ return;
+ case 3:
+ W = value;
+ return;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
}
/// <summary>
- /// Constructs a new <see cref="Projection"/> from a <see cref="Transform3D"/>.
+ /// Access single values.
/// </summary>
- /// <param name="transform">The <see cref="Transform3D"/>.</param>
- public Projection(Transform3D transform)
+ /// <param name="column">Which column vector.</param>
+ /// <param name="row">Which row of the column.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="column"/> or <paramref name="row"/> are not 0, 1, 2 or 3.
+ /// </exception>
+ public real_t this[int column, int row]
{
- x = new Vector4(transform.basis.Row0.x, transform.basis.Row1.x, transform.basis.Row2.x, 0);
- y = new Vector4(transform.basis.Row0.y, transform.basis.Row1.y, transform.basis.Row2.y, 0);
- z = new Vector4(transform.basis.Row0.z, transform.basis.Row1.z, transform.basis.Row2.z, 0);
- w = new Vector4(transform.origin.x, transform.origin.y, transform.origin.z, 1);
+ readonly get
+ {
+ switch (column)
+ {
+ case 0:
+ return X[row];
+ case 1:
+ return Y[row];
+ case 2:
+ return Z[row];
+ case 3:
+ return W[row];
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
+ set
+ {
+ switch (column)
+ {
+ case 0:
+ X[row] = value;
+ return;
+ case 1:
+ Y[row] = value;
+ return;
+ case 2:
+ Z[row] = value;
+ return;
+ case 3:
+ W[row] = value;
+ return;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
}
/// <summary>
- /// Constructs a new <see cref="Transform3D"/> from the <see cref="Projection"/>.
+ /// Creates a new <see cref="Projection"/> that projects positions from a depth range of
+ /// <c>-1</c> to <c>1</c> to one that ranges from <c>0</c> to <c>1</c>, and flips the projected
+ /// positions vertically, according to <paramref name="flipY"/>.
/// </summary>
- /// <param name="proj">The <see cref="Projection"/>.</param>
- public static explicit operator Transform3D(Projection proj)
- {
- return new Transform3D(
- new Basis(
- new Vector3(proj.x.x, proj.x.y, proj.x.z),
- new Vector3(proj.y.x, proj.y.y, proj.y.z),
- new Vector3(proj.z.x, proj.z.y, proj.z.z)
- ),
- new Vector3(proj.w.x, proj.w.y, proj.w.z)
- );
- }
-
+ /// <param name="flipY">If the projection should be flipped vertically.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateDepthCorrection(bool flipY)
{
return new Projection(
@@ -111,19 +178,44 @@ namespace Godot
);
}
- public static Projection CreateFitAabb(AABB aabb)
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that scales a given projection to fit around
+ /// a given <see cref="Aabb"/> in projection space.
+ /// </summary>
+ /// <param name="aabb">The Aabb to fit the projection around.</param>
+ /// <returns>The created projection.</returns>
+ public static Projection CreateFitAabb(Aabb aabb)
{
Vector3 min = aabb.Position;
Vector3 max = aabb.Position + aabb.Size;
return new Projection(
- new Vector4(2 / (max.x - min.x), 0, 0, 0),
- new Vector4(0, 2 / (max.y - min.y), 0, 0),
- new Vector4(0, 0, 2 / (max.z - min.z), 0),
- new Vector4(-(max.x + min.x) / (max.x - min.x), -(max.y + min.y) / (max.y - min.y), -(max.z + min.z) / (max.z - min.z), 1)
+ new Vector4(2 / (max.X - min.X), 0, 0, 0),
+ new Vector4(0, 2 / (max.Y - min.Y), 0, 0),
+ new Vector4(0, 0, 2 / (max.Z - min.Z), 0),
+ new Vector4(-(max.X + min.X) / (max.X - min.X), -(max.Y + min.Y) / (max.Y - min.Y), -(max.Z + min.Z) / (max.Z - min.Z), 1)
);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> for projecting positions onto a head-mounted display with
+ /// the given X:Y aspect ratio, distance between eyes, display width, distance to lens, oversampling factor,
+ /// and depth clipping planes.
+ /// <paramref name="eye"/> creates the projection for the left eye when set to 1,
+ /// or the right eye when set to 2.
+ /// </summary>
+ /// <param name="eye">
+ /// The eye to create the projection for.
+ /// The left eye when set to 1, the right eye when set to 2.
+ /// </param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="intraocularDist">The distance between the eyes.</param>
+ /// <param name="displayWidth">The display width.</param>
+ /// <param name="displayToLens">The distance to the lens.</param>
+ /// <param name="oversample">The oversampling factor.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateForHmd(int eye, real_t aspect, real_t intraocularDist, real_t displayWidth, real_t displayToLens, real_t oversample, real_t zNear, real_t zFar)
{
real_t f1 = (intraocularDist * (real_t)0.5) / displayToLens;
@@ -148,6 +240,17 @@ namespace Godot
}
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions in a frustum with
+ /// the given clipping planes.
+ /// </summary>
+ /// <param name="left">The left clipping distance.</param>
+ /// <param name="right">The right clipping distance.</param>
+ /// <param name="bottom">The bottom clipping distance.</param>
+ /// <param name="top">The top clipping distance.</param>
+ /// <param name="near">The near clipping distance.</param>
+ /// <param name="far">The far clipping distance.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t near, real_t far)
{
if (right <= left)
@@ -179,38 +282,77 @@ namespace Godot
);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions in a frustum with
+ /// the given size, X:Y aspect ratio, offset, and clipping planes.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="size">The frustum size.</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="offset">The offset to apply.</param>
+ /// <param name="near">The near clipping distance.</param>
+ /// <param name="far">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t near, real_t far, bool flipFov)
{
if (!flipFov)
{
size *= aspect;
}
- return CreateFrustum(-size / 2 + offset.x, +size / 2 + offset.x, -size / aspect / 2 + offset.y, +size / aspect / 2 + offset.y, near, far);
+ return CreateFrustum(-size / 2 + offset.X, +size / 2 + offset.X, -size / aspect / 2 + offset.Y, +size / aspect / 2 + offset.Y, near, far);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions into the given <see cref="Rect2"/>.
+ /// </summary>
+ /// <param name="rect">The Rect2 to project positions into.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateLightAtlasRect(Rect2 rect)
{
return new Projection(
- new Vector4(rect.Size.x, 0, 0, 0),
- new Vector4(0, rect.Size.y, 0, 0),
+ new Vector4(rect.Size.X, 0, 0, 0),
+ new Vector4(0, rect.Size.Y, 0, 0),
new Vector4(0, 0, 1, 0),
- new Vector4(rect.Position.x, rect.Position.y, 0, 1)
+ new Vector4(rect.Position.X, rect.Position.Y, 0, 1)
);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using an orthogonal projection with
+ /// the given clipping planes.
+ /// </summary>
+ /// <param name="left">The left clipping distance.</param>
+ /// <param name="right">The right clipping distance.</param>
+ /// <param name="bottom">The bottom clipping distance.</param>
+ /// <param name="top">The top clipping distance.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateOrthogonal(real_t left, real_t right, real_t bottom, real_t top, real_t zNear, real_t zFar)
{
Projection proj = Projection.Identity;
- proj.x.x = (real_t)2.0 / (right - left);
- proj.w.x = -((right + left) / (right - left));
- proj.y.y = (real_t)2.0 / (top - bottom);
- proj.w.y = -((top + bottom) / (top - bottom));
- proj.z.z = (real_t)(-2.0) / (zFar - zNear);
- proj.w.z = -((zFar + zNear) / (zFar - zNear));
- proj.w.w = (real_t)1.0;
+ proj.X.X = (real_t)2.0 / (right - left);
+ proj.W.X = -((right + left) / (right - left));
+ proj.Y.Y = (real_t)2.0 / (top - bottom);
+ proj.W.Y = -((top + bottom) / (top - bottom));
+ proj.Z.Z = (real_t)(-2.0) / (zFar - zNear);
+ proj.W.Z = -((zFar + zNear) / (zFar - zNear));
+ proj.W.W = (real_t)1.0;
return proj;
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using an orthogonal projection with
+ /// the given size, X:Y aspect ratio, and clipping planes.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="size">The frustum size.</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreateOrthogonalAspect(real_t size, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
{
if (!flipFov)
@@ -220,6 +362,17 @@ namespace Godot
return CreateOrthogonal(-size / 2, +size / 2, -size / aspect / 2, +size / aspect / 2, zNear, zFar);
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using a perspective projection with
+ /// the given Y-axis field of view (in degrees), X:Y aspect ratio, and clipping planes.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="fovyDegrees">The vertical field of view (in degrees).</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreatePerspective(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
{
if (flipFov)
@@ -228,27 +381,48 @@ namespace Godot
}
real_t radians = Mathf.DegToRad(fovyDegrees / (real_t)2.0);
real_t deltaZ = zFar - zNear;
- real_t sine = Mathf.Sin(radians);
+ (real_t sin, real_t cos) = Mathf.SinCos(radians);
- if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
+ if ((deltaZ == 0) || (sin == 0) || (aspect == 0))
{
return Zero;
}
- real_t cotangent = Mathf.Cos(radians) / sine;
+ real_t cotangent = cos / sin;
Projection proj = Projection.Identity;
- proj.x.x = cotangent / aspect;
- proj.y.y = cotangent;
- proj.z.z = -(zFar + zNear) / deltaZ;
- proj.z.w = -1;
- proj.w.z = -2 * zNear * zFar / deltaZ;
- proj.w.w = 0;
+ proj.X.X = cotangent / aspect;
+ proj.Y.Y = cotangent;
+ proj.Z.Z = -(zFar + zNear) / deltaZ;
+ proj.Z.W = -1;
+ proj.W.Z = -2 * zNear * zFar / deltaZ;
+ proj.W.W = 0;
return proj;
}
+ /// <summary>
+ /// Creates a new <see cref="Projection"/> that projects positions using a perspective projection with
+ /// the given Y-axis field of view (in degrees), X:Y aspect ratio, and clipping distances.
+ /// The projection is adjusted for a head-mounted display with the given distance between eyes and distance
+ /// to a point that can be focused on.
+ /// <paramref name="eye"/> creates the projection for the left eye when set to 1,
+ /// or the right eye when set to 2.
+ /// <paramref name="flipFov"/> determines whether the projection's field of view is flipped over its diagonal.
+ /// </summary>
+ /// <param name="fovyDegrees">The vertical field of view (in degrees).</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <param name="zNear">The near clipping distance.</param>
+ /// <param name="zFar">The far clipping distance.</param>
+ /// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
+ /// <param name="eye">
+ /// The eye to create the projection for.
+ /// The left eye when set to 1, the right eye when set to 2.
+ /// </param>
+ /// <param name="intraocularDist">The distance between the eyes.</param>
+ /// <param name="convergenceDist">The distance to a point of convergence that can be focused on.</param>
+ /// <returns>The created projection.</returns>
public static Projection CreatePerspectiveHmd(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov, int eye, real_t intraocularDist, real_t convergenceDist)
{
if (flipFov)
@@ -282,137 +456,217 @@ namespace Godot
}
Projection proj = CreateFrustum(left, right, -ymax, ymax, zNear, zFar);
Projection cm = Projection.Identity;
- cm.w.x = modeltranslation;
+ cm.W.X = modeltranslation;
return proj * cm;
}
- public real_t Determinant()
+ /// <summary>
+ /// Returns a scalar value that is the signed factor by which areas are scaled by this matrix.
+ /// If the sign is negative, the matrix flips the orientation of the area.
+ /// The determinant can be used to calculate the invertibility of a matrix or solve linear systems
+ /// of equations involving the matrix, among other applications.
+ /// </summary>
+ /// <returns>The determinant calculated from this projection.</returns>
+ 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 +
- x.z * y.y * z.w * w.x - x.y * y.z * z.w * w.x -
- x.w * y.z * z.x * w.y + x.z * y.w * z.x * w.y +
- x.w * y.x * z.z * w.y - x.x * y.w * z.z * w.y -
- x.z * y.x * z.w * w.y + x.x * y.z * z.w * w.y +
- x.w * y.y * z.x * w.z - x.y * y.w * z.x * w.z -
- x.w * y.x * z.y * w.z + x.x * y.w * z.y * w.z +
- x.y * y.x * z.w * w.z - x.x * y.y * z.w * w.z -
- x.z * y.y * z.x * w.w + x.y * y.z * z.x * w.w +
- x.z * y.x * z.y * w.w - x.x * y.z * z.y * w.w -
- x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w;
+ 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 +
+ X.Z * Y.Y * Z.W * W.X - X.Y * Y.Z * Z.W * W.X -
+ X.W * Y.Z * Z.X * W.Y + X.Z * Y.W * Z.X * W.Y +
+ X.W * Y.X * Z.Z * W.Y - X.X * Y.W * Z.Z * W.Y -
+ X.Z * Y.X * Z.W * W.Y + X.X * Y.Z * Z.W * W.Y +
+ X.W * Y.Y * Z.X * W.Z - X.Y * Y.W * Z.X * W.Z -
+ X.W * Y.X * Z.Y * W.Z + X.X * Y.W * Z.Y * W.Z +
+ X.Y * Y.X * Z.W * W.Z - X.X * Y.Y * Z.W * W.Z -
+ X.Z * Y.Y * Z.X * W.W + X.Y * Y.Z * Z.X * W.W +
+ X.Z * Y.X * Z.Y * W.W - X.X * Y.Z * Z.Y * W.W -
+ X.Y * Y.X * Z.Z * W.W + X.X * Y.Y * Z.Z * W.W;
}
- public real_t GetAspect()
+ /// <summary>
+ /// Returns the X:Y aspect ratio of this <see cref="Projection"/>'s viewport.
+ /// </summary>
+ /// <returns>The aspect ratio from this projection's viewport.</returns>
+ public readonly real_t GetAspect()
{
Vector2 vpHe = GetViewportHalfExtents();
- return vpHe.x / vpHe.y;
+ return vpHe.X / vpHe.Y;
}
- public real_t GetFov()
+ /// <summary>
+ /// Returns the horizontal field of view of the projection (in degrees).
+ /// </summary>
+ /// <returns>The horizontal field of view of this projection.</returns>
+ 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)
+ 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)
{
- return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0;
+ return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.X))) * (real_t)2.0;
}
else
{
- Plane leftPlane = new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x).Normalized();
- return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x)));
+ Plane leftPlane = new Plane(X.W + X.X, Y.W + Y.X, Z.W + Z.X, W.W + W.X).Normalized();
+ return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.X))) + Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.X)));
}
}
+ /// <summary>
+ /// Returns the vertical field of view of the projection (in degrees) associated with
+ /// the given horizontal field of view (in degrees) and aspect ratio.
+ /// </summary>
+ /// <param name="fovx">The horizontal field of view (in degrees).</param>
+ /// <param name="aspect">The aspect ratio.</param>
+ /// <returns>The vertical field of view of this projection.</returns>
public static real_t GetFovy(real_t fovx, real_t aspect)
{
return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0);
}
- public real_t GetLodMultiplier()
+ /// <summary>
+ /// Returns the factor by which the visible level of detail is scaled by this <see cref="Projection"/>.
+ /// </summary>
+ /// <returns>The level of detail factor for this projection.</returns>
+ public readonly real_t GetLodMultiplier()
{
if (IsOrthogonal())
{
- return GetViewportHalfExtents().x;
+ return GetViewportHalfExtents().X;
}
else
{
real_t zn = GetZNear();
- real_t width = GetViewportHalfExtents().x * (real_t)2.0;
+ real_t width = GetViewportHalfExtents().X * (real_t)2.0;
return (real_t)1.0 / (zn / width);
}
}
- public int GetPixelsPerMeter(int forPixelWidth)
+ /// <summary>
+ /// Returns the number of pixels with the given pixel width displayed per meter, after
+ /// this <see cref="Projection"/> is applied.
+ /// </summary>
+ /// <param name="forPixelWidth">The width for each pixel (in meters).</param>
+ /// <returns>The number of pixels per meter.</returns>
+ 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);
+ return (int)((result.X * (real_t)0.5 + (real_t)0.5) * forPixelWidth);
}
- public Plane GetProjectionPlane(Planes plane)
+ /// <summary>
+ /// Returns the clipping plane of this <see cref="Projection"/> whose index is given
+ /// by <paramref name="plane"/>.
+ /// <paramref name="plane"/> should be equal to one of <see cref="Planes.Near"/>,
+ /// <see cref="Planes.Far"/>, <see cref="Planes.Left"/>, <see cref="Planes.Top"/>,
+ /// <see cref="Planes.Right"/>, or <see cref="Planes.Bottom"/>.
+ /// </summary>
+ /// <param name="plane">The kind of clipping plane to get from the projection.</param>
+ /// <returns>The clipping plane of this projection.</returns>
+ public readonly Plane GetProjectionPlane(Planes plane)
{
Plane newPlane = plane switch
{
- Planes.Near => new Plane(x.w + x.z, y.w + y.z, z.w + z.z, w.w + w.z),
- Planes.Far => new Plane(x.w - x.z, y.w - y.z, z.w - z.z, w.w - w.z),
- Planes.Left => new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x),
- Planes.Top => new Plane(x.w - x.y, y.w - y.y, z.w - z.y, w.w - w.y),
- Planes.Right => new Plane(x.w - x.x, y.w - y.x, z.w - z.x, w.w - w.x),
- Planes.Bottom => new Plane(x.w + x.y, y.w + y.y, z.w + z.y, w.w + w.y),
+ Planes.Near => new Plane(X.W + X.Z, Y.W + Y.Z, Z.W + Z.Z, W.W + W.Z),
+ Planes.Far => new Plane(X.W - X.Z, Y.W - Y.Z, Z.W - Z.Z, W.W - W.Z),
+ Planes.Left => new Plane(X.W + X.X, Y.W + Y.X, Z.W + Z.X, W.W + W.X),
+ Planes.Top => new Plane(X.W - X.Y, Y.W - Y.Y, Z.W - Z.Y, W.W - W.Y),
+ Planes.Right => new Plane(X.W - X.X, Y.W - Y.X, Z.W - Z.X, W.W - W.X),
+ Planes.Bottom => new Plane(X.W + X.Y, Y.W + Y.Y, Z.W + Z.Y, W.W + W.Y),
_ => new Plane(),
};
newPlane.Normal = -newPlane.Normal;
return newPlane.Normalized();
}
- public Vector2 GetFarPlaneHalfExtents()
+ /// <summary>
+ /// Returns the dimensions of the far clipping plane of the projection, divided by two.
+ /// </summary>
+ /// <returns>The half extents for this projection's far plane.</returns>
+ 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);
+ return new Vector2(res.Value.X, res.Value.Y);
}
- public Vector2 GetViewportHalfExtents()
+ /// <summary>
+ /// Returns the dimensions of the viewport plane that this <see cref="Projection"/>
+ /// projects positions onto, divided by two.
+ /// </summary>
+ /// <returns>The half extents for this projection's viewport plane.</returns>
+ 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);
+ return new Vector2(res.Value.X, res.Value.Y);
}
- public real_t GetZFar()
+ /// <summary>
+ /// Returns the distance for this <see cref="Projection"/> beyond which positions are clipped.
+ /// </summary>
+ /// <returns>The distance beyond which positions are clipped.</returns>
+ public readonly real_t GetZFar()
{
return GetProjectionPlane(Planes.Far).D;
}
- public real_t GetZNear()
+ /// <summary>
+ /// Returns the distance for this <see cref="Projection"/> before which positions are clipped.
+ /// </summary>
+ /// <returns>The distance before which positions are clipped.</returns>
+ public readonly real_t GetZNear()
{
return -GetProjectionPlane(Planes.Near).D;
}
- public Projection FlippedY()
+ /// <summary>
+ /// Returns a copy of this <see cref="Projection"/> with the signs of the values of the Y column flipped.
+ /// </summary>
+ /// <returns>The flipped projection.</returns>
+ public readonly Projection FlippedY()
{
Projection proj = this;
- proj.y = -proj.y;
+ proj.Y = -proj.Y;
return proj;
}
- public Projection PerspectiveZNearAdjusted(real_t newZNear)
+ /// <summary>
+ /// Returns a <see cref="Projection"/> with the near clipping distance adjusted to be
+ /// <paramref name="newZNear"/>.
+ /// Note: The original <see cref="Projection"/> must be a perspective projection.
+ /// </summary>
+ /// <param name="newZNear">The near clipping distance to adjust the projection to.</param>
+ /// <returns>The adjusted projection.</returns>
+ public readonly Projection PerspectiveZNearAdjusted(real_t newZNear)
{
Projection proj = this;
real_t zFar = GetZFar();
real_t zNear = newZNear;
real_t deltaZ = zFar - zNear;
- proj.z.z = -(zFar + zNear) / deltaZ;
- proj.w.z = -2 * zNear * zFar / deltaZ;
+ proj.Z.Z = -(zFar + zNear) / deltaZ;
+ proj.W.Z = -2 * zNear * zFar / deltaZ;
return proj;
}
- public Projection JitterOffseted(Vector2 offset)
+ /// <summary>
+ /// Returns a <see cref="Projection"/> with the X and Y values from the given <see cref="Vector2"/>
+ /// added to the first and second values of the final column respectively.
+ /// </summary>
+ /// <param name="offset">The offset to apply to the projection.</param>
+ /// <returns>The offsetted projection.</returns>
+ public readonly Projection JitterOffseted(Vector2 offset)
{
Projection proj = this;
- proj.w.x += offset.x;
- proj.w.y += offset.y;
+ proj.W.X += offset.X;
+ proj.W.Y += offset.Y;
return proj;
}
- public Projection Inverse()
+ /// <summary>
+ /// Returns a <see cref="Projection"/> that performs the inverse of this <see cref="Projection"/>'s
+ /// projective transformation.
+ /// </summary>
+ /// <returns>The inverted projection.</returns>
+ public readonly Projection Inverse()
{
Projection proj = this;
int i, j, k;
@@ -535,9 +789,68 @@ namespace Godot
return proj;
}
- public bool IsOrthogonal()
+ /// <summary>
+ /// Returns <see langword="true"/> if this <see cref="Projection"/> performs an orthogonal projection.
+ /// </summary>
+ /// <returns>If the projection performs an orthogonal projection.</returns>
+ public readonly bool IsOrthogonal()
+ {
+ return W.W == (real_t)1.0;
+ }
+
+ // Constants
+ private static readonly Projection _zero = new Projection(
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0)
+ );
+ private static readonly Projection _identity = new Projection(
+ new Vector4(1, 0, 0, 0),
+ new Vector4(0, 1, 0, 0),
+ new Vector4(0, 0, 1, 0),
+ new Vector4(0, 0, 0, 1)
+ );
+
+ /// <summary>
+ /// Zero projection, a projection with all components set to <c>0</c>.
+ /// </summary>
+ /// <value>Equivalent to <c>new Projection(Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero)</c>.</value>
+ public static Projection Zero { get { return _zero; } }
+
+ /// <summary>
+ /// The identity projection, with no distortion applied.
+ /// This is used as a replacement for <c>Projection()</c> in GDScript.
+ /// Do not use <c>new Projection()</c> with no arguments in C#, because it sets all values to zero.
+ /// </summary>
+ /// <value>Equivalent to <c>new Projection(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1))</c>.</value>
+ public static Projection Identity { get { return _identity; } }
+
+ /// <summary>
+ /// Constructs a projection from 4 vectors (matrix columns).
+ /// </summary>
+ /// <param name="x">The X column, or column index 0.</param>
+ /// <param name="y">The Y column, or column index 1.</param>
+ /// <param name="z">The Z column, or column index 2.</param>
+ /// <param name="w">The W column, or column index 3.</param>
+ public Projection(Vector4 x, Vector4 y, Vector4 z, Vector4 w)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Projection"/> from a <see cref="Transform3D"/>.
+ /// </summary>
+ /// <param name="transform">The <see cref="Transform3D"/>.</param>
+ public Projection(Transform3D transform)
{
- return w.w == (real_t)1.0;
+ X = new Vector4(transform.Basis.Row0.X, transform.Basis.Row1.X, transform.Basis.Row2.X, 0);
+ Y = new Vector4(transform.Basis.Row0.Y, transform.Basis.Row1.Y, transform.Basis.Row2.Y, 0);
+ Z = new Vector4(transform.Basis.Row0.Z, transform.Basis.Row1.Z, transform.Basis.Row2.Z, 0);
+ W = new Vector4(transform.Origin.X, transform.Origin.Y, transform.Origin.Z, 1);
}
/// <summary>
@@ -552,25 +865,25 @@ namespace Godot
{
return new Projection(
new Vector4(
- left.x.x * right.x.x + left.y.x * right.x.y + left.z.x * right.x.z + left.w.x * right.x.w,
- left.x.y * right.x.x + left.y.y * right.x.y + left.z.y * right.x.z + left.w.y * right.x.w,
- left.x.z * right.x.x + left.y.z * right.x.y + left.z.z * right.x.z + left.w.z * right.x.w,
- left.x.w * right.x.x + left.y.w * right.x.y + left.z.w * right.x.z + left.w.w * right.x.w
+ left.X.X * right.X.X + left.Y.X * right.X.Y + left.Z.X * right.X.Z + left.W.X * right.X.W,
+ left.X.Y * right.X.X + left.Y.Y * right.X.Y + left.Z.Y * right.X.Z + left.W.Y * right.X.W,
+ left.X.Z * right.X.X + left.Y.Z * right.X.Y + left.Z.Z * right.X.Z + left.W.Z * right.X.W,
+ left.X.W * right.X.X + left.Y.W * right.X.Y + left.Z.W * right.X.Z + left.W.W * right.X.W
), new Vector4(
- left.x.x * right.y.x + left.y.x * right.y.y + left.z.x * right.y.z + left.w.x * right.y.w,
- left.x.y * right.y.x + left.y.y * right.y.y + left.z.y * right.y.z + left.w.y * right.y.w,
- left.x.z * right.y.x + left.y.z * right.y.y + left.z.z * right.y.z + left.w.z * right.y.w,
- left.x.w * right.y.x + left.y.w * right.y.y + left.z.w * right.y.z + left.w.w * right.y.w
+ left.X.X * right.Y.X + left.Y.X * right.Y.Y + left.Z.X * right.Y.Z + left.W.X * right.Y.W,
+ left.X.Y * right.Y.X + left.Y.Y * right.Y.Y + left.Z.Y * right.Y.Z + left.W.Y * right.Y.W,
+ left.X.Z * right.Y.X + left.Y.Z * right.Y.Y + left.Z.Z * right.Y.Z + left.W.Z * right.Y.W,
+ left.X.W * right.Y.X + left.Y.W * right.Y.Y + left.Z.W * right.Y.Z + left.W.W * right.Y.W
), new Vector4(
- left.x.x * right.z.x + left.y.x * right.z.y + left.z.x * right.z.z + left.w.x * right.z.w,
- left.x.y * right.z.x + left.y.y * right.z.y + left.z.y * right.z.z + left.w.y * right.z.w,
- left.x.z * right.z.x + left.y.z * right.z.y + left.z.z * right.z.z + left.w.z * right.z.w,
- left.x.w * right.z.x + left.y.w * right.z.y + left.z.w * right.z.z + left.w.w * right.z.w
+ left.X.X * right.Z.X + left.Y.X * right.Z.Y + left.Z.X * right.Z.Z + left.W.X * right.Z.W,
+ left.X.Y * right.Z.X + left.Y.Y * right.Z.Y + left.Z.Y * right.Z.Z + left.W.Y * right.Z.W,
+ left.X.Z * right.Z.X + left.Y.Z * right.Z.Y + left.Z.Z * right.Z.Z + left.W.Z * right.Z.W,
+ left.X.W * right.Z.X + left.Y.W * right.Z.Y + left.Z.W * right.Z.Z + left.W.W * right.Z.W
), new Vector4(
- left.x.x * right.w.x + left.y.x * right.w.y + left.z.x * right.w.z + left.w.x * right.w.w,
- left.x.y * right.w.x + left.y.y * right.w.y + left.z.y * right.w.z + left.w.y * right.w.w,
- left.x.z * right.w.x + left.y.z * right.w.y + left.z.z * right.w.z + left.w.z * right.w.w,
- left.x.w * right.w.x + left.y.w * right.w.y + left.z.w * right.w.z + left.w.w * right.w.w
+ left.X.X * right.W.X + left.Y.X * right.W.Y + left.Z.X * right.W.Z + left.W.X * right.W.W,
+ left.X.Y * right.W.X + left.Y.Y * right.W.Y + left.Z.Y * right.W.Z + left.W.Y * right.W.W,
+ left.X.Z * right.W.X + left.Y.Z * right.W.Y + left.Z.Z * right.W.Z + left.W.Z * right.W.W,
+ left.X.W * right.W.X + left.Y.W * right.W.Y + left.Z.W * right.W.Z + left.W.W * right.W.W
)
);
}
@@ -584,10 +897,10 @@ namespace Godot
public static Vector4 operator *(Projection proj, Vector4 vector)
{
return new Vector4(
- proj.x.x * vector.x + proj.y.x * vector.y + proj.z.x * vector.z + proj.w.x * vector.w,
- proj.x.y * vector.x + proj.y.y * vector.y + proj.z.y * vector.z + proj.w.y * vector.w,
- proj.x.z * vector.x + proj.y.z * vector.y + proj.z.z * vector.z + proj.w.z * vector.w,
- proj.x.w * vector.x + proj.y.w * vector.y + proj.z.w * vector.z + proj.w.w * vector.w
+ proj.X.X * vector.X + proj.Y.X * vector.Y + proj.Z.X * vector.Z + proj.W.X * vector.W,
+ proj.X.Y * vector.X + proj.Y.Y * vector.Y + proj.Z.Y * vector.Z + proj.W.Y * vector.W,
+ proj.X.Z * vector.X + proj.Y.Z * vector.Y + proj.Z.Z * vector.Z + proj.W.Z * vector.W,
+ proj.X.W * vector.X + proj.Y.W * vector.Y + proj.Z.W * vector.Z + proj.W.W * vector.W
);
}
@@ -600,10 +913,10 @@ namespace Godot
public static Vector4 operator *(Vector4 vector, Projection proj)
{
return new Vector4(
- proj.x.x * vector.x + proj.x.y * vector.y + proj.x.z * vector.z + proj.x.w * vector.w,
- proj.y.x * vector.x + proj.y.y * vector.y + proj.y.z * vector.z + proj.y.w * vector.w,
- proj.z.x * vector.x + proj.z.y * vector.y + proj.z.z * vector.z + proj.z.w * vector.w,
- proj.w.x * vector.x + proj.w.y * vector.y + proj.w.z * vector.z + proj.w.w * vector.w
+ proj.X.X * vector.X + proj.X.Y * vector.Y + proj.X.Z * vector.Z + proj.X.W * vector.W,
+ proj.Y.X * vector.X + proj.Y.Y * vector.Y + proj.Y.Z * vector.Z + proj.Y.W * vector.W,
+ proj.Z.X * vector.X + proj.Z.Y * vector.Y + proj.Z.Z * vector.Z + proj.Z.W * vector.W,
+ proj.W.X * vector.X + proj.W.Y * vector.Y + proj.W.Z * vector.Z + proj.W.W * vector.W
);
}
@@ -616,11 +929,11 @@ namespace Godot
public static Vector3 operator *(Projection proj, Vector3 vector)
{
Vector3 ret = new Vector3(
- proj.x.x * vector.x + proj.y.x * vector.y + proj.z.x * vector.z + proj.w.x,
- proj.x.y * vector.x + proj.y.y * vector.y + proj.z.y * vector.z + proj.w.y,
- proj.x.z * vector.x + proj.y.z * vector.y + proj.z.z * vector.z + proj.w.z
+ proj.X.X * vector.X + proj.Y.X * vector.Y + proj.Z.X * vector.Z + proj.W.X,
+ proj.X.Y * vector.X + proj.Y.Y * vector.Y + proj.Z.Y * vector.Z + proj.W.Y,
+ proj.X.Z * vector.X + proj.Y.Z * vector.Y + proj.Z.Z * vector.Z + proj.W.Z
);
- return ret / (proj.x.w * vector.x + proj.y.w * vector.y + proj.z.w * vector.z + proj.w.w);
+ return ret / (proj.X.W * vector.X + proj.Y.W * vector.Y + proj.Z.W * vector.Z + proj.W.W);
}
/// <summary>
@@ -646,177 +959,70 @@ namespace Godot
}
/// <summary>
- /// Access whole columns in the form of <see cref="Vector4"/>.
+ /// Constructs a new <see cref="Transform3D"/> from the <see cref="Projection"/>.
/// </summary>
- /// <param name="column">Which column vector.</param>
- /// <exception cref="ArgumentOutOfRangeException">
- /// <paramref name="column"/> is not 0, 1, 2 or 3.
- /// </exception>
- public Vector4 this[int column]
+ /// <param name="proj">The <see cref="Projection"/>.</param>
+ public static explicit operator Transform3D(Projection proj)
{
- get
- {
- switch (column)
- {
- case 0:
- return x;
- case 1:
- return y;
- case 2:
- return z;
- case 3:
- return w;
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
- set
- {
- switch (column)
- {
- case 0:
- x = value;
- return;
- case 1:
- y = value;
- return;
- case 2:
- z = value;
- return;
- case 3:
- w = value;
- return;
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
+ return new Transform3D(
+ new Basis(
+ new Vector3(proj.X.X, proj.X.Y, proj.X.Z),
+ new Vector3(proj.Y.X, proj.Y.Y, proj.Y.Z),
+ new Vector3(proj.Z.X, proj.Z.Y, proj.Z.Z)
+ ),
+ new Vector3(proj.W.X, proj.W.Y, proj.W.Z)
+ );
}
/// <summary>
- /// Access single values.
+ /// Returns <see langword="true"/> if the projection is exactly equal
+ /// to the given object (<see paramref="obj"/>).
/// </summary>
- /// <param name="column">Which column vector.</param>
- /// <param name="row">Which row of the column.</param>
- /// <exception cref="ArgumentOutOfRangeException">
- /// <paramref name="column"/> or <paramref name="row"/> are not 0, 1, 2 or 3.
- /// </exception>
- public real_t this[int column, int row]
+ /// <param name="obj">The object to compare with.</param>
+ /// <returns>Whether or not the vector and the object are equal.</returns>
+ public override readonly bool Equals(object obj)
{
- get
- {
- switch (column)
- {
- case 0:
- return x[row];
- case 1:
- return y[row];
- case 2:
- return z[row];
- case 3:
- return w[row];
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
- set
- {
- switch (column)
- {
- case 0:
- x[row] = value;
- return;
- case 1:
- y[row] = value;
- return;
- case 2:
- z[row] = value;
- return;
- case 3:
- w[row] = value;
- return;
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
+ return obj is Projection other && Equals(other);
}
- // Constants
- private static readonly Projection _zero = new Projection(
- new Vector4(0, 0, 0, 0),
- new Vector4(0, 0, 0, 0),
- new Vector4(0, 0, 0, 0),
- new Vector4(0, 0, 0, 0)
- );
- private static readonly Projection _identity = new Projection(
- new Vector4(1, 0, 0, 0),
- new Vector4(0, 1, 0, 0),
- new Vector4(0, 0, 1, 0),
- new Vector4(0, 0, 0, 1)
- );
-
- /// <summary>
- /// Zero projection, a projection with all components set to <c>0</c>.
- /// </summary>
- /// <value>Equivalent to <c>new Projection(Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero)</c>.</value>
- public static Projection Zero { get { return _zero; } }
-
/// <summary>
- /// The identity projection, with no distortion applied.
- /// This is used as a replacement for <c>Projection()</c> in GDScript.
- /// Do not use <c>new Projection()</c> with no arguments in C#, because it sets all values to zero.
+ /// Returns <see langword="true"/> if the projections are exactly equal.
/// </summary>
- /// <value>Equivalent to <c>new Projection(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1))</c>.</value>
- public static Projection Identity { get { return _identity; } }
+ /// <param name="other">The other projection.</param>
+ /// <returns>Whether or not the projections are exactly equal.</returns>
+ public readonly bool Equals(Projection other)
+ {
+ return X == other.X && Y == other.Y && Z == other.Z && W == other.W;
+ }
/// <summary>
/// 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();
+ return Y.GetHashCode() ^ X.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
}
/// <summary>
/// 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";
+ 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";
}
/// <summary>
/// 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)
- {
- 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" +
- $"{z.x.ToString(format)}, {z.y.ToString(format)}, {z.z.ToString(format)}, {z.w.ToString(format)}\n" +
- $"{w.x.ToString(format)}, {w.y.ToString(format)}, {w.z.ToString(format)}, {w.w.ToString(format)}\n";
- }
-
- /// <summary>
- /// Returns <see langword="true"/> if the projection is exactly equal
- /// to the given object (<see paramref="obj"/>).
- /// </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)
- {
- return obj is Projection other && Equals(other);
- }
-
- /// <summary>
- /// Returns <see langword="true"/> if the projections are exactly equal.
- /// </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 string ToString(string format)
{
- return x == other.x && y == other.y && z == other.z && w == other.w;
+ 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" +
+ $"{Z.X.ToString(format)}, {Z.Y.ToString(format)}, {Z.Z.ToString(format)}, {Z.W.ToString(format)}\n" +
+ $"{W.X.ToString(format)}, {W.Y.ToString(format)}, {W.Z.ToString(format)}, {W.W.ToString(format)}\n";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
index f01f0be985..9c2a6fc654 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -24,25 +24,25 @@ namespace Godot
/// X component of the quaternion (imaginary <c>i</c> axis part).
/// Quaternion components should usually not be manipulated directly.
/// </summary>
- public real_t x;
+ public real_t X;
/// <summary>
/// Y component of the quaternion (imaginary <c>j</c> axis part).
/// Quaternion components should usually not be manipulated directly.
/// </summary>
- public real_t y;
+ public real_t Y;
/// <summary>
/// Z component of the quaternion (imaginary <c>k</c> axis part).
/// Quaternion components should usually not be manipulated directly.
/// </summary>
- public real_t z;
+ public real_t Z;
/// <summary>
/// W component of the quaternion (real part).
/// Quaternion components should usually not be manipulated directly.
/// </summary>
- public real_t w;
+ public real_t W;
/// <summary>
/// Access quaternion components using their index.
@@ -51,25 +51,25 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1, 2 or 3.
/// </exception>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="x"/>,
- /// <c>[1]</c> is equivalent to <see cref="y"/>,
- /// <c>[2]</c> is equivalent to <see cref="z"/>,
- /// <c>[3]</c> is equivalent to <see cref="w"/>.
+ /// <c>[0]</c> is equivalent to <see cref="X"/>,
+ /// <c>[1]</c> is equivalent to <see cref="Y"/>,
+ /// <c>[2]</c> is equivalent to <see cref="Z"/>,
+ /// <c>[3]</c> is equivalent to <see cref="W"/>.
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
case 2:
- return z;
+ return Z;
case 3:
- return w;
+ return W;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -79,16 +79,16 @@ namespace Godot
switch (index)
{
case 0:
- x = value;
+ X = value;
break;
case 1:
- y = value;
+ Y = value;
break;
case 2:
- z = value;
+ Z = value;
break;
case 3:
- w = value;
+ W = value;
break;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -97,27 +97,6 @@ namespace Godot
}
/// <summary>
- /// Returns the length (magnitude) of the quaternion.
- /// </summary>
- /// <seealso cref="LengthSquared"/>
- /// <value>Equivalent to <c>Mathf.Sqrt(LengthSquared)</c>.</value>
- public real_t Length
- {
- get { return Mathf.Sqrt(LengthSquared); }
- }
-
- /// <summary>
- /// Returns the squared length (squared magnitude) of the quaternion.
- /// This method runs faster than <see cref="Length"/>, so prefer it if
- /// 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
- {
- get { return Dot(this); }
- }
-
- /// <summary>
/// Returns the angle between this quaternion and <paramref name="to"/>.
/// This is the magnitude of the angle you would need to rotate
/// by to get from one to the other.
@@ -128,7 +107,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 +122,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())
@@ -176,9 +155,9 @@ namespace Godot
Quaternion lnPre = (fromQ.Inverse() * preQ).Log();
Quaternion lnPost = (fromQ.Inverse() * postQ).Log();
Quaternion ln = new Quaternion(
- Mathf.CubicInterpolate(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight),
- Mathf.CubicInterpolate(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight),
- Mathf.CubicInterpolate(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight),
+ Mathf.CubicInterpolate(lnFrom.X, lnTo.X, lnPre.X, lnPost.X, weight),
+ Mathf.CubicInterpolate(lnFrom.Y, lnTo.Y, lnPre.Y, lnPost.Y, weight),
+ Mathf.CubicInterpolate(lnFrom.Z, lnTo.Z, lnPre.Z, lnPost.Z, weight),
0);
Quaternion q1 = fromQ * ln.Exp();
@@ -188,13 +167,13 @@ namespace Godot
lnPre = (toQ.Inverse() * preQ).Log();
lnPost = (toQ.Inverse() * postQ).Log();
ln = new Quaternion(
- Mathf.CubicInterpolate(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight),
- Mathf.CubicInterpolate(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight),
- Mathf.CubicInterpolate(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight),
+ Mathf.CubicInterpolate(lnFrom.X, lnTo.X, lnPre.X, lnPost.X, weight),
+ Mathf.CubicInterpolate(lnFrom.Y, lnTo.Y, lnPre.Y, lnPost.Y, weight),
+ Mathf.CubicInterpolate(lnFrom.Z, lnTo.Z, lnPre.Z, lnPost.Z, weight),
0);
Quaternion q2 = toQ * ln.Exp();
- // To cancel error made by Expmap ambiguity, do blends.
+ // To cancel error made by Expmap ambiguity, do blending.
return q1.Slerp(q2, weight);
}
@@ -212,7 +191,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())
@@ -245,9 +224,9 @@ namespace Godot
Quaternion lnPre = (fromQ.Inverse() * preQ).Log();
Quaternion lnPost = (fromQ.Inverse() * postQ).Log();
Quaternion ln = new Quaternion(
- Mathf.CubicInterpolateInTime(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight, bT, preAT, postBT),
- Mathf.CubicInterpolateInTime(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight, bT, preAT, postBT),
- Mathf.CubicInterpolateInTime(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight, bT, preAT, postBT),
+ Mathf.CubicInterpolateInTime(lnFrom.X, lnTo.X, lnPre.X, lnPost.X, weight, bT, preAT, postBT),
+ Mathf.CubicInterpolateInTime(lnFrom.Y, lnTo.Y, lnPre.Y, lnPost.Y, weight, bT, preAT, postBT),
+ Mathf.CubicInterpolateInTime(lnFrom.Z, lnTo.Z, lnPre.Z, lnPost.Z, weight, bT, preAT, postBT),
0);
Quaternion q1 = fromQ * ln.Exp();
@@ -257,13 +236,13 @@ namespace Godot
lnPre = (toQ.Inverse() * preQ).Log();
lnPost = (toQ.Inverse() * postQ).Log();
ln = new Quaternion(
- Mathf.CubicInterpolateInTime(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight, bT, preAT, postBT),
- Mathf.CubicInterpolateInTime(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight, bT, preAT, postBT),
- Mathf.CubicInterpolateInTime(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight, bT, preAT, postBT),
+ Mathf.CubicInterpolateInTime(lnFrom.X, lnTo.X, lnPre.X, lnPost.X, weight, bT, preAT, postBT),
+ Mathf.CubicInterpolateInTime(lnFrom.Y, lnTo.Y, lnPre.Y, lnPost.Y, weight, bT, preAT, postBT),
+ Mathf.CubicInterpolateInTime(lnFrom.Z, lnTo.Z, lnPre.Z, lnPost.Z, weight, bT, preAT, postBT),
0);
Quaternion q2 = toQ * ln.Exp();
- // To cancel error made by Expmap ambiguity, do blends.
+ // To cancel error made by Expmap ambiguity, do blending.
return q1.Slerp(q2, weight);
}
@@ -272,14 +251,14 @@ 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);
+ 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);
+ Vector3 v = new Vector3(X, Y, Z);
real_t theta = v.Length();
v = v.Normalized();
if (theta < Mathf.Epsilon || !v.IsNormalized())
@@ -289,20 +268,20 @@ namespace Godot
return new Quaternion(v, theta);
}
- public real_t GetAngle()
+ public readonly real_t GetAngle()
{
- return 2 * Mathf.Acos(w);
+ return 2 * Mathf.Acos(W);
}
- public Vector3 GetAxis()
+ public readonly Vector3 GetAxis()
{
- if (Mathf.Abs(w) > 1 - Mathf.Epsilon)
+ if (Mathf.Abs(W) > 1 - Mathf.Epsilon)
{
- return new Vector3(x, y, z);
+ return new Vector3(X, Y, Z);
}
- real_t r = 1 / Mathf.Sqrt(1 - w * w);
- return new Vector3(x * r, y * r, z * r);
+ real_t r = 1 / Mathf.Sqrt(1 - W * W);
+ return new Vector3(X * r, Y * r, Z * r);
}
/// <summary>
@@ -312,7 +291,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 +307,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())
@@ -336,31 +315,62 @@ namespace Godot
throw new InvalidOperationException("Quaternion is not normalized.");
}
#endif
- return new Quaternion(-x, -y, -z, w);
+ return new Quaternion(-X, -Y, -Z, W);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this quaternion is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return Mathf.IsFinite(X) && Mathf.IsFinite(Y) && Mathf.IsFinite(Z) && Mathf.IsFinite(W);
}
/// <summary>
/// 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;
+ 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);
+ return new Quaternion(v.X, v.Y, v.Z, 0);
+ }
+
+ /// <summary>
+ /// Returns the length (magnitude) of the quaternion.
+ /// </summary>
+ /// <seealso cref="LengthSquared"/>
+ /// <value>Equivalent to <c>Mathf.Sqrt(LengthSquared)</c>.</value>
+ public readonly real_t Length()
+ {
+ return Mathf.Sqrt(LengthSquared());
+ }
+
+ /// <summary>
+ /// Returns the squared length (squared magnitude) of the quaternion.
+ /// This method runs faster than <see cref="Length"/>, so prefer it if
+ /// you need to compare quaternions or need the squared length for some formula.
+ /// </summary>
+ /// <value>Equivalent to <c>Dot(this)</c>.</value>
+ public readonly real_t LengthSquared()
+ {
+ return Dot(this);
}
/// <summary>
/// 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;
+ return this / Length();
}
/// <summary>
@@ -372,7 +382,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())
@@ -422,10 +432,10 @@ namespace Godot
// Calculate final values.
return new Quaternion
(
- (scale0 * x) + (scale1 * to1.x),
- (scale0 * y) + (scale1 * to1.y),
- (scale0 * z) + (scale1 * to1.z),
- (scale0 * w) + (scale1 * to1.w)
+ (scale0 * X) + (scale1 * to1.X),
+ (scale0 * Y) + (scale1 * to1.Y),
+ (scale0 * Z) + (scale1 * to1.Z),
+ (scale0 * W) + (scale1 * to1.W)
);
}
@@ -437,7 +447,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())
@@ -464,10 +474,10 @@ namespace Godot
return new Quaternion
(
- (invFactor * x) + (newFactor * to.x),
- (invFactor * y) + (newFactor * to.y),
- (invFactor * z) + (newFactor * to.z),
- (invFactor * w) + (newFactor * to.w)
+ (invFactor * X) + (newFactor * to.X),
+ (invFactor * Y) + (newFactor * to.Y),
+ (invFactor * Z) + (newFactor * to.Z),
+ (invFactor * W) + (newFactor * to.W)
);
}
@@ -491,10 +501,10 @@ namespace Godot
/// <param name="w">W component of the quaternion (real part).</param>
public Quaternion(real_t x, real_t y, real_t z, real_t w)
{
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
}
/// <summary>
@@ -525,21 +535,20 @@ namespace Godot
if (d == 0f)
{
- x = 0f;
- y = 0f;
- z = 0f;
- w = 0f;
+ X = 0f;
+ Y = 0f;
+ Z = 0f;
+ W = 0f;
}
else
{
- real_t sinAngle = Mathf.Sin(angle * 0.5f);
- real_t cosAngle = Mathf.Cos(angle * 0.5f);
- real_t s = sinAngle / d;
-
- x = axis.x * s;
- y = axis.y * s;
- z = axis.z * s;
- w = cosAngle;
+ (real_t sin, real_t cos) = Mathf.SinCos(angle * 0.5f);
+ real_t s = sin / d;
+
+ X = axis.X * s;
+ Y = axis.Y * s;
+ Z = axis.Z * s;
+ W = cos;
}
}
@@ -550,20 +559,20 @@ namespace Godot
if (d < -1.0f + Mathf.Epsilon)
{
- x = 0f;
- y = 1f;
- z = 0f;
- w = 0f;
+ X = 0f;
+ Y = 1f;
+ Z = 0f;
+ W = 0f;
}
else
{
real_t s = Mathf.Sqrt((1.0f + d) * 2.0f);
real_t rs = 1.0f / s;
- x = c.x * rs;
- y = c.y * rs;
- z = c.z * rs;
- w = s * 0.5f;
+ X = c.X * rs;
+ Y = c.Y * rs;
+ Z = c.Z * rs;
+ W = s * 0.5f;
}
}
@@ -575,20 +584,17 @@ namespace Godot
/// <param name="eulerYXZ">Euler angles that the quaternion will be rotated by.</param>
public static Quaternion FromEuler(Vector3 eulerYXZ)
{
- real_t halfA1 = eulerYXZ.y * 0.5f;
- real_t halfA2 = eulerYXZ.x * 0.5f;
- real_t halfA3 = eulerYXZ.z * 0.5f;
+ real_t halfA1 = eulerYXZ.Y * 0.5f;
+ real_t halfA2 = eulerYXZ.X * 0.5f;
+ real_t halfA3 = eulerYXZ.Z * 0.5f;
// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
// a3 is the angle of the first rotation, following the notation in this reference.
- real_t cosA1 = Mathf.Cos(halfA1);
- real_t sinA1 = Mathf.Sin(halfA1);
- real_t cosA2 = Mathf.Cos(halfA2);
- real_t sinA2 = Mathf.Sin(halfA2);
- real_t cosA3 = Mathf.Cos(halfA3);
- real_t sinA3 = Mathf.Sin(halfA3);
+ (real_t sinA1, real_t cosA1) = Mathf.SinCos(halfA1);
+ (real_t sinA2, real_t cosA2) = Mathf.SinCos(halfA2);
+ (real_t sinA3, real_t cosA3) = Mathf.SinCos(halfA3);
return new Quaternion(
(sinA1 * cosA2 * sinA3) + (cosA1 * sinA2 * cosA3),
@@ -610,10 +616,10 @@ namespace Godot
{
return new Quaternion
(
- (left.w * right.x) + (left.x * right.w) + (left.y * right.z) - (left.z * right.y),
- (left.w * right.y) + (left.y * right.w) + (left.z * right.x) - (left.x * right.z),
- (left.w * right.z) + (left.z * right.w) + (left.x * right.y) - (left.y * right.x),
- (left.w * right.w) - (left.x * right.x) - (left.y * right.y) - (left.z * right.z)
+ (left.W * right.X) + (left.X * right.W) + (left.Y * right.Z) - (left.Z * right.Y),
+ (left.W * right.Y) + (left.Y * right.W) + (left.Z * right.X) - (left.X * right.Z),
+ (left.W * right.Z) + (left.Z * right.W) + (left.X * right.Y) - (left.Y * right.X),
+ (left.W * right.W) - (left.X * right.X) - (left.Y * right.Y) - (left.Z * right.Z)
);
}
@@ -631,9 +637,9 @@ namespace Godot
throw new InvalidOperationException("Quaternion is not normalized.");
}
#endif
- var u = new Vector3(quaternion.x, quaternion.y, quaternion.z);
+ var u = new Vector3(quaternion.X, quaternion.Y, quaternion.Z);
Vector3 uv = u.Cross(vector);
- return vector + (((uv * quaternion.w) + u.Cross(uv)) * 2);
+ return vector + (((uv * quaternion.W) + u.Cross(uv)) * 2);
}
/// <summary>
@@ -659,7 +665,7 @@ namespace Godot
/// <returns>The added quaternion.</returns>
public static Quaternion operator +(Quaternion left, Quaternion right)
{
- return new Quaternion(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);
+ return new Quaternion(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
@@ -673,20 +679,20 @@ namespace Godot
/// <returns>The subtracted quaternion.</returns>
public static Quaternion operator -(Quaternion left, Quaternion right)
{
- return new Quaternion(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);
+ return new Quaternion(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Returns the negative value of the <see cref="Quaternion"/>.
/// This is the same as writing
- /// <c>new Quaternion(-q.x, -q.y, -q.z, -q.w)</c>. This operation
+ /// <c>new Quaternion(-q.X, -q.Y, -q.Z, -q.W)</c>. This operation
/// results in a quaternion that represents the same rotation.
/// </summary>
/// <param name="quat">The quaternion to negate.</param>
/// <returns>The negated quaternion.</returns>
public static Quaternion operator -(Quaternion quat)
{
- return new Quaternion(-quat.x, -quat.y, -quat.z, -quat.w);
+ return new Quaternion(-quat.X, -quat.Y, -quat.Z, -quat.W);
}
/// <summary>
@@ -700,7 +706,7 @@ namespace Godot
/// <returns>The multiplied quaternion.</returns>
public static Quaternion operator *(Quaternion left, real_t right)
{
- return new Quaternion(left.x * right, left.y * right, left.z * right, left.w * right);
+ return new Quaternion(left.X * right, left.Y * right, left.Z * right, left.W * right);
}
/// <summary>
@@ -714,7 +720,7 @@ namespace Godot
/// <returns>The multiplied quaternion.</returns>
public static Quaternion operator *(real_t left, Quaternion right)
{
- return new Quaternion(right.x * left, right.y * left, right.z * left, right.w * left);
+ return new Quaternion(right.X * left, right.Y * left, right.Z * left, right.W * left);
}
/// <summary>
@@ -762,7 +768,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,9 +778,9 @@ 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;
+ return X == other.X && Y == other.Y && Z == other.Z && W == other.W;
}
/// <summary>
@@ -783,36 +789,36 @@ 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);
+ return Mathf.IsEqualApprox(X, other.X) && Mathf.IsEqualApprox(Y, other.Y) && Mathf.IsEqualApprox(Z, other.Z) && Mathf.IsEqualApprox(W, other.W);
}
/// <summary>
/// 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();
+ return Y.GetHashCode() ^ X.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
}
/// <summary>
/// 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})";
+ return $"({X}, {Y}, {Z}, {W})";
}
/// <summary>
/// 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)})";
+ 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
deleted file mode 100644
index a31fef8360..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using Godot.NativeInterop;
-
-namespace Godot
-{
- /// <summary>
- /// The RID type is used to access the unique integer ID of a resource.
- /// They are opaque, which means they do not grant access to the associated
- /// resource by themselves. They are used by and with the low-level Server
- /// classes such as <see cref="RenderingServer"/>.
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- public struct RID
- {
- private ulong _id; // Default is 0
-
- internal RID(ulong id)
- {
- _id = id;
- }
-
- /// <summary>
- /// Constructs a new <see cref="RID"/> for the given <see cref="Object"/> <paramref name="from"/>.
- /// </summary>
- public RID(Object from)
- => _id = from is Resource res ? res.GetRid()._id : default;
-
- /// <summary>
- /// Returns the ID of the referenced resource.
- /// </summary>
- /// <returns>The ID of the referenced resource.</returns>
- public ulong Id => _id;
-
- /// <summary>
- /// Converts this <see cref="RID"/> to a string.
- /// </summary>
- /// <returns>A string representation of this RID.</returns>
- public override string ToString() => $"RID({Id})";
- }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index e80d75dacf..69444f8035 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,17 +45,17 @@ namespace Godot
/// </value>
public Vector2 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
/// <summary>
/// The area of this <see cref="Rect2"/>.
+ /// See also <see cref="HasArea"/>.
/// </summary>
- /// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public real_t Area
+ public readonly real_t Area
{
- get { return GetArea(); }
+ get { return _size.X * _size.Y; }
}
/// <summary>
@@ -63,10 +63,10 @@ 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));
+ Vector2 topLeft = new Vector2(Mathf.Min(_position.X, end.X), Mathf.Min(_position.Y, end.Y));
return new Rect2(topLeft, _size.Abs());
}
@@ -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;
@@ -88,30 +88,40 @@ namespace Godot
return new Rect2();
}
- newRect._position.x = Mathf.Max(b._position.x, _position.x);
- newRect._position.y = Mathf.Max(b._position.y, _position.y);
+ newRect._position.X = Mathf.Max(b._position.X, _position.X);
+ newRect._position.Y = Mathf.Max(b._position.Y, _position.Y);
Vector2 bEnd = b._position + b._size;
Vector2 end = _position + _size;
- newRect._size.x = Mathf.Min(bEnd.x, end.x) - newRect._position.x;
- newRect._size.y = Mathf.Min(bEnd.y, end.y) - newRect._position.y;
+ newRect._size.X = Mathf.Min(bEnd.X, end.X) - newRect._position.X;
+ newRect._size.Y = Mathf.Min(bEnd.Y, end.Y) - newRect._position.Y;
return newRect;
}
/// <summary>
+ /// Returns <see langword="true"/> if this <see cref="Rect2"/> is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public bool IsFinite()
+ {
+ return _position.IsFinite() && _size.IsFinite();
+ }
+
+ /// <summary>
/// Returns <see langword="true"/> if this <see cref="Rect2"/> completely encloses another one.
/// </summary>
/// <param name="b">The other <see cref="Rect2"/> that may be enclosed.</param>
/// <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 &&
- b._position.y + b._size.y < _position.y + _size.y;
+ return b._position.X >= _position.X && b._position.Y >= _position.Y &&
+ b._position.X + b._size.X < _position.X + _size.X &&
+ b._position.Y + b._size.Y < _position.Y + _size.Y;
}
/// <summary>
@@ -119,29 +129,29 @@ 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;
Vector2 begin = expanded._position;
Vector2 end = expanded._position + expanded._size;
- if (to.x < begin.x)
+ if (to.X < begin.X)
{
- begin.x = to.x;
+ begin.X = to.X;
}
- if (to.y < begin.y)
+ if (to.Y < begin.Y)
{
- begin.y = to.y;
+ begin.Y = to.Y;
}
- if (to.x > end.x)
+ if (to.X > end.X)
{
- end.x = to.x;
+ end.X = to.X;
}
- if (to.y > end.y)
+ if (to.Y > end.Y)
{
- end.y = to.y;
+ end.Y = to.Y;
}
expanded._position = begin;
@@ -151,20 +161,11 @@ namespace Godot
}
/// <summary>
- /// Returns the area of the <see cref="Rect2"/>.
- /// </summary>
- /// <returns>The area.</returns>
- public real_t GetArea()
- {
- return _size.x * _size.y;
- }
-
- /// <summary>
/// Returns the center of the <see cref="Rect2"/>, which is equal
/// 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,14 +178,14 @@ 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;
- g._position.x -= by;
- g._position.y -= by;
- g._size.x += by * 2;
- g._size.y += by * 2;
+ g._position.X -= by;
+ g._position.Y -= by;
+ g._size.X += by * 2;
+ g._size.Y += by * 2;
return g;
}
@@ -200,14 +201,14 @@ 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;
- g._position.x -= left;
- g._position.y -= top;
- g._size.x += left + right;
- g._size.y += top + bottom;
+ g._position.X -= left;
+ g._position.Y -= top;
+ g._size.X += left + right;
+ g._size.Y += top + bottom;
return g;
}
@@ -221,7 +222,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;
@@ -237,14 +238,14 @@ namespace Godot
/// Returns <see langword="true"/> if the <see cref="Rect2"/> has
/// area, and <see langword="false"/> if the <see cref="Rect2"/>
/// is linear, empty, or has a negative <see cref="Size"/>.
- /// See also <see cref="GetArea"/>.
+ /// See also <see cref="Area"/>.
/// </summary>
/// <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;
+ return _size.X > 0.0f && _size.Y > 0.0f;
}
/// <summary>
@@ -255,16 +256,16 @@ 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)
+ if (point.X < _position.X)
return false;
- if (point.y < _position.y)
+ if (point.Y < _position.Y)
return false;
- if (point.x >= _position.x + _size.x)
+ if (point.X >= _position.X + _size.X)
return false;
- if (point.y >= _position.y + _size.y)
+ if (point.Y >= _position.Y + _size.Y)
return false;
return true;
@@ -281,42 +282,42 @@ 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)
{
- if (_position.x > b._position.x + b._size.x)
+ if (_position.X > b._position.X + b._size.X)
{
return false;
}
- if (_position.x + _size.x < b._position.x)
+ if (_position.X + _size.X < b._position.X)
{
return false;
}
- if (_position.y > b._position.y + b._size.y)
+ if (_position.Y > b._position.Y + b._size.Y)
{
return false;
}
- if (_position.y + _size.y < b._position.y)
+ if (_position.Y + _size.Y < b._position.Y)
{
return false;
}
}
else
{
- if (_position.x >= b._position.x + b._size.x)
+ if (_position.X >= b._position.X + b._size.X)
{
return false;
}
- if (_position.x + _size.x <= b._position.x)
+ if (_position.X + _size.X <= b._position.X)
{
return false;
}
- if (_position.y >= b._position.y + b._size.y)
+ if (_position.Y >= b._position.Y + b._size.Y)
{
return false;
}
- if (_position.y + _size.y <= b._position.y)
+ if (_position.Y + _size.Y <= b._position.Y)
{
return false;
}
@@ -330,15 +331,15 @@ 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;
- newRect._position.x = Mathf.Min(b._position.x, _position.x);
- newRect._position.y = Mathf.Min(b._position.y, _position.y);
+ newRect._position.X = Mathf.Min(b._position.X, _position.X);
+ newRect._position.Y = Mathf.Min(b._position.Y, _position.Y);
- newRect._size.x = Mathf.Max(b._position.x + b._size.x, _position.x + _size.x);
- newRect._size.y = Mathf.Max(b._position.y + b._size.y, _position.y + _size.y);
+ newRect._size.X = Mathf.Max(b._position.X + b._size.X, _position.X + _size.X);
+ newRect._size.Y = Mathf.Max(b._position.Y + b._size.Y, _position.Y + _size.Y);
newRect._size -= newRect._position; // Make relative again
@@ -426,7 +427,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 +437,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 +448,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 +457,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 +466,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 +475,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..2099d0abca 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2I.cs
@@ -4,23 +4,23 @@ using System.Runtime.InteropServices;
namespace Godot
{
/// <summary>
- /// 2D axis-aligned bounding box using integers. Rect2i consists of a position, a size, and
+ /// 2D axis-aligned bounding box using integers. Rect2I consists of a position, a size, and
/// several utility functions. It is typically used for fast overlap tests.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- public struct Rect2i : IEquatable<Rect2i>
+ public struct Rect2I : IEquatable<Rect2I>
{
- private Vector2i _position;
- private Vector2i _size;
+ private Vector2I _position;
+ private Vector2I _size;
/// <summary>
/// Beginning corner. Typically has values lower than <see cref="End"/>.
/// </summary>
/// <value>Directly uses a private field.</value>
- public Vector2i Position
+ public Vector2I Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -29,9 +29,9 @@ namespace Godot
/// If the size is negative, you can use <see cref="Abs"/> to fix it.
/// </summary>
/// <value>Directly uses a private field.</value>
- public Vector2i Size
+ public Vector2I Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -43,105 +43,105 @@ namespace Godot
/// Getting is equivalent to <paramref name="value"/> = <see cref="Position"/> + <see cref="Size"/>,
/// setting is equivalent to <see cref="Size"/> = <paramref name="value"/> - <see cref="Position"/>
/// </value>
- public Vector2i End
+ public Vector2I End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
/// <summary>
- /// The area of this <see cref="Rect2i"/>.
+ /// The area of this <see cref="Rect2I"/>.
+ /// See also <see cref="HasArea"/>.
/// </summary>
- /// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public int Area
+ public readonly int Area
{
- get { return GetArea(); }
+ get { return _size.X * _size.Y; }
}
/// <summary>
- /// Returns a <see cref="Rect2i"/> with equivalent position and size, modified so that
+ /// Returns a <see cref="Rect2I"/> with equivalent position and size, modified so that
/// the top-left corner is the origin and width and height are positive.
/// </summary>
- /// <returns>The modified <see cref="Rect2i"/>.</returns>
- public Rect2i Abs()
+ /// <returns>The modified <see cref="Rect2I"/>.</returns>
+ public readonly Rect2I Abs()
{
- Vector2i end = End;
- Vector2i topLeft = new Vector2i(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
- return new Rect2i(topLeft, _size.Abs());
+ Vector2I end = End;
+ Vector2I topLeft = new Vector2I(Mathf.Min(_position.X, end.X), Mathf.Min(_position.Y, end.Y));
+ return new Rect2I(topLeft, _size.Abs());
}
/// <summary>
- /// Returns the intersection of this <see cref="Rect2i"/> and <paramref name="b"/>.
- /// If the rectangles do not intersect, an empty <see cref="Rect2i"/> is returned.
+ /// Returns the intersection of this <see cref="Rect2I"/> and <paramref name="b"/>.
+ /// If the rectangles do not intersect, an empty <see cref="Rect2I"/> is returned.
/// </summary>
- /// <param name="b">The other <see cref="Rect2i"/>.</param>
+ /// <param name="b">The other <see cref="Rect2I"/>.</param>
/// <returns>
- /// The intersection of this <see cref="Rect2i"/> and <paramref name="b"/>,
- /// or an empty <see cref="Rect2i"/> if they do not intersect.
+ /// 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;
+ Rect2I newRect = b;
if (!Intersects(newRect))
{
- return new Rect2i();
+ return new Rect2I();
}
- newRect._position.x = Mathf.Max(b._position.x, _position.x);
- newRect._position.y = Mathf.Max(b._position.y, _position.y);
+ newRect._position.X = Mathf.Max(b._position.X, _position.X);
+ newRect._position.Y = Mathf.Max(b._position.Y, _position.Y);
- Vector2i bEnd = b._position + b._size;
- Vector2i end = _position + _size;
+ Vector2I bEnd = b._position + b._size;
+ Vector2I end = _position + _size;
- newRect._size.x = Mathf.Min(bEnd.x, end.x) - newRect._position.x;
- newRect._size.y = Mathf.Min(bEnd.y, end.y) - newRect._position.y;
+ newRect._size.X = Mathf.Min(bEnd.X, end.X) - newRect._position.X;
+ newRect._size.Y = Mathf.Min(bEnd.Y, end.Y) - newRect._position.Y;
return newRect;
}
/// <summary>
- /// Returns <see langword="true"/> if this <see cref="Rect2i"/> completely encloses another one.
+ /// Returns <see langword="true"/> if this <see cref="Rect2I"/> completely encloses another one.
/// </summary>
- /// <param name="b">The other <see cref="Rect2i"/> that may be enclosed.</param>
+ /// <param name="b">The other <see cref="Rect2I"/> that may be enclosed.</param>
/// <returns>
- /// A <see langword="bool"/> for whether or not this <see cref="Rect2i"/> encloses <paramref name="b"/>.
+ /// 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 &&
- b._position.y + b._size.y < _position.y + _size.y;
+ return b._position.X >= _position.X && b._position.Y >= _position.Y &&
+ b._position.X + b._size.X < _position.X + _size.X &&
+ b._position.Y + b._size.Y < _position.Y + _size.Y;
}
/// <summary>
- /// Returns this <see cref="Rect2i"/> expanded to include a given point.
+ /// Returns this <see cref="Rect2I"/> expanded to include a given point.
/// </summary>
/// <param name="to">The point to include.</param>
- /// <returns>The expanded <see cref="Rect2i"/>.</returns>
- public Rect2i Expand(Vector2i to)
+ /// <returns>The expanded <see cref="Rect2I"/>.</returns>
+ public readonly Rect2I Expand(Vector2I to)
{
- Rect2i expanded = this;
+ Rect2I expanded = this;
- Vector2i begin = expanded._position;
- Vector2i end = expanded._position + expanded._size;
+ Vector2I begin = expanded._position;
+ Vector2I end = expanded._position + expanded._size;
- if (to.x < begin.x)
+ if (to.X < begin.X)
{
- begin.x = to.x;
+ begin.X = to.X;
}
- if (to.y < begin.y)
+ if (to.Y < begin.Y)
{
- begin.y = to.y;
+ begin.Y = to.Y;
}
- if (to.x > end.x)
+ if (to.X > end.X)
{
- end.x = to.x;
+ end.X = to.X;
}
- if (to.y > end.y)
+ if (to.Y > end.Y)
{
- end.y = to.y;
+ end.Y = to.Y;
}
expanded._position = begin;
@@ -151,48 +151,39 @@ namespace Godot
}
/// <summary>
- /// Returns the area of the <see cref="Rect2i"/>.
- /// </summary>
- /// <returns>The area.</returns>
- public int GetArea()
- {
- return _size.x * _size.y;
- }
-
- /// <summary>
- /// Returns the center of the <see cref="Rect2i"/>, which is equal
+ /// Returns the center of the <see cref="Rect2I"/>, which is equal
/// to <see cref="Position"/> + (<see cref="Size"/> / 2).
/// If <see cref="Size"/> is an odd number, the returned center
/// value will be rounded towards <see cref="Position"/>.
/// </summary>
/// <returns>The center.</returns>
- public Vector2i GetCenter()
+ public readonly Vector2I GetCenter()
{
return _position + (_size / 2);
}
/// <summary>
- /// Returns a copy of the <see cref="Rect2i"/> grown by the specified amount
+ /// Returns a copy of the <see cref="Rect2I"/> grown by the specified amount
/// on all sides.
/// </summary>
/// <seealso cref="GrowIndividual(int, int, int, int)"/>
/// <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)
+ /// <returns>The grown <see cref="Rect2I"/>.</returns>
+ public readonly Rect2I Grow(int by)
{
- Rect2i g = this;
+ Rect2I g = this;
- g._position.x -= by;
- g._position.y -= by;
- g._size.x += by * 2;
- g._size.y += by * 2;
+ g._position.X -= by;
+ g._position.Y -= by;
+ g._size.X += by * 2;
+ g._size.Y += by * 2;
return g;
}
/// <summary>
- /// Returns a copy of the <see cref="Rect2i"/> grown by the specified amount
+ /// Returns a copy of the <see cref="Rect2I"/> grown by the specified amount
/// on each side individually.
/// </summary>
/// <seealso cref="Grow(int)"/>
@@ -201,31 +192,31 @@ namespace Godot
/// <param name="top">The amount to grow by on the top side.</param>
/// <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)
+ /// <returns>The grown <see cref="Rect2I"/>.</returns>
+ public readonly Rect2I GrowIndividual(int left, int top, int right, int bottom)
{
- Rect2i g = this;
+ Rect2I g = this;
- g._position.x -= left;
- g._position.y -= top;
- g._size.x += left + right;
- g._size.y += top + bottom;
+ g._position.X -= left;
+ g._position.Y -= top;
+ g._size.X += left + right;
+ g._size.Y += top + bottom;
return g;
}
/// <summary>
- /// Returns a copy of the <see cref="Rect2i"/> grown by the specified amount
+ /// Returns a copy of the <see cref="Rect2I"/> grown by the specified amount
/// on the specified <see cref="Side"/>.
/// </summary>
/// <seealso cref="Grow(int)"/>
/// <seealso cref="GrowIndividual(int, int, int, int)"/>
/// <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)
+ /// <returns>The grown <see cref="Rect2I"/>.</returns>
+ public readonly Rect2I GrowSide(Side side, int by)
{
- Rect2i g = this;
+ Rect2I g = this;
g = g.GrowIndividual(Side.Left == side ? by : 0,
Side.Top == side ? by : 0,
@@ -236,95 +227,76 @@ namespace Godot
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="Rect2i"/> has
- /// area, and <see langword="false"/> if the <see cref="Rect2i"/>
+ /// Returns <see langword="true"/> if the <see cref="Rect2I"/> has
+ /// area, and <see langword="false"/> if the <see cref="Rect2I"/>
/// is linear, empty, or has a negative <see cref="Size"/>.
- /// See also <see cref="GetArea"/>.
+ /// See also <see cref="Area"/>.
/// </summary>
/// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> has area.
+ /// 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;
+ return _size.X > 0 && _size.Y > 0;
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="Rect2i"/> contains a point,
+ /// Returns <see langword="true"/> if the <see cref="Rect2I"/> contains a point,
/// or <see langword="false"/> otherwise.
/// </summary>
/// <param name="point">The point to check.</param>
/// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> contains <paramref name="point"/>.
+ /// 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)
+ if (point.X < _position.X)
return false;
- if (point.y < _position.y)
+ if (point.Y < _position.Y)
return false;
- if (point.x >= _position.x + _size.x)
+ if (point.X >= _position.X + _size.X)
return false;
- if (point.y >= _position.y + _size.y)
+ if (point.Y >= _position.Y + _size.Y)
return false;
return true;
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="Rect2i"/> overlaps with <paramref name="b"/>
+ /// Returns <see langword="true"/> if the <see cref="Rect2I"/> overlaps with <paramref name="b"/>
/// (i.e. they have at least one point in common).
- ///
- /// If <paramref name="includeBorders"/> is <see langword="true"/>,
- /// they will also be considered overlapping if their borders touch,
- /// even without intersection.
/// </summary>
- /// <param name="b">The other <see cref="Rect2i"/> to check for intersections with.</param>
- /// <param name="includeBorders">Whether or not to consider borders.</param>
+ /// <param name="b">The other <see cref="Rect2I"/> to check for intersections with.</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)
{
- if (includeBorders)
- {
- if (_position.x > b._position.x + b._size.x)
- return false;
- if (_position.x + _size.x < b._position.x)
- return false;
- if (_position.y > b._position.y + b._size.y)
- return false;
- if (_position.y + _size.y < b._position.y)
- return false;
- }
- else
- {
- if (_position.x >= b._position.x + b._size.x)
- return false;
- if (_position.x + _size.x <= b._position.x)
- return false;
- if (_position.y >= b._position.y + b._size.y)
- return false;
- if (_position.y + _size.y <= b._position.y)
- return false;
- }
+ if (_position.X >= b._position.X + b._size.X)
+ return false;
+ if (_position.X + _size.X <= b._position.X)
+ return false;
+ if (_position.Y >= b._position.Y + b._size.Y)
+ return false;
+ if (_position.Y + _size.Y <= b._position.Y)
+ return false;
return true;
}
/// <summary>
- /// Returns a larger <see cref="Rect2i"/> that contains this <see cref="Rect2i"/> and <paramref name="b"/>.
+ /// Returns a larger <see cref="Rect2I"/> that contains this <see cref="Rect2I"/> and <paramref name="b"/>.
/// </summary>
- /// <param name="b">The other <see cref="Rect2i"/>.</param>
- /// <returns>The merged <see cref="Rect2i"/>.</returns>
- public Rect2i Merge(Rect2i b)
+ /// <param name="b">The other <see cref="Rect2I"/>.</param>
+ /// <returns>The merged <see cref="Rect2I"/>.</returns>
+ public readonly Rect2I Merge(Rect2I b)
{
- Rect2i newRect;
+ Rect2I newRect;
- newRect._position.x = Mathf.Min(b._position.x, _position.x);
- newRect._position.y = Mathf.Min(b._position.y, _position.y);
+ newRect._position.X = Mathf.Min(b._position.X, _position.X);
+ newRect._position.Y = Mathf.Min(b._position.Y, _position.Y);
- newRect._size.x = Mathf.Max(b._position.x + b._size.x, _position.x + _size.x);
- newRect._size.y = Mathf.Max(b._position.y + b._size.y, _position.y + _size.y);
+ newRect._size.X = Mathf.Max(b._position.X + b._size.X, _position.X + _size.X);
+ newRect._size.Y = Mathf.Max(b._position.Y + b._size.Y, _position.Y + _size.Y);
newRect._size -= newRect._position; // Make relative again
@@ -332,93 +304,93 @@ namespace Godot
}
/// <summary>
- /// Constructs a <see cref="Rect2i"/> from a position and size.
+ /// Constructs a <see cref="Rect2I"/> from a position and size.
/// </summary>
/// <param name="position">The position.</param>
/// <param name="size">The size.</param>
- public Rect2i(Vector2i position, Vector2i size)
+ public Rect2I(Vector2I position, Vector2I size)
{
_position = position;
_size = size;
}
/// <summary>
- /// Constructs a <see cref="Rect2i"/> from a position, width, and height.
+ /// Constructs a <see cref="Rect2I"/> from a position, width, and height.
/// </summary>
/// <param name="position">The position.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
- public Rect2i(Vector2i position, int width, int height)
+ public Rect2I(Vector2I position, int width, int height)
{
_position = position;
- _size = new Vector2i(width, height);
+ _size = new Vector2I(width, height);
}
/// <summary>
- /// Constructs a <see cref="Rect2i"/> from x, y, and size.
+ /// Constructs a <see cref="Rect2I"/> from x, y, and size.
/// </summary>
/// <param name="x">The position's X coordinate.</param>
/// <param name="y">The position's Y coordinate.</param>
/// <param name="size">The size.</param>
- public Rect2i(int x, int y, Vector2i size)
+ public Rect2I(int x, int y, Vector2I size)
{
- _position = new Vector2i(x, y);
+ _position = new Vector2I(x, y);
_size = size;
}
/// <summary>
- /// Constructs a <see cref="Rect2i"/> from x, y, width, and height.
+ /// Constructs a <see cref="Rect2I"/> from x, y, width, and height.
/// </summary>
/// <param name="x">The position's X coordinate.</param>
/// <param name="y">The position's Y coordinate.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
- public Rect2i(int x, int y, int width, int height)
+ public Rect2I(int x, int y, int width, int height)
{
- _position = new Vector2i(x, y);
- _size = new Vector2i(width, height);
+ _position = new Vector2I(x, y);
+ _size = new Vector2I(width, height);
}
/// <summary>
/// Returns <see langword="true"/> if the
- /// <see cref="Rect2i"/>s are exactly equal.
+ /// <see cref="Rect2I"/>s are exactly equal.
/// </summary>
/// <param name="left">The left rect.</param>
/// <param name="right">The right rect.</param>
/// <returns>Whether or not the rects are equal.</returns>
- public static bool operator ==(Rect2i left, Rect2i right)
+ public static bool operator ==(Rect2I left, Rect2I right)
{
return left.Equals(right);
}
/// <summary>
/// Returns <see langword="true"/> if the
- /// <see cref="Rect2i"/>s are not equal.
+ /// <see cref="Rect2I"/>s are not equal.
/// </summary>
/// <param name="left">The left rect.</param>
/// <param name="right">The right rect.</param>
/// <returns>Whether or not the rects are not equal.</returns>
- public static bool operator !=(Rect2i left, Rect2i right)
+ public static bool operator !=(Rect2I left, Rect2I right)
{
return !left.Equals(right);
}
/// <summary>
- /// Converts this <see cref="Rect2i"/> to a <see cref="Rect2"/>.
+ /// Converts this <see cref="Rect2I"/> to a <see cref="Rect2"/>.
/// </summary>
/// <param name="value">The rect to convert.</param>
- public static implicit operator Rect2(Rect2i value)
+ public static implicit operator Rect2(Rect2I value)
{
return new Rect2(value._position, value._size);
}
/// <summary>
- /// Converts a <see cref="Rect2"/> to a <see cref="Rect2i"/>.
+ /// Converts a <see cref="Rect2"/> to a <see cref="Rect2I"/>.
/// </summary>
/// <param name="value">The rect to convert.</param>
- public static explicit operator Rect2i(Rect2 value)
+ public static explicit operator Rect2I(Rect2 value)
{
- return new Rect2i((Vector2i)value.Position, (Vector2i)value.Size);
+ return new Rect2I((Vector2I)value.Position, (Vector2I)value.Size);
}
/// <summary>
@@ -426,9 +398,9 @@ 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);
+ return obj is Rect2I other && Equals(other);
}
/// <summary>
@@ -436,34 +408,34 @@ 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);
}
/// <summary>
- /// Serves as the hash function for <see cref="Rect2i"/>.
+ /// 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();
}
/// <summary>
- /// Converts this <see cref="Rect2i"/> to a string.
+ /// 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}";
}
/// <summary>
- /// Converts this <see cref="Rect2i"/> to a string with the given <paramref name="format"/>.
+ /// 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/Rid.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs
new file mode 100644
index 0000000000..350626389b
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Godot.NativeInterop;
+
+namespace Godot
+{
+ /// <summary>
+ /// The RID type is used to access a low-level resource by its unique ID.
+ /// RIDs are opaque, which means they do not grant access to the resource
+ /// by themselves. They are used by the low-level server classes, such as
+ /// <see cref="DisplayServer"/>, <see cref="RenderingServer"/>,
+ /// <see cref="TextServer"/>, etc.
+ ///
+ /// A low-level resource may correspond to a high-level <see cref="Resource"/>,
+ /// such as <see cref="Texture"/> or <see cref="Mesh"/>
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly struct Rid : IEquatable<Rid>
+ {
+ private readonly ulong _id; // Default is 0
+
+ internal Rid(ulong id)
+ {
+ _id = id;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Rid"/> for the given <see cref="GodotObject"/> <paramref name="from"/>.
+ /// </summary>
+ public Rid(GodotObject from)
+ => _id = from is Resource res ? res.GetRid()._id : default;
+
+ /// <summary>
+ /// Returns the ID of the referenced low-level resource.
+ /// </summary>
+ /// <returns>The ID of the referenced resource.</returns>
+ public ulong Id => _id;
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the <see cref="Rid"/> is not <c>0</c>.
+ /// </summary>
+ /// <returns>Whether or not the ID is valid.</returns>
+ public bool IsValid => _id != 0;
+
+ /// <summary>
+ /// Returns <see langword="true"/> if both <see cref="Rid"/>s are equal,
+ /// which means they both refer to the same low-level resource.
+ /// </summary>
+ /// <param name="left">The left RID.</param>
+ /// <param name="right">The right RID.</param>
+ /// <returns>Whether or not the RIDs are equal.</returns>
+ public static bool operator ==(Rid left, Rid right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the <see cref="Rid"/>s are not equal.
+ /// </summary>
+ /// <param name="left">The left RID.</param>
+ /// <param name="right">The right RID.</param>
+ /// <returns>Whether or not the RIDs are equal.</returns>
+ public static bool operator !=(Rid left, Rid right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this RID and <paramref name="obj"/> are equal.
+ /// </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 readonly bool Equals(object obj)
+ {
+ return obj is Rid other && Equals(other);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the RIDs are equal.
+ /// </summary>
+ /// <param name="other">The other RID.</param>
+ /// <returns>Whether or not the RIDs are equal.</returns>
+ public readonly bool Equals(Rid other)
+ {
+ return _id == other.Id;
+ }
+
+ /// <summary>
+ /// Serves as the hash function for <see cref="Rid"/>.
+ /// </summary>
+ /// <returns>A hash code for this RID.</returns>
+ public override readonly int GetHashCode()
+ {
+ return HashCode.Combine(_id);
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Rid"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this Rid.</returns>
+ public override string ToString() => $"RID({Id})";
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs
index 3f50df0a0d..9ac8abd37b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs
@@ -3,30 +3,36 @@ namespace Godot
/// <summary>
/// Represents a signal defined in an object.
/// </summary>
- public readonly struct SignalInfo
+ public readonly struct Signal : IAwaitable<Variant[]>
{
- private readonly Object _owner;
+ private readonly GodotObject _owner;
private readonly StringName _signalName;
/// <summary>
/// Object that contains the signal.
/// </summary>
- public Object Owner => _owner;
+ public GodotObject Owner => _owner;
+
/// <summary>
/// Name of the signal.
/// </summary>
public StringName Name => _signalName;
/// <summary>
- /// Creates a new <see cref="SignalInfo"/> with the name <paramref name="name"/>
+ /// Creates a new <see cref="Signal"/> with the name <paramref name="name"/>
/// in the specified <paramref name="owner"/>.
/// </summary>
/// <param name="owner">Object that contains the signal.</param>
/// <param name="name">Name of the signal.</param>
- public SignalInfo(Object owner, StringName name)
+ public Signal(GodotObject owner, StringName name)
{
_owner = owner;
_signalName = name;
}
+
+ public IAwaiter<Variant[]> GetAwaiter()
+ {
+ return new SignalAwaiter(_owner, _signalName, _owner);
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
index 96fb891086..a67f626d35 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
@@ -10,13 +10,13 @@ namespace Godot
private Variant[] _result;
private Action _continuation;
- public SignalAwaiter(Object source, StringName signal, Object target)
+ public SignalAwaiter(GodotObject source, StringName signal, GodotObject target)
{
var awaiterGcHandle = CustomGCHandle.AllocStrong(this);
using godot_string_name signalSrc = NativeFuncs.godotsharp_string_name_new_copy(
(godot_string_name)(signal?.NativeValue ?? default));
- NativeFuncs.godotsharp_internal_signal_awaiter_connect(Object.GetPtr(source), in signalSrc,
- Object.GetPtr(target), GCHandle.ToIntPtr(awaiterGcHandle));
+ NativeFuncs.godotsharp_internal_signal_awaiter_connect(GodotObject.GetPtr(source), in signalSrc,
+ GodotObject.GetPtr(target), GCHandle.ToIntPtr(awaiterGcHandle));
}
public bool IsCompleted => _completed;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index d77baab24b..df67e075ac 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Security;
+using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Godot.NativeInterop;
@@ -67,36 +69,6 @@ namespace Godot
}
/// <summary>
- /// If the string is a path to a file, return the path to the file without the extension.
- /// </summary>
- /// <seealso cref="GetExtension(string)"/>
- /// <seealso cref="GetBaseDir(string)"/>
- /// <seealso cref="GetFile(string)"/>
- /// <param name="instance">The path to a file.</param>
- /// <returns>The path to the file without the extension.</returns>
- public static string GetBaseName(this string instance)
- {
- int index = instance.LastIndexOf('.');
-
- if (index > 0)
- return instance.Substring(0, index);
-
- return instance;
- }
-
- /// <summary>
- /// Returns <see langword="true"/> if the strings begins
- /// with the given string <paramref name="text"/>.
- /// </summary>
- /// <param name="instance">The string to check.</param>
- /// <param name="text">The beginning string.</param>
- /// <returns>If the string begins with the given string.</returns>
- public static bool BeginsWith(this string instance, string text)
- {
- return instance.StartsWith(text);
- }
-
- /// <summary>
/// Returns the bigrams (pairs of consecutive letters) of this string.
/// </summary>
/// <param name="instance">The string that will be used.</param>
@@ -144,15 +116,15 @@ namespace Godot
}
/// <summary>
- /// Returns the amount of substrings <paramref name="what"/> in the string.
+ /// Returns the number of occurrences of substring <paramref name="what"/> in the string.
/// </summary>
/// <param name="instance">The string where the substring will be searched.</param>
/// <param name="what">The substring that will be counted.</param>
- /// <param name="caseSensitive">If the search is case sensitive.</param>
/// <param name="from">Index to start searching from.</param>
/// <param name="to">Index to stop searching at.</param>
- /// <returns>Amount of substrings in the string.</returns>
- public static int Count(this string instance, string what, bool caseSensitive = true, int from = 0, int to = 0)
+ /// <param name="caseSensitive">If the search is case sensitive.</param>
+ /// <returns>Number of occurrences of the substring in the string.</returns>
+ public static int Count(this string instance, string what, int from = 0, int to = 0, bool caseSensitive = true)
{
if (what.Length == 0)
{
@@ -211,6 +183,82 @@ namespace Godot
}
/// <summary>
+ /// Returns the number of occurrences of substring <paramref name="what"/> (ignoring case)
+ /// between <paramref name="from"/> and <paramref name="to"/> positions. If <paramref name="from"/>
+ /// and <paramref name="to"/> equals 0 the whole string will be used. If only <paramref name="to"/>
+ /// equals 0 the remained substring will be used.
+ /// </summary>
+ /// <param name="instance">The string where the substring will be searched.</param>
+ /// <param name="what">The substring that will be counted.</param>
+ /// <param name="from">Index to start searching from.</param>
+ /// <param name="to">Index to stop searching at.</param>
+ /// <returns>Number of occurrences of the substring in the string.</returns>
+ public static int CountN(this string instance, string what, int from = 0, int to = 0)
+ {
+ return instance.Count(what, from, to, caseSensitive: false);
+ }
+
+ /// <summary>
+ /// Returns a copy of the string with indentation (leading tabs and spaces) removed.
+ /// See also <see cref="Indent"/> to add indentation.
+ /// </summary>
+ /// <param name="instance">The string to remove the indentation from.</param>
+ /// <returns>The string with the indentation removed.</returns>
+ public static string Dedent(this string instance)
+ {
+ var sb = new StringBuilder();
+ string indent = "";
+ bool hasIndent = false;
+ bool hasText = false;
+ int lineStart = 0;
+ int indentStop = -1;
+
+ for (int i = 0; i < instance.Length; i++)
+ {
+ char c = instance[i];
+ if (c == '\n')
+ {
+ if (hasText)
+ {
+ sb.Append(instance.Substring(indentStop, i - indentStop));
+ }
+ sb.Append('\n');
+ hasText = false;
+ lineStart = i + 1;
+ indentStop = -1;
+ }
+ else if (!hasText)
+ {
+ if (c > 32)
+ {
+ hasText = true;
+ if (!hasIndent)
+ {
+ hasIndent = true;
+ indent = instance.Substring(lineStart, i - lineStart);
+ indentStop = i;
+ }
+ }
+ if (hasIndent && indentStop < 0)
+ {
+ int j = i - lineStart;
+ if (j >= indent.Length || c != indent[j])
+ {
+ indentStop = i;
+ }
+ }
+ }
+ }
+
+ if (hasText)
+ {
+ sb.Append(instance.Substring(indentStop, instance.Length - indentStop));
+ }
+
+ return sb.ToString();
+ }
+
+ /// <summary>
/// Returns a copy of the string with special characters escaped using the C language standard.
/// </summary>
/// <param name="instance">The string to escape.</param>
@@ -229,7 +277,6 @@ namespace Godot
sb.Replace("\v", "\\v");
sb.Replace("\'", "\\'");
sb.Replace("\"", "\\\"");
- sb.Replace("?", "\\?");
return sb.ToString();
}
@@ -253,7 +300,6 @@ namespace Godot
sb.Replace("\\v", "\v");
sb.Replace("\\'", "\'");
sb.Replace("\\\"", "\"");
- sb.Replace("\\?", "?");
sb.Replace("\\\\", "\\");
return sb.ToString();
@@ -445,29 +491,6 @@ namespace Godot
}
/// <summary>
- /// Returns <see langword="true"/> if the strings ends
- /// with the given string <paramref name="text"/>.
- /// </summary>
- /// <param name="instance">The string to check.</param>
- /// <param name="text">The ending string.</param>
- /// <returns>If the string ends with the given string.</returns>
- public static bool EndsWith(this string instance, string text)
- {
- return instance.EndsWith(text);
- }
-
- /// <summary>
- /// Erase <paramref name="chars"/> characters from the string starting from <paramref name="pos"/>.
- /// </summary>
- /// <param name="instance">The string to modify.</param>
- /// <param name="pos">Starting position from which to erase.</param>
- /// <param name="chars">Amount of characters to erase.</param>
- public static void Erase(this StringBuilder instance, int pos, int chars)
- {
- instance.Remove(pos, chars);
- }
-
- /// <summary>
/// Returns the extension without the leading period character (<c>.</c>)
/// if the string is a valid file name or path. If the string does not contain
/// an extension, returns an empty string instead.
@@ -491,7 +514,7 @@ namespace Godot
/// <returns>The extension of the file or an empty string.</returns>
public static string GetExtension(this string instance)
{
- int pos = instance.FindLast(".");
+ int pos = instance.RFind(".");
if (pos < 0)
return instance;
@@ -500,12 +523,16 @@ namespace Godot
}
/// <summary>
- /// Find the first occurrence of a substring. Optionally, the search starting position can be passed.
+ /// Returns the index of the first occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing
+ /// to the end of the string.
+ /// Note: If you just want to know whether a string contains a substring, use the
+ /// <see cref="string.Contains(string)"/> method.
/// </summary>
/// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
+ /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param>
@@ -521,9 +548,9 @@ namespace Godot
/// Find the first occurrence of a char. Optionally, the search starting position can be passed.
/// </summary>
/// <seealso cref="Find(string, string, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
+ /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param>
@@ -531,50 +558,21 @@ namespace Godot
/// <returns>The first instance of the char, or -1 if not found.</returns>
public static int Find(this string instance, char what, int from = 0, bool caseSensitive = true)
{
- // TODO: Could be more efficient if we get a char version of `IndexOf`.
- // See https://github.com/dotnet/runtime/issues/44116
- return instance.IndexOf(what.ToString(), from,
- caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
- }
+ if (caseSensitive)
+ return instance.IndexOf(what, from);
- /// <summary>Find the last occurrence of a substring.</summary>
- /// <seealso cref="Find(string, string, int, bool)"/>
- /// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
- /// <seealso cref="FindN(string, string, int)"/>
- /// <param name="instance">The string that will be searched.</param>
- /// <param name="what">The substring to find.</param>
- /// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
- /// <returns>The starting position of the substring, or -1 if not found.</returns>
- public static int FindLast(this string instance, string what, bool caseSensitive = true)
- {
- return instance.FindLast(what, instance.Length - 1, caseSensitive);
- }
-
- /// <summary>Find the last occurrence of a substring specifying the search starting position.</summary>
- /// <seealso cref="Find(string, string, int, bool)"/>
- /// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindN(string, string, int)"/>
- /// <param name="instance">The string that will be searched.</param>
- /// <param name="what">The substring to find.</param>
- /// <param name="from">The search starting position.</param>
- /// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
- /// <returns>The starting position of the substring, or -1 if not found.</returns>
- public static int FindLast(this string instance, string what, int from, bool caseSensitive = true)
- {
- return instance.LastIndexOf(what, from,
- caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
+ return CultureInfo.InvariantCulture.CompareInfo.IndexOf(instance, what, from, CompareOptions.OrdinalIgnoreCase);
}
/// <summary>
- /// Find the first occurrence of a substring but search as case-insensitive.
- /// Optionally, the search starting position can be passed.
+ /// Returns the index of the first case-insensitive occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing
+ /// to the end of the string.
/// </summary>
/// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="Find(string, char, int, bool)"/>
- /// <seealso cref="FindLast(string, string, bool)"/>
- /// <seealso cref="FindLast(string, string, int, bool)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
+ /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param>
@@ -607,7 +605,7 @@ namespace Godot
}
else
{
- if (instance.BeginsWith("/"))
+ if (instance.StartsWith('/'))
{
rs = instance.Substring(1);
directory = "/";
@@ -618,7 +616,7 @@ namespace Godot
}
}
- int sep = Mathf.Max(rs.FindLast("/"), rs.FindLast("\\"));
+ int sep = Mathf.Max(rs.RFind("/"), rs.RFind("\\"));
if (sep == -1)
return directory;
@@ -627,6 +625,24 @@ namespace Godot
}
/// <summary>
+ /// If the string is a path to a file, return the path to the file without the extension.
+ /// </summary>
+ /// <seealso cref="GetExtension(string)"/>
+ /// <seealso cref="GetBaseDir(string)"/>
+ /// <seealso cref="GetFile(string)"/>
+ /// <param name="instance">The path to a file.</param>
+ /// <returns>The path to the file without the extension.</returns>
+ public static string GetBaseName(this string instance)
+ {
+ int index = instance.RFind(".");
+
+ if (index > 0)
+ return instance.Substring(0, index);
+
+ return instance;
+ }
+
+ /// <summary>
/// If the string is a path to a file, return the file and ignore the base directory.
/// </summary>
/// <seealso cref="GetBaseName(string)"/>
@@ -636,7 +652,7 @@ namespace Godot
/// <returns>The file name.</returns>
public static string GetFile(this string instance)
{
- int sep = Mathf.Max(instance.FindLast("/"), instance.FindLast("\\"));
+ int sep = Mathf.Max(instance.RFind("/"), instance.RFind("\\"));
if (sep == -1)
return instance;
@@ -645,30 +661,52 @@ namespace Godot
}
/// <summary>
- /// Converts the given byte array of ASCII encoded text to a string.
- /// Faster alternative to <see cref="GetStringFromUTF8"/> if the
+ /// Converts ASCII encoded array to string.
+ /// Fast alternative to <see cref="GetStringFromUtf8"/> if the
/// content is ASCII-only. Unlike the UTF-8 function this function
/// maps every byte to a character in the array. Multibyte sequences
/// will not be interpreted correctly. For parsing user input always
- /// use <see cref="GetStringFromUTF8"/>.
+ /// use <see cref="GetStringFromUtf8"/>.
/// </summary>
/// <param name="bytes">A byte array of ASCII characters (on the range of 0-127).</param>
/// <returns>A string created from the bytes.</returns>
- public static string GetStringFromASCII(this byte[] bytes)
+ public static string GetStringFromAscii(this byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
/// <summary>
- /// Converts the given byte array of UTF-8 encoded text to a string.
- /// Slower than <see cref="GetStringFromASCII"/> but supports UTF-8
+ /// Converts UTF-16 encoded array to string using the little endian byte order.
+ /// </summary>
+ /// <param name="bytes">A byte array of UTF-16 characters.</param>
+ /// <returns>A string created from the bytes.</returns>
+ public static string GetStringFromUtf16(this byte[] bytes)
+ {
+ return Encoding.Unicode.GetString(bytes);
+ }
+
+ /// <summary>
+ /// Converts UTF-32 encoded array to string using the little endian byte order.
+ /// </summary>
+ /// <param name="bytes">A byte array of UTF-32 characters.</param>
+ /// <returns>A string created from the bytes.</returns>
+ public static string GetStringFromUtf32(this byte[] bytes)
+ {
+ return Encoding.UTF32.GetString(bytes);
+ }
+
+ /// <summary>
+ /// Converts UTF-8 encoded array to string.
+ /// Slower than <see cref="GetStringFromAscii"/> but supports UTF-8
/// encoded data. Use this function if you are unsure about the
/// source of the data. For user input this function
/// should always be preferred.
/// </summary>
- /// <param name="bytes">A byte array of UTF-8 characters (a character may take up multiple bytes).</param>
+ /// <param name="bytes">
+ /// A byte array of UTF-8 characters (a character may take up multiple bytes).
+ /// </param>
/// <returns>A string created from the bytes.</returns>
- public static string GetStringFromUTF8(this byte[] bytes)
+ public static string GetStringFromUtf8(this byte[] bytes)
{
return Encoding.UTF8.GetString(bytes);
}
@@ -768,18 +806,44 @@ namespace Godot
}
/// <summary>
- /// Inserts a substring at a given position.
+ /// Returns a copy of the string with lines indented with <paramref name="prefix"/>.
+ /// For example, the string can be indented with two tabs using <c>"\t\t"</c>,
+ /// or four spaces using <c>" "</c>. The prefix can be any string so it can
+ /// also be used to comment out strings with e.g. <c>"// </c>.
+ /// See also <see cref="Dedent"/> to remove indentation.
+ /// Note: Empty lines are kept empty.
/// </summary>
- /// <param name="instance">The string to modify.</param>
- /// <param name="pos">Position at which to insert the substring.</param>
- /// <param name="what">Substring to insert.</param>
- /// <returns>
- /// The string with <paramref name="what"/> inserted at the given
- /// position <paramref name="pos"/>.
- /// </returns>
- public static string Insert(this string instance, int pos, string what)
+ /// <param name="instance">The string to add indentation to.</param>
+ /// <param name="prefix">The string to use as indentation.</param>
+ /// <returns>The string with indentation added.</returns>
+ public static string Indent(this string instance, string prefix)
{
- return instance.Insert(pos, what);
+ var sb = new StringBuilder();
+ int lineStart = 0;
+
+ for (int i = 0; i < instance.Length; i++)
+ {
+ char c = instance[i];
+ if (c == '\n')
+ {
+ if (i == lineStart)
+ {
+ sb.Append(c); // Leave empty lines empty.
+ }
+ else
+ {
+ sb.Append(prefix);
+ sb.Append(instance.Substring(lineStart, i - lineStart + 1));
+ }
+ lineStart = i + 1;
+ }
+ }
+ if (lineStart != instance.Length)
+ {
+ sb.Append(prefix);
+ sb.Append(instance.Substring(lineStart));
+ }
+ return sb.ToString();
}
/// <summary>
@@ -875,19 +939,94 @@ namespace Godot
return instance.IsSubsequenceOf(text, caseSensitive: false);
}
+ private static readonly char[] _invalidFileNameCharacters = { ':', '/', '\\', '?', '*', '"', '|', '%', '<', '>' };
+
/// <summary>
- /// Check whether the string contains a valid <see langword="float"/>.
+ /// Returns <see langword="true"/> if this string is free from characters that
+ /// aren't allowed in file names.
/// </summary>
/// <param name="instance">The string to check.</param>
+ /// <returns>If the string contains a valid file name.</returns>
+ public static bool IsValidFileName(this string instance)
+ {
+ var stripped = instance.Trim();
+ if (instance != stripped)
+ return false;
+
+ if (string.IsNullOrEmpty(stripped))
+ return false;
+
+ return instance.IndexOfAny(_invalidFileNameCharacters) == -1;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this string contains a valid <see langword="float"/>.
+ /// This is inclusive of integers, and also supports exponents.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print("1.7".IsValidFloat()) // Prints "True"
+ /// GD.Print("24".IsValidFloat()) // Prints "True"
+ /// GD.Print("7e3".IsValidFloat()) // Prints "True"
+ /// GD.Print("Hello".IsValidFloat()) // Prints "False"
+ /// </code>
+ /// </example>
+ /// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid floating point number.</returns>
public static bool IsValidFloat(this string instance)
{
- float f;
- return float.TryParse(instance, out f);
+ return float.TryParse(instance, out _);
}
/// <summary>
- /// Check whether the string contains a valid color in HTML notation.
+ /// Returns <see langword="true"/> if this string contains a valid hexadecimal number.
+ /// If <paramref name="withPrefix"/> is <see langword="true"/>, then a validity of the
+ /// hexadecimal number is determined by <c>0x</c> prefix, for instance: <c>0xDEADC0DE</c>.
+ /// </summary>
+ /// <param name="instance">The string to check.</param>
+ /// <param name="withPrefix">If the string must contain the <c>0x</c> prefix to be valid.</param>
+ /// <returns>If the string contains a valid hexadecimal number.</returns>
+ public static bool IsValidHexNumber(this string instance, bool withPrefix = false)
+ {
+ if (string.IsNullOrEmpty(instance))
+ return false;
+
+ int from = 0;
+ if (instance.Length != 1 && instance[0] == '+' || instance[0] == '-')
+ {
+ from++;
+ }
+
+ if (withPrefix)
+ {
+ if (instance.Length < 3)
+ return false;
+ if (instance[from] != '0' || instance[from + 1] != 'x')
+ return false;
+ from += 2;
+ }
+
+ for (int i = from; i < instance.Length; i++)
+ {
+ char c = instance[i];
+ if (IsHexDigit(c))
+ continue;
+
+ return false;
+ }
+
+ return true;
+
+ static bool IsHexDigit(char c)
+ {
+ return char.IsDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+ }
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this string contains a valid color in hexadecimal
+ /// HTML notation. Other HTML notations such as named colors or <c>hsl()</c> aren't
+ /// considered valid by this method and will return <see langword="false"/>.
/// </summary>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid HTML color.</returns>
@@ -897,10 +1036,17 @@ namespace Godot
}
/// <summary>
- /// Check whether the string is a valid identifier. As is common in
- /// programming languages, a valid identifier may contain only letters,
- /// digits and underscores (_) and the first character may not be a digit.
+ /// Returns <see langword="true"/> if this string is a valid identifier.
+ /// A valid identifier may contain only letters, digits and underscores (<c>_</c>)
+ /// and the first character may not be a digit.
/// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print("good_ident_1".IsValidIdentifier()) // Prints "True"
+ /// GD.Print("1st_bad_ident".IsValidIdentifier()) // Prints "False"
+ /// GD.Print("bad_ident_#2".IsValidIdentifier()) // Prints "False"
+ /// </code>
+ /// </example>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid identifier.</returns>
public static bool IsValidIdentifier(this string instance)
@@ -928,38 +1074,73 @@ namespace Godot
}
/// <summary>
- /// Check whether the string contains a valid integer.
+ /// Returns <see langword="true"/> if this string contains a valid <see langword="int"/>.
/// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print("7".IsValidInt()) // Prints "True"
+ /// GD.Print("14.6".IsValidInt()) // Prints "False"
+ /// GD.Print("L".IsValidInt()) // Prints "False"
+ /// GD.Print("+3".IsValidInt()) // Prints "True"
+ /// GD.Print("-12".IsValidInt()) // Prints "True"
+ /// </code>
+ /// </example>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid integer.</returns>
- public static bool IsValidInteger(this string instance)
+ public static bool IsValidInt(this string instance)
{
- int f;
- return int.TryParse(instance, out f);
+ return int.TryParse(instance, out _);
}
/// <summary>
- /// Check whether the string contains a valid IP address.
+ /// Returns <see langword="true"/> if this string contains only a well-formatted
+ /// IPv4 or IPv6 address. This method considers reserved IP addresses such as
+ /// <c>0.0.0.0</c> as valid.
/// </summary>
/// <param name="instance">The string to check.</param>
/// <returns>If the string contains a valid IP address.</returns>
public static bool IsValidIPAddress(this string instance)
{
- // TODO: Support IPv6 addresses
- string[] ip = instance.Split(".");
+ if (instance.Contains(':'))
+ {
+ string[] ip = instance.Split(':');
- if (ip.Length != 4)
- return false;
+ for (int i = 0; i < ip.Length; i++)
+ {
+ string n = ip[i];
+ if (n.Length == 0)
+ continue;
+
+ if (n.IsValidHexNumber(withPrefix: false))
+ {
+ long nint = n.HexToInt();
+ if (nint < 0 || nint > 0xffff)
+ return false;
- for (int i = 0; i < ip.Length; i++)
+ continue;
+ }
+
+ if (!n.IsValidIPAddress())
+ return false;
+ }
+ }
+ else
{
- string n = ip[i];
- if (!n.IsValidInteger())
- return false;
+ string[] ip = instance.Split('.');
- int val = n.ToInt();
- if (val < 0 || val > 255)
+ if (ip.Length != 4)
return false;
+
+ for (int i = 0; i < ip.Length; i++)
+ {
+ string n = ip[i];
+ if (!n.IsValidInt())
+ return false;
+
+ int val = n.ToInt();
+ if (val < 0 || val > 255)
+ return false;
+ }
}
return true;
@@ -1005,44 +1186,6 @@ namespace Godot
}
/// <summary>
- /// Returns the length of the string in characters.
- /// </summary>
- /// <param name="instance">The string to check.</param>
- /// <returns>The length of the string.</returns>
- public static int Length(this string instance)
- {
- return instance.Length;
- }
-
- /// <summary>
- /// Returns a copy of the string with characters removed from the left.
- /// </summary>
- /// <seealso cref="RStrip(string, string)"/>
- /// <param name="instance">The string to remove characters from.</param>
- /// <param name="chars">The characters to be removed.</param>
- /// <returns>A copy of the string with characters removed from the left.</returns>
- public static string LStrip(this string instance, string chars)
- {
- int len = instance.Length;
- int beg;
-
- for (beg = 0; beg < len; beg++)
- {
- if (chars.Find(instance[beg]) == -1)
- {
- break;
- }
- }
-
- if (beg == 0)
- {
- return instance;
- }
-
- return instance.Substr(beg, len - beg);
- }
-
- /// <summary>
/// Do a simple expression match, where '*' matches zero or more
/// arbitrary characters and '?' matches any single character except '.'.
/// </summary>
@@ -1114,29 +1257,25 @@ namespace Godot
/// <summary>
/// Returns the MD5 hash of the string as an array of bytes.
/// </summary>
- /// <seealso cref="MD5Text(string)"/>
+ /// <seealso cref="Md5Text(string)"/>
/// <param name="instance">The string to hash.</param>
/// <returns>The MD5 hash of the string.</returns>
- public static byte[] MD5Buffer(this string instance)
+ public static byte[] Md5Buffer(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_md5_buffer(instanceStr, out var md5Buffer);
- using (md5Buffer)
- return Marshaling.ConvertNativePackedByteArrayToSystemArray(md5Buffer);
+#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms
+ return MD5.HashData(Encoding.UTF8.GetBytes(instance));
+#pragma warning restore CA5351
}
/// <summary>
/// Returns the MD5 hash of the string as a string.
/// </summary>
- /// <seealso cref="MD5Buffer(string)"/>
+ /// <seealso cref="Md5Buffer(string)"/>
/// <param name="instance">The string to hash.</param>
/// <returns>The MD5 hash of the string.</returns>
- public static string MD5Text(this string instance)
+ public static string Md5Text(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_md5_text(instanceStr, out var md5Text);
- using (md5Text)
- return Marshaling.ConvertStringToManaged(md5Text);
+ return instance.Md5Buffer().HexEncode();
}
/// <summary>
@@ -1153,17 +1292,6 @@ namespace Godot
}
/// <summary>
- /// Returns the character code at position <paramref name="at"/>.
- /// </summary>
- /// <param name="instance">The string to check.</param>
- /// <param name="at">The position int the string for the character to check.</param>
- /// <returns>The character code.</returns>
- public static int OrdAt(this string instance, int at)
- {
- return instance[at];
- }
-
- /// <summary>
/// Format a number to have an exact number of <paramref name="digits"/>
/// after the decimal point.
/// </summary>
@@ -1284,34 +1412,47 @@ namespace Godot
}
/// <summary>
- /// Perform a search for a substring, but start from the end of the string instead of the beginning.
+ /// Returns the index of the last occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing to
+ /// the beginning of the string.
/// </summary>
+ /// <seealso cref="Find(string, string, int, bool)"/>
+ /// <seealso cref="Find(string, char, int, bool)"/>
+ /// <seealso cref="FindN(string, string, int)"/>
/// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to search in the string.</param>
/// <param name="from">The position at which to start searching.</param>
+ /// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
/// <returns>The position at which the substring was found, or -1 if not found.</returns>
- public static int RFind(this string instance, string what, int from = -1)
+ public static int RFind(this string instance, string what, int from = -1, bool caseSensitive = true)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- using godot_string whatStr = Marshaling.ConvertStringToNative(instance);
- return NativeFuncs.godotsharp_string_rfind(instanceStr, whatStr, from);
+ if (from == -1)
+ from = instance.Length - 1;
+
+ return instance.LastIndexOf(what, from,
+ caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
/// <summary>
- /// Perform a search for a substring, but start from the end of the string instead of the beginning.
- /// Also search case-insensitive.
+ /// Returns the index of the last case-insensitive occurrence of the specified string in this instance,
+ /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing to
+ /// the beginning of the string.
/// </summary>
- /// <seealso cref="RFind(string, string, int)"/>
+ /// <seealso cref="Find(string, string, int, bool)"/>
+ /// <seealso cref="Find(string, char, int, bool)"/>
+ /// <seealso cref="FindN(string, string, int)"/>
+ /// <seealso cref="RFind(string, string, int, bool)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to search in the string.</param>
/// <param name="from">The position at which to start searching.</param>
/// <returns>The position at which the substring was found, or -1 if not found.</returns>
public static int RFindN(this string instance, string what, int from = -1)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- using godot_string whatStr = Marshaling.ConvertStringToNative(instance);
- return NativeFuncs.godotsharp_string_rfindn(instanceStr, whatStr, from);
+ if (from == -1)
+ from = instance.Length - 1;
+
+ return instance.LastIndexOf(what, from, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@@ -1333,59 +1474,49 @@ namespace Godot
}
/// <summary>
- /// Returns a copy of the string with characters removed from the right.
+ /// Returns the SHA-1 hash of the string as an array of bytes.
/// </summary>
- /// <seealso cref="LStrip(string, string)"/>
- /// <param name="instance">The string to remove characters from.</param>
- /// <param name="chars">The characters to be removed.</param>
- /// <returns>A copy of the string with characters removed from the right.</returns>
- public static string RStrip(this string instance, string chars)
+ /// <seealso cref="Sha1Text(string)"/>
+ /// <param name="instance">The string to hash.</param>
+ /// <returns>The SHA-1 hash of the string.</returns>
+ public static byte[] Sha1Buffer(this string instance)
{
- int len = instance.Length;
- int end;
-
- for (end = len - 1; end >= 0; end--)
- {
- if (chars.Find(instance[end]) == -1)
- {
- break;
- }
- }
-
- if (end == len - 1)
- {
- return instance;
- }
+#pragma warning disable CA5350 // Do Not Use Weak Cryptographic Algorithms
+ return SHA1.HashData(Encoding.UTF8.GetBytes(instance));
+#pragma warning restore CA5350
+ }
- return instance.Substr(0, end + 1);
+ /// <summary>
+ /// Returns the SHA-1 hash of the string as a string.
+ /// </summary>
+ /// <seealso cref="Sha1Buffer(string)"/>
+ /// <param name="instance">The string to hash.</param>
+ /// <returns>The SHA-1 hash of the string.</returns>
+ public static string Sha1Text(this string instance)
+ {
+ return instance.Sha1Buffer().HexEncode();
}
/// <summary>
/// Returns the SHA-256 hash of the string as an array of bytes.
/// </summary>
- /// <seealso cref="SHA256Text(string)"/>
+ /// <seealso cref="Sha256Text(string)"/>
/// <param name="instance">The string to hash.</param>
/// <returns>The SHA-256 hash of the string.</returns>
- public static byte[] SHA256Buffer(this string instance)
+ public static byte[] Sha256Buffer(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_sha256_buffer(instanceStr, out var sha256Buffer);
- using (sha256Buffer)
- return Marshaling.ConvertNativePackedByteArrayToSystemArray(sha256Buffer);
+ return SHA256.HashData(Encoding.UTF8.GetBytes(instance));
}
/// <summary>
/// Returns the SHA-256 hash of the string as a string.
/// </summary>
- /// <seealso cref="SHA256Buffer(string)"/>
+ /// <seealso cref="Sha256Buffer(string)"/>
/// <param name="instance">The string to hash.</param>
/// <returns>The SHA-256 hash of the string.</returns>
- public static string SHA256Text(this string instance)
+ public static string Sha256Text(this string instance)
{
- using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
- NativeFuncs.godotsharp_string_sha256_text(instanceStr, out var sha256Text);
- using (sha256Text)
- return Marshaling.ConvertStringToManaged(sha256Text);
+ return instance.Sha256Buffer().HexEncode();
}
/// <summary>
@@ -1457,7 +1588,7 @@ namespace Godot
/// <returns>The array of strings split from the string.</returns>
public static string[] Split(this string instance, string divisor, bool allowEmpty = true)
{
- return instance.Split(new[] { divisor },
+ return instance.Split(divisor,
allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
}
@@ -1505,8 +1636,10 @@ namespace Godot
};
/// <summary>
- /// Returns a copy of the string stripped of any non-printable character at the beginning and the end.
- /// The optional arguments are used to toggle stripping on the left and right edges respectively.
+ /// Returns a copy of the string stripped of any non-printable character
+ /// (including tabulations, spaces and line breaks) at the beginning and the end.
+ /// The optional arguments are used to toggle stripping on the left and right
+ /// edges respectively.
/// </summary>
/// <param name="instance">The string to strip.</param>
/// <param name="left">If the left side should be stripped.</param>
@@ -1524,6 +1657,30 @@ namespace Godot
return instance.TrimEnd(_nonPrintable);
}
+
+ /// <summary>
+ /// Returns a copy of the string stripped of any escape character.
+ /// These include all non-printable control characters of the first page
+ /// of the ASCII table (&lt; 32), such as tabulation (<c>\t</c>) and
+ /// newline (<c>\n</c> and <c>\r</c>) characters, but not spaces.
+ /// </summary>
+ /// <param name="instance">The string to strip.</param>
+ /// <returns>The string stripped of any escape characters.</returns>
+ public static string StripEscapes(this string instance)
+ {
+ var sb = new StringBuilder();
+ for (int i = 0; i < instance.Length; i++)
+ {
+ // Escape characters on first page of the ASCII table, before 32 (Space).
+ if (instance[i] < 32)
+ continue;
+
+ sb.Append(instance[i]);
+ }
+
+ return sb.ToString();
+ }
+
/// <summary>
/// Returns part of the string from the position <paramref name="from"/>, with length <paramref name="len"/>.
/// </summary>
@@ -1541,13 +1698,15 @@ namespace Godot
/// <summary>
/// Converts the String (which is a character array) to PackedByteArray (which is an array of bytes).
- /// The conversion is speeded up in comparison to <see cref="ToUTF8(string)"/> with the assumption
- /// that all the characters the String contains are only ASCII characters.
+ /// The conversion is faster compared to <see cref="ToUtf8Buffer(string)"/>,
+ /// as this method assumes that all the characters in the String are ASCII characters.
/// </summary>
- /// <seealso cref="ToUTF8(string)"/>
+ /// <seealso cref="ToUtf8Buffer(string)"/>
+ /// <seealso cref="ToUtf16Buffer(string)"/>
+ /// <seealso cref="ToUtf32Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
/// <returns>The string as ASCII encoded bytes.</returns>
- public static byte[] ToAscii(this string instance)
+ public static byte[] ToAsciiBuffer(this string instance)
{
return Encoding.ASCII.GetBytes(instance);
}
@@ -1575,41 +1734,76 @@ namespace Godot
}
/// <summary>
- /// Returns the string converted to lowercase.
+ /// Converts the string (which is an array of characters) to an UTF-16 encoded array of bytes.
/// </summary>
- /// <seealso cref="ToUpper(string)"/>
+ /// <seealso cref="ToAsciiBuffer(string)"/>
+ /// <seealso cref="ToUtf32Buffer(string)"/>
+ /// <seealso cref="ToUtf8Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
- /// <returns>The string converted to lowercase.</returns>
- public static string ToLower(this string instance)
+ /// <returns>The string as UTF-16 encoded bytes.</returns>
+ public static byte[] ToUtf16Buffer(this string instance)
{
- return instance.ToLower();
+ return Encoding.Unicode.GetBytes(instance);
}
/// <summary>
- /// Returns the string converted to uppercase.
+ /// Converts the string (which is an array of characters) to an UTF-32 encoded array of bytes.
/// </summary>
- /// <seealso cref="ToLower(string)"/>
+ /// <seealso cref="ToAsciiBuffer(string)"/>
+ /// <seealso cref="ToUtf16Buffer(string)"/>
+ /// <seealso cref="ToUtf8Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
- /// <returns>The string converted to uppercase.</returns>
- public static string ToUpper(this string instance)
+ /// <returns>The string as UTF-32 encoded bytes.</returns>
+ public static byte[] ToUtf32Buffer(this string instance)
{
- return instance.ToUpper();
+ return Encoding.UTF32.GetBytes(instance);
}
/// <summary>
- /// Converts the String (which is an array of characters) to PackedByteArray (which is an array of bytes).
- /// The conversion is a bit slower than <see cref="ToAscii(string)"/>, but supports all UTF-8 characters.
- /// Therefore, you should prefer this function over <see cref="ToAscii(string)"/>.
+ /// Converts the string (which is an array of characters) to an UTF-8 encoded array of bytes.
+ /// The conversion is a bit slower than <see cref="ToAsciiBuffer(string)"/>,
+ /// but supports all UTF-8 characters. Therefore, you should prefer this function
+ /// over <see cref="ToAsciiBuffer(string)"/>.
/// </summary>
- /// <seealso cref="ToAscii(string)"/>
+ /// <seealso cref="ToAsciiBuffer(string)"/>
+ /// <seealso cref="ToUtf16Buffer(string)"/>
+ /// <seealso cref="ToUtf32Buffer(string)"/>
/// <param name="instance">The string to convert.</param>
/// <returns>The string as UTF-8 encoded bytes.</returns>
- public static byte[] ToUTF8(this string instance)
+ public static byte[] ToUtf8Buffer(this string instance)
{
return Encoding.UTF8.GetBytes(instance);
}
/// <summary>
+ /// Removes a given string from the start if it starts with it or leaves the string unchanged.
+ /// </summary>
+ /// <param name="instance">The string to remove the prefix from.</param>
+ /// <param name="prefix">The string to remove from the start.</param>
+ /// <returns>A copy of the string with the prefix string removed from the start.</returns>
+ public static string TrimPrefix(this string instance, string prefix)
+ {
+ if (instance.StartsWith(prefix))
+ return instance.Substring(prefix.Length);
+
+ return instance;
+ }
+
+ /// <summary>
+ /// Removes a given string from the end if it ends with it or leaves the string unchanged.
+ /// </summary>
+ /// <param name="instance">The string to remove the suffix from.</param>
+ /// <param name="suffix">The string to remove from the end.</param>
+ /// <returns>A copy of the string with the suffix string removed from the end.</returns>
+ public static string TrimSuffix(this string instance, string suffix)
+ {
+ if (instance.EndsWith(suffix))
+ return instance.Substring(0, instance.Length - suffix.Length);
+
+ return instance;
+ }
+
+ /// <summary>
/// Decodes a string in URL encoded format. This is meant to
/// decode parameters in a URL when receiving an HTTP request.
/// This mostly wraps around <see cref="Uri.UnescapeDataString"/>,
@@ -1636,6 +1830,25 @@ namespace Godot
return Uri.EscapeDataString(instance);
}
+ private const string _uniqueNodePrefix = "%";
+ private static readonly string[] _invalidNodeNameCharacters = { ".", ":", "@", "/", "\"", _uniqueNodePrefix };
+
+ /// <summary>
+ /// Removes any characters from the string that are prohibited in
+ /// <see cref="Node"/> names (<c>.</c> <c>:</c> <c>@</c> <c>/</c> <c>"</c>).
+ /// </summary>
+ /// <param name="instance">The string to sanitize.</param>
+ /// <returns>The string sanitized as a valid node name.</returns>
+ public static string ValidateNodeName(this string instance)
+ {
+ string name = instance.Replace(_invalidNodeNameCharacters[0], "");
+ for (int i = 1; i < _invalidNodeNameCharacters.Length; i++)
+ {
+ name = name.Replace(_invalidNodeNameCharacters[i], "");
+ }
+ return name;
+ }
+
/// <summary>
/// Returns a copy of the string with special characters escaped using the XML standard.
/// </summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
index b9ee0bc278..97d28f9ee9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
@@ -10,7 +10,7 @@ namespace Godot
/// Comparing them is much faster than with regular strings, because only the pointers are compared,
/// not the whole strings.
/// </summary>
- public sealed class StringName : IDisposable
+ public sealed class StringName : IDisposable, IEquatable<StringName>
{
internal godot_string_name.movable NativeValue;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index 894667db76..d7392dbda8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -1,4 +1,5 @@
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Godot
@@ -18,61 +19,51 @@ namespace Godot
/// <summary>
/// The basis matrix's X vector (column 0). Equivalent to array index <c>[0]</c>.
/// </summary>
- public Vector2 x;
+ public Vector2 X;
/// <summary>
/// The basis matrix's Y vector (column 1). Equivalent to array index <c>[1]</c>.
/// </summary>
- public Vector2 y;
+ public Vector2 Y;
/// <summary>
/// The origin vector (column 2, the third column). Equivalent to array index <c>[2]</c>.
/// The origin vector represents translation.
/// </summary>
- public Vector2 origin;
+ public Vector2 Origin;
/// <summary>
- /// The rotation of this transformation matrix.
+ /// Returns the transform's rotation (in radians).
/// </summary>
- /// <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
+ public readonly real_t Rotation => Mathf.Atan2(X.Y, X.X);
+
+ /// <summary>
+ /// Returns the scale.
+ /// </summary>
+ public readonly Vector2 Scale
{
get
{
- return Mathf.Atan2(x.y, x.x);
- }
- set
- {
- Vector2 scale = Scale;
- x.x = y.y = Mathf.Cos(value);
- x.y = y.x = Mathf.Sin(value);
- y.x *= -1;
- Scale = scale;
+ real_t detSign = Mathf.Sign(BasisDeterminant());
+ return new Vector2(X.Length(), detSign * Y.Length());
}
}
/// <summary>
- /// The scale of this transformation matrix.
+ /// Returns the transform's skew (in radians).
/// </summary>
- /// <value>Equivalent to the lengths of each column vector, but Y is negative if the determinant is negative.</value>
- public Vector2 Scale
+ public readonly real_t Skew
{
get
{
real_t detSign = Mathf.Sign(BasisDeterminant());
- return new Vector2(x.Length(), detSign * y.Length());
- }
- set
- {
- value /= Scale; // Value becomes what's called "delta_scale" in core.
- x *= value.x;
- y *= value.y;
+ return Mathf.Acos(X.Normalized().Dot(detSign * Y.Normalized())) - Mathf.Pi * 0.5f;
}
}
/// <summary>
/// Access whole columns in the form of <see cref="Vector2"/>.
- /// The third column is the <see cref="origin"/> vector.
+ /// The third column is the <see cref="Origin"/> vector.
/// </summary>
/// <param name="column">Which column vector.</param>
/// <exception cref="ArgumentOutOfRangeException">
@@ -80,16 +71,16 @@ namespace Godot
/// </exception>
public Vector2 this[int column]
{
- get
+ readonly get
{
switch (column)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
case 2:
- return origin;
+ return Origin;
default:
throw new ArgumentOutOfRangeException(nameof(column));
}
@@ -99,13 +90,13 @@ namespace Godot
switch (column)
{
case 0:
- x = value;
+ X = value;
return;
case 1:
- y = value;
+ Y = value;
return;
case 2:
- origin = value;
+ Origin = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(column));
@@ -115,13 +106,13 @@ namespace Godot
/// <summary>
/// Access matrix elements in column-major order.
- /// The third column is the <see cref="origin"/> vector.
+ /// The third column is the <see cref="Origin"/> vector.
/// </summary>
/// <param name="column">Which column, the matrix horizontal position.</param>
/// <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 +130,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 +139,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,26 +161,27 @@ namespace Godot
/// and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
- private real_t BasisDeterminant()
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private readonly real_t BasisDeterminant()
{
- return (x.x * y.y) - (x.y * y.x);
+ return (X.X * Y.Y) - (X.Y * Y.X);
}
/// <summary>
/// Returns a vector transformed (multiplied) by the basis matrix.
- /// This method does not account for translation (the <see cref="origin"/> vector).
+ /// This method does not account for translation (the <see cref="Origin"/> vector).
/// </summary>
/// <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));
}
/// <summary>
/// Returns a vector transformed (multiplied) by the inverse basis matrix.
- /// This method does not account for translation (the <see cref="origin"/> vector).
+ /// This method does not account for translation (the <see cref="Origin"/> vector).
///
/// Note: This results in a multiplication by the inverse of the
/// basis matrix only if it represents a rotation-reflection.
@@ -198,9 +189,9 @@ 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));
+ return new Vector2(X.Dot(v), Y.Dot(v));
}
/// <summary>
@@ -209,47 +200,15 @@ 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;
-
- Vector2 s1 = Scale;
- Vector2 s2 = transform.Scale;
-
- // Slerp rotation
- var v1 = new Vector2(Mathf.Cos(r1), Mathf.Sin(r1));
- var v2 = new Vector2(Mathf.Cos(r2), Mathf.Sin(r2));
-
- real_t dot = v1.Dot(v2);
-
- dot = Mathf.Clamp(dot, -1.0f, 1.0f);
-
- Vector2 v;
-
- if (dot > 0.9995f)
- {
- // Linearly interpolate to avoid numerical precision issues
- v = v1.Lerp(v2, weight).Normalized();
- }
- else
- {
- real_t angle = weight * Mathf.Acos(dot);
- Vector2 v3 = (v2 - (v1 * dot)).Normalized();
- v = (v1 * Mathf.Cos(angle)) + (v3 * Mathf.Sin(angle));
- }
-
- // Extract parameters
- Vector2 p1 = origin;
- Vector2 p2 = transform.origin;
-
- // Construct matrix
- var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.Lerp(p2, weight));
- Vector2 scale = s1.Lerp(s2, weight);
- res.x *= scale;
- res.y *= scale;
-
- return res;
+ return new Transform2D
+ (
+ Mathf.LerpAngle(Rotation, transform.Rotation, weight),
+ Scale.Lerp(transform.Scale, weight),
+ Mathf.LerpAngle(Skew, transform.Skew, weight),
+ Origin.Lerp(transform.Origin, weight)
+ );
}
/// <summary>
@@ -258,40 +217,49 @@ 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);
+ inv.Origin = inv.BasisXform(-inv.Origin);
return inv;
}
/// <summary>
+ /// Returns <see langword="true"/> if this transform is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return X.IsFinite() && Y.IsFinite() && Origin.IsFinite();
+ }
+
+ /// <summary>
/// Returns the transform with the basis orthogonal (90 degrees),
/// 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;
+ Transform2D ortho = this;
- Vector2 onX = on.x;
- Vector2 onY = on.y;
+ Vector2 orthoX = ortho.X;
+ Vector2 orthoY = ortho.Y;
- onX.Normalize();
- onY = onY - (onX * onX.Dot(onY));
- onY.Normalize();
+ orthoX.Normalize();
+ orthoY = orthoY - orthoX * orthoX.Dot(orthoY);
+ orthoY.Normalize();
- on.x = onX;
- on.y = onY;
+ ortho.X = orthoX;
+ ortho.Y = orthoY;
- return on;
+ return ortho;
}
/// <summary>
@@ -301,9 +269,9 @@ 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());
+ return new Transform2D(angle, new Vector2()) * this;
}
/// <summary>
@@ -313,9 +281,9 @@ 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;
+ return this * new Transform2D(angle, new Vector2());
}
/// <summary>
@@ -325,12 +293,12 @@ 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;
- copy.y *= scale;
- copy.origin *= scale;
+ copy.X *= scale;
+ copy.Y *= scale;
+ copy.Origin *= scale;
return copy;
}
@@ -341,20 +309,20 @@ 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;
- copy.y *= scale;
+ copy.X *= scale;
+ copy.Y *= scale;
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,10 +334,10 @@ 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;
+ copy.Origin += offset;
return copy;
}
@@ -380,10 +348,10 @@ 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);
+ copy.Origin += copy.BasisXform(offset);
return copy;
}
@@ -418,26 +386,26 @@ namespace Godot
/// <param name="originPos">The origin vector, or column index 2.</param>
public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 originPos)
{
- x = xAxis;
- y = yAxis;
- origin = originPos;
+ X = xAxis;
+ Y = yAxis;
+ Origin = originPos;
}
/// <summary>
/// Constructs a transformation matrix from the given components.
- /// Arguments are named such that xy is equal to calling x.y
- /// </summary>
- /// <param name="xx">The X component of the X column vector, accessed via <c>t.x.x</c> or <c>[0][0]</c>.</param>
- /// <param name="xy">The Y component of the X column vector, accessed via <c>t.x.y</c> or <c>[0][1]</c>.</param>
- /// <param name="yx">The X component of the Y column vector, accessed via <c>t.y.x</c> or <c>[1][0]</c>.</param>
- /// <param name="yy">The Y component of the Y column vector, accessed via <c>t.y.y</c> or <c>[1][1]</c>.</param>
- /// <param name="ox">The X component of the origin vector, accessed via <c>t.origin.x</c> or <c>[2][0]</c>.</param>
- /// <param name="oy">The Y component of the origin vector, accessed via <c>t.origin.y</c> or <c>[2][1]</c>.</param>
+ /// Arguments are named such that xy is equal to calling <c>X.Y</c>.
+ /// </summary>
+ /// <param name="xx">The X component of the X column vector, accessed via <c>t.X.X</c> or <c>[0][0]</c>.</param>
+ /// <param name="xy">The Y component of the X column vector, accessed via <c>t.X.Y</c> or <c>[0][1]</c>.</param>
+ /// <param name="yx">The X component of the Y column vector, accessed via <c>t.Y.X</c> or <c>[1][0]</c>.</param>
+ /// <param name="yy">The Y component of the Y column vector, accessed via <c>t.Y.Y</c> or <c>[1][1]</c>.</param>
+ /// <param name="ox">The X component of the origin vector, accessed via <c>t.Origin.X</c> or <c>[2][0]</c>.</param>
+ /// <param name="oy">The Y component of the origin vector, accessed via <c>t.Origin.Y</c> or <c>[2][1]</c>.</param>
public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy)
{
- x = new Vector2(xx, xy);
- y = new Vector2(yx, yy);
- origin = new Vector2(ox, oy);
+ X = new Vector2(xx, xy);
+ Y = new Vector2(yx, yy);
+ Origin = new Vector2(ox, oy);
}
/// <summary>
@@ -448,10 +416,31 @@ namespace Godot
/// <param name="origin">The origin vector, or column index 2.</param>
public Transform2D(real_t rotation, Vector2 origin)
{
- x.x = y.y = Mathf.Cos(rotation);
- x.y = y.x = Mathf.Sin(rotation);
- y.x *= -1;
- this.origin = origin;
+ (real_t sin, real_t cos) = Mathf.SinCos(rotation);
+ X.X = Y.Y = cos;
+ X.Y = Y.X = sin;
+ Y.X *= -1;
+ Origin = origin;
+ }
+
+ /// <summary>
+ /// Constructs a transformation matrix from a <paramref name="rotation"/> value,
+ /// <paramref name="scale"/> vector, <paramref name="skew"/> value, and
+ /// <paramref name="origin"/> vector.
+ /// </summary>
+ /// <param name="rotation">The rotation of the new transform, in radians.</param>
+ /// <param name="scale">The scale of the new transform.</param>
+ /// <param name="skew">The skew of the new transform, in radians.</param>
+ /// <param name="origin">The origin vector, or column index 2.</param>
+ public Transform2D(real_t rotation, Vector2 scale, real_t skew, Vector2 origin)
+ {
+ (real_t rotationSin, real_t rotationCos) = Mathf.SinCos(rotation);
+ (real_t rotationSkewSin, real_t rotationSkewCos) = Mathf.SinCos(rotation + skew);
+ X.X = rotationCos * scale.X;
+ Y.Y = rotationSkewCos * scale.Y;
+ Y.X = -rotationSkewSin * scale.Y;
+ X.Y = rotationSin * scale.X;
+ Origin = origin;
}
/// <summary>
@@ -464,17 +453,17 @@ namespace Godot
/// <returns>The composed transform.</returns>
public static Transform2D operator *(Transform2D left, Transform2D right)
{
- left.origin = left * right.origin;
+ left.Origin = left * right.Origin;
- real_t x0 = left.Tdotx(right.x);
- real_t x1 = left.Tdoty(right.x);
- real_t y0 = left.Tdotx(right.y);
- real_t y1 = left.Tdoty(right.y);
+ real_t x0 = left.Tdotx(right.X);
+ real_t x1 = left.Tdoty(right.X);
+ real_t y0 = left.Tdotx(right.Y);
+ real_t y1 = left.Tdoty(right.Y);
- left.x.x = x0;
- left.x.y = x1;
- left.y.x = y0;
- left.y.y = y1;
+ left.X.X = x0;
+ left.X.Y = x1;
+ left.Y.X = y0;
+ left.Y.Y = y1;
return left;
}
@@ -487,7 +476,7 @@ namespace Godot
/// <returns>The transformed Vector2.</returns>
public static Vector2 operator *(Transform2D transform, Vector2 vector)
{
- return new Vector2(transform.Tdotx(vector), transform.Tdoty(vector)) + transform.origin;
+ return new Vector2(transform.Tdotx(vector), transform.Tdoty(vector)) + transform.Origin;
}
/// <summary>
@@ -498,8 +487,8 @@ namespace Godot
/// <returns>The inversely transformed Vector2.</returns>
public static Vector2 operator *(Vector2 vector, Transform2D transform)
{
- Vector2 vInv = vector - transform.origin;
- return new Vector2(transform.x.Dot(vInv), transform.y.Dot(vInv));
+ Vector2 vInv = vector - transform.Origin;
+ return new Vector2(transform.X.Dot(vInv), transform.Y.Dot(vInv));
}
/// <summary>
@@ -511,8 +500,8 @@ namespace Godot
public static Rect2 operator *(Transform2D transform, Rect2 rect)
{
Vector2 pos = transform * rect.Position;
- Vector2 toX = transform.x * rect.Size.x;
- Vector2 toY = transform.y * rect.Size.y;
+ Vector2 toX = transform.X * rect.Size.X;
+ Vector2 toY = transform.Y * rect.Size.Y;
return new Rect2(pos, new Vector2()).Expand(pos + toX).Expand(pos + toY).Expand(pos + toX + toY);
}
@@ -526,9 +515,9 @@ namespace Godot
public static Rect2 operator *(Rect2 rect, Transform2D transform)
{
Vector2 pos = rect.Position * transform;
- Vector2 to1 = new Vector2(rect.Position.x, rect.Position.y + rect.Size.y) * transform;
- Vector2 to2 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y + rect.Size.y) * transform;
- Vector2 to3 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y) * transform;
+ Vector2 to1 = new Vector2(rect.Position.X, rect.Position.Y + rect.Size.Y) * transform;
+ Vector2 to2 = new Vector2(rect.Position.X + rect.Size.X, rect.Position.Y + rect.Size.Y) * transform;
+ Vector2 to3 = new Vector2(rect.Position.X + rect.Size.X, rect.Position.Y) * transform;
return new Rect2(pos, new Vector2()).Expand(to1).Expand(to2).Expand(to3);
}
@@ -603,7 +592,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,9 +604,9 @@ 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);
+ return X.Equals(other.X) && Y.Equals(other.Y) && Origin.Equals(other.Origin);
}
/// <summary>
@@ -626,36 +615,36 @@ 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);
+ return X.IsEqualApprox(other.X) && Y.IsEqualApprox(other.Y) && Origin.IsEqualApprox(other.Origin);
}
/// <summary>
/// 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();
+ return X.GetHashCode() ^ Y.GetHashCode() ^ Origin.GetHashCode();
}
/// <summary>
/// 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}]";
+ return $"[X: {X}, Y: {Y}, O: {Origin}]";
}
/// <summary>
/// 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)}]";
+ 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..b34e95c04d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -6,7 +6,7 @@ namespace Godot
/// <summary>
/// 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations.
/// It can represent transformations such as translation, rotation, or scaling.
- /// It consists of a <see cref="Basis"/> (first 3 columns) and a
+ /// It consists of a <see cref="Godot.Basis"/> (first 3 columns) and a
/// <see cref="Vector3"/> for the origin (last column).
///
/// For more information, read this documentation article:
@@ -17,19 +17,19 @@ namespace Godot
public struct Transform3D : IEquatable<Transform3D>
{
/// <summary>
- /// The <see cref="Basis"/> of this transform. Contains the X, Y, and Z basis
+ /// The <see cref="Godot.Basis"/> of this transform. Contains the X, Y, and Z basis
/// vectors (columns 0 to 2) and is responsible for rotation and scale.
/// </summary>
- public Basis basis;
+ public Basis Basis;
/// <summary>
/// The origin vector (column 3, the fourth column). Equivalent to array index <c>[3]</c>.
/// </summary>
- public Vector3 origin;
+ public Vector3 Origin;
/// <summary>
/// Access whole columns in the form of <see cref="Vector3"/>.
- /// The fourth column is the <see cref="origin"/> vector.
+ /// The fourth column is the <see cref="Origin"/> vector.
/// </summary>
/// <param name="column">Which column vector.</param>
/// <exception cref="ArgumentOutOfRangeException">
@@ -37,18 +37,18 @@ namespace Godot
/// </exception>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
case 0:
- return basis.Column0;
+ return Basis.Column0;
case 1:
- return basis.Column1;
+ return Basis.Column1;
case 2:
- return basis.Column2;
+ return Basis.Column2;
case 3:
- return origin;
+ return Origin;
default:
throw new ArgumentOutOfRangeException(nameof(column));
}
@@ -58,16 +58,16 @@ namespace Godot
switch (column)
{
case 0:
- basis.Column0 = value;
+ Basis.Column0 = value;
return;
case 1:
- basis.Column1 = value;
+ Basis.Column1 = value;
return;
case 2:
- basis.Column2 = value;
+ Basis.Column2 = value;
return;
case 3:
- origin = value;
+ Origin = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(column));
@@ -77,28 +77,28 @@ namespace Godot
/// <summary>
/// Access matrix elements in column-major order.
- /// The fourth column is the <see cref="origin"/> vector.
+ /// The fourth column is the <see cref="Origin"/> vector.
/// </summary>
/// <param name="column">Which column, the matrix horizontal position.</param>
/// <param name="row">Which row, the matrix vertical position.</param>
public real_t this[int column, int row]
{
- get
+ readonly get
{
if (column == 3)
{
- return origin[row];
+ return Origin[row];
}
- return basis[column, row];
+ return Basis[column, row];
}
set
{
if (column == 3)
{
- origin[row] = value;
+ Origin[row] = value;
return;
}
- basis[column, row] = value;
+ Basis[column, row] = value;
}
}
@@ -108,23 +108,37 @@ 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);
+ Basis basisInv = Basis.Inverse();
+ return new Transform3D(basisInv, basisInv * -Origin);
}
/// <summary>
- /// Interpolates this transform to the other <paramref name="transform"/> by <paramref name="weight"/>.
+ /// Returns a transform interpolated between this transform and another
+ /// <paramref name="transform"/> by a given <paramref name="weight"/>
+ /// (on the range of 0.0 to 1.0).
/// </summary>
/// <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);
- return new Transform3D(retBasis, retOrigin);
+ Vector3 sourceScale = Basis.Scale;
+ Quaternion sourceRotation = Basis.GetRotationQuaternion();
+ Vector3 sourceLocation = Origin;
+
+ Vector3 destinationScale = transform.Basis.Scale;
+ Quaternion destinationRotation = transform.Basis.GetRotationQuaternion();
+ Vector3 destinationLocation = transform.Origin;
+
+ var interpolated = new Transform3D();
+ Quaternion quaternion = sourceRotation.Slerp(destinationRotation, weight).Normalized();
+ Vector3 scale = sourceScale.Lerp(destinationScale, weight);
+ interpolated.Basis.SetQuaternionScale(quaternion, scale);
+ interpolated.Origin = sourceLocation.Lerp(destinationLocation, weight);
+
+ return interpolated;
}
/// <summary>
@@ -133,10 +147,20 @@ 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);
+ Basis basisTr = Basis.Transposed();
+ return new Transform3D(basisTr, basisTr * -Origin);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this transform is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return Basis.IsFinite() && Origin.IsFinite();
}
/// <summary>
@@ -155,7 +179,7 @@ namespace Godot
public readonly Transform3D LookingAt(Vector3 target, Vector3 up)
{
Transform3D t = this;
- t.SetLookAt(origin, target, up);
+ t.SetLookAt(Origin, target, up);
return t;
}
@@ -164,9 +188,9 @@ 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);
+ return new Transform3D(Basis.Orthonormalized(), Origin);
}
/// <summary>
@@ -192,10 +216,10 @@ 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);
+ return new Transform3D(Basis * tmpBasis, Origin);
}
/// <summary>
@@ -205,9 +229,9 @@ 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);
+ return new Transform3D(Basis.Scaled(scale), Origin * scale);
}
/// <summary>
@@ -217,38 +241,10 @@ 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);
- }
-
- /// <summary>
- /// Returns a transform spherically interpolated between this transform and
- /// another <paramref name="transform"/> by <paramref name="weight"/>.
- /// </summary>
- /// <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)
- {
- /* not sure if very "efficient" but good enough? */
-
- Vector3 sourceScale = basis.Scale;
- Quaternion sourceRotation = basis.GetRotationQuaternion();
- Vector3 sourceLocation = origin;
-
- Vector3 destinationScale = transform.basis.Scale;
- Quaternion destinationRotation = transform.basis.GetRotationQuaternion();
- Vector3 destinationLocation = transform.origin;
-
- var interpolated = new Transform3D();
- Quaternion quaternion = sourceRotation.Slerp(destinationRotation, weight).Normalized();
- Vector3 scale = sourceScale.Lerp(destinationScale, weight);
- interpolated.basis.SetQuaternionScale(quaternion, scale);
- interpolated.origin = sourceLocation.Lerp(destinationLocation, weight);
-
- return interpolated;
+ return new Transform3D(Basis * tmpBasis, Origin);
}
private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
@@ -269,9 +265,9 @@ namespace Godot
column0.Normalize();
column1.Normalize();
- basis = new Basis(column0, column1, column2);
+ Basis = new Basis(column0, column1, column2);
- origin = eye;
+ Origin = eye;
}
/// <summary>
@@ -281,9 +277,9 @@ 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);
+ return new Transform3D(Basis, Origin + offset);
}
/// <summary>
@@ -293,13 +289,13 @@ 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
+ return new Transform3D(Basis, new Vector3
(
- origin[0] + basis.Row0.Dot(offset),
- origin[1] + basis.Row1.Dot(offset),
- origin[2] + basis.Row2.Dot(offset)
+ Origin[0] + Basis.Row0.Dot(offset),
+ Origin[1] + Basis.Row1.Dot(offset),
+ Origin[2] + Basis.Row2.Dot(offset)
));
}
@@ -341,32 +337,65 @@ namespace Godot
/// <param name="origin">The origin vector, or column index 3.</param>
public Transform3D(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
{
- basis = new Basis(column0, column1, column2);
- this.origin = origin;
+ Basis = new Basis(column0, column1, column2);
+ Origin = origin;
}
/// <summary>
- /// Constructs a transformation matrix from the given <paramref name="quaternion"/>
- /// and <paramref name="origin"/> vector.
+ /// Constructs a transformation matrix from the given components.
+ /// Arguments are named such that xy is equal to calling <c>Basis.X.Y</c>.
/// </summary>
- /// <param name="quaternion">The <see cref="Quaternion"/> to create the basis from.</param>
- /// <param name="origin">The origin vector, or column index 3.</param>
- public Transform3D(Quaternion quaternion, Vector3 origin)
+ /// <param name="xx">The X component of the X column vector, accessed via <c>t.Basis.X.X</c> or <c>[0][0]</c>.</param>
+ /// <param name="yx">The X component of the Y column vector, accessed via <c>t.Basis.Y.X</c> or <c>[1][0]</c>.</param>
+ /// <param name="zx">The X component of the Z column vector, accessed via <c>t.Basis.Z.X</c> or <c>[2][0]</c>.</param>
+ /// <param name="xy">The Y component of the X column vector, accessed via <c>t.Basis.X.Y</c> or <c>[0][1]</c>.</param>
+ /// <param name="yy">The Y component of the Y column vector, accessed via <c>t.Basis.Y.Y</c> or <c>[1][1]</c>.</param>
+ /// <param name="zy">The Y component of the Z column vector, accessed via <c>t.Basis.Y.Y</c> or <c>[2][1]</c>.</param>
+ /// <param name="xz">The Z component of the X column vector, accessed via <c>t.Basis.X.Y</c> or <c>[0][2]</c>.</param>
+ /// <param name="yz">The Z component of the Y column vector, accessed via <c>t.Basis.Y.Y</c> or <c>[1][2]</c>.</param>
+ /// <param name="zz">The Z component of the Z column vector, accessed via <c>t.Basis.Y.Y</c> or <c>[2][2]</c>.</param>
+ /// <param name="ox">The X component of the origin vector, accessed via <c>t.Origin.X</c> or <c>[2][0]</c>.</param>
+ /// <param name="oy">The Y component of the origin vector, accessed via <c>t.Origin.Y</c> or <c>[2][1]</c>.</param>
+ /// <param name="oz">The Z component of the origin vector, accessed via <c>t.Origin.Z</c> or <c>[2][2]</c>.</param>
+ public Transform3D(real_t xx, real_t yx, real_t zx, real_t xy, real_t yy, real_t zy, real_t xz, real_t yz, real_t zz, real_t ox, real_t oy, real_t oz)
{
- basis = new Basis(quaternion);
- this.origin = origin;
+ Basis = new Basis(xx, yx, zx, xy, yy, zy, xz, yz, zz);
+ Origin = new Vector3(ox, oy, oz);
}
/// <summary>
/// Constructs a transformation matrix from the given <paramref name="basis"/> and
/// <paramref name="origin"/> vector.
/// </summary>
- /// <param name="basis">The <see cref="Basis"/> to create the basis from.</param>
+ /// <param name="basis">The <see cref="Godot.Basis"/> to create the basis from.</param>
/// <param name="origin">The origin vector, or column index 3.</param>
public Transform3D(Basis basis, Vector3 origin)
{
- this.basis = basis;
- this.origin = origin;
+ Basis = basis;
+ Origin = origin;
+ }
+
+ /// <summary>
+ /// Constructs a transformation matrix from the given <paramref name="projection"/>
+ /// by trimming the last row of the projection matrix (<c>projection.X.W</c>,
+ /// <c>projection.Y.W</c>, <c>projection.Z.W</c>, and <c>projection.W.W</c>
+ /// are not copied over).
+ /// </summary>
+ /// <param name="projection">The <see cref="Projection"/> to create the transform from.</param>
+ public Transform3D(Projection projection)
+ {
+ Basis = new Basis
+ (
+ projection.X.X, projection.Y.X, projection.Z.X,
+ projection.X.Y, projection.Y.Y, projection.Z.Y,
+ projection.X.Z, projection.Y.Z, projection.Z.Z
+ );
+ Origin = new Vector3
+ (
+ projection.W.X,
+ projection.W.Y,
+ projection.W.Z
+ );
}
/// <summary>
@@ -379,8 +408,8 @@ namespace Godot
/// <returns>The composed transform.</returns>
public static Transform3D operator *(Transform3D left, Transform3D right)
{
- left.origin = left * right.origin;
- left.basis *= right.basis;
+ left.Origin = left * right.Origin;
+ left.Basis *= right.Basis;
return left;
}
@@ -394,9 +423,9 @@ namespace Godot
{
return new Vector3
(
- transform.basis.Row0.Dot(vector) + transform.origin.x,
- transform.basis.Row1.Dot(vector) + transform.origin.y,
- transform.basis.Row2.Dot(vector) + transform.origin.z
+ transform.Basis.Row0.Dot(vector) + transform.Origin.X,
+ transform.Basis.Row1.Dot(vector) + transform.Origin.Y,
+ transform.Basis.Row2.Dot(vector) + transform.Origin.Z
);
}
@@ -411,13 +440,13 @@ namespace Godot
/// <returns>The inversely transformed Vector3.</returns>
public static Vector3 operator *(Vector3 vector, Transform3D transform)
{
- Vector3 vInv = vector - transform.origin;
+ Vector3 vInv = vector - transform.Origin;
return new Vector3
(
- (transform.basis.Row0[0] * vInv.x) + (transform.basis.Row1[0] * vInv.y) + (transform.basis.Row2[0] * vInv.z),
- (transform.basis.Row0[1] * vInv.x) + (transform.basis.Row1[1] * vInv.y) + (transform.basis.Row2[1] * vInv.z),
- (transform.basis.Row0[2] * vInv.x) + (transform.basis.Row1[2] * vInv.y) + (transform.basis.Row2[2] * vInv.z)
+ (transform.Basis.Row0[0] * vInv.X) + (transform.Basis.Row1[0] * vInv.Y) + (transform.Basis.Row2[0] * vInv.Z),
+ (transform.Basis.Row0[1] * vInv.X) + (transform.Basis.Row1[1] * vInv.Y) + (transform.Basis.Row2[1] * vInv.Z),
+ (transform.Basis.Row0[2] * vInv.X) + (transform.Basis.Row1[2] * vInv.Y) + (transform.Basis.Row2[2] * vInv.Z)
);
}
@@ -427,19 +456,19 @@ namespace Godot
/// <param name="transform">The transformation to apply.</param>
/// <param name="aabb">An AABB to transform.</param>
/// <returns>The transformed AABB.</returns>
- public static AABB operator *(Transform3D transform, AABB aabb)
+ public static Aabb operator *(Transform3D transform, Aabb aabb)
{
Vector3 min = aabb.Position;
Vector3 max = aabb.Position + aabb.Size;
- Vector3 tmin = transform.origin;
- Vector3 tmax = transform.origin;
+ Vector3 tmin = transform.Origin;
+ Vector3 tmax = transform.Origin;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
- real_t e = transform.basis[i][j] * min[j];
- real_t f = transform.basis[i][j] * max[j];
+ real_t e = transform.Basis[i][j] * min[j];
+ real_t f = transform.Basis[i][j] * max[j];
if (e < f)
{
tmin[i] += e;
@@ -453,7 +482,7 @@ namespace Godot
}
}
- return new AABB(tmin, tmax - tmin);
+ return new Aabb(tmin, tmax - tmin);
}
/// <summary>
@@ -462,18 +491,18 @@ namespace Godot
/// <param name="aabb">An AABB to inversely transform.</param>
/// <param name="transform">The transformation to apply.</param>
/// <returns>The inversely transformed AABB.</returns>
- public static AABB operator *(AABB aabb, Transform3D transform)
+ public static Aabb operator *(Aabb aabb, Transform3D transform)
{
- Vector3 pos = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y + aabb.Size.y, aabb.Position.z + aabb.Size.z) * transform;
- Vector3 to1 = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y + aabb.Size.y, aabb.Position.z) * transform;
- Vector3 to2 = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y, aabb.Position.z + aabb.Size.z) * transform;
- Vector3 to3 = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y, aabb.Position.z) * transform;
- Vector3 to4 = new Vector3(aabb.Position.x, aabb.Position.y + aabb.Size.y, aabb.Position.z + aabb.Size.z) * transform;
- Vector3 to5 = new Vector3(aabb.Position.x, aabb.Position.y + aabb.Size.y, aabb.Position.z) * transform;
- Vector3 to6 = new Vector3(aabb.Position.x, aabb.Position.y, aabb.Position.z + aabb.Size.z) * transform;
- Vector3 to7 = new Vector3(aabb.Position.x, aabb.Position.y, aabb.Position.z) * transform;
+ Vector3 pos = new Vector3(aabb.Position.X + aabb.Size.X, aabb.Position.Y + aabb.Size.Y, aabb.Position.Z + aabb.Size.Z) * transform;
+ Vector3 to1 = new Vector3(aabb.Position.X + aabb.Size.X, aabb.Position.Y + aabb.Size.Y, aabb.Position.Z) * transform;
+ Vector3 to2 = new Vector3(aabb.Position.X + aabb.Size.X, aabb.Position.Y, aabb.Position.Z + aabb.Size.Z) * transform;
+ Vector3 to3 = new Vector3(aabb.Position.X + aabb.Size.X, aabb.Position.Y, aabb.Position.Z) * transform;
+ Vector3 to4 = new Vector3(aabb.Position.X, aabb.Position.Y + aabb.Size.Y, aabb.Position.Z + aabb.Size.Z) * transform;
+ Vector3 to5 = new Vector3(aabb.Position.X, aabb.Position.Y + aabb.Size.Y, aabb.Position.Z) * transform;
+ Vector3 to6 = new Vector3(aabb.Position.X, aabb.Position.Y, aabb.Position.Z + aabb.Size.Z) * transform;
+ Vector3 to7 = new Vector3(aabb.Position.X, aabb.Position.Y, aabb.Position.Z) * transform;
- return new AABB(pos, new Vector3()).Expand(to1).Expand(to2).Expand(to3).Expand(to4).Expand(to5).Expand(to6).Expand(to7);
+ return new Aabb(pos, new Vector3()).Expand(to1).Expand(to2).Expand(to3).Expand(to4).Expand(to5).Expand(to6).Expand(to7);
}
/// <summary>
@@ -484,7 +513,7 @@ namespace Godot
/// <returns>The transformed Plane.</returns>
public static Plane operator *(Transform3D transform, Plane plane)
{
- Basis bInvTrans = transform.basis.Inverse().Transposed();
+ Basis bInvTrans = transform.Basis.Inverse().Transposed();
// Transform a single point on the plane.
Vector3 point = transform * (plane.Normal * plane.D);
@@ -505,7 +534,7 @@ namespace Godot
public static Plane operator *(Plane plane, Transform3D transform)
{
Transform3D tInv = transform.AffineInverse();
- Basis bTrans = transform.basis.Transposed();
+ Basis bTrans = transform.Basis.Transposed();
// Transform a single point on the plane.
Vector3 point = tInv * (plane.Normal * plane.D);
@@ -608,7 +637,7 @@ namespace Godot
/// <returns>Whether or not the matrices are exactly equal.</returns>
public readonly bool Equals(Transform3D other)
{
- return basis.Equals(other.basis) && origin.Equals(other.origin);
+ return Basis.Equals(other.Basis) && Origin.Equals(other.Origin);
}
/// <summary>
@@ -617,36 +646,36 @@ 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);
+ return Basis.IsEqualApprox(other.Basis) && Origin.IsEqualApprox(other.Origin);
}
/// <summary>
/// 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();
+ return Basis.GetHashCode() ^ Origin.GetHashCode();
}
/// <summary>
/// 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}]";
+ return $"[X: {Basis.X}, Y: {Basis.Y}, Z: {Basis.Z}, O: {Origin}]";
}
/// <summary>
/// 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)}]";
+ 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/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs
index d354509dbf..9aad965ad0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs
@@ -60,13 +60,13 @@ public partial struct Variant : IDisposable
case Type.Int:
case Type.Float:
case Type.Vector2:
- case Type.Vector2i:
+ case Type.Vector2I:
case Type.Rect2:
- case Type.Rect2i:
+ case Type.Rect2I:
case Type.Vector3:
- case Type.Vector3i:
+ case Type.Vector3I:
case Type.Vector4:
- case Type.Vector4i:
+ case Type.Vector4I:
case Type.Plane:
case Type.Quaternion:
case Type.Color:
@@ -109,16 +109,58 @@ public partial struct Variant : IDisposable
public override string ToString() => AsString();
- public object? Obj
- {
- get
+ public object? Obj =>
+ _obj ??= NativeVar.DangerousSelfRef.Type switch
{
- if (_obj == null)
- _obj = Marshaling.ConvertVariantToManagedObject((godot_variant)NativeVar);
-
- return _obj;
- }
- }
+ Type.Bool => AsBool(),
+ Type.Int => AsInt64(),
+ Type.Float => AsDouble(),
+ Type.String => AsString(),
+ Type.Vector2 => AsVector2(),
+ Type.Vector2I => AsVector2I(),
+ Type.Rect2 => AsRect2(),
+ Type.Rect2I => AsRect2I(),
+ Type.Vector3 => AsVector3(),
+ Type.Vector3I => AsVector3I(),
+ Type.Transform2D => AsTransform2D(),
+ Type.Vector4 => AsVector4(),
+ Type.Vector4I => AsVector4I(),
+ Type.Plane => AsPlane(),
+ Type.Quaternion => AsQuaternion(),
+ Type.Aabb => AsAabb(),
+ Type.Basis => AsBasis(),
+ Type.Transform3D => AsTransform3D(),
+ Type.Projection => AsProjection(),
+ Type.Color => AsColor(),
+ Type.StringName => AsStringName(),
+ Type.NodePath => AsNodePath(),
+ Type.Rid => AsRid(),
+ Type.Object => AsGodotObject(),
+ Type.Callable => AsCallable(),
+ Type.Signal => AsSignal(),
+ Type.Dictionary => AsGodotDictionary(),
+ Type.Array => AsGodotArray(),
+ Type.PackedByteArray => AsByteArray(),
+ Type.PackedInt32Array => AsInt32Array(),
+ Type.PackedInt64Array => AsInt64Array(),
+ Type.PackedFloat32Array => AsFloat32Array(),
+ Type.PackedFloat64Array => AsFloat64Array(),
+ Type.PackedStringArray => AsStringArray(),
+ Type.PackedVector2Array => AsVector2Array(),
+ Type.PackedVector3Array => AsVector3Array(),
+ Type.PackedColorArray => AsColorArray(),
+ Type.Nil => null,
+ Type.Max or _ =>
+ throw new InvalidOperationException($"Invalid Variant type: {NativeVar.DangerousSelfRef.Type}"),
+ };
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Variant From<[MustBeVariant] T>(in T from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFrom(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public T As<[MustBeVariant] T>() =>
+ VariantUtils.ConvertTo<T>(NativeVar.DangerousSelfRef);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool AsBool() =>
@@ -170,23 +212,23 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string AsString() =>
- VariantUtils.ConvertToStringObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToString((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 AsVector2() =>
VariantUtils.ConvertToVector2((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector2i AsVector2i() =>
- VariantUtils.ConvertToVector2i((godot_variant)NativeVar);
+ public Vector2I AsVector2I() =>
+ VariantUtils.ConvertToVector2I((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rect2 AsRect2() =>
VariantUtils.ConvertToRect2((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Rect2i AsRect2i() =>
- VariantUtils.ConvertToRect2i((godot_variant)NativeVar);
+ public Rect2I AsRect2I() =>
+ VariantUtils.ConvertToRect2I((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Transform2D AsTransform2D() =>
@@ -197,8 +239,8 @@ public partial struct Variant : IDisposable
VariantUtils.ConvertToVector3((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector3i AsVector3i() =>
- VariantUtils.ConvertToVector3i((godot_variant)NativeVar);
+ public Vector3I AsVector3I() =>
+ VariantUtils.ConvertToVector3I((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Basis AsBasis() =>
@@ -217,16 +259,16 @@ public partial struct Variant : IDisposable
VariantUtils.ConvertToVector4((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4i AsVector4i() =>
- VariantUtils.ConvertToVector4i((godot_variant)NativeVar);
+ public Vector4I AsVector4I() =>
+ VariantUtils.ConvertToVector4I((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Projection AsProjection() =>
VariantUtils.ConvertToProjection((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public AABB AsAABB() =>
- VariantUtils.ConvertToAABB((godot_variant)NativeVar);
+ public Aabb AsAabb() =>
+ VariantUtils.ConvertToAabb((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Color AsColor() =>
@@ -238,11 +280,11 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Callable AsCallable() =>
- VariantUtils.ConvertToCallableManaged((godot_variant)NativeVar);
+ VariantUtils.ConvertToCallable((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public SignalInfo AsSignalInfo() =>
- VariantUtils.ConvertToSignalInfo((godot_variant)NativeVar);
+ public Signal AsSignal() =>
+ VariantUtils.ConvertToSignal((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte[] AsByteArray() =>
@@ -282,16 +324,16 @@ public partial struct Variant : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T[] AsGodotObjectArray<T>()
- where T : Godot.Object =>
+ where T : GodotObject =>
VariantUtils.ConvertToSystemArrayOfGodotObject<T>((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Collections.Dictionary<TKey, TValue> AsGodotDictionary<TKey, TValue>() =>
- VariantUtils.ConvertToDictionaryObject<TKey, TValue>((godot_variant)NativeVar);
+ public Collections.Dictionary<TKey, TValue> AsGodotDictionary<[MustBeVariant] TKey, [MustBeVariant] TValue>() =>
+ VariantUtils.ConvertToDictionary<TKey, TValue>((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Collections.Array<T> AsGodotArray<T>() =>
- VariantUtils.ConvertToArrayObject<T>((godot_variant)NativeVar);
+ public Collections.Array<T> AsGodotArray<[MustBeVariant] T>() =>
+ VariantUtils.ConvertToArray<T>((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public StringName[] AsSystemArrayOfStringName() =>
@@ -302,32 +344,32 @@ public partial struct Variant : IDisposable
VariantUtils.ConvertToSystemArrayOfNodePath((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public RID[] AsSystemArrayOfRID() =>
- VariantUtils.ConvertToSystemArrayOfRID((godot_variant)NativeVar);
+ public Rid[] AsSystemArrayOfRid() =>
+ VariantUtils.ConvertToSystemArrayOfRid((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Godot.Object AsGodotObject() =>
+ public GodotObject AsGodotObject() =>
VariantUtils.ConvertToGodotObject((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public StringName AsStringName() =>
- VariantUtils.ConvertToStringNameObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToStringName((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public NodePath AsNodePath() =>
- VariantUtils.ConvertToNodePathObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToNodePath((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public RID AsRID() =>
- VariantUtils.ConvertToRID((godot_variant)NativeVar);
+ public Rid AsRid() =>
+ VariantUtils.ConvertToRid((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Collections.Dictionary AsGodotDictionary() =>
- VariantUtils.ConvertToDictionaryObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToDictionary((godot_variant)NativeVar);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Collections.Array AsGodotArray() =>
- VariantUtils.ConvertToArrayObject((godot_variant)NativeVar);
+ VariantUtils.ConvertToArray((godot_variant)NativeVar);
// Explicit conversion operators to supported types
@@ -374,13 +416,13 @@ public partial struct Variant : IDisposable
public static explicit operator Vector2(Variant from) => from.AsVector2();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator Vector2i(Variant from) => from.AsVector2i();
+ public static explicit operator Vector2I(Variant from) => from.AsVector2I();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Rect2(Variant from) => from.AsRect2();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator Rect2i(Variant from) => from.AsRect2i();
+ public static explicit operator Rect2I(Variant from) => from.AsRect2I();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Transform2D(Variant from) => from.AsTransform2D();
@@ -389,7 +431,7 @@ public partial struct Variant : IDisposable
public static explicit operator Vector3(Variant from) => from.AsVector3();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator Vector3i(Variant from) => from.AsVector3i();
+ public static explicit operator Vector3I(Variant from) => from.AsVector3I();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Basis(Variant from) => from.AsBasis();
@@ -404,13 +446,13 @@ public partial struct Variant : IDisposable
public static explicit operator Vector4(Variant from) => from.AsVector4();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator Vector4i(Variant from) => from.AsVector4i();
+ public static explicit operator Vector4I(Variant from) => from.AsVector4I();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Projection(Variant from) => from.AsProjection();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator AABB(Variant from) => from.AsAABB();
+ public static explicit operator Aabb(Variant from) => from.AsAabb();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Color(Variant from) => from.AsColor();
@@ -422,7 +464,7 @@ public partial struct Variant : IDisposable
public static explicit operator Callable(Variant from) => from.AsCallable();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator SignalInfo(Variant from) => from.AsSignalInfo();
+ public static explicit operator Signal(Variant from) => from.AsSignal();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator byte[](Variant from) => from.AsByteArray();
@@ -458,10 +500,10 @@ public partial struct Variant : IDisposable
public static explicit operator NodePath[](Variant from) => from.AsSystemArrayOfNodePath();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator RID[](Variant from) => from.AsSystemArrayOfRID();
+ public static explicit operator Rid[](Variant from) => from.AsSystemArrayOfRid();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator Godot.Object(Variant from) => from.AsGodotObject();
+ public static explicit operator GodotObject(Variant from) => from.AsGodotObject();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator StringName(Variant from) => from.AsStringName();
@@ -470,7 +512,7 @@ public partial struct Variant : IDisposable
public static explicit operator NodePath(Variant from) => from.AsNodePath();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator RID(Variant from) => from.AsRID();
+ public static explicit operator Rid(Variant from) => from.AsRid();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Collections.Dictionary(Variant from) => from.AsGodotDictionary();
@@ -524,13 +566,13 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(Vector2 from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(Vector2i from) => from;
+ public static Variant CreateFrom(Vector2I from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Rect2 from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(Rect2i from) => from;
+ public static Variant CreateFrom(Rect2I from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Transform2D from) => from;
@@ -539,7 +581,7 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(Vector3 from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(Vector3i from) => from;
+ public static Variant CreateFrom(Vector3I from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Basis from) => from;
@@ -554,13 +596,13 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(Vector4 from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(Vector4i from) => from;
+ public static Variant CreateFrom(Vector4I from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Projection from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(AABB from) => from;
+ public static Variant CreateFrom(Aabb from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Color from) => from;
@@ -572,7 +614,7 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(Callable from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(SignalInfo from) => from;
+ public static Variant CreateFrom(Signal from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Span<byte> from) => from;
@@ -602,14 +644,14 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(Span<Color> from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(Godot.Object[] from) => from;
+ public static Variant CreateFrom(GodotObject[] from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom<TKey, TValue>(Collections.Dictionary<TKey, TValue> from) =>
+ public static Variant CreateFrom<[MustBeVariant] TKey, [MustBeVariant] TValue>(Collections.Dictionary<TKey, TValue> from) =>
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromDictionary(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom<T>(Collections.Array<T> from) =>
+ public static Variant CreateFrom<[MustBeVariant] T>(Collections.Array<T> from) =>
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromArray(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -619,10 +661,10 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(Span<NodePath> from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(Span<RID> from) => from;
+ public static Variant CreateFrom(Span<Rid> from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(Godot.Object from) => from;
+ public static Variant CreateFrom(GodotObject from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(StringName from) => from;
@@ -631,7 +673,7 @@ public partial struct Variant : IDisposable
public static Variant CreateFrom(NodePath from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Variant CreateFrom(RID from) => from;
+ public static Variant CreateFrom(Rid from) => from;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Variant CreateFrom(Collections.Dictionary from) => from;
@@ -698,16 +740,16 @@ public partial struct Variant : IDisposable
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector2(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(Vector2i from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector2i(from));
+ public static implicit operator Variant(Vector2I from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector2I(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(Rect2 from) =>
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRect2(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(Rect2i from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRect2i(from));
+ public static implicit operator Variant(Rect2I from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRect2I(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(Transform2D from) =>
@@ -718,8 +760,8 @@ public partial struct Variant : IDisposable
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector3(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(Vector3i from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector3i(from));
+ public static implicit operator Variant(Vector3I from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector3I(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(Basis from) =>
@@ -738,16 +780,16 @@ public partial struct Variant : IDisposable
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector4(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(Vector4i from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector4i(from));
+ public static implicit operator Variant(Vector4I from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector4I(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(Projection from) =>
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromProjection(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(AABB from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromAABB(from));
+ public static implicit operator Variant(Aabb from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromAabb(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(Color from) =>
@@ -762,8 +804,8 @@ public partial struct Variant : IDisposable
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromCallable(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(SignalInfo from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignalInfo(from));
+ public static implicit operator Variant(Signal from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignal(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(byte[] from) =>
@@ -802,7 +844,7 @@ public partial struct Variant : IDisposable
(Variant)from.AsSpan();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(Godot.Object[] from) =>
+ public static implicit operator Variant(GodotObject[] from) =>
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfGodotObject(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -814,7 +856,7 @@ public partial struct Variant : IDisposable
(Variant)from.AsSpan();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(RID[] from) =>
+ public static implicit operator Variant(Rid[] from) =>
(Variant)from.AsSpan();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -862,11 +904,11 @@ public partial struct Variant : IDisposable
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfNodePath(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(Span<RID> from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfRID(from));
+ public static implicit operator Variant(Span<Rid> from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfRid(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(Godot.Object from) =>
+ public static implicit operator Variant(GodotObject from) =>
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromGodotObject(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -878,8 +920,8 @@ public partial struct Variant : IDisposable
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromNodePath(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Variant(RID from) =>
- CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRID(from));
+ public static implicit operator Variant(Rid from) =>
+ CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRid(from));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Variant(Collections.Dictionary from) =>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 87f397891e..0bf8f25f06 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -29,12 +29,12 @@ namespace Godot
/// <summary>
/// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
- public real_t x;
+ public real_t X;
/// <summary>
/// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
- public real_t y;
+ public real_t Y;
/// <summary>
/// Access vector components using their index.
@@ -43,19 +43,19 @@ namespace Godot
/// <paramref name="index"/> is not 0 or 1.
/// </exception>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="x"/>,
- /// <c>[1]</c> is equivalent to <see cref="y"/>.
+ /// <c>[0]</c> is equivalent to <see cref="X"/>,
+ /// <c>[1]</c> is equivalent to <see cref="Y"/>.
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -65,10 +65,10 @@ namespace Godot
switch (index)
{
case 0:
- x = value;
+ X = value;
return;
case 1:
- y = value;
+ Y = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -79,10 +79,10 @@ 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;
+ x = X;
+ y = Y;
}
internal void Normalize()
@@ -91,13 +91,13 @@ namespace Godot
if (lengthsq == 0)
{
- x = y = 0f;
+ X = Y = 0f;
}
else
{
real_t length = Mathf.Sqrt(lengthsq);
- x /= length;
- y /= length;
+ X /= length;
+ Y /= length;
}
}
@@ -105,21 +105,21 @@ 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));
+ return new Vector2(Mathf.Abs(X), Mathf.Abs(Y));
}
/// <summary>
/// Returns this vector's angle with respect to the X axis, or (1, 0) vector, in radians.
///
/// Equivalent to the result of <see cref="Mathf.Atan2(real_t, real_t)"/> when
- /// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
+ /// 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);
+ return Mathf.Atan2(Y, X);
}
/// <summary>
@@ -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,18 +137,18 @@ 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);
+ return Mathf.Atan2(to.Y - Y, to.X - X);
}
/// <summary>
- /// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
+ /// 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()
+ /// <returns>The <see cref="X"/> component divided by the <see cref="Y"/> component.</returns>
+ public readonly real_t Aspect()
{
- return x / y;
+ return X / Y;
}
/// <summary>
@@ -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,9 +165,9 @@ 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));
+ return new Vector2(Mathf.Ceil(X), Mathf.Ceil(Y));
}
/// <summary>
@@ -178,12 +178,12 @@ 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
(
- Mathf.Clamp(x, min.x, max.x),
- Mathf.Clamp(y, min.y, max.y)
+ Mathf.Clamp(X, min.X, max.X),
+ Mathf.Clamp(Y, min.Y, max.Y)
);
}
@@ -192,9 +192,9 @@ 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);
+ return (X * with.Y) - (Y * with.X);
}
/// <summary>
@@ -206,12 +206,12 @@ 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
(
- Mathf.CubicInterpolate(x, b.x, preA.x, postB.x, weight),
- Mathf.CubicInterpolate(y, b.y, preA.y, postB.y, weight)
+ Mathf.CubicInterpolate(X, b.X, preA.X, postB.X, weight),
+ Mathf.CubicInterpolate(Y, b.Y, preA.Y, postB.Y, weight)
);
}
@@ -229,34 +229,48 @@ 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
(
- Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT),
- Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT)
+ Mathf.CubicInterpolateInTime(X, b.X, preA.X, postB.X, weight, t, preAT, postBT),
+ Mathf.CubicInterpolateInTime(Y, b.Y, preA.Y, postB.Y, weight, t, preAT, postBT)
);
}
/// <summary>
/// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector
- /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
+ /// and the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
/// </summary>
/// <param name="control1">Control point that defines the bezier curve.</param>
/// <param name="control2">Control point that defines the bezier curve.</param>
/// <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;
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
+ return new Vector2
+ (
+ Mathf.BezierInterpolate(X, control1.X, control2.X, end.X, t),
+ Mathf.BezierInterpolate(Y, control1.Y, control2.Y, end.Y, t)
+ );
+ }
- return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ /// <summary>
+ /// Returns the derivative at the given <paramref name="t"/> on the Bezier curve defined by this vector
+ /// and the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination value for the interpolation.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public readonly Vector2 BezierDerivative(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
+ {
+ return new Vector2(
+ Mathf.BezierDerivative(X, control1.X, control2.X, end.X, t),
+ Mathf.BezierDerivative(Y, control1.Y, control2.Y, end.Y, t)
+ );
}
/// <summary>
@@ -264,9 +278,9 @@ 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();
+ return new Vector2(to.X - X, to.Y - Y).Normalized();
}
/// <summary>
@@ -276,9 +290,9 @@ 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);
+ return (X - to.X) * (X - to.X) + (Y - to.Y) * (Y - to.Y);
}
/// <summary>
@@ -286,9 +300,9 @@ 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));
+ return Mathf.Sqrt((X - to.X) * (X - to.X) + (Y - to.Y) * (Y - to.Y));
}
/// <summary>
@@ -296,34 +310,44 @@ 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);
+ return (X * with.X) + (Y * with.Y);
}
/// <summary>
/// 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));
+ return new Vector2(Mathf.Floor(X), Mathf.Floor(Y));
}
/// <summary>
- /// Returns the inverse of this vector. This is the same as <c>new Vector2(1 / v.x, 1 / v.y)</c>.
+ /// 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);
+ return new Vector2(1 / X, 1 / Y);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return Mathf.IsFinite(X) && Mathf.IsFinite(Y);
}
/// <summary>
/// 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,9 +357,9 @@ 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));
+ return Mathf.Sqrt((X * X) + (Y * Y));
}
/// <summary>
@@ -344,9 +368,9 @@ 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);
+ return (X * X) + (Y * Y);
}
/// <summary>
@@ -356,30 +380,12 @@ 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
(
- Mathf.Lerp(x, to.x, weight),
- Mathf.Lerp(y, to.y, weight)
- );
- }
-
- /// <summary>
- /// Returns the result of the linear interpolation between
- /// this vector and <paramref name="to"/> by the vector amount <paramref name="weight"/>.
- /// </summary>
- /// <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 Vector2 Lerp(Vector2 to, Vector2 weight)
- {
- return new Vector2
- (
- Mathf.Lerp(x, to.x, weight.x),
- Mathf.Lerp(y, to.y, weight.y)
+ Mathf.Lerp(X, to.X, weight),
+ Mathf.Lerp(Y, to.Y, weight)
);
}
@@ -388,7 +394,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,9 +413,9 @@ 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;
+ return X < Y ? Axis.Y : Axis.X;
}
/// <summary>
@@ -417,9 +423,9 @@ 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;
+ return X < Y ? Axis.X : Axis.Y;
}
/// <summary>
@@ -428,7 +434,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 +449,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,11 +464,11 @@ 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);
- v.y = Mathf.PosMod(y, mod);
+ v.X = Mathf.PosMod(X, mod);
+ v.Y = Mathf.PosMod(Y, mod);
return v;
}
@@ -474,11 +480,11 @@ 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);
- v.y = Mathf.PosMod(y, modv.y);
+ v.X = Mathf.PosMod(X, modv.X);
+ v.Y = Mathf.PosMod(Y, modv.Y);
return v;
}
@@ -487,7 +493,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 +503,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,13 +519,14 @@ 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);
- return new Vector2(
- x * cosi - y * sine,
- x * sine + y * cosi);
+ (real_t sin, real_t cos) = Mathf.SinCos(angle);
+ return new Vector2
+ (
+ X * cos - Y * sin,
+ X * sin + Y * cos
+ );
}
/// <summary>
@@ -527,9 +534,9 @@ 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));
+ return new Vector2(Mathf.Round(X), Mathf.Round(Y));
}
/// <summary>
@@ -538,11 +545,11 @@ 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);
- v.y = Mathf.Sign(y);
+ v.X = Mathf.Sign(X);
+ v.Y = Mathf.Sign(Y);
return v;
}
@@ -557,7 +564,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 +584,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,9 +595,9 @@ 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));
+ return new Vector2(Mathf.Snapped(X, step.X), Mathf.Snapped(Y, step.Y));
}
/// <summary>
@@ -598,9 +605,9 @@ 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);
+ return new Vector2(Y, -X);
}
// Constants
@@ -657,8 +664,8 @@ namespace Godot
/// <param name="y">The vector's Y component.</param>
public Vector2(real_t x, real_t y)
{
- this.x = x;
- this.y = y;
+ X = x;
+ Y = y;
}
/// <summary>
@@ -669,7 +676,8 @@ namespace Godot
/// <returns>The resulting vector.</returns>
public static Vector2 FromAngle(real_t angle)
{
- return new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
+ (real_t sin, real_t cos) = Mathf.SinCos(angle);
+ return new Vector2(cos, sin);
}
/// <summary>
@@ -681,8 +689,8 @@ namespace Godot
/// <returns>The added vector.</returns>
public static Vector2 operator +(Vector2 left, Vector2 right)
{
- left.x += right.x;
- left.y += right.y;
+ left.X += right.X;
+ left.Y += right.Y;
return left;
}
@@ -695,14 +703,14 @@ namespace Godot
/// <returns>The subtracted vector.</returns>
public static Vector2 operator -(Vector2 left, Vector2 right)
{
- left.x -= right.x;
- left.y -= right.y;
+ left.X -= right.X;
+ left.Y -= right.Y;
return left;
}
/// <summary>
/// Returns the negative value of the <see cref="Vector2"/>.
- /// This is the same as writing <c>new Vector2(-v.x, -v.y)</c>.
+ /// This is the same as writing <c>new Vector2(-v.X, -v.Y)</c>.
/// This operation flips the direction of the vector while
/// keeping the same magnitude.
/// With floats, the number zero can be either positive or negative.
@@ -711,8 +719,8 @@ namespace Godot
/// <returns>The negated/flipped vector.</returns>
public static Vector2 operator -(Vector2 vec)
{
- vec.x = -vec.x;
- vec.y = -vec.y;
+ vec.X = -vec.X;
+ vec.Y = -vec.Y;
return vec;
}
@@ -725,8 +733,8 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector2 operator *(Vector2 vec, real_t scale)
{
- vec.x *= scale;
- vec.y *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
return vec;
}
@@ -739,8 +747,8 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector2 operator *(real_t scale, Vector2 vec)
{
- vec.x *= scale;
- vec.y *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
return vec;
}
@@ -753,8 +761,8 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector2 operator *(Vector2 left, Vector2 right)
{
- left.x *= right.x;
- left.y *= right.y;
+ left.X *= right.X;
+ left.Y *= right.Y;
return left;
}
@@ -767,8 +775,8 @@ namespace Godot
/// <returns>The divided vector.</returns>
public static Vector2 operator /(Vector2 vec, real_t divisor)
{
- vec.x /= divisor;
- vec.y /= divisor;
+ vec.X /= divisor;
+ vec.Y /= divisor;
return vec;
}
@@ -781,8 +789,8 @@ namespace Godot
/// <returns>The divided vector.</returns>
public static Vector2 operator /(Vector2 vec, Vector2 divisorv)
{
- vec.x /= divisorv.x;
- vec.y /= divisorv.y;
+ vec.X /= divisorv.X;
+ vec.Y /= divisorv.Y;
return vec;
}
@@ -804,8 +812,8 @@ namespace Godot
/// <returns>The remainder vector.</returns>
public static Vector2 operator %(Vector2 vec, real_t divisor)
{
- vec.x %= divisor;
- vec.y %= divisor;
+ vec.X %= divisor;
+ vec.Y %= divisor;
return vec;
}
@@ -827,8 +835,8 @@ namespace Godot
/// <returns>The remainder vector.</returns>
public static Vector2 operator %(Vector2 vec, Vector2 divisorv)
{
- vec.x %= divisorv.x;
- vec.y %= divisorv.y;
+ vec.X %= divisorv.X;
+ vec.Y %= divisorv.Y;
return vec;
}
@@ -871,11 +879,11 @@ namespace Godot
/// <returns>Whether or not the left is less than the right.</returns>
public static bool operator <(Vector2 left, Vector2 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
@@ -891,11 +899,11 @@ namespace Godot
/// <returns>Whether or not the left is greater than the right.</returns>
public static bool operator >(Vector2 left, Vector2 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
@@ -911,11 +919,11 @@ namespace Godot
/// <returns>Whether or not the left is less than or equal to the right.</returns>
public static bool operator <=(Vector2 left, Vector2 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y <= right.y;
+ return left.Y <= right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
@@ -931,11 +939,11 @@ namespace Godot
/// <returns>Whether or not the left is greater than or equal to the right.</returns>
public static bool operator >=(Vector2 left, Vector2 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y >= right.y;
+ return left.Y >= right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
@@ -946,7 +954,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,9 +966,9 @@ 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;
+ return X == other.X && Y == other.Y;
}
/// <summary>
@@ -969,36 +977,48 @@ 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);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector's values are approximately zero,
+ /// by running <see cref="Mathf.IsZeroApprox(real_t)"/> on each component.
+ /// This method is faster than using <see cref="IsEqualApprox"/> with one value
+ /// as a zero vector.
+ /// </summary>
+ /// <returns>Whether or not the vector is approximately zero.</returns>
+ public readonly bool IsZeroApprox()
{
- return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
+ return Mathf.IsZeroApprox(X) && Mathf.IsZeroApprox(Y);
}
/// <summary>
/// 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();
+ return Y.GetHashCode() ^ X.GetHashCode();
}
/// <summary>
/// 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})";
+ return $"({X}, {Y})";
}
/// <summary>
/// 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)})";
+ 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..e849939ebb 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs
@@ -8,7 +8,7 @@ namespace Godot
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- public struct Vector2i : IEquatable<Vector2i>
+ public struct Vector2I : IEquatable<Vector2I>
{
/// <summary>
/// Enumerated index values for the axes.
@@ -29,12 +29,12 @@ namespace Godot
/// <summary>
/// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
- public int x;
+ public int X;
/// <summary>
/// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
- public int y;
+ public int Y;
/// <summary>
/// Access vector components using their index.
@@ -43,19 +43,19 @@ namespace Godot
/// <paramref name="index"/> is not 0 or 1.
/// </exception>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="x"/>,
- /// <c>[1]</c> is equivalent to <see cref="y"/>.
+ /// <c>[0]</c> is equivalent to <see cref="X"/>,
+ /// <c>[1]</c> is equivalent to <see cref="Y"/>.
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -65,10 +65,10 @@ namespace Godot
switch (index)
{
case 0:
- x = value;
+ X = value;
return;
case 1:
- y = value;
+ Y = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -79,60 +79,28 @@ 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;
+ x = X;
+ y = Y;
}
/// <summary>
/// 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));
+ return new Vector2I(Mathf.Abs(X), Mathf.Abs(Y));
}
/// <summary>
- /// Returns this vector's angle with respect to the X axis, or (1, 0) vector, in radians.
- ///
- /// Equivalent to the result of <see cref="Mathf.Atan2(real_t, real_t)"/> when
- /// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
+ /// Returns the aspect ratio of this vector, the ratio of <see cref="X"/> to <see cref="Y"/>.
/// </summary>
- /// <returns>The angle of this vector, in radians.</returns>
- public real_t Angle()
+ /// <returns>The <see cref="X"/> component divided by the <see cref="Y"/> component.</returns>
+ public readonly real_t Aspect()
{
- return Mathf.Atan2(y, x);
- }
-
- /// <summary>
- /// Returns the angle to the given vector, in radians.
- /// </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)
- {
- return Mathf.Atan2(Cross(to), Dot(to));
- }
-
- /// <summary>
- /// Returns the angle between the line connecting the two points and the X axis, in radians.
- /// </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)
- {
- return Mathf.Atan2(y - to.y, x - to.x);
- }
-
- /// <summary>
- /// 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()
- {
- return x / (real_t)y;
+ return X / (real_t)Y;
}
/// <summary>
@@ -143,66 +111,24 @@ 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
+ return new Vector2I
(
- Mathf.Clamp(x, min.x, max.x),
- Mathf.Clamp(y, min.y, max.y)
+ Mathf.Clamp(X, min.X, max.X),
+ Mathf.Clamp(Y, min.Y, max.Y)
);
}
/// <summary>
- /// Returns the cross product of this vector and <paramref name="with"/>.
- /// </summary>
- /// <param name="with">The other vector.</param>
- /// <returns>The cross product vector.</returns>
- public int Cross(Vector2i with)
- {
- return x * with.y - y * with.x;
- }
-
- /// <summary>
- /// Returns the squared distance between this vector and <paramref name="to"/>.
- /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if
- /// you need to compare vectors or need the squared distance for some formula.
- /// </summary>
- /// <param name="to">The other vector to use.</param>
- /// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector2i to)
- {
- return (to - this).LengthSquared();
- }
-
- /// <summary>
- /// Returns the distance between this vector and <paramref name="to"/>.
- /// </summary>
- /// <param name="to">The other vector to use.</param>
- /// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector2i to)
- {
- return (to - this).Length();
- }
-
- /// <summary>
- /// Returns the dot product of this vector and <paramref name="with"/>.
- /// </summary>
- /// <param name="with">The other vector to use.</param>
- /// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector2i with)
- {
- return x * with.x + y * with.y;
- }
-
- /// <summary>
/// Returns the length (magnitude) of this vector.
/// </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;
+ int x2 = X * X;
+ int y2 = Y * Y;
return Mathf.Sqrt(x2 + y2);
}
@@ -213,10 +139,10 @@ 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;
+ int x2 = X * X;
+ int y2 = Y * Y;
return x2 + y2;
}
@@ -226,9 +152,9 @@ 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;
+ return X < Y ? Axis.Y : Axis.X;
}
/// <summary>
@@ -236,41 +162,9 @@ 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()
- {
- return x < y ? Axis.X : Axis.Y;
- }
-
- /// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components
- /// and <paramref name="mod"/>.
- /// </summary>
- /// <param name="mod">A value representing the divisor of the operation.</param>
- /// <returns>
- /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
- /// </returns>
- public Vector2i PosMod(int mod)
+ public readonly Axis MinAxisIndex()
{
- Vector2i v = this;
- v.x = Mathf.PosMod(v.x, mod);
- v.y = Mathf.PosMod(v.y, mod);
- return v;
- }
-
- /// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components
- /// and <paramref name="modv"/>'s components.
- /// </summary>
- /// <param name="modv">A vector representing the divisors of the operation.</param>
- /// <returns>
- /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
- /// </returns>
- public Vector2i PosMod(Vector2i modv)
- {
- Vector2i v = this;
- v.x = Mathf.PosMod(v.x, modv.x);
- v.y = Mathf.PosMod(v.y, modv.y);
- return v;
+ return X < Y ? Axis.X : Axis.Y;
}
/// <summary>
@@ -279,260 +173,222 @@ 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);
- v.y = Mathf.Sign(v.y);
+ Vector2I v = this;
+ v.X = Mathf.Sign(v.X);
+ v.Y = Mathf.Sign(v.Y);
return v;
}
- /// <summary>
- /// Returns a perpendicular vector rotated 90 degrees counter-clockwise
- /// compared to the original, with the same length.
- /// </summary>
- /// <returns>The perpendicular vector.</returns>
- public Vector2i Orthogonal()
- {
- return new Vector2i(y, -x);
- }
-
// Constants
- private static readonly Vector2i _zero = new Vector2i(0, 0);
- private static readonly Vector2i _one = new Vector2i(1, 1);
+ private static readonly Vector2I _zero = new Vector2I(0, 0);
+ private static readonly Vector2I _one = new Vector2I(1, 1);
- private static readonly Vector2i _up = new Vector2i(0, -1);
- private static readonly Vector2i _down = new Vector2i(0, 1);
- private static readonly Vector2i _right = new Vector2i(1, 0);
- private static readonly Vector2i _left = new Vector2i(-1, 0);
+ private static readonly Vector2I _up = new Vector2I(0, -1);
+ private static readonly Vector2I _down = new Vector2I(0, 1);
+ private static readonly Vector2I _right = new Vector2I(1, 0);
+ private static readonly Vector2I _left = new Vector2I(-1, 0);
/// <summary>
/// Zero vector, a vector with all components set to <c>0</c>.
/// </summary>
- /// <value>Equivalent to <c>new Vector2i(0, 0)</c>.</value>
- public static Vector2i Zero { get { return _zero; } }
+ /// <value>Equivalent to <c>new Vector2I(0, 0)</c>.</value>
+ public static Vector2I Zero { get { return _zero; } }
/// <summary>
/// One vector, a vector with all components set to <c>1</c>.
/// </summary>
- /// <value>Equivalent to <c>new Vector2i(1, 1)</c>.</value>
- public static Vector2i One { get { return _one; } }
+ /// <value>Equivalent to <c>new Vector2I(1, 1)</c>.</value>
+ public static Vector2I One { get { return _one; } }
/// <summary>
/// Up unit vector. Y is down in 2D, so this vector points -Y.
/// </summary>
- /// <value>Equivalent to <c>new Vector2i(0, -1)</c>.</value>
- public static Vector2i Up { get { return _up; } }
+ /// <value>Equivalent to <c>new Vector2I(0, -1)</c>.</value>
+ public static Vector2I Up { get { return _up; } }
/// <summary>
/// Down unit vector. Y is down in 2D, so this vector points +Y.
/// </summary>
- /// <value>Equivalent to <c>new Vector2i(0, 1)</c>.</value>
- public static Vector2i Down { get { return _down; } }
+ /// <value>Equivalent to <c>new Vector2I(0, 1)</c>.</value>
+ public static Vector2I Down { get { return _down; } }
/// <summary>
/// Right unit vector. Represents the direction of right.
/// </summary>
- /// <value>Equivalent to <c>new Vector2i(1, 0)</c>.</value>
- public static Vector2i Right { get { return _right; } }
+ /// <value>Equivalent to <c>new Vector2I(1, 0)</c>.</value>
+ public static Vector2I Right { get { return _right; } }
/// <summary>
/// Left unit vector. Represents the direction of left.
/// </summary>
- /// <value>Equivalent to <c>new Vector2i(-1, 0)</c>.</value>
- public static Vector2i Left { get { return _left; } }
+ /// <value>Equivalent to <c>new Vector2I(-1, 0)</c>.</value>
+ public static Vector2I Left { get { return _left; } }
/// <summary>
- /// Constructs a new <see cref="Vector2i"/> with the given components.
+ /// Constructs a new <see cref="Vector2I"/> with the given components.
/// </summary>
/// <param name="x">The vector's X component.</param>
/// <param name="y">The vector's Y component.</param>
- public Vector2i(int x, int y)
+ public Vector2I(int x, int y)
{
- this.x = x;
- this.y = y;
+ X = x;
+ Y = y;
}
/// <summary>
- /// Adds each component of the <see cref="Vector2i"/>
- /// with the components of the given <see cref="Vector2i"/>.
+ /// Adds each component of the <see cref="Vector2I"/>
+ /// with the components of the given <see cref="Vector2I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The added vector.</returns>
- public static Vector2i operator +(Vector2i left, Vector2i right)
+ public static Vector2I operator +(Vector2I left, Vector2I right)
{
- left.x += right.x;
- left.y += right.y;
+ left.X += right.X;
+ left.Y += right.Y;
return left;
}
/// <summary>
- /// Subtracts each component of the <see cref="Vector2i"/>
- /// by the components of the given <see cref="Vector2i"/>.
+ /// Subtracts each component of the <see cref="Vector2I"/>
+ /// by the components of the given <see cref="Vector2I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The subtracted vector.</returns>
- public static Vector2i operator -(Vector2i left, Vector2i right)
+ public static Vector2I operator -(Vector2I left, Vector2I right)
{
- left.x -= right.x;
- left.y -= right.y;
+ left.X -= right.X;
+ left.Y -= right.Y;
return left;
}
/// <summary>
- /// Returns the negative value of the <see cref="Vector2i"/>.
- /// This is the same as writing <c>new Vector2i(-v.x, -v.y)</c>.
+ /// Returns the negative value of the <see cref="Vector2I"/>.
+ /// This is the same as writing <c>new Vector2I(-v.X, -v.Y)</c>.
/// This operation flips the direction of the vector while
/// keeping the same magnitude.
/// </summary>
/// <param name="vec">The vector to negate/flip.</param>
/// <returns>The negated/flipped vector.</returns>
- public static Vector2i operator -(Vector2i vec)
+ public static Vector2I operator -(Vector2I vec)
{
- vec.x = -vec.x;
- vec.y = -vec.y;
+ vec.X = -vec.X;
+ vec.Y = -vec.Y;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector2i"/>
+ /// Multiplies each component of the <see cref="Vector2I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The vector to multiply.</param>
/// <param name="scale">The scale to multiply by.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector2i operator *(Vector2i vec, int scale)
+ public static Vector2I operator *(Vector2I vec, int scale)
{
- vec.x *= scale;
- vec.y *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector2i"/>
+ /// Multiplies each component of the <see cref="Vector2I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="scale">The scale to multiply by.</param>
/// <param name="vec">The vector to multiply.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector2i operator *(int scale, Vector2i vec)
+ public static Vector2I operator *(int scale, Vector2I vec)
{
- vec.x *= scale;
- vec.y *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector2i"/>
- /// by the components of the given <see cref="Vector2i"/>.
+ /// Multiplies each component of the <see cref="Vector2I"/>
+ /// by the components of the given <see cref="Vector2I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector2i operator *(Vector2i left, Vector2i right)
+ public static Vector2I operator *(Vector2I left, Vector2I right)
{
- left.x *= right.x;
- left.y *= right.y;
+ left.X *= right.X;
+ left.Y *= right.Y;
return left;
}
/// <summary>
- /// Divides each component of the <see cref="Vector2i"/>
+ /// Divides each component of the <see cref="Vector2I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisor">The divisor value.</param>
/// <returns>The divided vector.</returns>
- public static Vector2i operator /(Vector2i vec, int divisor)
+ public static Vector2I operator /(Vector2I vec, int divisor)
{
- vec.x /= divisor;
- vec.y /= divisor;
+ vec.X /= divisor;
+ vec.Y /= divisor;
return vec;
}
/// <summary>
- /// Divides each component of the <see cref="Vector2i"/>
- /// by the components of the given <see cref="Vector2i"/>.
+ /// Divides each component of the <see cref="Vector2I"/>
+ /// by the components of the given <see cref="Vector2I"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisorv">The divisor vector.</param>
/// <returns>The divided vector.</returns>
- public static Vector2i operator /(Vector2i vec, Vector2i divisorv)
+ public static Vector2I operator /(Vector2I vec, Vector2I divisorv)
{
- vec.x /= divisorv.x;
- vec.y /= divisorv.y;
+ vec.X /= divisorv.X;
+ vec.Y /= divisorv.Y;
return vec;
}
/// <summary>
- /// Gets the remainder of each component of the <see cref="Vector2i"/>
+ /// Gets the remainder of each component of the <see cref="Vector2I"/>
/// with the components of the given <see langword="int"/>.
/// This operation uses truncated division, which is often not desired
/// as it does not work well with negative numbers.
- /// Consider using <see cref="PosMod(int)"/> instead
+ /// Consider using <see cref="Mathf.PosMod(int, int)"/> instead
/// if you want to handle negative numbers.
/// </summary>
/// <example>
/// <code>
- /// GD.Print(new Vector2i(10, -20) % 7); // Prints "(3, -6)"
+ /// GD.Print(new Vector2I(10, -20) % 7); // Prints "(3, -6)"
/// </code>
/// </example>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisor">The divisor value.</param>
/// <returns>The remainder vector.</returns>
- public static Vector2i operator %(Vector2i vec, int divisor)
+ public static Vector2I operator %(Vector2I vec, int divisor)
{
- vec.x %= divisor;
- vec.y %= divisor;
+ vec.X %= divisor;
+ vec.Y %= divisor;
return vec;
}
/// <summary>
- /// Gets the remainder of each component of the <see cref="Vector2i"/>
- /// with the components of the given <see cref="Vector2i"/>.
+ /// Gets the remainder of each component of the <see cref="Vector2I"/>
+ /// with the components of the given <see cref="Vector2I"/>.
/// This operation uses truncated division, which is often not desired
/// as it does not work well with negative numbers.
- /// Consider using <see cref="PosMod(Vector2i)"/> instead
+ /// Consider using <see cref="Mathf.PosMod(int, int)"/> instead
/// if you want to handle negative numbers.
/// </summary>
/// <example>
/// <code>
- /// GD.Print(new Vector2i(10, -20) % new Vector2i(7, 8)); // Prints "(3, -4)"
+ /// GD.Print(new Vector2I(10, -20) % new Vector2I(7, 8)); // Prints "(3, -4)"
/// </code>
/// </example>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisorv">The divisor vector.</param>
/// <returns>The remainder vector.</returns>
- public static Vector2i operator %(Vector2i vec, Vector2i divisorv)
- {
- vec.x %= divisorv.x;
- vec.y %= divisorv.y;
- return vec;
- }
-
- /// <summary>
- /// Performs a bitwise AND operation with this <see cref="Vector2i"/>
- /// and the given <see langword="int"/>.
- /// </summary>
- /// <param name="vec">The vector to AND with.</param>
- /// <param name="and">The integer to AND with.</param>
- /// <returns>The result of the bitwise AND.</returns>
- public static Vector2i operator &(Vector2i vec, int and)
- {
- vec.x &= and;
- vec.y &= and;
- return vec;
- }
-
- /// <summary>
- /// Performs a bitwise AND operation with this <see cref="Vector2i"/>
- /// and the given <see cref="Vector2i"/>.
- /// </summary>
- /// <param name="vec">The left vector to AND with.</param>
- /// <param name="andv">The right vector to AND with.</param>
- /// <returns>The result of the bitwise AND.</returns>
- public static Vector2i operator &(Vector2i vec, Vector2i andv)
+ public static Vector2I operator %(Vector2I vec, Vector2I divisorv)
{
- vec.x &= andv.x;
- vec.y &= andv.y;
+ vec.X %= divisorv.X;
+ vec.Y %= divisorv.Y;
return vec;
}
@@ -542,7 +398,7 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public static bool operator ==(Vector2i left, Vector2i right)
+ public static bool operator ==(Vector2I left, Vector2I right)
{
return left.Equals(right);
}
@@ -553,13 +409,13 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the vectors are not equal.</returns>
- public static bool operator !=(Vector2i left, Vector2i right)
+ public static bool operator !=(Vector2I left, Vector2I right)
{
return !left.Equals(right);
}
/// <summary>
- /// Compares two <see cref="Vector2i"/> vectors by first checking if
+ /// Compares two <see cref="Vector2I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is less than
/// the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -569,17 +425,17 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is less than the right.</returns>
- public static bool operator <(Vector2i left, Vector2i right)
+ public static bool operator <(Vector2I left, Vector2I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
- /// Compares two <see cref="Vector2i"/> vectors by first checking if
+ /// Compares two <see cref="Vector2I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is greater than
/// the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -589,17 +445,17 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is greater than the right.</returns>
- public static bool operator >(Vector2i left, Vector2i right)
+ public static bool operator >(Vector2I left, Vector2I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
- /// Compares two <see cref="Vector2i"/> vectors by first checking if
+ /// Compares two <see cref="Vector2I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is less than
/// or equal to the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -609,17 +465,17 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is less than or equal to the right.</returns>
- public static bool operator <=(Vector2i left, Vector2i right)
+ public static bool operator <=(Vector2I left, Vector2I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y <= right.y;
+ return left.Y <= right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
- /// Compares two <see cref="Vector2i"/> vectors by first checking if
+ /// Compares two <see cref="Vector2I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is greater than
/// or equal to the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -629,33 +485,33 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is greater than or equal to the right.</returns>
- public static bool operator >=(Vector2i left, Vector2i right)
+ public static bool operator >=(Vector2I left, Vector2I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- return left.y >= right.y;
+ return left.Y >= right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
- /// Converts this <see cref="Vector2i"/> to a <see cref="Vector2"/>.
+ /// Converts this <see cref="Vector2I"/> to a <see cref="Vector2"/>.
/// </summary>
/// <param name="value">The vector to convert.</param>
- public static implicit operator Vector2(Vector2i value)
+ public static implicit operator Vector2(Vector2I value)
{
- return new Vector2(value.x, value.y);
+ return new Vector2(value.X, value.Y);
}
/// <summary>
- /// Converts a <see cref="Vector2"/> to a <see cref="Vector2i"/>.
+ /// Converts a <see cref="Vector2"/> to a <see cref="Vector2I"/>.
/// </summary>
/// <param name="value">The vector to convert.</param>
- public static explicit operator Vector2i(Vector2 value)
+ public static explicit operator Vector2I(Vector2 value)
{
- return new Vector2i(
- Mathf.RoundToInt(value.x),
- Mathf.RoundToInt(value.y)
+ return new Vector2I(
+ Mathf.RoundToInt(value.X),
+ Mathf.RoundToInt(value.Y)
);
}
@@ -665,9 +521,9 @@ 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);
+ return obj is Vector2I other && Equals(other);
}
/// <summary>
@@ -675,36 +531,36 @@ 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;
+ return X == other.X && Y == other.Y;
}
/// <summary>
- /// Serves as the hash function for <see cref="Vector2i"/>.
+ /// 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();
+ return Y.GetHashCode() ^ X.GetHashCode();
}
/// <summary>
- /// Converts this <see cref="Vector2i"/> to a string.
+ /// 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})";
+ return $"({X}, {Y})";
}
/// <summary>
- /// Converts this <see cref="Vector2i"/> to a string with the given <paramref name="format"/>.
+ /// 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)})";
+ 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..c773c0fda6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -33,17 +33,17 @@ namespace Godot
/// <summary>
/// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
- public real_t x;
+ public real_t X;
/// <summary>
/// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
- public real_t y;
+ public real_t Y;
/// <summary>
/// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
/// </summary>
- public real_t z;
+ public real_t Z;
/// <summary>
/// Access vector components using their index.
@@ -52,22 +52,22 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1 or 2.
/// </exception>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="x"/>,
- /// <c>[1]</c> is equivalent to <see cref="y"/>,
- /// <c>[2]</c> is equivalent to <see cref="z"/>.
+ /// <c>[0]</c> is equivalent to <see cref="X"/>,
+ /// <c>[1]</c> is equivalent to <see cref="Y"/>,
+ /// <c>[2]</c> is equivalent to <see cref="Z"/>.
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
case 2:
- return z;
+ return Z;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -77,13 +77,13 @@ namespace Godot
switch (index)
{
case 0:
- x = value;
+ X = value;
return;
case 1:
- y = value;
+ Y = value;
return;
case 2:
- z = value;
+ Z = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -94,11 +94,11 @@ 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;
- z = this.z;
+ x = X;
+ y = Y;
+ z = Z;
}
internal void Normalize()
@@ -107,14 +107,14 @@ namespace Godot
if (lengthsq == 0)
{
- x = y = z = 0f;
+ X = Y = Z = 0f;
}
else
{
real_t length = Mathf.Sqrt(lengthsq);
- x /= length;
- y /= length;
- z /= length;
+ X /= length;
+ Y /= length;
+ Z /= length;
}
}
@@ -122,9 +122,9 @@ 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));
+ return new Vector3(Mathf.Abs(X), Mathf.Abs(Y), Mathf.Abs(Z));
}
/// <summary>
@@ -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,9 +151,9 @@ 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));
+ return new Vector3(Mathf.Ceil(X), Mathf.Ceil(Y), Mathf.Ceil(Z));
}
/// <summary>
@@ -164,13 +164,13 @@ 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
(
- Mathf.Clamp(x, min.x, max.x),
- Mathf.Clamp(y, min.y, max.y),
- Mathf.Clamp(z, min.z, max.z)
+ Mathf.Clamp(X, min.X, max.X),
+ Mathf.Clamp(Y, min.Y, max.Y),
+ Mathf.Clamp(Z, min.Z, max.Z)
);
}
@@ -179,13 +179,13 @@ 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
(
- (y * with.z) - (z * with.y),
- (z * with.x) - (x * with.z),
- (x * with.y) - (y * with.x)
+ (Y * with.Z) - (Z * with.Y),
+ (Z * with.X) - (X * with.Z),
+ (X * with.Y) - (Y * with.X)
);
}
@@ -198,13 +198,13 @@ 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
(
- Mathf.CubicInterpolate(x, b.x, preA.x, postB.x, weight),
- Mathf.CubicInterpolate(y, b.y, preA.y, postB.y, weight),
- Mathf.CubicInterpolate(z, b.z, preA.z, postB.z, weight)
+ Mathf.CubicInterpolate(X, b.X, preA.X, postB.X, weight),
+ Mathf.CubicInterpolate(Y, b.Y, preA.Y, postB.Y, weight),
+ Mathf.CubicInterpolate(Z, b.Z, preA.Z, postB.Z, weight)
);
}
@@ -222,35 +222,51 @@ 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
(
- Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT),
- Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT),
- Mathf.CubicInterpolateInTime(z, b.z, preA.z, postB.z, weight, t, preAT, postBT)
+ Mathf.CubicInterpolateInTime(X, b.X, preA.X, postB.X, weight, t, preAT, postBT),
+ Mathf.CubicInterpolateInTime(Y, b.Y, preA.Y, postB.Y, weight, t, preAT, postBT),
+ Mathf.CubicInterpolateInTime(Z, b.Z, preA.Z, postB.Z, weight, t, preAT, postBT)
);
}
/// <summary>
/// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector
- /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
+ /// and the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
/// </summary>
/// <param name="control1">Control point that defines the bezier curve.</param>
/// <param name="control2">Control point that defines the bezier curve.</param>
/// <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;
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
+ return new Vector3
+ (
+ Mathf.BezierInterpolate(X, control1.X, control2.X, end.X, t),
+ Mathf.BezierInterpolate(Y, control1.Y, control2.Y, end.Y, t),
+ Mathf.BezierInterpolate(Z, control1.Z, control2.Z, end.Z, t)
+ );
+ }
- return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ /// <summary>
+ /// Returns the derivative at the given <paramref name="t"/> on the Bezier curve defined by this vector
+ /// and the given <paramref name="control1"/>, <paramref name="control2"/>, and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination value for the interpolation.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public readonly Vector3 BezierDerivative(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
+ {
+ return new Vector3(
+ Mathf.BezierDerivative(X, control1.X, control2.X, end.X, t),
+ Mathf.BezierDerivative(Y, control1.Y, control2.Y, end.Y, t),
+ Mathf.BezierDerivative(Z, control1.Z, control2.Z, end.Y, t)
+ );
}
/// <summary>
@@ -258,9 +274,9 @@ 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();
+ return new Vector3(to.X - X, to.Y - Y, to.Z - Z).Normalized();
}
/// <summary>
@@ -270,7 +286,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 +297,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,34 +307,44 @@ 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);
+ return (X * with.X) + (Y * with.Y) + (Z * with.Z);
}
/// <summary>
/// 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));
+ return new Vector3(Mathf.Floor(X), Mathf.Floor(Y), Mathf.Floor(Z));
}
/// <summary>
- /// Returns the inverse of this vector. This is the same as <c>new Vector3(1 / v.x, 1 / v.y, 1 / v.z)</c>.
+ /// 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);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
{
- return new Vector3(1 / x, 1 / y, 1 / z);
+ return Mathf.IsFinite(X) && Mathf.IsFinite(Y) && Mathf.IsFinite(Z);
}
/// <summary>
/// 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,11 +354,11 @@ 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;
- real_t z2 = z * z;
+ real_t x2 = X * X;
+ real_t y2 = Y * Y;
+ real_t z2 = Z * Z;
return Mathf.Sqrt(x2 + y2 + z2);
}
@@ -343,11 +369,11 @@ 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;
- real_t z2 = z * z;
+ real_t x2 = X * X;
+ real_t y2 = Y * Y;
+ real_t z2 = Z * Z;
return x2 + y2 + z2;
}
@@ -359,30 +385,13 @@ 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
(
- Mathf.Lerp(x, to.x, weight),
- Mathf.Lerp(y, to.y, weight),
- Mathf.Lerp(z, to.z, weight)
- );
- }
-
- /// <summary>
- /// Returns the result of the linear interpolation between
- /// this vector and <paramref name="to"/> by the vector amount <paramref name="weight"/>.
- /// </summary>
- /// <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)
- {
- return new Vector3
- (
- Mathf.Lerp(x, to.x, weight.x),
- Mathf.Lerp(y, to.y, weight.y),
- Mathf.Lerp(z, to.z, weight.z)
+ Mathf.Lerp(X, to.X, weight),
+ Mathf.Lerp(Y, to.Y, weight),
+ Mathf.Lerp(Z, to.Z, weight)
);
}
@@ -391,7 +400,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,9 +419,9 @@ 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);
+ return X < Y ? (Y < Z ? Axis.Z : Axis.Y) : (X < Z ? Axis.Z : Axis.X);
}
/// <summary>
@@ -420,9 +429,9 @@ 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);
+ return X < Y ? (X < Z ? Axis.X : Axis.Z) : (Y < Z ? Axis.Y : Axis.Z);
}
/// <summary>
@@ -431,7 +440,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 +455,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,12 +467,12 @@ 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,
- y * with.x, y * with.y, y * with.z,
- z * with.x, z * with.y, z * with.z
+ X * with.X, X * with.Y, X * with.Z,
+ Y * with.X, Y * with.Y, Y * with.Z,
+ Z * with.X, Z * with.Y, Z * with.Z
);
}
@@ -475,12 +484,12 @@ 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);
- v.y = Mathf.PosMod(y, mod);
- v.z = Mathf.PosMod(z, mod);
+ v.X = Mathf.PosMod(X, mod);
+ v.Y = Mathf.PosMod(Y, mod);
+ v.Z = Mathf.PosMod(Z, mod);
return v;
}
@@ -492,12 +501,12 @@ 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);
- v.y = Mathf.PosMod(y, modv.y);
- v.z = Mathf.PosMod(z, modv.z);
+ v.X = Mathf.PosMod(X, modv.X);
+ v.Y = Mathf.PosMod(Y, modv.Y);
+ v.Z = Mathf.PosMod(Z, modv.Z);
return v;
}
@@ -506,7 +515,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 +525,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 +543,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,9 +559,9 @@ 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));
+ return new Vector3(Mathf.Round(X), Mathf.Round(Y), Mathf.Round(Z));
}
/// <summary>
@@ -561,12 +570,12 @@ 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);
- v.y = Mathf.Sign(y);
- v.z = Mathf.Sign(z);
+ v.X = Mathf.Sign(X);
+ v.Y = Mathf.Sign(Y);
+ v.Z = Mathf.Sign(Z);
return v;
}
@@ -579,7 +588,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 +607,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 +627,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,13 +638,13 @@ 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
(
- Mathf.Snapped(x, step.x),
- Mathf.Snapped(y, step.y),
- Mathf.Snapped(z, step.z)
+ Mathf.Snapped(X, step.X),
+ Mathf.Snapped(Y, step.Y),
+ Mathf.Snapped(Z, step.Z)
);
}
@@ -710,9 +719,9 @@ namespace Godot
/// <param name="z">The vector's Z component.</param>
public Vector3(real_t x, real_t y, real_t z)
{
- this.x = x;
- this.y = y;
- this.z = z;
+ X = x;
+ Y = y;
+ Z = z;
}
/// <summary>
@@ -724,9 +733,9 @@ namespace Godot
/// <returns>The added vector.</returns>
public static Vector3 operator +(Vector3 left, Vector3 right)
{
- left.x += right.x;
- left.y += right.y;
- left.z += right.z;
+ left.X += right.X;
+ left.Y += right.Y;
+ left.Z += right.Z;
return left;
}
@@ -739,15 +748,15 @@ namespace Godot
/// <returns>The subtracted vector.</returns>
public static Vector3 operator -(Vector3 left, Vector3 right)
{
- left.x -= right.x;
- left.y -= right.y;
- left.z -= right.z;
+ left.X -= right.X;
+ left.Y -= right.Y;
+ left.Z -= right.Z;
return left;
}
/// <summary>
/// Returns the negative value of the <see cref="Vector3"/>.
- /// This is the same as writing <c>new Vector3(-v.x, -v.y, -v.z)</c>.
+ /// This is the same as writing <c>new Vector3(-v.X, -v.Y, -v.Z)</c>.
/// This operation flips the direction of the vector while
/// keeping the same magnitude.
/// With floats, the number zero can be either positive or negative.
@@ -756,9 +765,9 @@ namespace Godot
/// <returns>The negated/flipped vector.</returns>
public static Vector3 operator -(Vector3 vec)
{
- vec.x = -vec.x;
- vec.y = -vec.y;
- vec.z = -vec.z;
+ vec.X = -vec.X;
+ vec.Y = -vec.Y;
+ vec.Z = -vec.Z;
return vec;
}
@@ -771,9 +780,9 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector3 operator *(Vector3 vec, real_t scale)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
return vec;
}
@@ -786,9 +795,9 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector3 operator *(real_t scale, Vector3 vec)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
return vec;
}
@@ -801,9 +810,9 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector3 operator *(Vector3 left, Vector3 right)
{
- left.x *= right.x;
- left.y *= right.y;
- left.z *= right.z;
+ left.X *= right.X;
+ left.Y *= right.Y;
+ left.Z *= right.Z;
return left;
}
@@ -816,9 +825,9 @@ namespace Godot
/// <returns>The divided vector.</returns>
public static Vector3 operator /(Vector3 vec, real_t divisor)
{
- vec.x /= divisor;
- vec.y /= divisor;
- vec.z /= divisor;
+ vec.X /= divisor;
+ vec.Y /= divisor;
+ vec.Z /= divisor;
return vec;
}
@@ -831,9 +840,9 @@ namespace Godot
/// <returns>The divided vector.</returns>
public static Vector3 operator /(Vector3 vec, Vector3 divisorv)
{
- vec.x /= divisorv.x;
- vec.y /= divisorv.y;
- vec.z /= divisorv.z;
+ vec.X /= divisorv.X;
+ vec.Y /= divisorv.Y;
+ vec.Z /= divisorv.Z;
return vec;
}
@@ -855,9 +864,9 @@ namespace Godot
/// <returns>The remainder vector.</returns>
public static Vector3 operator %(Vector3 vec, real_t divisor)
{
- vec.x %= divisor;
- vec.y %= divisor;
- vec.z %= divisor;
+ vec.X %= divisor;
+ vec.Y %= divisor;
+ vec.Z %= divisor;
return vec;
}
@@ -879,9 +888,9 @@ namespace Godot
/// <returns>The remainder vector.</returns>
public static Vector3 operator %(Vector3 vec, Vector3 divisorv)
{
- vec.x %= divisorv.x;
- vec.y %= divisorv.y;
- vec.z %= divisorv.z;
+ vec.X %= divisorv.X;
+ vec.Y %= divisorv.Y;
+ vec.Z %= divisorv.Z;
return vec;
}
@@ -924,15 +933,15 @@ namespace Godot
/// <returns>Whether or not the left is less than the right.</returns>
public static bool operator <(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z < right.z;
+ return left.Z < right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
@@ -948,15 +957,15 @@ namespace Godot
/// <returns>Whether or not the left is greater than the right.</returns>
public static bool operator >(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z > right.z;
+ return left.Z > right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
@@ -972,15 +981,15 @@ namespace Godot
/// <returns>Whether or not the left is less than or equal to the right.</returns>
public static bool operator <=(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z <= right.z;
+ return left.Z <= right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
@@ -996,15 +1005,15 @@ namespace Godot
/// <returns>Whether or not the left is greater than or equal to the right.</returns>
public static bool operator >=(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z >= right.z;
+ return left.Z >= right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
@@ -1015,7 +1024,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,9 +1036,9 @@ 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;
+ return X == other.X && Y == other.Y && Z == other.Z;
}
/// <summary>
@@ -1038,36 +1047,48 @@ 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);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector's values are approximately zero,
+ /// by running <see cref="Mathf.IsZeroApprox(real_t)"/> on each component.
+ /// This method is faster than using <see cref="IsEqualApprox"/> with one value
+ /// as a zero vector.
+ /// </summary>
+ /// <returns>Whether or not the vector is approximately zero.</returns>
+ public readonly bool IsZeroApprox()
{
- return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
+ return Mathf.IsZeroApprox(X) && Mathf.IsZeroApprox(Y) && Mathf.IsZeroApprox(Z);
}
/// <summary>
/// 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();
+ return Y.GetHashCode() ^ X.GetHashCode() ^ Z.GetHashCode();
}
/// <summary>
/// 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})";
+ return $"({X}, {Y}, {Z})";
}
/// <summary>
/// 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)})";
+ 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..fe899527ef 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs
@@ -8,7 +8,7 @@ namespace Godot
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- public struct Vector3i : IEquatable<Vector3i>
+ public struct Vector3I : IEquatable<Vector3I>
{
/// <summary>
/// Enumerated index values for the axes.
@@ -33,17 +33,17 @@ namespace Godot
/// <summary>
/// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
- public int x;
+ public int X;
/// <summary>
/// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
- public int y;
+ public int Y;
/// <summary>
/// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
/// </summary>
- public int z;
+ public int Z;
/// <summary>
/// Access vector components using their <paramref name="index"/>.
@@ -52,22 +52,22 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1 or 2.
/// </exception>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="x"/>,
- /// <c>[1]</c> is equivalent to <see cref="y"/>,
- /// <c>[2]</c> is equivalent to <see cref="z"/>.
+ /// <c>[0]</c> is equivalent to <see cref="X"/>,
+ /// <c>[1]</c> is equivalent to <see cref="Y"/>,
+ /// <c>[2]</c> is equivalent to <see cref="Z"/>.
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
case 2:
- return z;
+ return Z;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -77,13 +77,13 @@ namespace Godot
switch (index)
{
case 0:
- x = value;
+ X = value;
return;
case 1:
- y = value;
+ Y = value;
return;
case 2:
- z = value;
+ Z = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -94,20 +94,20 @@ 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;
- z = this.z;
+ x = X;
+ y = Y;
+ z = Z;
}
/// <summary>
/// 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));
+ return new Vector3I(Mathf.Abs(X), Mathf.Abs(Y), Mathf.Abs(Z));
}
/// <summary>
@@ -118,59 +118,26 @@ 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
+ return new Vector3I
(
- Mathf.Clamp(x, min.x, max.x),
- Mathf.Clamp(y, min.y, max.y),
- Mathf.Clamp(z, min.z, max.z)
+ Mathf.Clamp(X, min.X, max.X),
+ Mathf.Clamp(Y, min.Y, max.Y),
+ Mathf.Clamp(Z, min.Z, max.Z)
);
}
/// <summary>
- /// Returns the squared distance between this vector and <paramref name="to"/>.
- /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if
- /// you need to compare vectors or need the squared distance for some formula.
- /// </summary>
- /// <param name="to">The other vector to use.</param>
- /// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector3i to)
- {
- return (to - this).LengthSquared();
- }
-
- /// <summary>
- /// Returns the distance between this vector and <paramref name="to"/>.
- /// </summary>
- /// <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)
- {
- return (to - this).Length();
- }
-
- /// <summary>
- /// Returns the dot product of this vector and <paramref name="with"/>.
- /// </summary>
- /// <param name="with">The other vector to use.</param>
- /// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector3i with)
- {
- return x * with.x + y * with.y + z * with.z;
- }
-
- /// <summary>
/// Returns the length (magnitude) of this vector.
/// </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;
- int z2 = z * z;
+ int x2 = X * X;
+ int y2 = Y * Y;
+ int z2 = Z * Z;
return Mathf.Sqrt(x2 + y2 + z2);
}
@@ -181,11 +148,11 @@ 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;
- int z2 = z * z;
+ int x2 = X * X;
+ int y2 = Y * Y;
+ int z2 = Z * Z;
return x2 + y2 + z2;
}
@@ -195,9 +162,9 @@ 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);
+ return X < Y ? (Y < Z ? Axis.Z : Axis.Y) : (X < Z ? Axis.Z : Axis.X);
}
/// <summary>
@@ -205,43 +172,9 @@ 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);
- }
-
- /// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components
- /// and <paramref name="mod"/>.
- /// </summary>
- /// <param name="mod">A value representing the divisor of the operation.</param>
- /// <returns>
- /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
- /// </returns>
- public Vector3i PosMod(int mod)
- {
- Vector3i v = this;
- v.x = Mathf.PosMod(v.x, mod);
- v.y = Mathf.PosMod(v.y, mod);
- v.z = Mathf.PosMod(v.z, mod);
- return v;
- }
-
- /// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components
- /// and <paramref name="modv"/>'s components.
- /// </summary>
- /// <param name="modv">A vector representing the divisors of the operation.</param>
- /// <returns>
- /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
- /// </returns>
- public Vector3i PosMod(Vector3i modv)
- {
- Vector3i v = this;
- v.x = Mathf.PosMod(v.x, modv.x);
- v.y = Mathf.PosMod(v.y, modv.y);
- v.z = Mathf.PosMod(v.z, modv.z);
- return v;
+ return X < Y ? (X < Z ? Axis.X : Axis.Z) : (Y < Z ? Axis.Y : Axis.Z);
}
/// <summary>
@@ -250,281 +183,251 @@ 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);
- v.y = Mathf.Sign(v.y);
- v.z = Mathf.Sign(v.z);
+ Vector3I v = this;
+ v.X = Mathf.Sign(v.X);
+ v.Y = Mathf.Sign(v.Y);
+ v.Z = Mathf.Sign(v.Z);
return v;
}
// Constants
- private static readonly Vector3i _zero = new Vector3i(0, 0, 0);
- private static readonly Vector3i _one = new Vector3i(1, 1, 1);
+ private static readonly Vector3I _zero = new Vector3I(0, 0, 0);
+ private static readonly Vector3I _one = new Vector3I(1, 1, 1);
- private static readonly Vector3i _up = new Vector3i(0, 1, 0);
- private static readonly Vector3i _down = new Vector3i(0, -1, 0);
- private static readonly Vector3i _right = new Vector3i(1, 0, 0);
- private static readonly Vector3i _left = new Vector3i(-1, 0, 0);
- private static readonly Vector3i _forward = new Vector3i(0, 0, -1);
- private static readonly Vector3i _back = new Vector3i(0, 0, 1);
+ private static readonly Vector3I _up = new Vector3I(0, 1, 0);
+ private static readonly Vector3I _down = new Vector3I(0, -1, 0);
+ private static readonly Vector3I _right = new Vector3I(1, 0, 0);
+ private static readonly Vector3I _left = new Vector3I(-1, 0, 0);
+ private static readonly Vector3I _forward = new Vector3I(0, 0, -1);
+ private static readonly Vector3I _back = new Vector3I(0, 0, 1);
/// <summary>
/// Zero vector, a vector with all components set to <c>0</c>.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(0, 0, 0)</c>.</value>
- public static Vector3i Zero { get { return _zero; } }
+ /// <value>Equivalent to <c>new Vector3I(0, 0, 0)</c>.</value>
+ public static Vector3I Zero { get { return _zero; } }
/// <summary>
/// One vector, a vector with all components set to <c>1</c>.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(1, 1, 1)</c>.</value>
- public static Vector3i One { get { return _one; } }
+ /// <value>Equivalent to <c>new Vector3I(1, 1, 1)</c>.</value>
+ public static Vector3I One { get { return _one; } }
/// <summary>
/// Up unit vector.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(0, 1, 0)</c>.</value>
- public static Vector3i Up { get { return _up; } }
+ /// <value>Equivalent to <c>new Vector3I(0, 1, 0)</c>.</value>
+ public static Vector3I Up { get { return _up; } }
/// <summary>
/// Down unit vector.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(0, -1, 0)</c>.</value>
- public static Vector3i Down { get { return _down; } }
+ /// <value>Equivalent to <c>new Vector3I(0, -1, 0)</c>.</value>
+ public static Vector3I Down { get { return _down; } }
/// <summary>
/// Right unit vector. Represents the local direction of right,
/// and the global direction of east.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(1, 0, 0)</c>.</value>
- public static Vector3i Right { get { return _right; } }
+ /// <value>Equivalent to <c>new Vector3I(1, 0, 0)</c>.</value>
+ public static Vector3I Right { get { return _right; } }
/// <summary>
/// Left unit vector. Represents the local direction of left,
/// and the global direction of west.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(-1, 0, 0)</c>.</value>
- public static Vector3i Left { get { return _left; } }
+ /// <value>Equivalent to <c>new Vector3I(-1, 0, 0)</c>.</value>
+ public static Vector3I Left { get { return _left; } }
/// <summary>
/// Forward unit vector. Represents the local direction of forward,
/// and the global direction of north.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(0, 0, -1)</c>.</value>
- public static Vector3i Forward { get { return _forward; } }
+ /// <value>Equivalent to <c>new Vector3I(0, 0, -1)</c>.</value>
+ public static Vector3I Forward { get { return _forward; } }
/// <summary>
/// Back unit vector. Represents the local direction of back,
/// and the global direction of south.
/// </summary>
- /// <value>Equivalent to <c>new Vector3i(0, 0, 1)</c>.</value>
- public static Vector3i Back { get { return _back; } }
+ /// <value>Equivalent to <c>new Vector3I(0, 0, 1)</c>.</value>
+ public static Vector3I Back { get { return _back; } }
/// <summary>
- /// Constructs a new <see cref="Vector3i"/> with the given components.
+ /// Constructs a new <see cref="Vector3I"/> with the given components.
/// </summary>
/// <param name="x">The vector's X component.</param>
/// <param name="y">The vector's Y component.</param>
/// <param name="z">The vector's Z component.</param>
- public Vector3i(int x, int y, int z)
+ public Vector3I(int x, int y, int z)
{
- this.x = x;
- this.y = y;
- this.z = z;
+ X = x;
+ Y = y;
+ Z = z;
}
/// <summary>
- /// Adds each component of the <see cref="Vector3i"/>
- /// with the components of the given <see cref="Vector3i"/>.
+ /// Adds each component of the <see cref="Vector3I"/>
+ /// with the components of the given <see cref="Vector3I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The added vector.</returns>
- public static Vector3i operator +(Vector3i left, Vector3i right)
+ public static Vector3I operator +(Vector3I left, Vector3I right)
{
- left.x += right.x;
- left.y += right.y;
- left.z += right.z;
+ left.X += right.X;
+ left.Y += right.Y;
+ left.Z += right.Z;
return left;
}
/// <summary>
- /// Subtracts each component of the <see cref="Vector3i"/>
- /// by the components of the given <see cref="Vector3i"/>.
+ /// Subtracts each component of the <see cref="Vector3I"/>
+ /// by the components of the given <see cref="Vector3I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The subtracted vector.</returns>
- public static Vector3i operator -(Vector3i left, Vector3i right)
+ public static Vector3I operator -(Vector3I left, Vector3I right)
{
- left.x -= right.x;
- left.y -= right.y;
- left.z -= right.z;
+ left.X -= right.X;
+ left.Y -= right.Y;
+ left.Z -= right.Z;
return left;
}
/// <summary>
- /// Returns the negative value of the <see cref="Vector3i"/>.
- /// This is the same as writing <c>new Vector3i(-v.x, -v.y, -v.z)</c>.
+ /// Returns the negative value of the <see cref="Vector3I"/>.
+ /// This is the same as writing <c>new Vector3I(-v.X, -v.Y, -v.Z)</c>.
/// This operation flips the direction of the vector while
/// keeping the same magnitude.
/// </summary>
/// <param name="vec">The vector to negate/flip.</param>
/// <returns>The negated/flipped vector.</returns>
- public static Vector3i operator -(Vector3i vec)
+ public static Vector3I operator -(Vector3I vec)
{
- vec.x = -vec.x;
- vec.y = -vec.y;
- vec.z = -vec.z;
+ vec.X = -vec.X;
+ vec.Y = -vec.Y;
+ vec.Z = -vec.Z;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector3i"/>
+ /// Multiplies each component of the <see cref="Vector3I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The vector to multiply.</param>
/// <param name="scale">The scale to multiply by.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector3i operator *(Vector3i vec, int scale)
+ public static Vector3I operator *(Vector3I vec, int scale)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector3i"/>
+ /// Multiplies each component of the <see cref="Vector3I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="scale">The scale to multiply by.</param>
/// <param name="vec">The vector to multiply.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector3i operator *(int scale, Vector3i vec)
+ public static Vector3I operator *(int scale, Vector3I vec)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector3i"/>
- /// by the components of the given <see cref="Vector3i"/>.
+ /// Multiplies each component of the <see cref="Vector3I"/>
+ /// by the components of the given <see cref="Vector3I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector3i operator *(Vector3i left, Vector3i right)
+ public static Vector3I operator *(Vector3I left, Vector3I right)
{
- left.x *= right.x;
- left.y *= right.y;
- left.z *= right.z;
+ left.X *= right.X;
+ left.Y *= right.Y;
+ left.Z *= right.Z;
return left;
}
/// <summary>
- /// Divides each component of the <see cref="Vector3i"/>
+ /// Divides each component of the <see cref="Vector3I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisor">The divisor value.</param>
/// <returns>The divided vector.</returns>
- public static Vector3i operator /(Vector3i vec, int divisor)
+ public static Vector3I operator /(Vector3I vec, int divisor)
{
- vec.x /= divisor;
- vec.y /= divisor;
- vec.z /= divisor;
+ vec.X /= divisor;
+ vec.Y /= divisor;
+ vec.Z /= divisor;
return vec;
}
/// <summary>
- /// Divides each component of the <see cref="Vector3i"/>
- /// by the components of the given <see cref="Vector3i"/>.
+ /// Divides each component of the <see cref="Vector3I"/>
+ /// by the components of the given <see cref="Vector3I"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisorv">The divisor vector.</param>
/// <returns>The divided vector.</returns>
- public static Vector3i operator /(Vector3i vec, Vector3i divisorv)
+ public static Vector3I operator /(Vector3I vec, Vector3I divisorv)
{
- vec.x /= divisorv.x;
- vec.y /= divisorv.y;
- vec.z /= divisorv.z;
+ vec.X /= divisorv.X;
+ vec.Y /= divisorv.Y;
+ vec.Z /= divisorv.Z;
return vec;
}
/// <summary>
- /// Gets the remainder of each component of the <see cref="Vector3i"/>
+ /// Gets the remainder of each component of the <see cref="Vector3I"/>
/// with the components of the given <see langword="int"/>.
/// This operation uses truncated division, which is often not desired
/// as it does not work well with negative numbers.
- /// Consider using <see cref="PosMod(int)"/> instead
+ /// Consider using <see cref="Mathf.PosMod(int, int)"/> instead
/// if you want to handle negative numbers.
/// </summary>
/// <example>
/// <code>
- /// GD.Print(new Vector3i(10, -20, 30) % 7); // Prints "(3, -6, 2)"
+ /// GD.Print(new Vector3I(10, -20, 30) % 7); // Prints "(3, -6, 2)"
/// </code>
/// </example>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisor">The divisor value.</param>
/// <returns>The remainder vector.</returns>
- public static Vector3i operator %(Vector3i vec, int divisor)
+ public static Vector3I operator %(Vector3I vec, int divisor)
{
- vec.x %= divisor;
- vec.y %= divisor;
- vec.z %= divisor;
+ vec.X %= divisor;
+ vec.Y %= divisor;
+ vec.Z %= divisor;
return vec;
}
/// <summary>
- /// Gets the remainder of each component of the <see cref="Vector3i"/>
- /// with the components of the given <see cref="Vector3i"/>.
+ /// Gets the remainder of each component of the <see cref="Vector3I"/>
+ /// with the components of the given <see cref="Vector3I"/>.
/// This operation uses truncated division, which is often not desired
/// as it does not work well with negative numbers.
- /// Consider using <see cref="PosMod(Vector3i)"/> instead
+ /// Consider using <see cref="Mathf.PosMod(int, int)"/> instead
/// if you want to handle negative numbers.
/// </summary>
/// <example>
/// <code>
- /// GD.Print(new Vector3i(10, -20, 30) % new Vector3i(7, 8, 9)); // Prints "(3, -4, 3)"
+ /// GD.Print(new Vector3I(10, -20, 30) % new Vector3I(7, 8, 9)); // Prints "(3, -4, 3)"
/// </code>
/// </example>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisorv">The divisor vector.</param>
/// <returns>The remainder vector.</returns>
- public static Vector3i operator %(Vector3i vec, Vector3i divisorv)
- {
- vec.x %= divisorv.x;
- vec.y %= divisorv.y;
- vec.z %= divisorv.z;
- return vec;
- }
-
- /// <summary>
- /// Performs a bitwise AND operation with this <see cref="Vector3i"/>
- /// and the given <see langword="int"/>.
- /// </summary>
- /// <param name="vec">The vector to AND with.</param>
- /// <param name="and">The integer to AND with.</param>
- /// <returns>The result of the bitwise AND.</returns>
- public static Vector3i operator &(Vector3i vec, int and)
- {
- vec.x &= and;
- vec.y &= and;
- vec.z &= and;
- return vec;
- }
-
- /// <summary>
- /// Performs a bitwise AND operation with this <see cref="Vector3i"/>
- /// and the given <see cref="Vector3i"/>.
- /// </summary>
- /// <param name="vec">The left vector to AND with.</param>
- /// <param name="andv">The right vector to AND with.</param>
- /// <returns>The result of the bitwise AND.</returns>
- public static Vector3i operator &(Vector3i vec, Vector3i andv)
+ public static Vector3I operator %(Vector3I vec, Vector3I divisorv)
{
- vec.x &= andv.x;
- vec.y &= andv.y;
- vec.z &= andv.z;
+ vec.X %= divisorv.X;
+ vec.Y %= divisorv.Y;
+ vec.Z %= divisorv.Z;
return vec;
}
@@ -534,7 +437,7 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public static bool operator ==(Vector3i left, Vector3i right)
+ public static bool operator ==(Vector3I left, Vector3I right)
{
return left.Equals(right);
}
@@ -545,13 +448,13 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the vectors are not equal.</returns>
- public static bool operator !=(Vector3i left, Vector3i right)
+ public static bool operator !=(Vector3I left, Vector3I right)
{
return !left.Equals(right);
}
/// <summary>
- /// Compares two <see cref="Vector3i"/> vectors by first checking if
+ /// Compares two <see cref="Vector3I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is less than
/// the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -561,21 +464,21 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is less than the right.</returns>
- public static bool operator <(Vector3i left, Vector3i right)
+ public static bool operator <(Vector3I left, Vector3I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z < right.z;
+ return left.Z < right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
- /// Compares two <see cref="Vector3i"/> vectors by first checking if
+ /// Compares two <see cref="Vector3I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is greater than
/// the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -585,21 +488,21 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is greater than the right.</returns>
- public static bool operator >(Vector3i left, Vector3i right)
+ public static bool operator >(Vector3I left, Vector3I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z > right.z;
+ return left.Z > right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
- /// Compares two <see cref="Vector3i"/> vectors by first checking if
+ /// Compares two <see cref="Vector3I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is less than
/// or equal to the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -609,21 +512,21 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is less than or equal to the right.</returns>
- public static bool operator <=(Vector3i left, Vector3i right)
+ public static bool operator <=(Vector3I left, Vector3I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z <= right.z;
+ return left.Z <= right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
- /// Compares two <see cref="Vector3i"/> vectors by first checking if
+ /// Compares two <see cref="Vector3I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is greater than
/// or equal to the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -633,38 +536,38 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is greater than or equal to the right.</returns>
- public static bool operator >=(Vector3i left, Vector3i right)
+ public static bool operator >=(Vector3I left, Vector3I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- return left.z >= right.z;
+ return left.Z >= right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
- /// Converts this <see cref="Vector3i"/> to a <see cref="Vector3"/>.
+ /// Converts this <see cref="Vector3I"/> to a <see cref="Vector3"/>.
/// </summary>
/// <param name="value">The vector to convert.</param>
- public static implicit operator Vector3(Vector3i value)
+ public static implicit operator Vector3(Vector3I value)
{
- return new Vector3(value.x, value.y, value.z);
+ return new Vector3(value.X, value.Y, value.Z);
}
/// <summary>
- /// Converts a <see cref="Vector3"/> to a <see cref="Vector3i"/>.
+ /// Converts a <see cref="Vector3"/> to a <see cref="Vector3I"/>.
/// </summary>
/// <param name="value">The vector to convert.</param>
- public static explicit operator Vector3i(Vector3 value)
+ public static explicit operator Vector3I(Vector3 value)
{
- return new Vector3i(
- Mathf.RoundToInt(value.x),
- Mathf.RoundToInt(value.y),
- Mathf.RoundToInt(value.z)
+ return new Vector3I(
+ Mathf.RoundToInt(value.X),
+ Mathf.RoundToInt(value.Y),
+ Mathf.RoundToInt(value.Z)
);
}
@@ -674,9 +577,9 @@ 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);
+ return obj is Vector3I other && Equals(other);
}
/// <summary>
@@ -684,36 +587,36 @@ 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;
+ return X == other.X && Y == other.Y && Z == other.Z;
}
/// <summary>
- /// Serves as the hash function for <see cref="Vector3i"/>.
+ /// 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();
+ return Y.GetHashCode() ^ X.GetHashCode() ^ Z.GetHashCode();
}
/// <summary>
- /// Converts this <see cref="Vector3i"/> to a string.
+ /// 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})";
+ return $"({X}, {Y}, {Z})";
}
/// <summary>
- /// Converts this <see cref="Vector3i"/> to a string with the given <paramref name="format"/>.
+ /// 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)})";
+ 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..1fd39632b0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
@@ -37,22 +37,22 @@ namespace Godot
/// <summary>
/// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
- public real_t x;
+ public real_t X;
/// <summary>
/// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
- public real_t y;
+ public real_t Y;
/// <summary>
/// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
/// </summary>
- public real_t z;
+ public real_t Z;
/// <summary>
/// The vector's W component. Also accessible by using the index position <c>[3]</c>.
/// </summary>
- public real_t w;
+ public real_t W;
/// <summary>
/// Access vector components using their index.
@@ -61,25 +61,25 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1, 2 or 3.
/// </exception>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="x"/>,
- /// <c>[1]</c> is equivalent to <see cref="y"/>,
- /// <c>[2]</c> is equivalent to <see cref="z"/>.
- /// <c>[3]</c> is equivalent to <see cref="w"/>.
+ /// <c>[0]</c> is equivalent to <see cref="X"/>,
+ /// <c>[1]</c> is equivalent to <see cref="Y"/>,
+ /// <c>[2]</c> is equivalent to <see cref="Z"/>.
+ /// <c>[3]</c> is equivalent to <see cref="W"/>.
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
case 2:
- return z;
+ return Z;
case 3:
- return w;
+ return W;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -89,16 +89,16 @@ namespace Godot
switch (index)
{
case 0:
- x = value;
+ X = value;
return;
case 1:
- y = value;
+ Y = value;
return;
case 2:
- z = value;
+ Z = value;
return;
case 3:
- w = value;
+ W = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -109,12 +109,12 @@ 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;
- z = this.z;
- w = this.w;
+ x = X;
+ y = Y;
+ z = Z;
+ w = W;
}
internal void Normalize()
@@ -123,15 +123,15 @@ namespace Godot
if (lengthsq == 0)
{
- x = y = z = w = 0f;
+ X = Y = Z = W = 0f;
}
else
{
real_t length = Mathf.Sqrt(lengthsq);
- x /= length;
- y /= length;
- z /= length;
- w /= length;
+ X /= length;
+ Y /= length;
+ Z /= length;
+ W /= length;
}
}
@@ -139,18 +139,18 @@ 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));
+ return new Vector4(Mathf.Abs(X), Mathf.Abs(Y), Mathf.Abs(Z), Mathf.Abs(W));
}
/// <summary>
/// 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));
+ return new Vector4(Mathf.Ceil(X), Mathf.Ceil(Y), Mathf.Ceil(Z), Mathf.Ceil(W));
}
/// <summary>
@@ -161,14 +161,14 @@ 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
(
- Mathf.Clamp(x, min.x, max.x),
- Mathf.Clamp(y, min.y, max.y),
- Mathf.Clamp(z, min.z, max.z),
- Mathf.Clamp(w, min.w, max.w)
+ Mathf.Clamp(X, min.X, max.X),
+ Mathf.Clamp(Y, min.Y, max.Y),
+ Mathf.Clamp(Z, min.Z, max.Z),
+ Mathf.Clamp(W, min.W, max.W)
);
}
@@ -181,14 +181,14 @@ 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
(
- Mathf.CubicInterpolate(x, b.x, preA.x, postB.x, weight),
- Mathf.CubicInterpolate(y, b.y, preA.y, postB.y, weight),
- Mathf.CubicInterpolate(z, b.z, preA.z, postB.z, weight),
- Mathf.CubicInterpolate(w, b.w, preA.w, postB.w, weight)
+ Mathf.CubicInterpolate(X, b.X, preA.X, postB.X, weight),
+ Mathf.CubicInterpolate(Y, b.Y, preA.Y, postB.Y, weight),
+ Mathf.CubicInterpolate(Z, b.Z, preA.Z, postB.Z, weight),
+ Mathf.CubicInterpolate(W, b.W, preA.W, postB.W, weight)
);
}
@@ -206,14 +206,14 @@ 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
(
- Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT),
- Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT),
- Mathf.CubicInterpolateInTime(z, b.z, preA.z, postB.z, weight, t, preAT, postBT),
- Mathf.CubicInterpolateInTime(w, b.w, preA.w, postB.w, weight, t, preAT, postBT)
+ Mathf.CubicInterpolateInTime(X, b.X, preA.X, postB.X, weight, t, preAT, postBT),
+ Mathf.CubicInterpolateInTime(Y, b.Y, preA.Y, postB.Y, weight, t, preAT, postBT),
+ Mathf.CubicInterpolateInTime(Z, b.Z, preA.Z, postB.Z, weight, t, preAT, postBT),
+ Mathf.CubicInterpolateInTime(W, b.W, preA.W, postB.W, weight, t, preAT, postBT)
);
}
@@ -222,9 +222,9 @@ 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);
+ Vector4 ret = new Vector4(to.X - X, to.Y - Y, to.Z - Z, to.W - W);
ret.Normalize();
return ret;
}
@@ -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,34 +256,44 @@ 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);
+ return (X * with.X) + (Y * with.Y) + (Z * with.Z) + (W * with.W);
}
/// <summary>
/// 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));
+ return new Vector4(Mathf.Floor(X), Mathf.Floor(Y), Mathf.Floor(Z), Mathf.Floor(W));
}
/// <summary>
- /// 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>.
+ /// 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);
+ return new Vector4(1 / X, 1 / Y, 1 / Z, 1 / W);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector is finite, by calling
+ /// <see cref="Mathf.IsFinite"/> on each component.
+ /// </summary>
+ /// <returns>Whether this vector is finite or not.</returns>
+ public readonly bool IsFinite()
+ {
+ return Mathf.IsFinite(X) && Mathf.IsFinite(Y) && Mathf.IsFinite(Z) && Mathf.IsFinite(W);
}
/// <summary>
/// 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,12 +303,12 @@ 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;
- real_t z2 = z * z;
- real_t w2 = w * w;
+ real_t x2 = X * X;
+ real_t y2 = Y * Y;
+ real_t z2 = Z * Z;
+ real_t w2 = W * W;
return Mathf.Sqrt(x2 + y2 + z2 + w2);
}
@@ -309,12 +319,12 @@ 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;
- real_t z2 = z * z;
- real_t w2 = w * w;
+ real_t x2 = X * X;
+ real_t y2 = Y * Y;
+ real_t z2 = Z * Z;
+ real_t w2 = W * W;
return x2 + y2 + z2 + w2;
}
@@ -326,14 +336,14 @@ 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
(
- Mathf.Lerp(x, to.x, weight),
- Mathf.Lerp(y, to.y, weight),
- Mathf.Lerp(z, to.z, weight),
- Mathf.Lerp(w, to.w, weight)
+ Mathf.Lerp(X, to.X, weight),
+ Mathf.Lerp(Y, to.Y, weight),
+ Mathf.Lerp(Z, to.Z, weight),
+ Mathf.Lerp(W, to.W, weight)
);
}
@@ -342,10 +352,10 @@ 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;
+ real_t max_value = X;
for (int i = 1; i < 4; i++)
{
if (this[i] > max_value)
@@ -362,10 +372,10 @@ 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;
+ real_t min_value = X;
for (int i = 1; i < 4; i++)
{
if (this[i] <= min_value)
@@ -381,7 +391,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,13 +406,13 @@ 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),
- Mathf.PosMod(y, mod),
- Mathf.PosMod(z, mod),
- Mathf.PosMod(w, mod)
+ Mathf.PosMod(X, mod),
+ Mathf.PosMod(Y, mod),
+ Mathf.PosMod(Z, mod),
+ Mathf.PosMod(W, mod)
);
}
@@ -414,13 +424,13 @@ 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),
- Mathf.PosMod(y, modv.y),
- Mathf.PosMod(z, modv.z),
- Mathf.PosMod(w, modv.w)
+ Mathf.PosMod(X, modv.X),
+ Mathf.PosMod(Y, modv.Y),
+ Mathf.PosMod(Z, modv.Z),
+ Mathf.PosMod(W, modv.W)
);
}
@@ -429,9 +439,9 @@ 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));
+ return new Vector4(Mathf.Round(X), Mathf.Round(Y), Mathf.Round(Z), Mathf.Round(W));
}
/// <summary>
@@ -440,13 +450,13 @@ 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);
- v.y = Mathf.Sign(y);
- v.z = Mathf.Sign(z);
- v.w = Mathf.Sign(w);
+ v.X = Mathf.Sign(X);
+ v.Y = Mathf.Sign(Y);
+ v.Z = Mathf.Sign(Z);
+ v.W = Mathf.Sign(W);
return v;
}
@@ -456,13 +466,13 @@ 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),
- Mathf.Snapped(y, step.y),
- Mathf.Snapped(z, step.z),
- Mathf.Snapped(w, step.w)
+ Mathf.Snapped(X, step.X),
+ Mathf.Snapped(Y, step.Y),
+ Mathf.Snapped(Z, step.Z),
+ Mathf.Snapped(W, step.W)
);
}
@@ -496,10 +506,10 @@ namespace Godot
/// <param name="w">The vector's W component.</param>
public Vector4(real_t x, real_t y, real_t z, real_t w)
{
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
}
/// <summary>
@@ -511,10 +521,10 @@ namespace Godot
/// <returns>The added vector.</returns>
public static Vector4 operator +(Vector4 left, Vector4 right)
{
- left.x += right.x;
- left.y += right.y;
- left.z += right.z;
- left.w += right.w;
+ left.X += right.X;
+ left.Y += right.Y;
+ left.Z += right.Z;
+ left.W += right.W;
return left;
}
@@ -527,16 +537,16 @@ namespace Godot
/// <returns>The subtracted vector.</returns>
public static Vector4 operator -(Vector4 left, Vector4 right)
{
- left.x -= right.x;
- left.y -= right.y;
- left.z -= right.z;
- left.w -= right.w;
+ left.X -= right.X;
+ left.Y -= right.Y;
+ left.Z -= right.Z;
+ left.W -= right.W;
return left;
}
/// <summary>
/// Returns the negative value of the <see cref="Vector4"/>.
- /// This is the same as writing <c>new Vector4(-v.x, -v.y, -v.z, -v.w)</c>.
+ /// This is the same as writing <c>new Vector4(-v.X, -v.Y, -v.Z, -v.W)</c>.
/// This operation flips the direction of the vector while
/// keeping the same magnitude.
/// With floats, the number zero can be either positive or negative.
@@ -545,10 +555,10 @@ namespace Godot
/// <returns>The negated/flipped vector.</returns>
public static Vector4 operator -(Vector4 vec)
{
- vec.x = -vec.x;
- vec.y = -vec.y;
- vec.z = -vec.z;
- vec.w = -vec.w;
+ vec.X = -vec.X;
+ vec.Y = -vec.Y;
+ vec.Z = -vec.Z;
+ vec.W = -vec.W;
return vec;
}
@@ -561,10 +571,10 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector4 operator *(Vector4 vec, real_t scale)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
- vec.w *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
+ vec.W *= scale;
return vec;
}
@@ -577,10 +587,10 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector4 operator *(real_t scale, Vector4 vec)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
- vec.w *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
+ vec.W *= scale;
return vec;
}
@@ -593,10 +603,10 @@ namespace Godot
/// <returns>The multiplied vector.</returns>
public static Vector4 operator *(Vector4 left, Vector4 right)
{
- left.x *= right.x;
- left.y *= right.y;
- left.z *= right.z;
- left.w *= right.w;
+ left.X *= right.X;
+ left.Y *= right.Y;
+ left.Z *= right.Z;
+ left.W *= right.W;
return left;
}
@@ -609,10 +619,10 @@ namespace Godot
/// <returns>The divided vector.</returns>
public static Vector4 operator /(Vector4 vec, real_t divisor)
{
- vec.x /= divisor;
- vec.y /= divisor;
- vec.z /= divisor;
- vec.w /= divisor;
+ vec.X /= divisor;
+ vec.Y /= divisor;
+ vec.Z /= divisor;
+ vec.W /= divisor;
return vec;
}
@@ -625,10 +635,10 @@ namespace Godot
/// <returns>The divided vector.</returns>
public static Vector4 operator /(Vector4 vec, Vector4 divisorv)
{
- vec.x /= divisorv.x;
- vec.y /= divisorv.y;
- vec.z /= divisorv.z;
- vec.w /= divisorv.w;
+ vec.X /= divisorv.X;
+ vec.Y /= divisorv.Y;
+ vec.Z /= divisorv.Z;
+ vec.W /= divisorv.W;
return vec;
}
@@ -650,10 +660,10 @@ namespace Godot
/// <returns>The remainder vector.</returns>
public static Vector4 operator %(Vector4 vec, real_t divisor)
{
- vec.x %= divisor;
- vec.y %= divisor;
- vec.z %= divisor;
- vec.w %= divisor;
+ vec.X %= divisor;
+ vec.Y %= divisor;
+ vec.Z %= divisor;
+ vec.W %= divisor;
return vec;
}
@@ -675,10 +685,10 @@ namespace Godot
/// <returns>The remainder vector.</returns>
public static Vector4 operator %(Vector4 vec, Vector4 divisorv)
{
- vec.x %= divisorv.x;
- vec.y %= divisorv.y;
- vec.z %= divisorv.z;
- vec.w %= divisorv.w;
+ vec.X %= divisorv.X;
+ vec.Y %= divisorv.Y;
+ vec.Z %= divisorv.Z;
+ vec.W %= divisorv.W;
return vec;
}
@@ -721,19 +731,19 @@ namespace Godot
/// <returns>Whether or not the left is less than the right.</returns>
public static bool operator <(Vector4 left, Vector4 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w < right.w;
+ return left.W < right.W;
}
- return left.z < right.z;
+ return left.Z < right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
@@ -749,19 +759,19 @@ namespace Godot
/// <returns>Whether or not the left is greater than the right.</returns>
public static bool operator >(Vector4 left, Vector4 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w > right.w;
+ return left.W > right.W;
}
- return left.z > right.z;
+ return left.Z > right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
@@ -777,19 +787,19 @@ namespace Godot
/// <returns>Whether or not the left is less than or equal to the right.</returns>
public static bool operator <=(Vector4 left, Vector4 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w <= right.w;
+ return left.W <= right.W;
}
- return left.z < right.z;
+ return left.Z < right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
@@ -805,19 +815,19 @@ namespace Godot
/// <returns>Whether or not the left is greater than or equal to the right.</returns>
public static bool operator >=(Vector4 left, Vector4 right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w >= right.w;
+ return left.W >= right.W;
}
- return left.z > right.z;
+ return left.Z > right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
@@ -828,7 +838,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,9 +850,9 @@ 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;
+ return X == other.X && Y == other.Y && Z == other.Z && W == other.W;
}
/// <summary>
@@ -851,18 +861,30 @@ 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);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector's values are approximately zero,
+ /// by running <see cref="Mathf.IsZeroApprox(real_t)"/> on each component.
+ /// This method is faster than using <see cref="IsEqualApprox"/> with one value
+ /// as a zero vector.
+ /// </summary>
+ /// <returns>Whether or not the vector is approximately zero.</returns>
+ public readonly bool IsZeroApprox()
{
- return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
+ return Mathf.IsZeroApprox(X) && Mathf.IsZeroApprox(Y) && Mathf.IsZeroApprox(Z) && Mathf.IsZeroApprox(W);
}
/// <summary>
/// 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();
+ return Y.GetHashCode() ^ X.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
}
/// <summary>
@@ -871,16 +893,16 @@ namespace Godot
/// <returns>A string representation of this vector.</returns>
public override string ToString()
{
- return $"({x}, {y}, {z}, {w})";
+ return $"({X}, {Y}, {Z}, {W})";
}
/// <summary>
/// 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)})";
+ 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..f065327066 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs
@@ -8,7 +8,7 @@ namespace Godot
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- public struct Vector4i : IEquatable<Vector4i>
+ public struct Vector4I : IEquatable<Vector4I>
{
/// <summary>
/// Enumerated index values for the axes.
@@ -37,22 +37,22 @@ namespace Godot
/// <summary>
/// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
- public int x;
+ public int X;
/// <summary>
/// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
- public int y;
+ public int Y;
/// <summary>
/// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
/// </summary>
- public int z;
+ public int Z;
/// <summary>
/// The vector's W component. Also accessible by using the index position <c>[3]</c>.
/// </summary>
- public int w;
+ public int W;
/// <summary>
/// Access vector components using their <paramref name="index"/>.
@@ -61,25 +61,25 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1, 2 or 3.
/// </exception>
/// <value>
- /// <c>[0]</c> is equivalent to <see cref="x"/>,
- /// <c>[1]</c> is equivalent to <see cref="y"/>,
- /// <c>[2]</c> is equivalent to <see cref="z"/>.
- /// <c>[3]</c> is equivalent to <see cref="w"/>.
+ /// <c>[0]</c> is equivalent to <see cref="X"/>,
+ /// <c>[1]</c> is equivalent to <see cref="Y"/>,
+ /// <c>[2]</c> is equivalent to <see cref="Z"/>.
+ /// <c>[3]</c> is equivalent to <see cref="W"/>.
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
case 0:
- return x;
+ return X;
case 1:
- return y;
+ return Y;
case 2:
- return z;
+ return Z;
case 3:
- return w;
+ return W;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
@@ -89,16 +89,16 @@ namespace Godot
switch (index)
{
case 0:
- x = value;
+ X = value;
return;
case 1:
- y = value;
+ Y = value;
return;
case 2:
- z = value;
+ Z = value;
return;
case 3:
- w = value;
+ W = value;
return;
default:
throw new ArgumentOutOfRangeException(nameof(index));
@@ -109,21 +109,21 @@ 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;
- z = this.z;
- w = this.w;
+ x = X;
+ y = Y;
+ z = Z;
+ w = W;
}
/// <summary>
/// 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));
+ return new Vector4I(Mathf.Abs(X), Mathf.Abs(Y), Mathf.Abs(Z), Mathf.Abs(W));
}
/// <summary>
@@ -134,14 +134,14 @@ 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
+ return new Vector4I
(
- Mathf.Clamp(x, min.x, max.x),
- Mathf.Clamp(y, min.y, max.y),
- Mathf.Clamp(z, min.z, max.z),
- Mathf.Clamp(w, min.w, max.w)
+ Mathf.Clamp(X, min.X, max.X),
+ Mathf.Clamp(Y, min.Y, max.Y),
+ Mathf.Clamp(Z, min.Z, max.Z),
+ Mathf.Clamp(W, min.W, max.W)
);
}
@@ -150,12 +150,12 @@ 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;
- int z2 = z * z;
- int w2 = w * w;
+ int x2 = X * X;
+ int y2 = Y * Y;
+ int z2 = Z * Z;
+ int w2 = W * W;
return Mathf.Sqrt(x2 + y2 + z2 + w2);
}
@@ -166,12 +166,12 @@ 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;
- int z2 = z * z;
- int w2 = w * w;
+ int x2 = X * X;
+ int y2 = Y * Y;
+ int z2 = Z * Z;
+ int w2 = W * W;
return x2 + y2 + z2 + w2;
}
@@ -181,10 +181,10 @@ 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;
+ int max_value = X;
for (int i = 1; i < 4; i++)
{
if (this[i] > max_value)
@@ -201,10 +201,10 @@ 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;
+ int min_value = X;
for (int i = 1; i < 4; i++)
{
if (this[i] <= min_value)
@@ -222,245 +222,217 @@ 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));
+ return new Vector4I(Mathf.Sign(X), Mathf.Sign(Y), Mathf.Sign(Z), Mathf.Sign(W));
}
// Constants
- private static readonly Vector4i _zero = new Vector4i(0, 0, 0, 0);
- private static readonly Vector4i _one = new Vector4i(1, 1, 1, 1);
+ private static readonly Vector4I _zero = new Vector4I(0, 0, 0, 0);
+ private static readonly Vector4I _one = new Vector4I(1, 1, 1, 1);
/// <summary>
/// Zero vector, a vector with all components set to <c>0</c>.
/// </summary>
- /// <value>Equivalent to <c>new Vector4i(0, 0, 0, 0)</c>.</value>
- public static Vector4i Zero { get { return _zero; } }
+ /// <value>Equivalent to <c>new Vector4I(0, 0, 0, 0)</c>.</value>
+ public static Vector4I Zero { get { return _zero; } }
/// <summary>
/// One vector, a vector with all components set to <c>1</c>.
/// </summary>
- /// <value>Equivalent to <c>new Vector4i(1, 1, 1, 1)</c>.</value>
- public static Vector4i One { get { return _one; } }
+ /// <value>Equivalent to <c>new Vector4I(1, 1, 1, 1)</c>.</value>
+ public static Vector4I One { get { return _one; } }
/// <summary>
- /// Constructs a new <see cref="Vector4i"/> with the given components.
+ /// Constructs a new <see cref="Vector4I"/> with the given components.
/// </summary>
/// <param name="x">The vector's X component.</param>
/// <param name="y">The vector's Y component.</param>
/// <param name="z">The vector's Z component.</param>
/// <param name="w">The vector's W component.</param>
- public Vector4i(int x, int y, int z, int w)
+ public Vector4I(int x, int y, int z, int w)
{
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
}
/// <summary>
- /// Adds each component of the <see cref="Vector4i"/>
- /// with the components of the given <see cref="Vector4i"/>.
+ /// Adds each component of the <see cref="Vector4I"/>
+ /// with the components of the given <see cref="Vector4I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The added vector.</returns>
- public static Vector4i operator +(Vector4i left, Vector4i right)
+ public static Vector4I operator +(Vector4I left, Vector4I right)
{
- left.x += right.x;
- left.y += right.y;
- left.z += right.z;
- left.w += right.w;
+ left.X += right.X;
+ left.Y += right.Y;
+ left.Z += right.Z;
+ left.W += right.W;
return left;
}
/// <summary>
- /// Subtracts each component of the <see cref="Vector4i"/>
- /// by the components of the given <see cref="Vector4i"/>.
+ /// Subtracts each component of the <see cref="Vector4I"/>
+ /// by the components of the given <see cref="Vector4I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The subtracted vector.</returns>
- public static Vector4i operator -(Vector4i left, Vector4i right)
+ public static Vector4I operator -(Vector4I left, Vector4I right)
{
- left.x -= right.x;
- left.y -= right.y;
- left.z -= right.z;
- left.w -= right.w;
+ left.X -= right.X;
+ left.Y -= right.Y;
+ left.Z -= right.Z;
+ left.W -= right.W;
return left;
}
/// <summary>
- /// Returns the negative value of the <see cref="Vector4i"/>.
- /// This is the same as writing <c>new Vector4i(-v.x, -v.y, -v.z, -v.w)</c>.
+ /// Returns the negative value of the <see cref="Vector4I"/>.
+ /// This is the same as writing <c>new Vector4I(-v.X, -v.Y, -v.Z, -v.W)</c>.
/// This operation flips the direction of the vector while
/// keeping the same magnitude.
/// </summary>
/// <param name="vec">The vector to negate/flip.</param>
/// <returns>The negated/flipped vector.</returns>
- public static Vector4i operator -(Vector4i vec)
+ public static Vector4I operator -(Vector4I vec)
{
- vec.x = -vec.x;
- vec.y = -vec.y;
- vec.z = -vec.z;
- vec.w = -vec.w;
+ vec.X = -vec.X;
+ vec.Y = -vec.Y;
+ vec.Z = -vec.Z;
+ vec.W = -vec.W;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector4i"/>
+ /// Multiplies each component of the <see cref="Vector4I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The vector to multiply.</param>
/// <param name="scale">The scale to multiply by.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector4i operator *(Vector4i vec, int scale)
+ public static Vector4I operator *(Vector4I vec, int scale)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
- vec.w *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
+ vec.W *= scale;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector4i"/>
+ /// Multiplies each component of the <see cref="Vector4I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="scale">The scale to multiply by.</param>
/// <param name="vec">The vector to multiply.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector4i operator *(int scale, Vector4i vec)
+ public static Vector4I operator *(int scale, Vector4I vec)
{
- vec.x *= scale;
- vec.y *= scale;
- vec.z *= scale;
- vec.w *= scale;
+ vec.X *= scale;
+ vec.Y *= scale;
+ vec.Z *= scale;
+ vec.W *= scale;
return vec;
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector4i"/>
- /// by the components of the given <see cref="Vector4i"/>.
+ /// Multiplies each component of the <see cref="Vector4I"/>
+ /// by the components of the given <see cref="Vector4I"/>.
/// </summary>
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>The multiplied vector.</returns>
- public static Vector4i operator *(Vector4i left, Vector4i right)
+ public static Vector4I operator *(Vector4I left, Vector4I right)
{
- left.x *= right.x;
- left.y *= right.y;
- left.z *= right.z;
- left.w *= right.w;
+ left.X *= right.X;
+ left.Y *= right.Y;
+ left.Z *= right.Z;
+ left.W *= right.W;
return left;
}
/// <summary>
- /// Divides each component of the <see cref="Vector4i"/>
+ /// Divides each component of the <see cref="Vector4I"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisor">The divisor value.</param>
/// <returns>The divided vector.</returns>
- public static Vector4i operator /(Vector4i vec, int divisor)
+ public static Vector4I operator /(Vector4I vec, int divisor)
{
- vec.x /= divisor;
- vec.y /= divisor;
- vec.z /= divisor;
- vec.w /= divisor;
+ vec.X /= divisor;
+ vec.Y /= divisor;
+ vec.Z /= divisor;
+ vec.W /= divisor;
return vec;
}
/// <summary>
- /// Divides each component of the <see cref="Vector4i"/>
- /// by the components of the given <see cref="Vector4i"/>.
+ /// Divides each component of the <see cref="Vector4I"/>
+ /// by the components of the given <see cref="Vector4I"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisorv">The divisor vector.</param>
/// <returns>The divided vector.</returns>
- public static Vector4i operator /(Vector4i vec, Vector4i divisorv)
+ public static Vector4I operator /(Vector4I vec, Vector4I divisorv)
{
- vec.x /= divisorv.x;
- vec.y /= divisorv.y;
- vec.z /= divisorv.z;
- vec.w /= divisorv.w;
+ vec.X /= divisorv.X;
+ vec.Y /= divisorv.Y;
+ vec.Z /= divisorv.Z;
+ vec.W /= divisorv.W;
return vec;
}
/// <summary>
- /// Gets the remainder of each component of the <see cref="Vector4i"/>
+ /// Gets the remainder of each component of the <see cref="Vector4I"/>
/// with the components of the given <see langword="int"/>.
/// This operation uses truncated division, which is often not desired
/// as it does not work well with negative numbers.
+ /// Consider using <see cref="Mathf.PosMod(int, int)"/> instead
+ /// if you want to handle negative numbers.
/// </summary>
/// <example>
/// <code>
- /// GD.Print(new Vecto43i(10, -20, 30, -40) % 7); // Prints "(3, -6, 2, -5)"
+ /// GD.Print(new Vector4I(10, -20, 30, -40) % 7); // Prints "(3, -6, 2, -5)"
/// </code>
/// </example>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisor">The divisor value.</param>
/// <returns>The remainder vector.</returns>
- public static Vector4i operator %(Vector4i vec, int divisor)
+ public static Vector4I operator %(Vector4I vec, int divisor)
{
- vec.x %= divisor;
- vec.y %= divisor;
- vec.z %= divisor;
- vec.w %= divisor;
+ vec.X %= divisor;
+ vec.Y %= divisor;
+ vec.Z %= divisor;
+ vec.W %= divisor;
return vec;
}
/// <summary>
- /// Gets the remainder of each component of the <see cref="Vector4i"/>
- /// with the components of the given <see cref="Vector4i"/>.
+ /// Gets the remainder of each component of the <see cref="Vector4I"/>
+ /// with the components of the given <see cref="Vector4I"/>.
/// This operation uses truncated division, which is often not desired
/// as it does not work well with negative numbers.
+ /// Consider using <see cref="Mathf.PosMod(int, int)"/> instead
+ /// if you want to handle negative numbers.
/// </summary>
/// <example>
/// <code>
- /// GD.Print(new Vector4i(10, -20, 30, -40) % new Vector4i(6, 7, 8, 9)); // Prints "(4, -6, 6, -4)"
+ /// GD.Print(new Vector4I(10, -20, 30, -40) % new Vector4I(6, 7, 8, 9)); // Prints "(4, -6, 6, -4)"
/// </code>
/// </example>
/// <param name="vec">The dividend vector.</param>
/// <param name="divisorv">The divisor vector.</param>
/// <returns>The remainder vector.</returns>
- public static Vector4i operator %(Vector4i vec, Vector4i divisorv)
+ public static Vector4I operator %(Vector4I vec, Vector4I divisorv)
{
- vec.x %= divisorv.x;
- vec.y %= divisorv.y;
- vec.z %= divisorv.z;
- vec.w %= divisorv.w;
- return vec;
- }
-
- /// <summary>
- /// Performs a bitwise AND operation with this <see cref="Vector4i"/>
- /// and the given <see langword="int"/>.
- /// </summary>
- /// <param name="vec">The vector to AND with.</param>
- /// <param name="and">The integer to AND with.</param>
- /// <returns>The result of the bitwise AND.</returns>
- public static Vector4i operator &(Vector4i vec, int and)
- {
- vec.x &= and;
- vec.y &= and;
- vec.z &= and;
- vec.w &= and;
- return vec;
- }
-
- /// <summary>
- /// Performs a bitwise AND operation with this <see cref="Vector4i"/>
- /// and the given <see cref="Vector4i"/>.
- /// </summary>
- /// <param name="vec">The left vector to AND with.</param>
- /// <param name="andv">The right vector to AND with.</param>
- /// <returns>The result of the bitwise AND.</returns>
- public static Vector4i operator &(Vector4i vec, Vector4i andv)
- {
- vec.x &= andv.x;
- vec.y &= andv.y;
- vec.z &= andv.z;
- vec.w &= andv.w;
+ vec.X %= divisorv.X;
+ vec.Y %= divisorv.Y;
+ vec.Z %= divisorv.Z;
+ vec.W %= divisorv.W;
return vec;
}
@@ -470,7 +442,7 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public static bool operator ==(Vector4i left, Vector4i right)
+ public static bool operator ==(Vector4I left, Vector4I right)
{
return left.Equals(right);
}
@@ -481,13 +453,13 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the vectors are not equal.</returns>
- public static bool operator !=(Vector4i left, Vector4i right)
+ public static bool operator !=(Vector4I left, Vector4I right)
{
return !left.Equals(right);
}
/// <summary>
- /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// Compares two <see cref="Vector4I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is less than
/// the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -497,25 +469,25 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is less than the right.</returns>
- public static bool operator <(Vector4i left, Vector4i right)
+ public static bool operator <(Vector4I left, Vector4I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w < right.w;
+ return left.W < right.W;
}
- return left.z < right.z;
+ return left.Z < right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
- /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// Compares two <see cref="Vector4I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is greater than
/// the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -525,25 +497,25 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is greater than the right.</returns>
- public static bool operator >(Vector4i left, Vector4i right)
+ public static bool operator >(Vector4I left, Vector4I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w > right.w;
+ return left.W > right.W;
}
- return left.z > right.z;
+ return left.Z > right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
- /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// Compares two <see cref="Vector4I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is less than
/// or equal to the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -553,25 +525,25 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is less than or equal to the right.</returns>
- public static bool operator <=(Vector4i left, Vector4i right)
+ public static bool operator <=(Vector4I left, Vector4I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w <= right.w;
+ return left.W <= right.W;
}
- return left.z < right.z;
+ return left.Z < right.Z;
}
- return left.y < right.y;
+ return left.Y < right.Y;
}
- return left.x < right.x;
+ return left.X < right.X;
}
/// <summary>
- /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// Compares two <see cref="Vector4I"/> vectors by first checking if
/// the X value of the <paramref name="left"/> vector is greater than
/// or equal to the X value of the <paramref name="right"/> vector.
/// If the X values are exactly equal, then it repeats this check
@@ -581,43 +553,43 @@ namespace Godot
/// <param name="left">The left vector.</param>
/// <param name="right">The right vector.</param>
/// <returns>Whether or not the left is greater than or equal to the right.</returns>
- public static bool operator >=(Vector4i left, Vector4i right)
+ public static bool operator >=(Vector4I left, Vector4I right)
{
- if (left.x == right.x)
+ if (left.X == right.X)
{
- if (left.y == right.y)
+ if (left.Y == right.Y)
{
- if (left.z == right.z)
+ if (left.Z == right.Z)
{
- return left.w >= right.w;
+ return left.W >= right.W;
}
- return left.z > right.z;
+ return left.Z > right.Z;
}
- return left.y > right.y;
+ return left.Y > right.Y;
}
- return left.x > right.x;
+ return left.X > right.X;
}
/// <summary>
- /// Converts this <see cref="Vector4i"/> to a <see cref="Vector4"/>.
+ /// Converts this <see cref="Vector4I"/> to a <see cref="Vector4"/>.
/// </summary>
/// <param name="value">The vector to convert.</param>
- public static implicit operator Vector4(Vector4i value)
+ public static implicit operator Vector4(Vector4I value)
{
- return new Vector4(value.x, value.y, value.z, value.w);
+ return new Vector4(value.X, value.Y, value.Z, value.W);
}
/// <summary>
- /// Converts a <see cref="Vector4"/> to a <see cref="Vector4i"/>.
+ /// Converts a <see cref="Vector4"/> to a <see cref="Vector4I"/>.
/// </summary>
/// <param name="value">The vector to convert.</param>
- public static explicit operator Vector4i(Vector4 value)
+ public static explicit operator Vector4I(Vector4 value)
{
- return new Vector4i(
- Mathf.RoundToInt(value.x),
- Mathf.RoundToInt(value.y),
- Mathf.RoundToInt(value.z),
- Mathf.RoundToInt(value.w)
+ return new Vector4I(
+ Mathf.RoundToInt(value.X),
+ Mathf.RoundToInt(value.Y),
+ Mathf.RoundToInt(value.Z),
+ Mathf.RoundToInt(value.W)
);
}
@@ -627,9 +599,9 @@ 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);
+ return obj is Vector4I other && Equals(other);
}
/// <summary>
@@ -637,36 +609,36 @@ 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;
+ return X == other.X && Y == other.Y && Z == other.Z && W == other.W;
}
/// <summary>
- /// Serves as the hash function for <see cref="Vector4i"/>.
+ /// 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();
+ return Y.GetHashCode() ^ X.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
}
/// <summary>
- /// Converts this <see cref="Vector4i"/> to a string.
+ /// 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})";
+ return $"({X}, {Y}, {Z}, {W})";
}
/// <summary>
- /// Converts this <see cref="Vector4i"/> to a string with the given <paramref name="format"/>.
+ /// 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)})";
+ return $"({X.ToString(format)}, {Y.ToString(format)}, {Z.ToString(format)}), {W.ToString(format)})";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index e3fb254f49..7aa2f7e959 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -49,7 +49,7 @@
</ItemGroup>
<!-- Sources -->
<ItemGroup>
- <Compile Include="Core\AABB.cs" />
+ <Compile Include="Core\Aabb.cs" />
<Compile Include="Core\Bridge\GodotSerializationInfo.cs" />
<Compile Include="Core\Bridge\MethodInfo.cs" />
<Compile Include="Core\Callable.generics.cs" />
@@ -60,8 +60,9 @@
<Compile Include="Core\Attributes\ExportCategoryAttribute.cs" />
<Compile Include="Core\Attributes\ExportGroupAttribute.cs" />
<Compile Include="Core\Attributes\ExportSubgroupAttribute.cs" />
+ <Compile Include="Core\Attributes\GodotClassNameAttribute.cs" />
<Compile Include="Core\Attributes\MustBeVariantAttribute.cs" />
- <Compile Include="Core\Attributes\RPCAttribute.cs" />
+ <Compile Include="Core\Attributes\RpcAttribute.cs" />
<Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
<Compile Include="Core\Attributes\SignalAttribute.cs" />
<Compile Include="Core\Attributes\ToolAttribute.cs" />
@@ -80,11 +81,13 @@
<Compile Include="Core\DelegateUtils.cs" />
<Compile Include="Core\Dictionary.cs" />
<Compile Include="Core\Dispatcher.cs" />
+ <Compile Include="Core\Extensions\GodotObjectExtensions.cs" />
<Compile Include="Core\Extensions\NodeExtensions.cs" />
- <Compile Include="Core\Extensions\ObjectExtensions.cs" />
<Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
<Compile Include="Core\Extensions\ResourceLoaderExtensions.cs" />
<Compile Include="Core\GD.cs" />
+ <Compile Include="Core\GodotObject.base.cs" />
+ <Compile Include="Core\GodotObject.exceptions.cs" />
<Compile Include="Core\GodotSynchronizationContext.cs" />
<Compile Include="Core\GodotTaskScheduler.cs" />
<Compile Include="Core\GodotTraceListener.cs" />
@@ -101,37 +104,34 @@
<Compile Include="Core\NativeInterop\InteropUtils.cs" />
<Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
<Compile Include="Core\NativeInterop\NativeVariantPtrArgs.cs" />
- <Compile Include="Core\NativeInterop\VariantConversionCallbacks.cs" />
- <Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
<Compile Include="Core\NativeInterop\VariantUtils.cs" />
+ <Compile Include="Core\NativeInterop\VariantUtils.generic.cs" />
<Compile Include="Core\NodePath.cs" />
- <Compile Include="Core\Object.base.cs" />
- <Compile Include="Core\Object.exceptions.cs" />
<Compile Include="Core\Plane.cs" />
<Compile Include="Core\Projection.cs" />
<Compile Include="Core\Quaternion.cs" />
<Compile Include="Core\Rect2.cs" />
- <Compile Include="Core\Rect2i.cs" />
+ <Compile Include="Core\Rect2I.cs" />
<Compile Include="Core\ReflectionUtils.cs" />
- <Compile Include="Core\RID.cs" />
+ <Compile Include="Core\Rid.cs" />
<Compile Include="Core\NativeInterop\NativeFuncs.cs" />
<Compile Include="Core\NativeInterop\InteropStructs.cs" />
<Compile Include="Core\NativeInterop\Marshaling.cs" />
- <Compile Include="Core\SignalInfo.cs" />
+ <Compile Include="Core\Signal.cs" />
<Compile Include="Core\SignalAwaiter.cs" />
<Compile Include="Core\StringExtensions.cs" />
<Compile Include="Core\StringName.cs" />
<Compile Include="Core\Transform2D.cs" />
<Compile Include="Core\Transform3D.cs" />
+ <Compile Include="Core\Variant.cs" />
<Compile Include="Core\Vector2.cs" />
- <Compile Include="Core\Vector2i.cs" />
+ <Compile Include="Core\Vector2I.cs" />
<Compile Include="Core\Vector3.cs" />
- <Compile Include="Core\Vector3i.cs" />
+ <Compile Include="Core\Vector3I.cs" />
<Compile Include="Core\Vector4.cs" />
- <Compile Include="Core\Vector4i.cs" />
+ <Compile Include="Core\Vector4I.cs" />
<Compile Include="GlobalUsings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="Variant.cs" />
</ItemGroup>
<!--
We import a props file with auto-generated includes. This works well with Rider.
diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp
index e20a88076a..306ac333eb 100644
--- a/modules/mono/glue/runtime_interop.cpp
+++ b/modules/mono/glue/runtime_interop.cpp
@@ -1,36 +1,37 @@
-/*************************************************************************/
-/* runtime_interop.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* runtime_interop.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "runtime_interop.h"
#include "core/config/engine.h"
+#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
#include "core/io/marshalls.h"
@@ -45,6 +46,7 @@
#include "modules/mono/managed_callable.h"
#include "modules/mono/mono_gd/gd_mono_cache.h"
#include "modules/mono/signal_awaiter_utils.h"
+#include "modules/mono/utils/path_utils.h"
#ifdef __cplusplus
extern "C" {
@@ -84,7 +86,8 @@ void godotsharp_stack_info_vector_destroy(
void godotsharp_internal_script_debugger_send_error(const String *p_func,
const String *p_file, int32_t p_line, const String *p_err, const String *p_descr,
bool p_warning, const Vector<ScriptLanguage::StackInfo> *p_stack_info_vector) {
- EngineDebugger::get_script_debugger()->send_error(*p_func, *p_file, p_line, *p_err, *p_descr,
+ const String file = ProjectSettings::get_singleton()->localize_path(p_file->simplify_path());
+ EngineDebugger::get_script_debugger()->send_error(*p_func, file, p_line, *p_err, *p_descr,
true, p_warning ? ERR_HANDLER_WARNING : ERR_HANDLER_ERROR, *p_stack_info_vector);
}
@@ -514,6 +517,13 @@ void godotsharp_callable_call_deferred(Callable *p_callable, const Variant **p_a
p_callable->call_deferredp(p_args, p_arg_count);
}
+godot_color godotsharp_color_from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) {
+ godot_color ret;
+ Color *dest = (Color *)&ret;
+ memnew_placement(dest, Color(Color::from_ok_hsl(p_h, p_s, p_l, p_alpha)));
+ return ret;
+}
+
// GDNative functions
// gdnative.h
@@ -982,18 +992,78 @@ int32_t godotsharp_array_add(Array *p_self, const Variant *p_item) {
return p_self->size();
}
+int32_t godotsharp_array_add_range(Array *p_self, const Array *p_collection) {
+ p_self->append_array(*p_collection);
+ return p_self->size();
+}
+
+int32_t godotsharp_array_binary_search(const Array *p_self, int32_t p_index, int32_t p_length, const Variant *p_value) {
+ ERR_FAIL_COND_V(p_index < 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+ ERR_FAIL_COND_V(p_self->size() - p_index < p_length, -1);
+
+ const Variant &value = *p_value;
+ const Array &array = *p_self;
+
+ int lo = p_index;
+ int hi = p_index + p_length - 1;
+ while (lo <= hi) {
+ int mid = lo + ((hi - lo) >> 1);
+ const Variant &mid_item = array[mid];
+
+ if (mid_item == value) {
+ return mid;
+ }
+ if (mid_item < value) {
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+
+ return ~lo;
+}
+
void godotsharp_array_duplicate(const Array *p_self, bool p_deep, Array *r_dest) {
memnew_placement(r_dest, Array(p_self->duplicate(p_deep)));
}
-int32_t godotsharp_array_index_of(const Array *p_self, const Variant *p_item) {
- return p_self->find(*p_item);
+void godotsharp_array_fill(Array *p_self, const Variant *p_value) {
+ p_self->fill(*p_value);
+}
+
+int32_t godotsharp_array_index_of(const Array *p_self, const Variant *p_item, int32_t p_index = 0) {
+ return p_self->find(*p_item, p_index);
}
void godotsharp_array_insert(Array *p_self, int32_t p_index, const Variant *p_item) {
p_self->insert(p_index, *p_item);
}
+int32_t godotsharp_array_last_index_of(const Array *p_self, const Variant *p_item, int32_t p_index) {
+ return p_self->rfind(*p_item, p_index);
+}
+
+void godotsharp_array_make_read_only(Array *p_self) {
+ p_self->make_read_only();
+}
+
+void godotsharp_array_max(const Array *p_self, Variant *r_value) {
+ *r_value = p_self->max();
+}
+
+void godotsharp_array_min(const Array *p_self, Variant *r_value) {
+ *r_value = p_self->min();
+}
+
+void godotsharp_array_pick_random(const Array *p_self, Variant *r_value) {
+ *r_value = p_self->pick_random();
+}
+
+bool godotsharp_array_recursive_equal(const Array *p_self, const Array *p_other) {
+ return p_self->recursive_equal(*p_other, 0);
+}
+
void godotsharp_array_remove_at(Array *p_self, int32_t p_index) {
p_self->remove_at(p_index);
}
@@ -1002,10 +1072,22 @@ int32_t godotsharp_array_resize(Array *p_self, int32_t p_new_size) {
return (int32_t)p_self->resize(p_new_size);
}
+void godotsharp_array_reverse(Array *p_self) {
+ p_self->reverse();
+}
+
void godotsharp_array_shuffle(Array *p_self) {
p_self->shuffle();
}
+void godotsharp_array_slice(Array *p_self, int32_t p_start, int32_t p_end, int32_t p_step, bool p_deep, Array *r_dest) {
+ memnew_placement(r_dest, Array(p_self->slice(p_start, p_end, p_step, p_deep)));
+}
+
+void godotsharp_array_sort(Array *p_self) {
+ p_self->sort();
+}
+
void godotsharp_array_to_string(const Array *p_self, String *r_str) {
*r_str = Variant(*p_self).operator String();
}
@@ -1059,36 +1141,24 @@ void godotsharp_dictionary_duplicate(const Dictionary *p_self, bool p_deep, Dict
memnew_placement(r_dest, Dictionary(p_self->duplicate(p_deep)));
}
-bool godotsharp_dictionary_remove_key(Dictionary *p_self, const Variant *p_key) {
- return p_self->erase(*p_key);
-}
-
-void godotsharp_dictionary_to_string(const Dictionary *p_self, String *r_str) {
- *r_str = Variant(*p_self).operator String();
-}
-
-void godotsharp_string_md5_buffer(const String *p_self, PackedByteArray *r_md5_buffer) {
- memnew_placement(r_md5_buffer, PackedByteArray(p_self->md5_buffer()));
-}
-
-void godotsharp_string_md5_text(const String *p_self, String *r_md5_text) {
- memnew_placement(r_md5_text, String(p_self->md5_text()));
+void godotsharp_dictionary_merge(Dictionary *p_self, const Dictionary *p_dictionary, bool p_overwrite) {
+ p_self->merge(*p_dictionary, p_overwrite);
}
-int32_t godotsharp_string_rfind(const String *p_self, const String *p_what, int32_t p_from) {
- return p_self->rfind(*p_what, p_from);
+bool godotsharp_dictionary_recursive_equal(const Dictionary *p_self, const Dictionary *p_other) {
+ return p_self->recursive_equal(*p_other, 0);
}
-int32_t godotsharp_string_rfindn(const String *p_self, const String *p_what, int32_t p_from) {
- return p_self->rfindn(*p_what, p_from);
+bool godotsharp_dictionary_remove_key(Dictionary *p_self, const Variant *p_key) {
+ return p_self->erase(*p_key);
}
-void godotsharp_string_sha256_buffer(const String *p_self, PackedByteArray *r_sha256_buffer) {
- memnew_placement(r_sha256_buffer, PackedByteArray(p_self->sha256_buffer()));
+void godotsharp_dictionary_make_read_only(Dictionary *p_self) {
+ p_self->make_read_only();
}
-void godotsharp_string_sha256_text(const String *p_self, String *r_sha256_text) {
- memnew_placement(r_sha256_text, String(p_self->sha256_text()));
+void godotsharp_dictionary_to_string(const Dictionary *p_self, String *r_str) {
+ *r_str = Variant(*p_self).operator String();
}
void godotsharp_string_simplify_path(const String *p_self, String *r_simplified_path) {
@@ -1139,6 +1209,14 @@ bool godotsharp_node_path_is_absolute(const NodePath *p_self) {
return p_self->is_absolute();
}
+bool godotsharp_node_path_equals(const NodePath *p_self, const NodePath *p_other) {
+ return *p_self == *p_other;
+}
+
+int godotsharp_node_path_hash(const NodePath *p_self) {
+ return p_self->hash();
+}
+
void godotsharp_randomize() {
Math::randomize();
}
@@ -1197,21 +1275,6 @@ void godotsharp_weakref(Object *p_ptr, Ref<RefCounted> *r_weak_ref) {
memnew_placement(r_weak_ref, Ref<RefCounted>(wref));
}
-void godotsharp_str(const godot_array *p_what, godot_string *r_ret) {
- String &str = *memnew_placement(r_ret, String);
- const Array &what = *reinterpret_cast<const Array *>(p_what);
-
- for (int i = 0; i < what.size(); i++) {
- String os = what[i].operator String();
-
- if (i == 0) {
- str = os;
- } else {
- str += os;
- }
- }
-}
-
void godotsharp_print(const godot_string *p_what) {
print_line(*reinterpret_cast<const String *>(p_what));
}
@@ -1369,6 +1432,7 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_callable_get_data_for_marshalling,
(void *)godotsharp_callable_call,
(void *)godotsharp_callable_call_deferred,
+ (void *)godotsharp_color_from_ok_hsl,
(void *)godotsharp_method_bind_ptrcall,
(void *)godotsharp_method_bind_call,
(void *)godotsharp_variant_new_string_name,
@@ -1454,12 +1518,24 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_array_destroy,
(void *)godotsharp_dictionary_destroy,
(void *)godotsharp_array_add,
+ (void *)godotsharp_array_add_range,
+ (void *)godotsharp_array_binary_search,
(void *)godotsharp_array_duplicate,
+ (void *)godotsharp_array_fill,
(void *)godotsharp_array_index_of,
(void *)godotsharp_array_insert,
+ (void *)godotsharp_array_last_index_of,
+ (void *)godotsharp_array_make_read_only,
+ (void *)godotsharp_array_max,
+ (void *)godotsharp_array_min,
+ (void *)godotsharp_array_pick_random,
+ (void *)godotsharp_array_recursive_equal,
(void *)godotsharp_array_remove_at,
(void *)godotsharp_array_resize,
+ (void *)godotsharp_array_reverse,
(void *)godotsharp_array_shuffle,
+ (void *)godotsharp_array_slice,
+ (void *)godotsharp_array_sort,
(void *)godotsharp_array_to_string,
(void *)godotsharp_dictionary_try_get_value,
(void *)godotsharp_dictionary_set_value,
@@ -1471,14 +1547,11 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_dictionary_clear,
(void *)godotsharp_dictionary_contains_key,
(void *)godotsharp_dictionary_duplicate,
+ (void *)godotsharp_dictionary_merge,
+ (void *)godotsharp_dictionary_recursive_equal,
(void *)godotsharp_dictionary_remove_key,
+ (void *)godotsharp_dictionary_make_read_only,
(void *)godotsharp_dictionary_to_string,
- (void *)godotsharp_string_md5_buffer,
- (void *)godotsharp_string_md5_text,
- (void *)godotsharp_string_rfind,
- (void *)godotsharp_string_rfindn,
- (void *)godotsharp_string_sha256_buffer,
- (void *)godotsharp_string_sha256_text,
(void *)godotsharp_string_simplify_path,
(void *)godotsharp_string_to_camel_case,
(void *)godotsharp_string_to_pascal_case,
@@ -1491,6 +1564,8 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_node_path_get_subname,
(void *)godotsharp_node_path_get_subname_count,
(void *)godotsharp_node_path_is_absolute,
+ (void *)godotsharp_node_path_equals,
+ (void *)godotsharp_node_path_hash,
(void *)godotsharp_bytes_to_var,
(void *)godotsharp_convert,
(void *)godotsharp_hash,
@@ -1510,7 +1585,6 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_rand_from_seed,
(void *)godotsharp_seed,
(void *)godotsharp_weakref,
- (void *)godotsharp_str,
(void *)godotsharp_str_to_var,
(void *)godotsharp_var_to_bytes,
(void *)godotsharp_var_to_str,
diff --git a/modules/mono/glue/runtime_interop.h b/modules/mono/glue/runtime_interop.h
index 9725ced593..c1be4db7ab 100644
--- a/modules/mono/glue/runtime_interop.h
+++ b/modules/mono/glue/runtime_interop.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* runtime_interop.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* runtime_interop.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef RUNTIME_INTEROP_H
#define RUNTIME_INTEROP_H
diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h
index a81a52e4b8..08eeffc3db 100644
--- a/modules/mono/godotsharp_defs.h
+++ b/modules/mono/godotsharp_defs.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* godotsharp_defs.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* godotsharp_defs.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef GODOTSHARP_DEFS_H
#define GODOTSHARP_DEFS_H
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index d45bf4025f..d08dedcfcb 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* godotsharp_dirs.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* godotsharp_dirs.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "godotsharp_dirs.h"
diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h
index cdfb8e4787..82847f70dc 100644
--- a/modules/mono/godotsharp_dirs.h
+++ b/modules/mono/godotsharp_dirs.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* godotsharp_dirs.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* godotsharp_dirs.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef GODOTSHARP_DIRS_H
#define GODOTSHARP_DIRS_H
diff --git a/modules/mono/interop_types.h b/modules/mono/interop_types.h
index 6942a91559..811c444140 100644
--- a/modules/mono/interop_types.h
+++ b/modules/mono/interop_types.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* interop_types.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* interop_types.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef INTEROP_TYPES_H
#define INTEROP_TYPES_H
diff --git a/modules/mono/managed_callable.cpp b/modules/mono/managed_callable.cpp
index 28edc41d98..3e4eb5a966 100644
--- a/modules/mono/managed_callable.cpp
+++ b/modules/mono/managed_callable.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* managed_callable.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* managed_callable.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "managed_callable.h"
diff --git a/modules/mono/managed_callable.h b/modules/mono/managed_callable.h
index b3a137dedf..4936e69323 100644
--- a/modules/mono/managed_callable.h
+++ b/modules/mono/managed_callable.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* managed_callable.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* managed_callable.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef MANAGED_CALLABLE_H
#define MANAGED_CALLABLE_H
diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp
index 9cf0a641b9..efbcc335d4 100644
--- a/modules/mono/mono_gc_handle.cpp
+++ b/modules/mono/mono_gc_handle.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* mono_gc_handle.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* mono_gc_handle.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "mono_gc_handle.h"
diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h
index 4e4c13fee6..ff6c68727d 100644
--- a/modules/mono/mono_gc_handle.h
+++ b/modules/mono/mono_gc_handle.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* mono_gc_handle.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* mono_gc_handle.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef MONO_GC_HANDLE_H
#define MONO_GC_HANDLE_H
diff --git a/modules/mono/mono_gd/android_mono_config.h b/modules/mono/mono_gd/android_mono_config.h
index 9ee4bcf590..bb9c2a5d5b 100644
--- a/modules/mono/mono_gd/android_mono_config.h
+++ b/modules/mono/mono_gd/android_mono_config.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* android_mono_config.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* android_mono_config.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef ANDROID_MONO_CONFIG_H
#define ANDROID_MONO_CONFIG_H
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 3b87d9248a..86b0e04206 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* gd_mono.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* gd_mono.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "gd_mono.h"
@@ -289,7 +289,7 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime
}
#else
static String get_assembly_name() {
- String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
+ String assembly_name = GLOBAL_GET("dotnet/project/assembly_name");
if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
@@ -466,7 +466,7 @@ void GDMono::_init_godot_api_hashes() {
#ifdef TOOLS_ENABLED
bool GDMono::_load_project_assembly() {
- String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
+ String assembly_name = GLOBAL_GET("dotnet/project/assembly_name");
if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index 21252a5dca..080b2c4669 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* gd_mono.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* gd_mono.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef GD_MONO_H
#define GD_MONO_H
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index bfd803f326..3ef7554a3f 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* gd_mono_cache.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* gd_mono_cache.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "gd_mono_cache.h"
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 9c26fa2b0a..2554dfff97 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* gd_mono_cache.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* gd_mono_cache.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef GD_MONO_CACHE_H
#define GD_MONO_CACHE_H
diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp
index 7fb983cd37..6e8a5ce5c1 100644
--- a/modules/mono/mono_gd/support/android_support.cpp
+++ b/modules/mono/mono_gd/support/android_support.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* android_support.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* android_support.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "android_support.h"
diff --git a/modules/mono/mono_gd/support/android_support.h b/modules/mono/mono_gd/support/android_support.h
index 073cd31c65..5be4bac6e1 100644
--- a/modules/mono/mono_gd/support/android_support.h
+++ b/modules/mono/mono_gd/support/android_support.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* android_support.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* android_support.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef ANDROID_SUPPORT_H
#define ANDROID_SUPPORT_H
diff --git a/modules/mono/mono_gd/support/ios_support.h b/modules/mono/mono_gd/support/ios_support.h
index 03e86df698..cb397c8b46 100644
--- a/modules/mono/mono_gd/support/ios_support.h
+++ b/modules/mono/mono_gd/support/ios_support.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* ios_support.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* ios_support.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef IOS_SUPPORT_H
#define IOS_SUPPORT_H
diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm
index 7c941b9d1e..f4abf636b1 100644
--- a/modules/mono/mono_gd/support/ios_support.mm
+++ b/modules/mono/mono_gd/support/ios_support.mm
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* ios_support.mm */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* ios_support.mm */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "ios_support.h"
diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp
index 755e1f7a30..7dab4b037f 100644
--- a/modules/mono/register_types.cpp
+++ b/modules/mono/register_types.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* register_types.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* register_types.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "register_types.h"
diff --git a/modules/mono/register_types.h b/modules/mono/register_types.h
index bc2690c277..8b194434bb 100644
--- a/modules/mono/register_types.h
+++ b/modules/mono/register_types.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* register_types.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* register_types.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef MONO_REGISTER_TYPES_H
#define MONO_REGISTER_TYPES_H
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 66c9eca616..34b94b9755 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* signal_awaiter_utils.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* signal_awaiter_utils.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "signal_awaiter_utils.h"
diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h
index a53ae56bf5..635771f3dc 100644
--- a/modules/mono/signal_awaiter_utils.h
+++ b/modules/mono/signal_awaiter_utils.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* signal_awaiter_utils.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* signal_awaiter_utils.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef SIGNAL_AWAITER_UTILS_H
#define SIGNAL_AWAITER_UTILS_H
diff --git a/modules/mono/utils/macos_utils.cpp b/modules/mono/utils/macos_utils.cpp
index cd4f7a827e..8563c92dd8 100644
--- a/modules/mono/utils/macos_utils.cpp
+++ b/modules/mono/utils/macos_utils.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* macos_utils.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* macos_utils.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "macos_utils.h"
diff --git a/modules/mono/utils/macos_utils.h b/modules/mono/utils/macos_utils.h
index 0b74114685..dfe917db20 100644
--- a/modules/mono/utils/macos_utils.h
+++ b/modules/mono/utils/macos_utils.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* macos_utils.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* macos_utils.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef MONO_MACOS_UTILS_H
#define MONO_MACOS_UTILS_H
diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h
index b7bd9a2495..1e073ccb5e 100644
--- a/modules/mono/utils/macros.h
+++ b/modules/mono/utils/macros.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* macros.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* macros.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef MONO_MACROS_H
#define MONO_MACROS_H
diff --git a/modules/mono/utils/naming_utils.cpp b/modules/mono/utils/naming_utils.cpp
new file mode 100644
index 0000000000..62fbf815f8
--- /dev/null
+++ b/modules/mono/utils/naming_utils.cpp
@@ -0,0 +1,293 @@
+/**************************************************************************/
+/* naming_utils.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "naming_utils.h"
+
+#include "core/string/ucaps.h"
+#include "core/templates/hash_map.h"
+
+HashMap<String, String> _create_hashmap_from_vector(Vector<Pair<String, String>> vector) {
+ HashMap<String, String> hashmap = HashMap<String, String>(vector.size());
+ for (const Pair<String, String> &pair : vector) {
+ hashmap.insert(pair.first, pair.second);
+ }
+ return hashmap;
+}
+
+// Hardcoded collection of PascalCase name conversions.
+const HashMap<String, String> pascal_case_name_overrides = _create_hashmap_from_vector({
+ { "BitMap", "Bitmap" },
+ { "JSONRPC", "JsonRpc" },
+ { "Object", "GodotObject" },
+ { "OpenXRIPBinding", "OpenXRIPBinding" },
+ { "SkeletonModification2DCCDIK", "SkeletonModification2DCcdik" },
+ { "SkeletonModification2DFABRIK", "SkeletonModification2DFabrik" },
+ { "SkeletonModification3DCCDIK", "SkeletonModification3DCcdik" },
+ { "SkeletonModification3DFABRIK", "SkeletonModification3DFabrik" },
+ { "System", "System_" },
+ { "Thread", "GodotThread" },
+});
+
+// Hardcoded collection of PascalCase part conversions.
+const HashMap<String, String> pascal_case_part_overrides = _create_hashmap_from_vector({
+ { "AA", "AA" }, // Anti Aliasing
+ { "AO", "AO" }, // Ambient Occlusion
+ { "FILENAME", "FileName" },
+ { "FADEIN", "FadeIn" },
+ { "FADEOUT", "FadeOut" },
+ { "FX", "FX" },
+ { "GI", "GI" }, // Global Illumination
+ { "GZIP", "GZip" },
+ { "HBOX", "HBox" }, // Horizontal Box
+ { "ID", "Id" },
+ { "IO", "IO" }, // Input/Output
+ { "IP", "IP" }, // Internet Protocol
+ { "IV", "IV" }, // Initialization Vector
+ { "MACOS", "MacOS" },
+ { "NODEPATH", "NodePath" },
+ { "SPIRV", "SpirV" },
+ { "STDIN", "StdIn" },
+ { "STDOUT", "StdOut" },
+ { "USERNAME", "UserName" },
+ { "UV", "UV" },
+ { "UV2", "UV2" },
+ { "VBOX", "VBox" }, // Vertical Box
+ { "WHITESPACE", "WhiteSpace" },
+ { "WM", "WM" },
+ { "XR", "XR" },
+ { "XRAPI", "XRApi" },
+});
+
+String _get_pascal_case_part_override(String p_part, bool p_input_is_upper = true) {
+ if (!p_input_is_upper) {
+ for (int i = 0; i < p_part.length(); i++) {
+ p_part[i] = _find_upper(p_part[i]);
+ }
+ }
+
+ if (pascal_case_part_overrides.has(p_part)) {
+ return pascal_case_part_overrides.get(p_part);
+ }
+
+ return String();
+}
+
+Vector<String> _split_pascal_case(const String &p_identifier) {
+ Vector<String> parts;
+ int current_part_start = 0;
+ bool prev_was_upper = is_ascii_upper_case(p_identifier[0]);
+ for (int i = 1; i < p_identifier.length(); i++) {
+ if (prev_was_upper) {
+ if (is_digit(p_identifier[i]) || is_ascii_lower_case(p_identifier[i])) {
+ if (!is_digit(p_identifier[i])) {
+ // These conditions only apply when the separator is not a digit.
+ if (i - current_part_start == 1) {
+ // Upper character was only the beginning of a word.
+ prev_was_upper = false;
+ continue;
+ }
+ if (i != p_identifier.length()) {
+ // If this is not the last character, the last uppercase
+ // character is the start of the next word.
+ i--;
+ }
+ }
+ if (i - current_part_start > 0) {
+ parts.append(p_identifier.substr(current_part_start, i - current_part_start));
+ current_part_start = i;
+ prev_was_upper = false;
+ }
+ }
+ } else {
+ if (is_digit(p_identifier[i]) || is_ascii_upper_case(p_identifier[i])) {
+ parts.append(p_identifier.substr(current_part_start, i - current_part_start));
+ current_part_start = i;
+ prev_was_upper = true;
+ }
+ }
+ }
+
+ // Add the rest of the identifier as the last part.
+ if (current_part_start != p_identifier.length()) {
+ parts.append(p_identifier.substr(current_part_start));
+ }
+
+ return parts;
+}
+
+String pascal_to_pascal_case(const String &p_identifier) {
+ if (p_identifier.length() == 0) {
+ return p_identifier;
+ }
+
+ if (p_identifier.length() <= 2) {
+ return p_identifier.to_upper();
+ }
+
+ if (pascal_case_name_overrides.has(p_identifier)) {
+ // Use hardcoded value for the identifier.
+ return pascal_case_name_overrides.get(p_identifier);
+ }
+
+ Vector<String> parts = _split_pascal_case(p_identifier);
+
+ String ret;
+
+ for (String &part : parts) {
+ String part_override = _get_pascal_case_part_override(part);
+ if (!part_override.is_empty()) {
+ // Use hardcoded value for part.
+ ret += part_override;
+ continue;
+ }
+
+ if (part.length() <= 2 && part.to_upper() == part) {
+ // Acronym of length 1 or 2.
+ for (int j = 0; j < part.length(); j++) {
+ part[j] = _find_upper(part[j]);
+ }
+ ret += part;
+ continue;
+ }
+
+ part[0] = _find_upper(part[0]);
+ for (int i = 1; i < part.length(); i++) {
+ if (is_digit(part[i - 1])) {
+ // Use uppercase after digits.
+ part[i] = _find_upper(part[i]);
+ continue;
+ }
+
+ part[i] = _find_lower(part[i]);
+ }
+ ret += part;
+ }
+
+ return ret;
+}
+
+String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper) {
+ String ret;
+ Vector<String> parts = p_identifier.split("_", true);
+
+ for (int i = 0; i < parts.size(); i++) {
+ String part = parts[i];
+
+ String part_override = _get_pascal_case_part_override(part, p_input_is_upper);
+ if (!part_override.is_empty()) {
+ // Use hardcoded value for part.
+ ret += part_override;
+ continue;
+ }
+
+ if (!part.is_empty()) {
+ part[0] = _find_upper(part[0]);
+ for (int j = 1; j < part.length(); j++) {
+ if (is_digit(part[j - 1])) {
+ // Use uppercase after digits.
+ part[j] = _find_upper(part[j]);
+ continue;
+ }
+
+ if (p_input_is_upper) {
+ part[j] = _find_lower(part[j]);
+ }
+ }
+ ret += part;
+ } else {
+ if (i == 0 || i == (parts.size() - 1)) {
+ // Preserve underscores at the beginning and end
+ ret += "_";
+ } else {
+ // Preserve contiguous underscores
+ if (parts[i - 1].length()) {
+ ret += "__";
+ } else {
+ ret += "_";
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+String snake_to_camel_case(const String &p_identifier, bool p_input_is_upper) {
+ String ret;
+ Vector<String> parts = p_identifier.split("_", true);
+
+ for (int i = 0; i < parts.size(); i++) {
+ String part = parts[i];
+
+ String part_override = _get_pascal_case_part_override(part, p_input_is_upper);
+ if (!part_override.is_empty()) {
+ // Use hardcoded value for part.
+ if (i == 0) {
+ part_override[0] = _find_lower(part_override[0]);
+ }
+ ret += part_override;
+ continue;
+ }
+
+ if (!part.is_empty()) {
+ if (i == 0) {
+ part[0] = _find_lower(part[0]);
+ } else {
+ part[0] = _find_upper(part[0]);
+ }
+ for (int j = 1; j < part.length(); j++) {
+ if (is_digit(part[j - 1])) {
+ // Use uppercase after digits.
+ part[j] = _find_upper(part[j]);
+ continue;
+ }
+
+ if (p_input_is_upper) {
+ part[j] = _find_lower(part[j]);
+ }
+ }
+ ret += part;
+ } else {
+ if (i == 0 || i == (parts.size() - 1)) {
+ // Preserve underscores at the beginning and end
+ ret += "_";
+ } else {
+ // Preserve contiguous underscores
+ if (parts[i - 1].length()) {
+ ret += "__";
+ } else {
+ ret += "_";
+ }
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/modules/mono/utils/naming_utils.h b/modules/mono/utils/naming_utils.h
new file mode 100644
index 0000000000..ac64a5c114
--- /dev/null
+++ b/modules/mono/utils/naming_utils.h
@@ -0,0 +1,42 @@
+/**************************************************************************/
+/* naming_utils.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef MONO_NAMING_UTILS_H
+#define MONO_NAMING_UTILS_H
+
+#include "core/string/ustring.h"
+
+String pascal_to_pascal_case(const String &p_identifier);
+
+String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper = false);
+
+String snake_to_camel_case(const String &p_identifier, bool p_input_is_upper = false);
+
+#endif // MONO_NAMING_UTILS_H
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
index 269e41e2f4..b5a3816ed7 100644
--- a/modules/mono/utils/path_utils.cpp
+++ b/modules/mono/utils/path_utils.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* path_utils.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* path_utils.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "path_utils.h"
diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h
index d1c3d3ccfd..25d130fc58 100644
--- a/modules/mono/utils/path_utils.h
+++ b/modules/mono/utils/path_utils.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* path_utils.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* path_utils.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef MONO_PATH_UTILS_H
#define MONO_PATH_UTILS_H
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index b0f94310b8..c732d066d9 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* string_utils.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* string_utils.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "string_utils.h"
diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h
index b00dd9dde8..c261aaa7f7 100644
--- a/modules/mono/utils/string_utils.h
+++ b/modules/mono/utils/string_utils.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* string_utils.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* string_utils.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef MONO_STRING_UTILS_H
#define MONO_STRING_UTILS_H