summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/.editorconfig14
-rw-r--r--modules/mono/Directory.Build.props3
-rw-r--r--modules/mono/SdkPackageVersions.props6
-rw-r--r--modules/mono/build_scripts/godot_net_sdk_build.py24
-rw-r--r--modules/mono/build_scripts/mono_configure.py6
-rw-r--r--modules/mono/class_db_api_json.cpp43
-rw-r--r--modules/mono/csharp_script.cpp810
-rw-r--r--modules/mono/csharp_script.h98
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln18
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj43
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec22
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt1
-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.NET.Sdk/Sdk/Sdk.targets5
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs15
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs11
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj31
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs33
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs89
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj41
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props7
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs9
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs182
-rw-r--r--modules/mono/editor/GodotTools/.gitignore1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs32
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs82
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/IdentifierUtils.cs10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs47
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs17
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs33
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs126
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs56
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs86
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs41
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs39
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs162
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs14
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs36
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs85
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs26
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs31
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs13
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs12
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs8
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs61
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs48
-rw-r--r--modules/mono/editor/bindings_generator.cpp326
-rw-r--r--modules/mono/editor/bindings_generator.h44
-rw-r--r--modules/mono/editor/code_completion.cpp34
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp56
-rw-r--r--modules/mono/editor/godotsharp_export.cpp2
-rw-r--r--modules/mono/editor/script_class_parser.cpp753
-rw-r--r--modules/mono/editor/script_class_parser.h108
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs313
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs340
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs22
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs15
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ToolAttribute.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs205
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs44
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs176
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs587
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs374
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs41
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs148
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs27
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs435
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs127
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs243
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs36
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs162
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs126
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs)280
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs39
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs160
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs156
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs15
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs744
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs33
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs130
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs)175
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs254
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs136
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs248
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs139
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj9
-rw-r--r--modules/mono/glue/base_object_glue.cpp44
-rw-r--r--modules/mono/glue/collections_glue.cpp15
-rw-r--r--modules/mono/glue/glue_header.h2
-rw-r--r--modules/mono/glue/string_glue.cpp6
-rw-r--r--modules/mono/godotsharp_dirs.cpp16
-rw-r--r--modules/mono/mono_gc_handle.h6
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp71
-rw-r--r--modules/mono/mono_gd/gd_mono.h16
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp109
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h13
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp26
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h13
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp8
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp16
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp37
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.h3
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono_log.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp52
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h42
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp32
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_wasm_m2n.h2
-rw-r--r--modules/mono/mono_gd/support/android_support.cpp4
-rw-r--r--modules/mono/mono_gd/support/ios_support.mm8
-rw-r--r--modules/mono/register_types.cpp14
-rw-r--r--modules/mono/signal_awaiter_utils.h2
-rw-r--r--modules/mono/utils/mono_reg_utils.cpp2
-rw-r--r--modules/mono/utils/path_utils.cpp6
-rw-r--r--modules/mono/utils/string_utils.cpp8
138 files changed, 6085 insertions, 4597 deletions
diff --git a/modules/mono/.editorconfig b/modules/mono/.editorconfig
new file mode 100644
index 0000000000..c9dcd7724e
--- /dev/null
+++ b/modules/mono/.editorconfig
@@ -0,0 +1,14 @@
+[*.sln]
+indent_style = tab
+
+[*.{csproj,props,targets,nuspec,resx}]
+indent_style = space
+indent_size = 2
+
+[*.cs]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+max_line_length = 120
+csharp_indent_case_contents_when_block = false
diff --git a/modules/mono/Directory.Build.props b/modules/mono/Directory.Build.props
new file mode 100644
index 0000000000..fbf864b11b
--- /dev/null
+++ b/modules/mono/Directory.Build.props
@@ -0,0 +1,3 @@
+<Project>
+ <Import Project="$(MSBuildThisFileDirectory)\SdkPackageVersions.props" />
+</Project>
diff --git a/modules/mono/SdkPackageVersions.props b/modules/mono/SdkPackageVersions.props
new file mode 100644
index 0000000000..df3ebe581c
--- /dev/null
+++ b/modules/mono/SdkPackageVersions.props
@@ -0,0 +1,6 @@
+<Project>
+ <PropertyGroup>
+ <PackageVersion_Godot_NET_Sdk>4.0.0-dev5</PackageVersion_Godot_NET_Sdk>
+ <PackageVersion_Godot_SourceGenerators>4.0.0-dev2</PackageVersion_Godot_SourceGenerators>
+ </PropertyGroup>
+</Project>
diff --git a/modules/mono/build_scripts/godot_net_sdk_build.py b/modules/mono/build_scripts/godot_net_sdk_build.py
index 3bfba0f0f6..8c5a60d2db 100644
--- a/modules/mono/build_scripts/godot_net_sdk_build.py
+++ b/modules/mono/build_scripts/godot_net_sdk_build.py
@@ -21,6 +21,18 @@ def build_godot_net_sdk(source, target, env):
# No need to copy targets. The Godot.NET.Sdk csproj takes care of copying them.
+def get_nupkgs_versions(props_file):
+ import xml.etree.ElementTree as ET
+
+ tree = ET.parse(props_file)
+ root = tree.getroot()
+
+ return {
+ "Godot.NET.Sdk": root.find("./PropertyGroup/PackageVersion_Godot_NET_Sdk").text.strip(),
+ "Godot.SourceGenerators": root.find("./PropertyGroup/PackageVersion_Godot_SourceGenerators").text.strip(),
+ }
+
+
def build(env_mono):
assert env_mono["tools"]
@@ -30,14 +42,12 @@ def build(env_mono):
module_dir = os.getcwd()
- package_version_file = os.path.join(
- module_dir, "editor", "Godot.NET.Sdk", "Godot.NET.Sdk", "Godot.NET.Sdk_PackageVersion.txt"
- )
-
- with open(package_version_file, mode="r") as f:
- version = f.read().strip()
+ nupkgs_versions = get_nupkgs_versions(os.path.join(module_dir, "SdkPackageVersions.props"))
- target_filenames = ["Godot.NET.Sdk.%s.nupkg" % version]
+ target_filenames = [
+ "Godot.NET.Sdk.%s.nupkg" % nupkgs_versions["Godot.NET.Sdk"],
+ "Godot.SourceGenerators.%s.nupkg" % nupkgs_versions["Godot.SourceGenerators"],
+ ]
targets = [os.path.join(nupkgs_dir, filename) for filename in target_filenames]
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index 309abfbff7..8e441e7e07 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -101,12 +101,6 @@ def configure(env, env_mono):
mono_lib_names = ["mono-2.0-sgen", "monosgen-2.0"]
- is_travis = os.environ.get("TRAVIS") == "true"
-
- if is_travis:
- # Travis CI may have a Mono version lower than 5.12
- env_mono.Append(CPPDEFINES=["NO_PENDING_EXCEPTIONS"])
-
if is_android and not env["android_arch"] in android_arch_dirs:
raise RuntimeError("This module does not support the specified 'android_arch': " + env["android_arch"])
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
index 553c6eca53..0da06131af 100644
--- a/modules/mono/class_db_api_json.cpp
+++ b/modules/mono/class_db_api_json.cpp
@@ -33,8 +33,8 @@
#ifdef DEBUG_METHODS_ENABLED
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/json.h"
-#include "core/os/file_access.h"
#include "core/version.h"
void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
@@ -50,8 +50,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
//must be alphabetically sorted for hash to compute
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- ClassDB::ClassInfo *t = ClassDB::classes.getptr(E->get());
+ for (const StringName &E : names) {
+ ClassDB::ClassInfo *t = ClassDB::classes.getptr(E);
ERR_FAIL_COND(!t);
if (t->api != p_api || !t->exposed) {
continue;
@@ -84,11 +84,11 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array methods;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary method_dict;
methods.push_back(method_dict);
- MethodBind *mb = t->method_map[F->get()];
+ MethodBind *mb = t->method_map[F];
method_dict["name"] = mb->get_name();
method_dict["argument_count"] = mb->get_argument_count();
method_dict["return_type"] = mb->get_argument_type(-1);
@@ -141,12 +141,12 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array constants;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary constant_dict;
constants.push_back(constant_dict);
- constant_dict["name"] = F->get();
- constant_dict["value"] = t->constant_map[F->get()];
+ constant_dict["name"] = F;
+ constant_dict["value"] = t->constant_map[F];
}
if (!constants.is_empty()) {
@@ -168,12 +168,12 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array signals;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary signal_dict;
signals.push_back(signal_dict);
- MethodInfo &mi = t->signal_map[F->get()];
- signal_dict["name"] = F->get();
+ MethodInfo &mi = t->signal_map[F];
+ signal_dict["name"] = F;
Array arguments;
signal_dict["arguments"] = arguments;
@@ -203,13 +203,13 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array properties;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary property_dict;
properties.push_back(property_dict);
- ClassDB::PropertySetGet *psg = t->property_setget.getptr(F->get());
+ ClassDB::PropertySetGet *psg = t->property_setget.getptr(F);
- property_dict["name"] = F->get();
+ property_dict["name"] = F;
property_dict["setter"] = psg->setter;
property_dict["getter"] = psg->getter;
}
@@ -222,15 +222,15 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array property_list;
//property list
- for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) {
+ for (const PropertyInfo &F : t->property_list) {
Dictionary property_dict;
property_list.push_back(property_dict);
- property_dict["name"] = F->get().name;
- property_dict["type"] = F->get().type;
- property_dict["hint"] = F->get().hint;
- property_dict["hint_string"] = F->get().hint_string;
- property_dict["usage"] = F->get().usage;
+ property_dict["name"] = F.name;
+ property_dict["type"] = F.type;
+ property_dict["hint"] = F.hint;
+ property_dict["hint_string"] = F.hint_string;
+ property_dict["usage"] = F.usage;
}
if (!property_list.is_empty()) {
@@ -240,7 +240,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
FileAccessRef f = FileAccess::open(p_output_file, FileAccess::WRITE);
ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_output_file + "'.");
- f->store_string(JSON::print(classes_dict, /*indent: */ "\t"));
+ JSON json;
+ f->store_string(json.stringify(classes_dict, "\t"));
f->close();
print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file));
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 25cc64393a..17846eb281 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -31,20 +31,22 @@
#include "csharp_script.h"
#include <mono/metadata/threads.h>
+#include <mono/metadata/tokentype.h>
#include <stdint.h>
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
-#include "core/io/json.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/mutex.h"
#include "core/os/os.h"
#include "core/os/thread.h"
#ifdef TOOLS_ENABLED
+#include "core/os/keyboard.h"
#include "editor/bindings_generator.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
#include "editor/node_dock.h"
#endif
@@ -82,6 +84,12 @@ static bool _create_project_solution_if_needed() {
CSharpLanguage *CSharpLanguage::singleton = nullptr;
+GDNativeInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = {
+ &_instance_binding_create_callback,
+ &_instance_binding_free_callback,
+ &_instance_binding_reference_callback
+};
+
String CSharpLanguage::get_name() const {
return "C#";
}
@@ -145,8 +153,8 @@ void CSharpLanguage::finalize() {
finalizing = true;
// Make sure all script binding gchandles are released before finalizing GDMono
- for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
- CSharpScriptBinding &script_binding = E->value();
+ for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
+ CSharpScriptBinding &script_binding = E.value;
if (!script_binding.gchandle.is_released()) {
script_binding.gchandle.release();
@@ -163,8 +171,8 @@ void CSharpLanguage::finalize() {
script_bindings.clear();
#ifdef DEBUG_ENABLED
- for (Map<ObjectID, int>::Element *E = unsafe_object_references.front(); E; E = E->next()) {
- const ObjectID &id = E->key();
+ for (const KeyValue<ObjectID, int> &E : unsafe_object_references) {
+ const ObjectID &id = E.key;
Object *obj = ObjectDB::get_instance(id);
if (obj) {
@@ -303,6 +311,26 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const {
}
}
+bool CSharpLanguage::is_control_flow_keyword(String p_keyword) const {
+ return p_keyword == "break" ||
+ p_keyword == "case" ||
+ p_keyword == "catch" ||
+ p_keyword == "continue" ||
+ p_keyword == "default" ||
+ p_keyword == "do" ||
+ p_keyword == "else" ||
+ p_keyword == "finally" ||
+ p_keyword == "for" ||
+ p_keyword == "foreach" ||
+ p_keyword == "goto" ||
+ p_keyword == "if" ||
+ p_keyword == "return" ||
+ p_keyword == "switch" ||
+ p_keyword == "throw" ||
+ p_keyword == "try" ||
+ p_keyword == "while";
+}
+
void CSharpLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("//"); // single-line comment
p_delimiters->push_back("/* */"); // delimited comment
@@ -311,7 +339,7 @@ void CSharpLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("' '"); // character literal
p_delimiters->push_back("\" \""); // regular string literal
- // Verbatim string literals (`@" "`) don't render correctly, so don't highlight them.
+ p_delimiters->push_back("@\" \""); // verbatim string literal
// Generic string highlighting suffices as a workaround for now.
}
@@ -327,7 +355,7 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin
String script_template = "using " BINDINGS_NAMESPACE ";\n"
"using System;\n"
"\n"
- "public class %CLASS% : %BASE%\n"
+ "public partial class %CLASS% : %BASE%\n"
"{\n"
" // Declare member variables here. Examples:\n"
" // private int a = 2;\n"
@@ -347,7 +375,7 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin
"}\n";
// Replaces all spaces in p_class_name with underscores to prevent
- // erronous C# Script templates from being generated when the object name
+ // invalid C# Script templates from being generated when the object name
// has spaces in it.
String class_name_no_spaces = p_class_name.replace(" ", "_");
String base_class_name = get_base_class_name(p_base_class_name, class_name_no_spaces);
@@ -355,7 +383,7 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin
.replace("%CLASS%", class_name_no_spaces);
Ref<CSharpScript> script;
- script.instance();
+ script.instantiate();
script->set_source_code(script_template);
script->set_name(class_name_no_spaces);
@@ -475,10 +503,10 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
Variant::VECTOR3I,
Variant::TRANSFORM2D,
Variant::PLANE,
- Variant::QUAT,
+ Variant::QUATERNION,
Variant::AABB,
Variant::BASIS,
- Variant::TRANSFORM,
+ Variant::TRANSFORM3D,
Variant::COLOR,
Variant::STRING_NAME,
Variant::NODE_PATH,
@@ -522,10 +550,10 @@ String CSharpLanguage::make_function(const String &, const String &, const Packe
String CSharpLanguage::_get_indentation() const {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- bool use_space_indentation = EDITOR_DEF("text_editor/indent/type", 0);
+ bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", 0);
if (use_space_indentation) {
- int indent_size = EDITOR_DEF("text_editor/indent/size", 4);
+ int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4);
String space_indent = "";
for (int i = 0; i < indent_size; i++) {
@@ -842,20 +870,25 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
List<Ref<CSharpScript>> to_reload;
// We need to keep reference instances alive during reloading
- List<Ref<Reference>> ref_instances;
+ List<Ref<RefCounted>> rc_instances;
- for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
- CSharpScriptBinding &script_binding = E->value();
- Reference *ref = Object::cast_to<Reference>(script_binding.owner);
- if (ref) {
- ref_instances.push_back(Ref<Reference>(ref));
+ for (const KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
+ const CSharpScriptBinding &script_binding = E.value;
+ RefCounted *rc = Object::cast_to<RefCounted>(script_binding.owner);
+ if (rc) {
+ rc_instances.push_back(Ref<RefCounted>(rc));
}
}
// As scripts are going to be reloaded, must proceed without locking here
- for (List<Ref<CSharpScript>>::Element *E = scripts.front(); E; E = E->next()) {
- Ref<CSharpScript> &script = E->get();
+ for (Ref<CSharpScript> &script : scripts) {
+ // If someone removes a script from a node, deletes the script, builds, adds a script to the
+ // same node, then builds again, the script might have no path and also no script_class. In
+ // that case, we can't (and don't need to) reload it.
+ if (script->get_path().is_empty() && !script->script_class) {
+ continue;
+ }
to_reload.push_back(script);
@@ -867,24 +900,23 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Script::instances are deleted during managed object disposal, which happens on domain finalize.
// Only placeholders are kept. Therefore we need to keep a copy before that happens.
- for (Set<Object *>::Element *F = script->instances.front(); F; F = F->next()) {
- Object *obj = F->get();
+ for (Object *&obj : script->instances) {
script->pending_reload_instances.insert(obj->get_instance_id());
- Reference *ref = Object::cast_to<Reference>(obj);
- if (ref) {
- ref_instances.push_back(Ref<Reference>(ref));
+ RefCounted *rc = Object::cast_to<RefCounted>(obj);
+ if (rc) {
+ rc_instances.push_back(Ref<RefCounted>(rc));
}
}
#ifdef TOOLS_ENABLED
- for (Set<PlaceHolderScriptInstance *>::Element *F = script->placeholders.front(); F; F = F->next()) {
- Object *obj = F->get()->get_owner();
+ for (PlaceHolderScriptInstance *&script_instance : script->placeholders) {
+ Object *obj = script_instance->get_owner();
script->pending_reload_instances.insert(obj->get_instance_id());
- Reference *ref = Object::cast_to<Reference>(obj);
- if (ref) {
- ref_instances.push_back(Ref<Reference>(ref));
+ RefCounted *rc = Object::cast_to<RefCounted>(obj);
+ if (rc) {
+ rc_instances.push_back(Ref<RefCounted>(rc));
}
}
#endif
@@ -892,9 +924,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Save state and remove script from instances
Map<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state;
- for (Set<Object *>::Element *F = script->instances.front(); F; F = F->next()) {
- Object *obj = F->get();
-
+ for (Object *&obj : script->instances) {
ERR_CONTINUE(!obj->get_script_instance());
CSharpInstance *csi = static_cast<CSharpInstance *>(obj->get_script_instance());
@@ -916,9 +946,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
// After the state of all instances is saved, clear scripts and script instances
- for (List<Ref<CSharpScript>>::Element *E = scripts.front(); E; E = E->next()) {
- Ref<CSharpScript> &script = E->get();
-
+ for (Ref<CSharpScript> &script : scripts) {
while (script->instances.front()) {
Object *obj = script->instances.front()->get();
obj->set_script(REF()); // Remove script and existing script instances (placeholder are not removed before domain reload)
@@ -931,11 +959,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
if (gdmono->reload_scripts_domain() != OK) {
// Failed to reload the scripts domain
// Make sure to add the scripts back to their owners before returning
- for (List<Ref<CSharpScript>>::Element *E = to_reload.front(); E; E = E->next()) {
- Ref<CSharpScript> scr = E->get();
-
- for (const Map<ObjectID, CSharpScript::StateBackup>::Element *F = scr->pending_reload_state.front(); F; F = F->next()) {
- Object *obj = ObjectDB::get_instance(F->key());
+ for (Ref<CSharpScript> &scr : to_reload) {
+ for (const KeyValue<ObjectID, CSharpScript::StateBackup> &F : scr->pending_reload_state) {
+ Object *obj = ObjectDB::get_instance(F.key);
if (!obj) {
continue;
@@ -955,8 +981,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
#endif
// Restore Variant properties state, it will be kept by the placeholder until the next script reloading
- for (List<Pair<StringName, Variant>>::Element *G = scr->pending_reload_state[obj_id].properties.front(); G; G = G->next()) {
- placeholder->property_set_fallback(G->get().first, G->get().second, nullptr);
+ for (const Pair<StringName, Variant> &G : scr->pending_reload_state[obj_id].properties) {
+ placeholder->property_set_fallback(G.first, G.second, nullptr);
}
scr->pending_reload_state.erase(obj_id);
@@ -968,9 +994,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
List<Ref<CSharpScript>> to_reload_state;
- for (List<Ref<CSharpScript>>::Element *E = to_reload.front(); E; E = E->next()) {
- Ref<CSharpScript> script = E->get();
-
+ for (Ref<CSharpScript> &script : to_reload) {
#ifdef TOOLS_ENABLED
script->exports_invalidated = true;
#endif
@@ -1023,8 +1047,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
StringName native_name = NATIVE_GDMONOCLASS_NAME(script->native);
{
- for (Set<ObjectID>::Element *F = script->pending_reload_instances.front(); F; F = F->next()) {
- ObjectID obj_id = F->get();
+ for (const ObjectID &obj_id : script->pending_reload_instances) {
Object *obj = ObjectDB::get_instance(obj_id);
if (!obj) {
@@ -1075,11 +1098,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
to_reload_state.push_back(script);
}
- for (List<Ref<CSharpScript>>::Element *E = to_reload_state.front(); E; E = E->next()) {
- Ref<CSharpScript> script = E->get();
-
- for (Set<ObjectID>::Element *F = script->pending_reload_instances.front(); F; F = F->next()) {
- ObjectID obj_id = F->get();
+ for (Ref<CSharpScript> &script : to_reload_state) {
+ for (const ObjectID &obj_id : script->pending_reload_instances) {
Object *obj = ObjectDB::get_instance(obj_id);
if (!obj) {
@@ -1093,16 +1113,16 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
CSharpScript::StateBackup &state_backup = script->pending_reload_state[obj_id];
- for (List<Pair<StringName, Variant>>::Element *G = state_backup.properties.front(); G; G = G->next()) {
- obj->get_script_instance()->set(G->get().first, G->get().second);
+ for (const Pair<StringName, Variant> &G : state_backup.properties) {
+ obj->get_script_instance()->set(G.first, G.second);
}
CSharpInstance *csi = CAST_CSHARP_INSTANCE(obj->get_script_instance());
if (csi) {
- for (List<Pair<StringName, Array>>::Element *G = state_backup.event_signals.front(); G; G = G->next()) {
- const StringName &name = G->get().first;
- const Array &serialized_data = G->get().second;
+ for (const Pair<StringName, Array> &G : state_backup.event_signals) {
+ const StringName &name = G.first;
+ const Array &serialized_data = G.second;
Map<StringName, CSharpScript::EventSignal>::Element *match = script->event_signals.find(name);
@@ -1146,9 +1166,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
{
MutexLock lock(ManagedCallable::instances_mutex);
- for (Map<ManagedCallable *, Array>::Element *elem = ManagedCallable::instances_pending_reload.front(); elem; elem = elem->next()) {
- ManagedCallable *managed_callable = elem->key();
- const Array &serialized_data = elem->value();
+ for (const KeyValue<ManagedCallable *, Array> &elem : ManagedCallable::instances_pending_reload) {
+ ManagedCallable *managed_callable = elem.key;
+ const Array &serialized_data = elem.value;
MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data);
MonoDelegate *delegate = nullptr;
@@ -1182,46 +1202,56 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
#endif
-void CSharpLanguage::_load_scripts_metadata() {
- scripts_metadata.clear();
+void CSharpLanguage::lookup_script_for_class(GDMonoClass *p_class) {
+ if (!p_class->has_attribute(CACHED_CLASS(ScriptPathAttribute))) {
+ return;
+ }
- String scripts_metadata_filename = "scripts_metadata.";
+ MonoObject *attr = p_class->get_attribute(CACHED_CLASS(ScriptPathAttribute));
+ String path = CACHED_FIELD(ScriptPathAttribute, path)->get_string_value(attr);
-#ifdef TOOLS_ENABLED
- scripts_metadata_filename += Engine::get_singleton()->is_editor_hint() ? "editor" : "editor_player";
-#else
-#ifdef DEBUG_ENABLED
- scripts_metadata_filename += "debug";
-#else
- scripts_metadata_filename += "release";
-#endif
-#endif
+ dotnet_script_lookup_map[path] = DotNetScriptLookupInfo(
+ p_class->get_namespace(), p_class->get_name(), p_class);
+}
- String scripts_metadata_path = GodotSharpDirs::get_res_metadata_dir().plus_file(scripts_metadata_filename);
+void CSharpLanguage::lookup_scripts_in_assembly(GDMonoAssembly *p_assembly) {
+ if (p_assembly->has_attribute(CACHED_CLASS(AssemblyHasScriptsAttribute))) {
+ MonoObject *attr = p_assembly->get_attribute(CACHED_CLASS(AssemblyHasScriptsAttribute));
+ bool requires_lookup = CACHED_FIELD(AssemblyHasScriptsAttribute, requiresLookup)->get_bool_value(attr);
- if (FileAccess::exists(scripts_metadata_path)) {
- String old_json;
+ if (requires_lookup) {
+ // This is supported for scenarios where specifying all types would be cumbersome,
+ // 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.
+ MonoImage *image = p_assembly->get_image();
- Error ferr = read_all_file_utf8(scripts_metadata_path, old_json);
+ int rows = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
- ERR_FAIL_COND(ferr != OK);
+ for (int i = 1; i < rows; i++) {
+ // We don't search inner classes, only top-level.
+ MonoClass *mono_class = mono_class_get(image, (i + 1) | MONO_TOKEN_TYPE_DEF);
- Variant old_dict_var;
- String err_str;
- int err_line;
- Error json_err = JSON::parse(old_json, old_dict_var, err_str, err_line);
- if (json_err != OK) {
- ERR_PRINT("Failed to parse metadata file: '" + err_str + "' (" + String::num_int64(err_line) + ").");
- return;
- }
+ if (!mono_class_is_assignable_from(CACHED_CLASS_RAW(GodotObject), mono_class)) {
+ continue;
+ }
- scripts_metadata = old_dict_var.operator Dictionary();
- scripts_metadata_invalidated = false;
+ GDMonoClass *current = p_assembly->get_class(mono_class);
+ if (current) {
+ lookup_script_for_class(current);
+ }
+ }
+ } else {
+ // This is the most likely scenario as we use C# source generators
+ MonoArray *script_types = (MonoArray *)CACHED_FIELD(AssemblyHasScriptsAttribute, scriptTypes)->get_value(attr);
- print_verbose("Successfully loaded scripts metadata");
- } else {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_PRINT("Missing scripts metadata file.");
+ int length = mono_array_length(script_types);
+
+ for (int i = 0; i < length; i++) {
+ MonoReflectionType *reftype = mono_array_get(script_types, MonoReflectionType *, i);
+ ManagedType type = ManagedType::from_reftype(reftype);
+ ERR_CONTINUE(!type.type_class);
+ lookup_script_for_class(type.type_class);
+ }
}
}
}
@@ -1282,8 +1312,8 @@ bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
}
void CSharpLanguage::_on_scripts_domain_unloaded() {
- for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
- CSharpScriptBinding &script_binding = E->value();
+ for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
+ CSharpScriptBinding &script_binding = E.value;
script_binding.gchandle.release();
script_binding.inited = false;
}
@@ -1300,7 +1330,7 @@ void CSharpLanguage::_on_scripts_domain_unloaded() {
}
#endif
- scripts_metadata_invalidated = true;
+ dotnet_script_lookup_map.clear();
}
#ifdef TOOLS_ENABLED
@@ -1325,6 +1355,7 @@ void CSharpLanguage::_editor_init_callback() {
// Enable it as a plugin
EditorNode::add_editor_plugin(godotsharp_editor);
+ ED_SHORTCUT("mono/build_solution", TTR("Build Solution"), KEY_MASK_ALT | KEY_B);
godotsharp_editor->enable_plugin();
get_singleton()->godotsharp_editor = godotsharp_editor;
@@ -1407,61 +1438,61 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
r_script_binding.owner = p_object;
// Tie managed to unmanaged
- Reference *ref = Object::cast_to<Reference>(p_object);
+ RefCounted *rc = Object::cast_to<RefCounted>(p_object);
- if (ref) {
+ if (rc) {
// Unsafe refcount increment. The managed instance also counts as a reference.
// This way if the unmanaged world has no references to our owner
// but the managed instance is alive, the refcount will be 1 instead of 0.
- // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
+ // See: godot_icall_RefCounted_Dtor(MonoObject *p_obj, Object *p_ptr)
- ref->reference();
- CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ rc->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(rc);
}
return true;
}
-void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) {
- MutexLock lock(language_bind_mutex);
+Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
+ return script_bindings.insert(p_object, p_script_binding);
+}
- Map<Object *, CSharpScriptBinding>::Element *match = script_bindings.find(p_object);
+void *CSharpLanguage::_instance_binding_create_callback(void *, void *p_instance) {
+ CSharpLanguage *csharp_lang = CSharpLanguage::get_singleton();
+
+ MutexLock lock(csharp_lang->language_bind_mutex);
+
+ Map<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance);
if (match) {
return (void *)match;
}
CSharpScriptBinding script_binding;
- if (!setup_csharp_script_binding(script_binding, p_object)) {
- return nullptr;
- }
-
- return (void *)insert_script_binding(p_object, script_binding);
+ return (void *)csharp_lang->insert_script_binding((Object *)p_instance, script_binding);
}
-Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
- return script_bindings.insert(p_object, p_script_binding);
-}
+void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_binding) {
+ CSharpLanguage *csharp_lang = CSharpLanguage::get_singleton();
-void CSharpLanguage::free_instance_binding_data(void *p_data) {
if (GDMono::get_singleton() == nullptr) {
#ifdef DEBUG_ENABLED
- CRASH_COND(!script_bindings.is_empty());
+ CRASH_COND(!csharp_lang->script_bindings.is_empty());
#endif
// Mono runtime finalized, all the gchandle bindings were already released
return;
}
- if (finalizing) {
+ if (csharp_lang->finalizing) {
return; // inside CSharpLanguage::finish(), all the gchandle bindings are released there
}
GD_MONO_ASSERT_THREAD_ATTACHED;
{
- MutexLock lock(language_bind_mutex);
+ MutexLock lock(csharp_lang->language_bind_mutex);
- Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_data;
+ Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_binding;
CSharpScriptBinding &script_binding = data->value();
@@ -1475,99 +1506,122 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
script_binding.gchandle.release();
}
- script_bindings.erase(data);
+ csharp_lang->script_bindings.erase(data);
}
}
-void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
- Reference *ref_owner = Object::cast_to<Reference>(p_object);
+GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) {
+ CRASH_COND(!p_binding);
+
+ CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
+
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(script_binding.owner);
#ifdef DEBUG_ENABLED
- CRASH_COND(!ref_owner);
- CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
+ CRASH_COND(!rc_owner);
#endif
- void *data = p_object->get_script_instance_binding(get_language_index());
- CRASH_COND(!data);
-
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
MonoGCHandleData &gchandle = script_binding.gchandle;
+ int refcount = rc_owner->reference_get_count();
+
if (!script_binding.inited) {
- return;
+ return refcount == 0;
}
- if (ref_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
- GD_MONO_SCOPE_THREAD_ATTACH;
+ if (p_reference) {
+ // Refcount incremented
+ if (refcount > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
- // The reference count was increased after the managed side was the only one referencing our owner.
- // This means the owner is being referenced again by the unmanaged side,
- // so the owner must hold the managed side alive again to avoid it from being GCed.
+ // The reference count was increased after the managed side was the only one referencing our owner.
+ // This means the owner is being referenced again by the unmanaged side,
+ // so the owner must hold the managed side alive again to avoid it from being GCed.
- MonoObject *target = gchandle.get_target();
- if (!target) {
- return; // Called after the managed side was collected, so nothing to do here
- }
+ MonoObject *target = gchandle.get_target();
+ if (!target) {
+ return false; // Called after the managed side was collected, so nothing to do here
+ }
- // Release the current weak handle and replace it with a strong handle.
- MonoGCHandleData strong_gchandle = MonoGCHandleData::new_strong_handle(target);
- gchandle.release();
- gchandle = strong_gchandle;
- }
-}
+ // Release the current weak handle and replace it with a strong handle.
+ MonoGCHandleData strong_gchandle = MonoGCHandleData::new_strong_handle(target);
+ gchandle.release();
+ gchandle = strong_gchandle;
+ }
-bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
- Reference *ref_owner = Object::cast_to<Reference>(p_object);
+ return false;
+ } else {
+ // Refcount decremented
+ if (refcount == 1 && !gchandle.is_released() && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
-#ifdef DEBUG_ENABLED
- CRASH_COND(!ref_owner);
- CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
-#endif
+ // If owner owner is no longer referenced by the unmanaged side,
+ // the managed instance takes responsibility of deleting the owner when GCed.
- void *data = p_object->get_script_instance_binding(get_language_index());
- CRASH_COND(!data);
+ MonoObject *target = gchandle.get_target();
+ if (!target) {
+ return refcount == 0; // Called after the managed side was collected, so nothing to do here
+ }
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
- MonoGCHandleData &gchandle = script_binding.gchandle;
+ // Release the current strong handle and replace it with a weak handle.
+ MonoGCHandleData weak_gchandle = MonoGCHandleData::new_weak_handle(target);
+ gchandle.release();
+ gchandle = weak_gchandle;
- int refcount = ref_owner->reference_get_count();
+ return false;
+ }
- if (!script_binding.inited) {
return refcount == 0;
}
+}
- if (refcount == 1 && !gchandle.is_released() && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
- GD_MONO_SCOPE_THREAD_ATTACH;
+void *CSharpLanguage::get_instance_binding(Object *p_object) {
+ void *binding = p_object->get_instance_binding(get_singleton(), &_instance_binding_callbacks);
- // If owner owner is no longer referenced by the unmanaged side,
- // the managed instance takes responsibility of deleting the owner when GCed.
+ // Initially this was in `_instance_binding_create_callback`. However, after the new instance
+ // binding re-write it was resulting in a deadlock in `_instance_binding_reference`, as
+ // `setup_csharp_script_binding` may call `reference()`. It was moved here outside to fix that.
- MonoObject *target = gchandle.get_target();
- if (!target) {
- return refcount == 0; // Called after the managed side was collected, so nothing to do here
- }
+ if (binding) {
+ CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)binding)->value();
- // Release the current strong handle and replace it with a weak handle.
- MonoGCHandleData weak_gchandle = MonoGCHandleData::new_weak_handle(target);
- gchandle.release();
- gchandle = weak_gchandle;
+ if (!script_binding.inited) {
+ MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
- return false;
+ if (!script_binding.inited) { // Another thread may have set it up
+ CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, p_object);
+ }
+ }
}
- return refcount == 0;
+ return binding;
+}
+
+void *CSharpLanguage::get_existing_instance_binding(Object *p_object) {
+#ifdef DEBUG_ENABLED
+ CRASH_COND(p_object->has_instance_binding(p_object));
+#endif
+ return p_object->get_instance_binding(get_singleton(), &_instance_binding_callbacks);
+}
+
+void CSharpLanguage::set_instance_binding(Object *p_object, void *p_binding) {
+ p_object->set_instance_binding(get_singleton(), p_binding, &_instance_binding_callbacks);
+}
+
+bool CSharpLanguage::has_instance_binding(Object *p_object) {
+ return p_object->has_instance_binding(get_singleton());
}
CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle) {
CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(p_script)));
- Reference *ref = Object::cast_to<Reference>(p_owner);
+ RefCounted *rc = Object::cast_to<RefCounted>(p_owner);
- instance->base_ref = ref != nullptr;
+ instance->base_ref_counted = rc != nullptr;
instance->owner = p_owner;
instance->gchandle = p_gchandle;
- if (instance->base_ref) {
+ if (instance->base_ref_counted) {
instance->_reference_owner_unsafe();
}
@@ -1703,12 +1757,12 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
}
void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state) {
- List<PropertyInfo> pinfo;
- get_property_list(&pinfo);
+ List<PropertyInfo> property_list;
+ get_property_list(&property_list);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+ for (const PropertyInfo &prop_info : property_list) {
Pair<StringName, Variant> state_pair;
- state_pair.first = E->get().name;
+ state_pair.first = prop_info.name;
ManagedType managedType;
@@ -1731,8 +1785,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
MonoObject *owner_managed = get_mono_object();
ERR_FAIL_NULL(owner_managed);
- for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) {
- const CSharpScript::EventSignal &event_signal = E->value();
+ for (const KeyValue<StringName, CSharpScript::EventSignal> &E : script->event_signals) {
+ const CSharpScript::EventSignal &event_signal = E.value;
MonoDelegate *delegate_field_value = (MonoDelegate *)event_signal.field->get_value(owner_managed);
if (!delegate_field_value) {
@@ -1759,8 +1813,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
}
void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
- for (Map<StringName, PropertyInfo>::Element *E = script->member_info.front(); E; E = E->next()) {
- p_properties->push_back(E->value());
+ for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
+ p_properties->push_back(E.value);
}
// Call _get_property_list
@@ -1810,6 +1864,28 @@ Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool *
return Variant::NIL;
}
+void CSharpInstance::get_method_list(List<MethodInfo> *p_list) const {
+ if (!script->is_valid() || !script->script_class)
+ return;
+
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
+ // TODO: We're filtering out constructors but there may be other methods unsuitable for explicit calls.
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ const Vector<GDMonoMethod *> &methods = top->get_all_methods();
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodInfo minfo = methods[i]->get_method_info();
+ if (minfo.name != CACHED_STRING_NAME(dotctor)) {
+ p_list->push_back(minfo);
+ }
+ }
+
+ top = top->get_parent_class();
+ }
+}
+
bool CSharpInstance::has_method(const StringName &p_method) const {
if (!script.is_valid()) {
return false;
@@ -1869,7 +1945,7 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
bool CSharpInstance::_reference_owner_unsafe() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
CRASH_COND(unsafe_referenced); // already referenced
#endif
@@ -1880,7 +1956,7 @@ bool CSharpInstance::_reference_owner_unsafe() {
// See: _unreference_owner_unsafe()
// May not me referenced yet, so we must use init_ref() instead of reference()
- if (static_cast<Reference *>(owner)->init_ref()) {
+ if (static_cast<RefCounted *>(owner)->init_ref()) {
CSharpLanguage::get_singleton()->post_unsafe_reference(owner);
unsafe_referenced = true;
}
@@ -1890,7 +1966,7 @@ bool CSharpInstance::_reference_owner_unsafe() {
bool CSharpInstance::_unreference_owner_unsafe() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
#endif
@@ -1907,7 +1983,7 @@ bool CSharpInstance::_unreference_owner_unsafe() {
// Destroying the owner here means self destructing, so we defer the owner destruction to the caller.
CSharpLanguage::get_singleton()->pre_unsafe_unreference(owner);
- return static_cast<Reference *>(owner)->unreference();
+ return static_cast<RefCounted *>(owner)->unreference();
}
MonoObject *CSharpInstance::_internal_new_managed() {
@@ -1939,7 +2015,7 @@ MonoObject *CSharpInstance::_internal_new_managed() {
// Tie managed to unmanaged
gchandle = MonoGCHandleData::new_strong_handle(mono_object);
- if (base_ref) {
+ if (base_ref_counted) {
_reference_owner_unsafe(); // Here, after assigning the gchandle (for the refcount_incremented callback)
}
@@ -1956,7 +2032,7 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
disconnect_event_signals();
#ifdef DEBUG_ENABLED
- CRASH_COND(base_ref);
+ CRASH_COND(base_ref_counted);
CRASH_COND(gchandle.is_released());
#endif
CSharpLanguage::get_singleton()->release_script_gchandle(p_obj, gchandle);
@@ -1964,7 +2040,7 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance) {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(gchandle.is_released());
#endif
@@ -1999,41 +2075,38 @@ void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_f
}
void CSharpInstance::connect_event_signals() {
- for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) {
- const CSharpScript::EventSignal &event_signal = E->value();
+ for (const KeyValue<StringName, CSharpScript::EventSignal> &E : script->event_signals) {
+ const CSharpScript::EventSignal &event_signal = E.value;
StringName signal_name = event_signal.field->get_name();
// TODO: Use pooling for ManagedCallable instances.
- auto event_signal_callable = memnew(EventSignalCallable(owner, &event_signal));
+ EventSignalCallable *event_signal_callable = memnew(EventSignalCallable(owner, &event_signal));
- owner->connect(signal_name, Callable(event_signal_callable));
+ Callable callable(event_signal_callable);
+ connected_event_signals.push_back(callable);
+ owner->connect(signal_name, callable);
}
}
void CSharpInstance::disconnect_event_signals() {
- for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) {
- const CSharpScript::EventSignal &event_signal = E->value();
-
- StringName signal_name = event_signal.field->get_name();
-
- // TODO: It would be great if we could store this EventSignalCallable on the stack.
- // The problem is that Callable memdeletes it when it's destructed...
- auto event_signal_callable = memnew(EventSignalCallable(owner, &event_signal));
-
- owner->disconnect(signal_name, Callable(event_signal_callable));
+ for (const Callable &callable : connected_event_signals) {
+ const EventSignalCallable *event_signal_callable = static_cast<const EventSignalCallable *>(callable.get_custom());
+ owner->disconnect(event_signal_callable->get_signal(), callable);
}
+
+ connected_event_signals.clear();
}
void CSharpInstance::refcount_incremented() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
#endif
- Reference *ref_owner = Object::cast_to<Reference>(owner);
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(owner);
- if (ref_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ if (rc_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
GD_MONO_SCOPE_THREAD_ATTACH;
// The reference count was increased after the managed side was the only one referencing our owner.
@@ -2049,13 +2122,13 @@ void CSharpInstance::refcount_incremented() {
bool CSharpInstance::refcount_decremented() {
#ifdef DEBUG_ENABLED
- CRASH_COND(!base_ref);
+ CRASH_COND(!base_ref_counted);
CRASH_COND(owner == nullptr);
#endif
- Reference *ref_owner = Object::cast_to<Reference>(owner);
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(owner);
- int refcount = ref_owner->reference_get_count();
+ int refcount = rc_owner->reference_get_count();
if (refcount == 1 && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -2076,46 +2149,10 @@ bool CSharpInstance::refcount_decremented() {
return ref_dying;
}
-Vector<ScriptNetData> CSharpInstance::get_rpc_methods() const {
+const Vector<Multiplayer::RPCConfig> CSharpInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t CSharpInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName CSharpInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_method(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_mode_by_id(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> CSharpInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t CSharpInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName CSharpInstance::get_rset_property(const uint16_t p_rset_member_id) const {
- return script->get_rset_property(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- return script->get_rset_mode_by_id(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
void CSharpInstance::notification(int p_notification) {
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -2126,12 +2163,12 @@ void CSharpInstance::notification(int p_notification) {
predelete_notified = true;
- if (base_ref) {
- // It's not safe to proceed if the owner derives Reference and the refcount reached 0.
+ if (base_ref_counted) {
+ // It's not safe to proceed if the owner derives RefCounted and the refcount reached 0.
// At this point, Dispose() was already called (manually or from the finalizer) so
// that's not a problem. The refcount wouldn't have reached 0 otherwise, since the
// managed side references it and Dispose() needs to be called to release it.
- // However, this means C# Reference scripts can't receive NOTIFICATION_PREDELETE, but
+ // However, this means C# RefCounted scripts can't receive NOTIFICATION_PREDELETE, but
// this is likely the case with GDScript as well: https://github.com/godotengine/godot/issues/6784
return;
}
@@ -2257,15 +2294,15 @@ CSharpInstance::~CSharpInstance() {
}
// If not being called from the owner's destructor, and we still hold a reference to the owner
- if (base_ref && !ref_dying && owner && unsafe_referenced) {
+ if (base_ref_counted && !ref_dying && owner && unsafe_referenced) {
// The owner's script or script instance is being replaced (or removed)
// Transfer ownership to an "instance binding"
- Reference *ref_owner = static_cast<Reference *>(owner);
+ RefCounted *rc_owner = static_cast<RefCounted *>(owner);
// We will unreference the owner before referencing it again, so we need to keep it alive
- Ref<Reference> scope_keep_owner_alive(ref_owner);
+ Ref<RefCounted> scope_keep_owner_alive(rc_owner);
(void)scope_keep_owner_alive;
// Unreference the owner here, before the new "instance binding" references it.
@@ -2273,24 +2310,14 @@ CSharpInstance::~CSharpInstance() {
bool die = _unreference_owner_unsafe();
CRASH_COND(die); // `owner_keep_alive` holds a reference, so it can't die
- void *data = owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+ void *data = CSharpLanguage::get_instance_binding(owner);
CRASH_COND(data == nullptr);
-
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
-
- if (!script_binding.inited) {
- MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
-
- if (!script_binding.inited) { // Other thread may have set it up
- // Already had a binding that needs to be setup
- CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, owner);
- CRASH_COND(!script_binding.inited);
- }
- }
+ CRASH_COND(!script_binding.inited);
#ifdef DEBUG_ENABLED
// The "instance binding" holds a reference so the refcount should be at least 2 before `scope_keep_owner_alive` goes out of scope
- CRASH_COND(ref_owner->reference_get_count() <= 1);
+ CRASH_COND(rc_owner->reference_get_count() <= 1);
#endif
}
@@ -2320,12 +2347,12 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List
base_cache->_update_exports_values(values, propnames);
}
- for (Map<StringName, Variant>::Element *E = exported_members_defval_cache.front(); E; E = E->next()) {
- values[E->key()] = E->get();
+ for (const KeyValue<StringName, Variant> &E : exported_members_defval_cache) {
+ values[E.key] = E.value;
}
- for (List<PropertyInfo>::Element *E = exported_members_cache.front(); E; E = E->next()) {
- propnames.push_back(E->get());
+ for (const PropertyInfo &prop_info : exported_members_cache) {
+ propnames.push_back(prop_info);
}
}
@@ -2377,7 +2404,7 @@ void CSharpScript::_update_member_info_no_exports() {
}
#endif
-bool CSharpScript::_update_exports() {
+bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_update) {
#ifdef TOOLS_ENABLED
bool is_editor = Engine::get_singleton()->is_editor_hint();
if (is_editor) {
@@ -2518,7 +2545,7 @@ bool CSharpScript::_update_exports() {
#ifdef TOOLS_ENABLED
if (is_editor) {
// Need to check this here, before disposal
- bool base_ref = Object::cast_to<Reference>(tmp_native) != nullptr;
+ bool base_ref_counted = Object::cast_to<RefCounted>(tmp_native) != nullptr;
// Dispose the temporary managed instance
@@ -2533,7 +2560,7 @@ bool CSharpScript::_update_exports() {
GDMonoUtils::free_gchandle(tmp_pinned_gchandle);
tmp_object = nullptr;
- if (tmp_native && !base_ref) {
+ if (tmp_native && !base_ref_counted) {
Node *node = Object::cast_to<Node>(tmp_native);
if (node && node->is_inside_tree()) {
ERR_PRINT("Temporary instance was added to the scene tree.");
@@ -2549,14 +2576,18 @@ bool CSharpScript::_update_exports() {
if (is_editor) {
placeholder_fallback_enabled = false;
- if (placeholders.size()) {
+ if ((changed || p_instance_to_update) && placeholders.size()) {
// Update placeholders if any
Map<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
- for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
- E->get()->update(propnames, values);
+ if (changed) {
+ for (PlaceHolderScriptInstance *&script_instance : placeholders) {
+ script_instance->update(propnames, values);
+ }
+ } else {
+ p_instance_to_update->update(propnames, values);
}
}
}
@@ -3017,7 +3048,6 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
p_script->rpc_functions.clear();
- p_script->rpc_variables.clear();
GDMonoClass *top = p_script->script_class;
while (top && top != p_script->native) {
@@ -3029,11 +3059,14 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
Vector<GDMonoMethod *> methods = top->get_all_methods();
for (int i = 0; i < methods.size(); i++) {
if (!methods[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
+ Multiplayer::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
+ if (Multiplayer::RPC_MODE_DISABLED != mode) {
+ Multiplayer::RPCConfig nd;
nd.name = methods[i]->get_name();
- nd.mode = mode;
+ nd.rpc_mode = mode;
+ // TODO Transfer mode, channel
+ nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
+ nd.channel = 0;
if (-1 == p_script->rpc_functions.find(nd)) {
p_script->rpc_functions.push_back(nd);
}
@@ -3042,51 +3075,16 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
}
}
- {
- Vector<GDMonoField *> fields = top->get_all_fields();
- for (int i = 0; i < fields.size(); i++) {
- if (!fields[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(fields[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = fields[i]->get_name();
- nd.mode = mode;
- if (-1 == p_script->rpc_variables.find(nd)) {
- p_script->rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
- {
- Vector<GDMonoProperty *> properties = top->get_all_properties();
- for (int i = 0; i < properties.size(); i++) {
- if (!properties[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(properties[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = properties[i]->get_name();
- nd.mode = mode;
- if (-1 == p_script->rpc_variables.find(nd)) {
- p_script->rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
top = top->get_parent_class();
}
// Sort so we are 100% that they are always the same.
- p_script->rpc_functions.sort_custom<SortNetData>();
- p_script->rpc_variables.sort_custom<SortNetData>();
+ p_script->rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
p_script->load_script_signals(p_script->script_class, p_script->native);
}
-bool CSharpScript::can_instance() const {
+bool CSharpScript::can_instantiate() const {
#ifdef TOOLS_ENABLED
bool extra_cond = tool || ScriptServer::is_scripting_enabled();
#else
@@ -3117,7 +3115,7 @@ StringName CSharpScript::get_instance_base_type() const {
}
}
-CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error) {
+CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error) {
GD_MONO_ASSERT_THREAD_ATTACHED;
/* STEP 1, CREATE */
@@ -3133,15 +3131,15 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
ERR_FAIL_V_MSG(nullptr, "Constructor not found.");
}
- Ref<Reference> ref;
- if (p_isref) {
+ Ref<RefCounted> ref;
+ if (p_is_ref_counted) {
// Hold it alive. Important if we have to dispose a script instance binding before creating the CSharpInstance.
- ref = Ref<Reference>(static_cast<Reference *>(p_owner));
+ ref = Ref<RefCounted>(static_cast<RefCounted *>(p_owner));
}
// If the object had a script instance binding, dispose it before adding the CSharpInstance
- if (p_owner->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index())) {
- void *data = p_owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+ if (CSharpLanguage::has_instance_binding(p_owner)) {
+ void *data = CSharpLanguage::get_existing_instance_binding(p_owner);
CRASH_COND(data == nullptr);
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -3162,7 +3160,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
}
CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(this)));
- instance->base_ref = p_isref;
+ instance->base_ref_counted = p_is_ref_counted;
instance->owner = p_owner;
instance->owner->set_script_instance(instance);
@@ -3187,7 +3185,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
// Tie managed to unmanaged
instance->gchandle = MonoGCHandleData::new_strong_handle(mono_object);
- if (instance->base_ref) {
+ if (instance->base_ref_counted) {
instance->_reference_owner_unsafe(); // Here, after assigning the gchandle (for the refcount_incremented callback)
}
@@ -3219,10 +3217,10 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
GD_MONO_SCOPE_THREAD_ATTACH;
- Object *owner = ClassDB::instance(NATIVE_GDMONOCLASS_NAME(native));
+ Object *owner = ClassDB::instantiate(NATIVE_GDMONOCLASS_NAME(native));
REF ref;
- Reference *r = Object::cast_to<Reference>(owner);
+ RefCounted *r = Object::cast_to<RefCounted>(owner);
if (r) {
ref = REF(r);
}
@@ -3230,7 +3228,7 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error);
if (!instance) {
if (ref.is_null()) {
- memdelete(owner); //no owner, sorry
+ memdelete(owner); // no owner, sorry
}
return Variant();
}
@@ -3253,24 +3251,24 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) {
if (EngineDebugger::is_active()) {
CSharpLanguage::get_singleton()->debug_break_parse(get_path(), 0,
"Script inherits from native type '" + String(native_name) +
- "', so it can't be instanced in object of type: '" + p_this->get_class() + "'");
+ "', so it can't be instantiated in object of type: '" + p_this->get_class() + "'");
}
ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(native_name) +
- "', so it can't be instanced in object of type: '" + p_this->get_class() + "'.");
+ "', so it can't be instantiated in object of type: '" + p_this->get_class() + "'.");
}
}
GD_MONO_SCOPE_THREAD_ATTACH;
Callable::CallError unchecked_error;
- return _create_instance(nullptr, 0, p_this, Object::cast_to<Reference>(p_this) != nullptr, unchecked_error);
+ return _create_instance(nullptr, 0, p_this, Object::cast_to<RefCounted>(p_this) != nullptr, unchecked_error);
}
PlaceHolderScriptInstance *CSharpScript::placeholder_instance_create(Object *p_this) {
#ifdef TOOLS_ENABLED
PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(CSharpLanguage::get_singleton(), Ref<Script>(this), p_this));
placeholders.insert(si);
- _update_exports();
+ _update_exports(si);
return si;
#else
return nullptr;
@@ -3307,10 +3305,19 @@ void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const {
GD_MONO_SCOPE_THREAD_ATTACH;
- // TODO: Filter out things unsuitable for explicit calls, like constructors.
- const Vector<GDMonoMethod *> &methods = script_class->get_all_methods();
- for (int i = 0; i < methods.size(); ++i) {
- p_list->push_back(methods[i]->get_method_info());
+ // TODO: We're filtering out constructors but there may be other methods unsuitable for explicit calls.
+ GDMonoClass *top = script_class;
+
+ while (top && top != native) {
+ const Vector<GDMonoMethod *> &methods = top->get_all_methods();
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodInfo minfo = methods[i]->get_method_info();
+ if (minfo.name != CACHED_STRING_NAME(dotctor)) {
+ p_list->push_back(methods[i]->get_method_info());
+ }
+ }
+
+ top = top->get_parent_class();
}
}
@@ -3356,45 +3363,34 @@ Error CSharpScript::reload(bool p_keep_state) {
GD_MONO_SCOPE_THREAD_ATTACH;
- GDMonoAssembly *project_assembly = GDMono::get_singleton()->get_project_assembly();
+ const DotNetScriptLookupInfo *lookup_info =
+ CSharpLanguage::get_singleton()->lookup_dotnet_script(get_path());
- if (project_assembly) {
- const Variant *script_metadata_var = CSharpLanguage::get_singleton()->get_scripts_metadata().getptr(get_path());
- if (script_metadata_var) {
- Dictionary script_metadata = script_metadata_var->operator Dictionary()["class"];
- const Variant *namespace_ = script_metadata.getptr("namespace");
- const Variant *class_name = script_metadata.getptr("class_name");
- ERR_FAIL_NULL_V(namespace_, ERR_BUG);
- ERR_FAIL_NULL_V(class_name, ERR_BUG);
- GDMonoClass *klass = project_assembly->get_class(namespace_->operator String(), class_name->operator String());
- if (klass && CACHED_CLASS(GodotObject)->is_assignable_from(klass)) {
- script_class = klass;
- }
- } else {
- // Missing script metadata. Fallback to legacy method
- script_class = project_assembly->get_object_derived_class(name);
+ if (lookup_info) {
+ GDMonoClass *klass = lookup_info->script_class;
+ if (klass) {
+ ERR_FAIL_COND_V(!CACHED_CLASS(GodotObject)->is_assignable_from(klass), FAILED);
+ script_class = klass;
}
+ }
- valid = script_class != nullptr;
+ valid = script_class != nullptr;
- if (script_class) {
+ if (script_class) {
#ifdef DEBUG_ENABLED
- print_verbose("Found class " + script_class->get_full_name() + " for script " + get_path());
+ print_verbose("Found class " + script_class->get_full_name() + " for script " + get_path());
#endif
- native = GDMonoUtils::get_class_native_base(script_class);
+ native = GDMonoUtils::get_class_native_base(script_class);
- CRASH_COND(native == nullptr);
+ CRASH_COND(native == nullptr);
- update_script_class_info(this);
+ update_script_class_info(this);
- _update_exports();
- }
-
- return OK;
+ _update_exports();
}
- return ERR_FILE_MISSING_DEPENDENCIES;
+ return OK;
}
ScriptLanguage *CSharpScript::get_language() const {
@@ -3429,11 +3425,11 @@ bool CSharpScript::has_script_signal(const StringName &p_signal) const {
}
void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
- for (const Map<StringName, Vector<SignalParameter>>::Element *E = _signals.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, Vector<SignalParameter>> &E : _signals) {
MethodInfo mi;
- mi.name = E->key();
+ mi.name = E.key;
- const Vector<SignalParameter> &params = E->value();
+ const Vector<SignalParameter> &params = E.value;
for (int i = 0; i < params.size(); i++) {
const SignalParameter &param = params[i];
@@ -3448,11 +3444,11 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
r_signals->push_back(mi);
}
- for (const Map<StringName, EventSignal>::Element *E = event_signals.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, EventSignal> &E : event_signals) {
MethodInfo mi;
- mi.name = E->key();
+ mi.name = E.key;
- const EventSignal &event_signal = E->value();
+ const EventSignal &event_signal = E.value;
const Vector<SignalParameter> &params = event_signal.parameters;
for (int i = 0; i < params.size(); i++) {
const SignalParameter &param = params[i];
@@ -3492,8 +3488,8 @@ Ref<Script> CSharpScript::get_base_script() const {
}
void CSharpScript::get_script_property_list(List<PropertyInfo> *p_list) const {
- for (Map<StringName, PropertyInfo>::Element *E = member_info.front(); E; E = E->next()) {
- p_list->push_back(E->value());
+ for (const KeyValue<StringName, PropertyInfo> &E : member_info) {
+ p_list->push_back(E.value);
}
}
@@ -3502,83 +3498,21 @@ int CSharpScript::get_member_line(const StringName &p_member) const {
return -1;
}
-MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const {
+Multiplayer::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const {
if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) {
- return MultiplayerAPI::RPC_MODE_REMOTE;
- }
- if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) {
- return MultiplayerAPI::RPC_MODE_MASTER;
+ return Multiplayer::RPC_MODE_ANY;
}
if (p_member->has_attribute(CACHED_CLASS(PuppetAttribute))) {
- return MultiplayerAPI::RPC_MODE_PUPPET;
- }
- if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute))) {
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- }
- if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute))) {
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- }
- if (p_member->has_attribute(CACHED_CLASS(PuppetSyncAttribute))) {
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
+ return Multiplayer::RPC_MODE_AUTHORITY;
}
- return MultiplayerAPI::RPC_MODE_DISABLED;
+ return Multiplayer::RPC_MODE_DISABLED;
}
-Vector<ScriptNetData> CSharpScript::get_rpc_methods() const {
+const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const {
return rpc_functions;
}
-uint16_t CSharpScript::get_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < rpc_functions.size(); i++) {
- if (rpc_functions[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName CSharpScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName());
- return rpc_functions[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode(const StringName &p_method) const {
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> CSharpScript::get_rset_properties() const {
- return rpc_variables;
-}
-
-uint16_t CSharpScript::get_rset_property_id(const StringName &p_variable) const {
- for (int i = 0; i < rpc_variables.size(); i++) {
- if (rpc_variables[i].name == p_variable) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName CSharpScript::get_rset_property(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName());
- return rpc_variables[p_rset_member_id].name;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rset_member_id].mode;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rset_mode(const StringName &p_variable) const {
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
Error CSharpScript::load_source_code(const String &p_path) {
Error ferr = read_all_file_utf8(p_path, source);
@@ -3635,8 +3569,8 @@ CSharpScript::~CSharpScript() {
void CSharpScript::get_members(Set<StringName> *p_members) {
#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
if (p_members) {
- for (Set<StringName>::Element *E = exported_members_names.front(); E; E = E->next()) {
- p_members->insert(E->get());
+ for (const StringName &member_name : exported_members_names) {
+ p_members->insert(member_name);
}
}
#endif
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index a31135cd32..afc17f694a 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -66,6 +66,18 @@ TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
#define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst))
+struct DotNetScriptLookupInfo {
+ String class_namespace;
+ String class_name;
+ GDMonoClass *script_class = nullptr;
+
+ DotNetScriptLookupInfo() {} // Required by HashMap...
+
+ DotNetScriptLookupInfo(const String &p_class_namespace, const String &p_class_name, GDMonoClass *p_script_class) :
+ class_namespace(p_class_namespace), class_name(p_class_name), script_class(p_script_class) {
+ }
+};
+
class CSharpScript : public Script {
GDCLASS(CSharpScript, Script);
@@ -124,8 +136,7 @@ private:
Map<StringName, EventSignal> event_signals;
bool signals_invalidated = true;
- Vector<ScriptNetData> rpc_functions;
- Vector<ScriptNetData> rpc_variables;
+ Vector<Multiplayer::RPCConfig> rpc_functions;
#ifdef TOOLS_ENABLED
List<PropertyInfo> exported_members_cache; // members_cache
@@ -152,14 +163,14 @@ private:
void load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class);
bool _get_signal(GDMonoClass *p_class, GDMonoMethod *p_delegate_invoke, Vector<SignalParameter> &params);
- bool _update_exports();
+ bool _update_exports(PlaceHolderScriptInstance *p_instance_to_update = nullptr);
bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported);
#ifdef TOOLS_ENABLED
static int _try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string);
#endif
- CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error);
+ CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
// Do not use unless you know what you are doing
@@ -168,7 +179,7 @@ private:
static void update_script_class_info(Ref<CSharpScript> p_script);
static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
- MultiplayerAPI::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;
+ Multiplayer::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;
protected:
static void _bind_methods();
@@ -180,7 +191,7 @@ protected:
void _get_property_list(List<PropertyInfo> *p_properties) const;
public:
- bool can_instance() const override;
+ bool can_instantiate() const override;
StringName get_instance_base_type() const override;
ScriptInstance *instance_create(Object *p_this) override;
PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this) override;
@@ -223,17 +234,7 @@ public:
int get_member_line(const StringName &p_member) const override;
- Vector<ScriptNetData> get_rpc_methods() const override;
- uint16_t get_rpc_method_id(const StringName &p_method) const override;
- StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- Vector<ScriptNetData> get_rset_properties() const override;
- uint16_t get_rset_property_id(const StringName &p_variable) const override;
- StringName get_rset_property(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
#ifdef TOOLS_ENABLED
bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -250,7 +251,7 @@ class CSharpInstance : public ScriptInstance {
friend class CSharpLanguage;
Object *owner = nullptr;
- bool base_ref = false;
+ bool base_ref_counted = false;
bool ref_dying = false;
bool unsafe_referenced = false;
bool predelete_notified = false;
@@ -259,6 +260,8 @@ class CSharpInstance : public ScriptInstance {
Ref<CSharpScript> script;
MonoGCHandleData gchandle;
+ List<Callable> connected_event_signals;
+
bool _reference_owner_unsafe();
/*
@@ -290,7 +293,7 @@ public:
void get_property_list(List<PropertyInfo> *p_properties) const override;
Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const override;
- /* TODO */ void get_method_list(List<MethodInfo> *p_list) const override {}
+ void get_method_list(List<MethodInfo> *p_list) const override;
bool has_method(const StringName &p_method) const override;
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
@@ -308,17 +311,7 @@ public:
void refcount_incremented() override;
bool refcount_decremented() override;
- Vector<ScriptNetData> get_rpc_methods() const override;
- uint16_t get_rpc_method_id(const StringName &p_method) const override;
- StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- Vector<ScriptNetData> get_rset_properties() const override;
- uint16_t get_rset_property_id(const StringName &p_variable) const override;
- StringName get_rset_property(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
void notification(int p_notification) override;
void _call_notification(int p_notification);
@@ -390,16 +383,15 @@ class CSharpLanguage : public ScriptLanguage {
int lang_idx = -1;
- Dictionary scripts_metadata;
- bool scripts_metadata_invalidated = true;
+ HashMap<String, DotNetScriptLookupInfo> dotnet_script_lookup_map;
+
+ void lookup_script_for_class(GDMonoClass *p_class);
// For debug_break and debug_break_parse
int _debug_parse_err_line = -1;
String _debug_parse_err_file;
String _debug_error;
- void _load_scripts_metadata();
-
friend class GDMono;
void _on_scripts_domain_unloaded();
@@ -409,7 +401,18 @@ class CSharpLanguage : public ScriptLanguage {
static void _editor_init_callback();
#endif
+ 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 GDNativeInstanceBindingCallbacks _instance_binding_callbacks;
+
public:
+ static void *get_instance_binding(Object *p_object);
+ static void *get_existing_instance_binding(Object *p_object);
+ static void set_instance_binding(Object *p_object, void *p_binding);
+ static bool has_instance_binding(Object *p_object);
+
StringNameCache string_names;
const Mutex &get_language_bind_mutex() { return language_bind_mutex; }
@@ -436,18 +439,13 @@ public:
void reload_assemblies(bool p_soft_reload);
#endif
- _FORCE_INLINE_ Dictionary get_scripts_metadata_or_nothing() {
- return scripts_metadata_invalidated ? Dictionary() : scripts_metadata;
- }
+ _FORCE_INLINE_ ManagedCallableMiddleman *get_managed_callable_middleman() const { return managed_callable_middleman; }
- _FORCE_INLINE_ const Dictionary &get_scripts_metadata() {
- if (scripts_metadata_invalidated) {
- _load_scripts_metadata();
- }
- return scripts_metadata;
- }
+ void lookup_scripts_in_assembly(GDMonoAssembly *p_assembly);
- _FORCE_INLINE_ ManagedCallableMiddleman *get_managed_callable_middleman() const { return managed_callable_middleman; }
+ const DotNetScriptLookupInfo *lookup_dotnet_script(const String &p_script_path) const {
+ return dotnet_script_lookup_map.getptr(p_script_path);
+ }
String get_name() const override;
@@ -462,14 +460,14 @@ public:
/* EDITOR FUNCTIONS */
void get_reserved_words(List<String> *p_words) const override;
+ bool is_control_flow_keyword(String p_keyword) const override;
void get_comment_delimiters(List<String> *p_delimiters) const override;
void get_string_delimiters(List<String> *p_delimiters) const override;
Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const override;
bool is_using_templates() override;
void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) override;
- /* TODO */ bool validate(const String &p_script, int &r_line_error, int &r_col_error,
- String &r_test_error, const String &p_path, List<String> *r_functions,
- List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override {
+ /* TODO */ bool validate(const String &p_script, const String &p_path, List<String> *r_functions,
+ List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override {
return true;
}
String validate_path(const String &p_path) const override;
@@ -520,12 +518,6 @@ public:
void thread_enter() override;
void thread_exit() override;
- // Don't use these. I'm watching you
- void *alloc_instance_binding_data(Object *p_object) override;
- void free_instance_binding_data(void *p_data) override;
- void refcount_incremented_instance_binding(Object *p_object) override;
- bool refcount_decremented_instance_binding(Object *p_object) override;
-
Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
index 56c0cb7703..d1868f52ef 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
@@ -2,6 +2,12 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.NET.Sdk", "Godot.NET.Sdk\Godot.NET.Sdk.csproj", "{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators", "Godot.SourceGenerators\Godot.SourceGenerators.csproj", "{32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators.Sample", "Godot.SourceGenerators.Sample\Godot.SourceGenerators.Sample.csproj", "{7297A614-8DF5-43DE-9EAD-99671B26BD1F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharp", "..\..\glue\GodotSharp\GodotSharp\GodotSharp.csproj", "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -12,5 +18,17 @@ Global
{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
index 8304d9e321..4e9e7184da 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
@@ -8,43 +8,34 @@
<PackageId>Godot.NET.Sdk</PackageId>
<Version>4.0.0</Version>
- <PackageProjectUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk</PackageProjectUrl>
+ <PackageVersion>$(PackageVersion_Godot_NET_Sdk)</PackageVersion>
+ <RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk</RepositoryUrl>
+ <PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
<PackageType>MSBuildSdk</PackageType>
<PackageTags>MSBuildSdk</PackageTags>
+ <PackageLicenseExpression>MIT</PackageLicenseExpression>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
- </PropertyGroup>
- <PropertyGroup>
- <NuspecFile>Godot.NET.Sdk.nuspec</NuspecFile>
- <GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetNuSpecProperties</GenerateNuspecDependsOn>
+ <!-- Exclude target framework from the package dependencies as we don't include the build output -->
+ <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
+ <IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>
- <Target Name="ReadGodotNETSdkVersion" BeforeTargets="BeforeBuild;BeforeRebuild;CoreCompile">
- <PropertyGroup>
- <PackageVersion>$([System.IO.File]::ReadAllText('$(ProjectDir)Godot.NET.Sdk_PackageVersion.txt').Trim())</PackageVersion>
- </PropertyGroup>
- </Target>
-
- <Target Name="SetNuSpecProperties" Condition=" Exists('$(NuspecFile)') " DependsOnTargets="ReadGodotNETSdkVersion">
- <PropertyGroup>
- <NuspecProperties>
- id=$(PackageId);
- description=$(Description);
- authors=$(Authors);
- version=$(PackageVersion);
- packagetype=$(PackageType);
- tags=$(PackageTags);
- projecturl=$(PackageProjectUrl)
- </NuspecProperties>
- </PropertyGroup>
- </Target>
+ <ItemGroup>
+ <!-- Package Sdk\Sdk.props and Sdk\Sdk.targets file -->
+ <None Include="Sdk\Sdk.props" Pack="true" PackagePath="Sdk" />
+ <None Include="Sdk\Sdk.targets" Pack="true" PackagePath="Sdk" />
+ <!-- SdkPackageVersions.props -->
+ <None Include="..\..\..\SdkPackageVersions.props" Pack="true" PackagePath="Sdk">
+ <Link>Sdk\SdkPackageVersions.props</Link>
+ </None>
+ </ItemGroup>
<Target Name="CopyNupkgToSConsOutputDir" AfterTargets="Pack">
<PropertyGroup>
<GodotSourceRootPath>$(SolutionDir)\..\..\..\..\</GodotSourceRootPath>
<GodotOutputDataDir>$(GodotSourceRootPath)\bin\GodotSharp\</GodotOutputDataDir>
</PropertyGroup>
- <Copy SourceFiles="$(OutputPath)$(PackageId).$(PackageVersion).nupkg"
- DestinationFolder="$(GodotOutputDataDir)Tools\nupkgs\" />
+ <Copy SourceFiles="$(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="$(GodotOutputDataDir)Tools\nupkgs\" />
</Target>
</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec
deleted file mode 100644
index ba68a4da43..0000000000
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<package xmlns="http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd">
- <metadata>
- <id>$id$</id>
- <version>$version$</version>
- <description>$description$</description>
- <authors>$authors$</authors>
- <owners>$authors$</owners>
- <projectUrl>$projecturl$</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
- <license type="expression">MIT</license>
- <licenseUrl>https://licenses.nuget.org/MIT</licenseUrl>
- <tags>$tags$</tags>
- <packageTypes>
- <packageType name="$packagetype$" />
- </packageTypes>
- <repository url="$projecturl$" />
- </metadata>
- <files>
- <file src="Sdk\**" target="Sdk" />
- </files>
-</package>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt
deleted file mode 100644
index 34749489b9..0000000000
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt
+++ /dev/null
@@ -1 +0,0 @@
-4.0.0-dev3
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 5febcf3175..0128f5c706 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
@@ -1,4 +1,6 @@
<Project>
+ <Import Project="$(MSBuildThisFileDirectory)\SdkPackageVersions.props" />
+
<PropertyGroup>
<!-- Determines if we should import Microsoft.NET.Sdk, if it wasn't already imported. -->
<GodotSdkImportsMicrosoftNetSdk Condition=" '$(UsingMicrosoftNETSdk)' != 'true' ">true</GodotSdkImportsMicrosoftNetSdk>
@@ -94,6 +96,7 @@
<DefineConstants>$(GodotDefineConstants);$(DefineConstants)</DefineConstants>
</PropertyGroup>
+ <!-- Godot API references -->
<ItemGroup>
<!--
TODO:
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
index f5afd75505..92e299d2f3 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
@@ -14,4 +14,9 @@
-->
<DefineConstants Condition=" '$(GodotRealTIsDouble)' == 'true' ">GODOT_REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
+
+ <!-- C# source generators -->
+ <ItemGroup Condition=" '$(DisableImplicitGodotGeneratorReferences)' != 'true' ">
+ <PackageReference Include="Godot.SourceGenerators" Version="$(PackageVersion_Godot_SourceGenerators)" />
+ </ItemGroup>
</Project>
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
new file mode 100644
index 0000000000..5eaebc4474
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
@@ -0,0 +1,15 @@
+namespace Godot.SourceGenerators.Sample
+{
+ partial class Bar : Godot.Object
+ {
+ }
+
+ // Foo in another file
+ partial class Foo
+ {
+ }
+
+ partial class NotSameNameAsFile : Godot.Object
+ {
+ }
+}
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
new file mode 100644
index 0000000000..21a5bfe560
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
@@ -0,0 +1,11 @@
+namespace Godot.SourceGenerators.Sample
+{
+ partial class Foo : Godot.Object
+ {
+ }
+
+ // Foo again in the same file
+ partial class Foo
+ {
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj
new file mode 100644
index 0000000000..24f7909861
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj
@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>netstandard2.1</TargetFramework>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <!-- $(GodotProjectDir) would normally be defined by the Godot.NET.Sdk -->
+ <GodotProjectDir>$(MSBuildProjectDirectory)</GodotProjectDir>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <!-- The emitted files are not part of the compilation nor design.
+ They're only for peeking at the generated sources. Sometimes the
+ emitted files get corrupted, but that won't break anything. -->
+ <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
+ <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\glue\GodotSharp\GodotSharp\GodotSharp.csproj">
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\Godot.SourceGenerators\Godot.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
+ </ItemGroup>
+
+ <!-- This file is imported automatically when using PackageReference to
+ reference Godot.SourceGenerators, but not when using ProjectReference -->
+ <Import Project="..\Godot.SourceGenerators\Godot.SourceGenerators.props" />
+
+</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
new file mode 100644
index 0000000000..4867c986e6
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
@@ -0,0 +1,33 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Godot.SourceGenerators
+{
+ public static class Common
+ {
+ public static void ReportNonPartialGodotScriptClass(
+ GeneratorExecutionContext context,
+ ClassDeclarationSyntax cds, INamedTypeSymbol symbol
+ )
+ {
+ string message =
+ "Missing partial modifier on declaration of type '" +
+ $"{symbol.FullQualifiedName()}' which is a subclass of '{GodotClasses.Object}'";
+
+ string description = $"{message}. Subclasses of '{GodotClasses.Object}' must be " +
+ "declared with the partial modifier or annotated with the " +
+ $"attribute '{GodotClasses.DisableGodotGeneratorsAttr}'.";
+
+ context.ReportDiagnostic(Diagnostic.Create(
+ new DiagnosticDescriptor(id: "GODOT-G0001",
+ title: message,
+ messageFormat: message,
+ category: "Usage",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ description),
+ cds.GetLocation(),
+ cds.SyntaxTree.FilePath));
+ }
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
new file mode 100644
index 0000000000..e16f72f43a
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -0,0 +1,89 @@
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Godot.SourceGenerators
+{
+ static class ExtensionMethods
+ {
+ public static bool TryGetGlobalAnalyzerProperty(
+ this GeneratorExecutionContext context, string property, out string? value
+ ) => context.AnalyzerConfigOptions.GlobalOptions
+ .TryGetValue("build_property." + property, out value);
+
+ private static bool InheritsFrom(this INamedTypeSymbol? symbol, string baseName)
+ {
+ if (symbol == null)
+ return false;
+
+ while (true)
+ {
+ if (symbol.ToString() == baseName)
+ {
+ return true;
+ }
+
+ if (symbol.BaseType != null)
+ {
+ symbol = symbol.BaseType;
+ continue;
+ }
+
+ break;
+ }
+
+ return false;
+ }
+
+ private static bool IsGodotScriptClass(
+ this ClassDeclarationSyntax cds, Compilation compilation,
+ out INamedTypeSymbol? symbol
+ )
+ {
+ var sm = compilation.GetSemanticModel(cds.SyntaxTree);
+
+ var classTypeSymbol = sm.GetDeclaredSymbol(cds);
+
+ if (classTypeSymbol?.BaseType == null
+ || !classTypeSymbol.BaseType.InheritsFrom(GodotClasses.Object))
+ {
+ symbol = null;
+ return false;
+ }
+
+ symbol = classTypeSymbol;
+ return true;
+ }
+
+ public static IEnumerable<(ClassDeclarationSyntax cds, INamedTypeSymbol symbol)> SelectGodotScriptClasses(
+ this IEnumerable<ClassDeclarationSyntax> source,
+ Compilation compilation
+ )
+ {
+ foreach (var cds in source)
+ {
+ if (cds.IsGodotScriptClass(compilation, out var symbol))
+ yield return (cds, symbol!);
+ }
+ }
+
+ public static bool IsPartial(this ClassDeclarationSyntax cds)
+ => cds.Modifiers.Any(SyntaxKind.PartialKeyword);
+
+ public static bool HasDisableGeneratorsAttribute(this INamedTypeSymbol symbol)
+ => symbol.GetAttributes().Any(attr =>
+ attr.AttributeClass?.ToString() == GodotClasses.DisableGodotGeneratorsAttr);
+
+ private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
+
+ public static string FullQualifiedName(this INamedTypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
new file mode 100644
index 0000000000..11d8e0f72b
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
@@ -0,0 +1,41 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <LangVersion>8.0</LangVersion>
+ <Nullable>enable</Nullable>
+ </PropertyGroup>
+ <PropertyGroup>
+ <Description>Core C# source generator for Godot projects.</Description>
+ <Authors>Godot Engine contributors</Authors>
+
+ <PackageId>Godot.SourceGenerators</PackageId>
+ <Version>4.0.0</Version>
+ <PackageVersion>$(PackageVersion_Godot_SourceGenerators)</PackageVersion>
+ <RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators</RepositoryUrl>
+ <PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
+ <PackageLicenseExpression>MIT</PackageLicenseExpression>
+
+ <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+ <!-- Do not include the generator as a lib dependency -->
+ <IncludeBuildOutput>false</IncludeBuildOutput>
+ </PropertyGroup>
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
+ <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.1" PrivateAssets="all" />
+ </ItemGroup>
+ <ItemGroup>
+ <!-- Package the generator in the analyzer directory of the nuget package -->
+ <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
+
+ <!-- Package the props file -->
+ <None Include="Godot.SourceGenerators.props" Pack="true" PackagePath="build" Visible="false" />
+ </ItemGroup>
+
+ <Target Name="CopyNupkgToSConsOutputDir" AfterTargets="Pack">
+ <PropertyGroup>
+ <GodotSourceRootPath>$(SolutionDir)\..\..\..\..\</GodotSourceRootPath>
+ <GodotOutputDataDir>$(GodotSourceRootPath)\bin\GodotSharp\</GodotOutputDataDir>
+ </PropertyGroup>
+ <Copy SourceFiles="$(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="$(GodotOutputDataDir)Tools\nupkgs\" />
+ </Target>
+</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props
new file mode 100644
index 0000000000..f9b47ad5b1
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props
@@ -0,0 +1,7 @@
+<Project>
+ <ItemGroup>
+ <!-- $(GodotProjectDir) is defined by Godot.NET.Sdk -->
+ <CompilerVisibleProperty Include="GodotProjectDir" />
+ <CompilerVisibleProperty Include="GodotScriptPathAttributeGenerator" />
+ </ItemGroup>
+</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
new file mode 100644
index 0000000000..29e41d155a
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
@@ -0,0 +1,9 @@
+namespace Godot.SourceGenerators
+{
+ public static class GodotClasses
+ {
+ public const string Object = "Godot.Object";
+ public const string DisableGodotGeneratorsAttr = "Godot.DisableGodotGeneratorsAttribute";
+ public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
new file mode 100644
index 0000000000..a51728e221
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
@@ -0,0 +1,182 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+
+namespace Godot.SourceGenerators
+{
+ [Generator]
+ public class ScriptPathAttributeGenerator : ISourceGenerator
+ {
+ public void Execute(GeneratorExecutionContext context)
+ {
+ if (context.TryGetGlobalAnalyzerProperty("GodotScriptPathAttributeGenerator", out string? toggle)
+ && toggle == "disabled")
+ {
+ return;
+ }
+
+ // NOTE: IsNullOrEmpty doesn't work well with nullable checks
+ // ReSharper disable once ReplaceWithStringIsNullOrEmpty
+ if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDir", out string? godotProjectDir)
+ || godotProjectDir!.Length == 0)
+ {
+ throw new InvalidOperationException("Property 'GodotProjectDir' is null or empty.");
+ }
+
+ var godotClasses = context.Compilation.SyntaxTrees
+ .SelectMany(tree =>
+ tree.GetRoot().DescendantNodes()
+ .OfType<ClassDeclarationSyntax>()
+ // Ignore inner classes
+ .Where(cds => !(cds.Parent is ClassDeclarationSyntax))
+ .SelectGodotScriptClasses(context.Compilation)
+ // Report and skip non-partial classes
+ .Where(x =>
+ {
+ if (x.cds.IsPartial() || x.symbol.HasDisableGeneratorsAttribute())
+ return true;
+ Common.ReportNonPartialGodotScriptClass(context, x.cds, x.symbol);
+ 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)
+ .GroupBy(x => x.symbol)
+ .ToDictionary(g => g.Key, g => g.Select(x => x.cds));
+
+ foreach (var godotClass in godotClasses)
+ {
+ VisitGodotScriptClass(context, godotProjectDir,
+ symbol: godotClass.Key,
+ classDeclarations: godotClass.Value);
+ }
+
+ if (godotClasses.Count <= 0)
+ return;
+
+ AddScriptTypesAssemblyAttr(context, godotClasses);
+ }
+
+ private static void VisitGodotScriptClass(
+ GeneratorExecutionContext context,
+ string godotProjectDir,
+ INamedTypeSymbol symbol,
+ IEnumerable<ClassDeclarationSyntax> classDeclarations
+ )
+ {
+ var attributes = new StringBuilder();
+
+ // Remember syntax trees for which we already added an attribute, to prevent unnecessary duplicates.
+ var attributedTrees = new List<SyntaxTree>();
+
+ foreach (var cds in classDeclarations)
+ {
+ if (attributedTrees.Contains(cds.SyntaxTree))
+ continue;
+
+ attributedTrees.Add(cds.SyntaxTree);
+
+ if (attributes.Length != 0)
+ attributes.Append("\n");
+
+ attributes.Append(@"[ScriptPathAttribute(""res://");
+ attributes.Append(RelativeToDir(cds.SyntaxTree.FilePath, godotProjectDir));
+ attributes.Append(@""")]");
+ }
+
+ string className = symbol.Name;
+
+ INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
+ string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
+ namespaceSymbol.FullQualifiedName() :
+ string.Empty;
+ bool hasNamespace = classNs.Length != 0;
+
+ string uniqueName = hasNamespace ?
+ classNs + "." + className + "_ScriptPath_Generated" :
+ className + "_ScriptPath_Generated";
+
+ var source = new StringBuilder();
+
+ // using Godot;
+ // namespace {classNs} {
+ // {attributesBuilder}
+ // partial class {className} { }
+ // }
+
+ source.Append("using Godot;\n");
+
+ if (hasNamespace)
+ {
+ source.Append("namespace ");
+ source.Append(classNs);
+ source.Append(" {\n\n");
+ }
+
+ source.Append(attributes);
+ source.Append("\n partial class ");
+ source.Append(className);
+ source.Append("\n{\n}\n");
+
+ if (hasNamespace)
+ {
+ source.Append("\n}\n");
+ }
+
+ context.AddSource(uniqueName, SourceText.From(source.ToString(), Encoding.UTF8));
+ }
+
+ private static void AddScriptTypesAssemblyAttr(GeneratorExecutionContext context,
+ Dictionary<INamedTypeSymbol, IEnumerable<ClassDeclarationSyntax>> godotClasses)
+ {
+ var sourceBuilder = new StringBuilder();
+
+ sourceBuilder.Append("[assembly:");
+ sourceBuilder.Append(GodotClasses.AssemblyHasScriptsAttr);
+ sourceBuilder.Append("(new System.Type[] {");
+
+ bool first = true;
+
+ foreach (var godotClass in godotClasses)
+ {
+ var qualifiedName = godotClass.Key.ToDisplayString(
+ NullableFlowState.NotNull, SymbolDisplayFormat.FullyQualifiedFormat);
+ if (!first)
+ sourceBuilder.Append(", ");
+ first = false;
+ sourceBuilder.Append("typeof(");
+ sourceBuilder.Append(qualifiedName);
+ sourceBuilder.Append(")");
+ }
+
+ sourceBuilder.Append("})]\n");
+
+ context.AddSource("AssemblyScriptTypes_Generated",
+ SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
+ }
+
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ }
+
+ private static string RelativeToDir(string path, string dir)
+ {
+ // Make sure the directory ends with a path separator
+ dir = Path.Combine(dir, " ").TrimEnd();
+
+ if (Path.DirectorySeparatorChar == '\\')
+ dir = dir.Replace("/", "\\") + "\\";
+
+ var fullPath = new Uri(Path.GetFullPath(path), UriKind.Absolute);
+ var relRoot = new Uri(Path.GetFullPath(dir), UriKind.Absolute);
+
+ // MakeRelativeUri converts spaces to %20, hence why we need UnescapeDataString
+ return Uri.UnescapeDataString(relRoot.MakeRelativeUri(fullPath).ToString());
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotTools/.gitignore b/modules/mono/editor/GodotTools/.gitignore
index 48e2f914d8..a41d1c89b5 100644
--- a/modules/mono/editor/GodotTools/.gitignore
+++ b/modules/mono/editor/GodotTools/.gitignore
@@ -353,4 +353,3 @@ healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
-
diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs
index 9b7b422276..2bf1cb7a18 100644
--- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs
@@ -12,12 +12,16 @@ namespace GodotTools.BuildLogger
public string Parameters { get; set; }
public LoggerVerbosity Verbosity { get; set; }
+ private StreamWriter _logStreamWriter;
+ private StreamWriter _issuesStreamWriter;
+ private int _indent;
+
public void Initialize(IEventSource eventSource)
{
if (null == Parameters)
throw new LoggerException("Log directory parameter not specified.");
- var parameters = Parameters.Split(new[] { ';' });
+ string[] parameters = Parameters.Split(new[] { ';' });
string logDir = parameters[0];
@@ -35,8 +39,8 @@ namespace GodotTools.BuildLogger
if (!Directory.Exists(logDir))
Directory.CreateDirectory(logDir);
- logStreamWriter = new StreamWriter(logFile);
- issuesStreamWriter = new StreamWriter(issuesFile);
+ _logStreamWriter = new StreamWriter(logFile);
+ _issuesStreamWriter = new StreamWriter(issuesFile);
}
catch (Exception ex)
{
@@ -66,12 +70,12 @@ namespace GodotTools.BuildLogger
private void eventSource_ProjectStarted(object sender, ProjectStartedEventArgs e)
{
WriteLine(e.Message);
- indent++;
+ _indent++;
}
private void eventSource_ProjectFinished(object sender, ProjectFinishedEventArgs e)
{
- indent--;
+ _indent--;
WriteLine(e.Message);
}
@@ -87,7 +91,7 @@ namespace GodotTools.BuildLogger
string errorLine = $@"error,{e.File.CsvEscape()},{e.LineNumber},{e.ColumnNumber}," +
$"{e.Code?.CsvEscape() ?? string.Empty},{e.Message.CsvEscape()}," +
$"{e.ProjectFile?.CsvEscape() ?? string.Empty}";
- issuesStreamWriter.WriteLine(errorLine);
+ _issuesStreamWriter.WriteLine(errorLine);
}
private void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
@@ -102,7 +106,7 @@ namespace GodotTools.BuildLogger
string warningLine = $@"warning,{e.File.CsvEscape()},{e.LineNumber},{e.ColumnNumber}," +
$"{e.Code?.CsvEscape() ?? string.Empty},{e.Message.CsvEscape()}," +
$"{e.ProjectFile?.CsvEscape() ?? string.Empty}";
- issuesStreamWriter.WriteLine(warningLine);
+ _issuesStreamWriter.WriteLine(warningLine);
}
private void eventSource_MessageRaised(object sender, BuildMessageEventArgs e)
@@ -136,28 +140,24 @@ namespace GodotTools.BuildLogger
private void WriteLine(string line)
{
- for (int i = indent; i > 0; i--)
+ for (int i = _indent; i > 0; i--)
{
- logStreamWriter.Write("\t");
+ _logStreamWriter.Write("\t");
}
- logStreamWriter.WriteLine(line);
+ _logStreamWriter.WriteLine(line);
}
public void Shutdown()
{
- logStreamWriter.Close();
- issuesStreamWriter.Close();
+ _logStreamWriter.Close();
+ _issuesStreamWriter.Close();
}
private bool IsVerbosityAtLeast(LoggerVerbosity checkVerbosity)
{
return Verbosity >= checkVerbosity;
}
-
- private StreamWriter logStreamWriter;
- private StreamWriter issuesStreamWriter;
- private int indent;
}
internal static class StringExtensions
diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs
index 43d40f2ad9..a4d7dedbd5 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs
@@ -7,7 +7,7 @@ namespace GodotTools.Core
{
public static class ProcessExtensions
{
- public static async Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default(CancellationToken))
+ public static async Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default)
{
var tcs = new TaskCompletionSource<bool>();
diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs
index b217ae4bf7..60a4f297c9 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs
@@ -7,6 +7,8 @@ namespace GodotTools.Core
{
public static class StringExtensions
{
+ private static readonly string _driveRoot = Path.GetPathRoot(Environment.CurrentDirectory);
+
public static string RelativeToPath(this string path, string dir)
{
// Make sure the directory ends with a path separator
@@ -49,13 +51,11 @@ namespace GodotTools.Core
return Path.DirectorySeparatorChar + path;
}
- private static readonly string DriveRoot = Path.GetPathRoot(Environment.CurrentDirectory);
-
public static bool IsAbsolutePath(this string path)
{
return path.StartsWith("/", StringComparison.Ordinal) ||
path.StartsWith("\\", StringComparison.Ordinal) ||
- path.StartsWith(DriveRoot, StringComparison.Ordinal);
+ path.StartsWith(_driveRoot, StringComparison.Ordinal);
}
public static string ToSafeDirName(this string dirName, bool allowDirSeparator = false)
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs
index 4db71500da..450c4bf0cb 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs
@@ -113,8 +113,7 @@ namespace GodotTools.IdeMessaging.CLI
}
}
- ExitMainLoop:
-
+ ExitMainLoop:
await forwarder.WriteLineToOutput("Event=Quit");
}
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
index cc0da44a13..355b21d63a 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
@@ -9,15 +9,40 @@ namespace GodotTools.ProjectEditor
{
public class DotNetSolution
{
- private string directoryPath;
- private readonly Dictionary<string, ProjectInfo> projects = new Dictionary<string, ProjectInfo>();
+ private const string _solutionTemplate =
+@"Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+{0}
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+{1}
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+{2}
+ EndGlobalSection
+EndGlobal
+";
+
+ private const string _projectDeclaration =
+@"Project(""{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}"") = ""{0}"", ""{1}"", ""{{{2}}}""
+EndProject";
+
+ private const string _solutionPlatformsConfig =
+@" {0}|Any CPU = {0}|Any CPU";
+
+ private const string _projectPlatformsConfig =
+@" {{{0}}}.{1}|Any CPU.ActiveCfg = {1}|Any CPU
+ {{{0}}}.{1}|Any CPU.Build.0 = {1}|Any CPU";
+
+ private string _directoryPath;
+ private readonly Dictionary<string, ProjectInfo> _projects = new Dictionary<string, ProjectInfo>();
public string Name { get; }
public string DirectoryPath
{
- get => directoryPath;
- set => directoryPath = value.IsAbsolutePath() ? value : Path.GetFullPath(value);
+ get => _directoryPath;
+ set => _directoryPath = value.IsAbsolutePath() ? value : Path.GetFullPath(value);
}
public class ProjectInfo
@@ -29,22 +54,22 @@ namespace GodotTools.ProjectEditor
public void AddNewProject(string name, ProjectInfo projectInfo)
{
- projects[name] = projectInfo;
+ _projects[name] = projectInfo;
}
public bool HasProject(string name)
{
- return projects.ContainsKey(name);
+ return _projects.ContainsKey(name);
}
public ProjectInfo GetProjectInfo(string name)
{
- return projects[name];
+ return _projects[name];
}
public bool RemoveProject(string name)
{
- return projects.Remove(name);
+ return _projects.Remove(name);
}
public void Save()
@@ -58,7 +83,7 @@ namespace GodotTools.ProjectEditor
bool isFirstProject = true;
- foreach (var pair in projects)
+ foreach (var pair in _projects)
{
string name = pair.Key;
ProjectInfo projectInfo = pair.Value;
@@ -66,7 +91,7 @@ namespace GodotTools.ProjectEditor
if (!isFirstProject)
projectsDecl += "\n";
- projectsDecl += string.Format(ProjectDeclaration,
+ projectsDecl += string.Format(_projectDeclaration,
name, projectInfo.PathRelativeToSolution.Replace("/", "\\"), projectInfo.Guid);
for (int i = 0; i < projectInfo.Configs.Count; i++)
@@ -79,15 +104,15 @@ namespace GodotTools.ProjectEditor
projPlatformsCfg += "\n";
}
- slnPlatformsCfg += string.Format(SolutionPlatformsConfig, config);
- projPlatformsCfg += string.Format(ProjectPlatformsConfig, projectInfo.Guid, config);
+ slnPlatformsCfg += string.Format(_solutionPlatformsConfig, config);
+ projPlatformsCfg += string.Format(_projectPlatformsConfig, projectInfo.Guid, config);
}
isFirstProject = false;
}
string solutionPath = Path.Combine(DirectoryPath, Name + ".sln");
- string content = string.Format(SolutionTemplate, projectsDecl, slnPlatformsCfg, projPlatformsCfg);
+ string content = string.Format(_solutionTemplate, projectsDecl, slnPlatformsCfg, projPlatformsCfg);
File.WriteAllText(solutionPath, content, Encoding.UTF8); // UTF-8 with BOM
}
@@ -97,37 +122,12 @@ namespace GodotTools.ProjectEditor
Name = name;
}
- const string SolutionTemplate =
-@"Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
-{0}
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
-{1}
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
-{2}
- EndGlobalSection
-EndGlobal
-";
-
- const string ProjectDeclaration =
-@"Project(""{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}"") = ""{0}"", ""{1}"", ""{{{2}}}""
-EndProject";
-
- const string SolutionPlatformsConfig =
-@" {0}|Any CPU = {0}|Any CPU";
-
- const string ProjectPlatformsConfig =
-@" {{{0}}}.{1}|Any CPU.ActiveCfg = {1}|Any CPU
- {{{0}}}.{1}|Any CPU.Build.0 = {1}|Any CPU";
-
public static void MigrateFromOldConfigNames(string slnPath)
{
if (!File.Exists(slnPath))
return;
- var input = File.ReadAllText(slnPath);
+ string input = File.ReadAllText(slnPath);
if (!Regex.IsMatch(input, Regex.Escape("Tools|Any CPU")))
return;
@@ -150,8 +150,8 @@ EndProject";
{"Tools|Any CPU", "ExportRelease|Any CPU"}
};
- var regex = new Regex(string.Join("|",dict.Keys.Select(Regex.Escape)));
- var result = regex.Replace(input,m => dict[m.Value]);
+ var regex = new Regex(string.Join("|", dict.Keys.Select(Regex.Escape)));
+ string result = regex.Replace(input, m => dict[m.Value]);
if (result != input)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/IdentifierUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/IdentifierUtils.cs
index ed77076df3..31363df9ef 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/IdentifierUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/IdentifierUtils.cs
@@ -91,7 +91,7 @@ namespace GodotTools.ProjectEditor
return identifier;
}
- static bool IsKeyword(string value, bool anyDoubleUnderscore)
+ private static bool IsKeyword(string value, bool anyDoubleUnderscore)
{
// Identifiers that start with double underscore are meant to be used for reserved keywords.
// Only existing keywords are enforced, but it may be useful to forbid any identifier
@@ -103,14 +103,14 @@ namespace GodotTools.ProjectEditor
}
else
{
- if (DoubleUnderscoreKeywords.Contains(value))
+ if (_doubleUnderscoreKeywords.Contains(value))
return true;
}
- return Keywords.Contains(value);
+ return _keywords.Contains(value);
}
- private static readonly HashSet<string> DoubleUnderscoreKeywords = new HashSet<string>
+ private static readonly HashSet<string> _doubleUnderscoreKeywords = new HashSet<string>
{
"__arglist",
"__makeref",
@@ -118,7 +118,7 @@ namespace GodotTools.ProjectEditor
"__refvalue",
};
- private static readonly HashSet<string> Keywords = new HashSet<string>
+ private static readonly HashSet<string> _keywords = new HashSet<string>
{
"as",
"do",
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
index 4e2c0f17cc..cdac9acb25 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
@@ -1,11 +1,5 @@
using System;
-using GodotTools.Core;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
using Microsoft.Build.Construction;
-using Microsoft.Build.Globbing;
namespace GodotTools.ProjectEditor
{
@@ -31,47 +25,6 @@ namespace GodotTools.ProjectEditor
return root != null ? new MSBuildProject(root) : null;
}
- private static List<string> GetAllFilesRecursive(string rootDirectory, string mask)
- {
- string[] files = Directory.GetFiles(rootDirectory, mask, SearchOption.AllDirectories);
-
- // We want relative paths
- for (int i = 0; i < files.Length; i++)
- {
- files[i] = files[i].RelativeToPath(rootDirectory);
- }
-
- return new List<string>(files);
- }
-
- // NOTE: Assumes auto-including items. Only used by the scripts metadata generator, which will be replaced with source generators in the future.
- public static IEnumerable<string> GetIncludeFiles(string projectPath, string itemType)
- {
- var excluded = new List<string>();
- var includedFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs");
-
- var root = ProjectRootElement.Open(projectPath);
- Debug.Assert(root != null);
-
- foreach (var item in root.Items)
- {
- if (string.IsNullOrEmpty(item.Condition))
- continue;
-
- if (item.ItemType != itemType)
- continue;
-
- string normalizedRemove = item.Remove.NormalizePath();
-
- var glob = MSBuildGlob.Parse(normalizedRemove);
- excluded.AddRange(includedFiles.Where(includedFile => glob.IsMatch(includedFile)));
- }
-
- includedFiles.RemoveAll(f => excluded.Contains(f));
-
- return includedFiles;
- }
-
public static void MigrateToProjectSdksStyle(MSBuildProject project, string projectName)
{
var origRoot = project.Root;
diff --git a/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
index 1d382dcb43..aab2d73bdd 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
+++ b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
@@ -3,7 +3,6 @@
<Target Name="SetPropertiesForGenerateGodotNupkgsVersions">
<PropertyGroup>
- <GodotNETSdkPackageVersionFile>$(SolutionDir)..\Godot.NET.Sdk\Godot.NET.Sdk\Godot.NET.Sdk_PackageVersion.txt</GodotNETSdkPackageVersionFile>
<GeneratedGodotNupkgsVersionsFile>$(IntermediateOutputPath)GodotNupkgsVersions.g.cs</GeneratedGodotNupkgsVersionsFile>
</PropertyGroup>
</Target>
@@ -18,13 +17,14 @@
</Target>
<Target Name="_GenerateGodotNupkgsVersionsFile"
DependsOnTargets="SetPropertiesForGenerateGodotNupkgsVersions"
- Inputs="$(MSBuildProjectFile);@(GodotNETSdkPackageVersionFile)"
+ Inputs="$(MSBuildProjectFile);$(MSBuildThisFileDirectory);$(MSBuildProjectFile)\..\..\..\SdkPackageVersions.props"
Outputs="$(GeneratedGodotNupkgsVersionsFile)">
<PropertyGroup>
<GenerateGodotNupkgsVersionsCode><![CDATA[
namespace $(RootNamespace) {
public class GeneratedGodotNupkgsVersions {
- public const string GodotNETSdk = "$([System.IO.File]::ReadAllText('$(GodotNETSdkPackageVersionFile)').Trim())"%3b
+ public const string GodotNETSdk = "$(PackageVersion_Godot_NET_Sdk)"%3b
+ public const string GodotSourceGenerators = "$(PackageVersion_Godot_SourceGenerators)"%3b
}
}
]]></GenerateGodotNupkgsVersionsCode>
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
index 51055dc9b9..28bf57dc21 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
@@ -7,13 +7,14 @@ using Path = System.IO.Path;
namespace GodotTools.Build
{
[Serializable]
- public sealed class BuildInfo : Reference // TODO Remove Reference once we have proper serialization
+ public sealed class BuildInfo : RefCounted // TODO Remove RefCounted once we have proper serialization
{
public string Solution { get; }
public string[] Targets { get; }
public string Configuration { get; }
public bool Restore { get; }
- public Array<string> CustomProperties { get; } = new Array<string>(); // TODO Use List once we have proper serialization
+ // TODO Use List once we have proper serialization
+ public Array<string> CustomProperties { get; } = new Array<string>();
public string LogsDirPath => Path.Combine(GodotSharpDirs.BuildLogsDirs, $"{Solution.MD5Text()}_{Configuration}");
@@ -32,12 +33,12 @@ namespace GodotTools.Build
unchecked
{
int hash = 17;
- hash = hash * 29 + Solution.GetHashCode();
- hash = hash * 29 + Targets.GetHashCode();
- hash = hash * 29 + Configuration.GetHashCode();
- hash = hash * 29 + Restore.GetHashCode();
- hash = hash * 29 + CustomProperties.GetHashCode();
- hash = hash * 29 + LogsDirPath.GetHashCode();
+ hash = (hash * 29) + Solution.GetHashCode();
+ hash = (hash * 29) + Targets.GetHashCode();
+ hash = (hash * 29) + Configuration.GetHashCode();
+ hash = (hash * 29) + Restore.GetHashCode();
+ hash = (hash * 29) + CustomProperties.GetHashCode();
+ hash = (hash * 29) + LogsDirPath.GetHashCode();
return hash;
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
index b96b0c8175..21bff70b15 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
@@ -32,7 +32,7 @@ namespace GodotTools.Build
private static void RemoveOldIssuesFile(BuildInfo buildInfo)
{
- var issuesFile = GetIssuesFilePath(buildInfo);
+ string issuesFile = GetIssuesFilePath(buildInfo);
if (!File.Exists(issuesFile))
return;
@@ -218,43 +218,12 @@ namespace GodotTools.Build
Godot.GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
}
- GenerateEditorScriptMetadata();
-
if (GodotSharpEditor.Instance.SkipBuildBeforePlaying)
return true; // Requested play from an external editor/IDE which already built the project
return BuildProjectBlocking("Debug");
}
- // NOTE: This will be replaced with C# source generators in 4.0
- public static void GenerateEditorScriptMetadata()
- {
- string editorScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor");
- string playerScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor_player");
-
- CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, editorScriptsMetadataPath);
-
- if (!File.Exists(editorScriptsMetadataPath))
- return;
-
- try
- {
- File.Copy(editorScriptsMetadataPath, playerScriptsMetadataPath);
- }
- catch (IOException e)
- {
- throw new IOException("Failed to copy scripts metadata file.", innerException: e);
- }
- }
-
- // NOTE: This will be replaced with C# source generators in 4.0
- public static string GenerateExportedGameScriptMetadata(bool isDebug)
- {
- string scriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, $"scripts_metadata.{(isDebug ? "debug" : "release")}");
- CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, scriptsMetadataPath);
- return scriptsMetadataPath;
- }
-
public static void Initialize()
{
// Build tool settings
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
index 1a1639aac7..b53347fc4c 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
@@ -11,7 +11,7 @@ namespace GodotTools.Build
public class BuildOutputView : VBoxContainer, ISerializationListener
{
[Serializable]
- private class BuildIssue : Reference // TODO Remove Reference once we have proper serialization
+ private class BuildIssue : RefCounted // TODO Remove RefCounted once we have proper serialization
{
public bool Warning { get; set; }
public string File { get; set; }
@@ -22,14 +22,6 @@ namespace GodotTools.Build
public string ProjectFile { get; set; }
}
- private readonly Array<BuildIssue> issues = new Array<BuildIssue>(); // TODO Use List once we have proper serialization
- private ItemList issuesList;
- private TextEdit buildLog;
- private PopupMenu issuesListContextMenu;
-
- private readonly object pendingBuildLogTextLock = new object();
- [NotNull] private string pendingBuildLogText = string.Empty;
-
[Signal] public event Action BuildStateChanged;
public bool HasBuildExited { get; private set; } = false;
@@ -60,13 +52,21 @@ namespace GodotTools.Build
}
}
- private BuildInfo BuildInfo { get; set; }
-
public bool LogVisible
{
- set => buildLog.Visible = value;
+ set => _buildLog.Visible = value;
}
+ // TODO Use List once we have proper serialization.
+ private readonly Array<BuildIssue> _issues = new Array<BuildIssue>();
+ private ItemList _issuesList;
+ private PopupMenu _issuesListContextMenu;
+ private TextEdit _buildLog;
+ private BuildInfo _buildInfo;
+
+ private readonly object _pendingBuildLogTextLock = new object();
+ [NotNull] private string _pendingBuildLogText = string.Empty;
+
private void LoadIssuesFromFile(string csvFile)
{
using (var file = new Godot.File())
@@ -107,7 +107,7 @@ namespace GodotTools.Build
else
ErrorCount += 1;
- issues.Add(issue);
+ _issues.Add(issue);
}
}
finally
@@ -119,21 +119,21 @@ namespace GodotTools.Build
private void IssueActivated(int idx)
{
- if (idx < 0 || idx >= issuesList.GetItemCount())
+ if (idx < 0 || idx >= _issuesList.GetItemCount())
throw new IndexOutOfRangeException("Item list index out of range");
// Get correct issue idx from issue list
- int issueIndex = (int)(long)issuesList.GetItemMetadata(idx);
+ int issueIndex = (int)(long)_issuesList.GetItemMetadata(idx);
- if (issueIndex < 0 || issueIndex >= issues.Count)
+ if (issueIndex < 0 || issueIndex >= _issues.Count)
throw new IndexOutOfRangeException("Issue index out of range");
- BuildIssue issue = issues[issueIndex];
+ BuildIssue issue = _issues[issueIndex];
if (string.IsNullOrEmpty(issue.ProjectFile) && string.IsNullOrEmpty(issue.File))
return;
- string projectDir = issue.ProjectFile.Length > 0 ? issue.ProjectFile.GetBaseDir() : BuildInfo.Solution.GetBaseDir();
+ string projectDir = issue.ProjectFile.Length > 0 ? issue.ProjectFile.GetBaseDir() : _buildInfo.Solution.GetBaseDir();
string file = Path.Combine(projectDir.SimplifyGodotPath(), issue.File.SimplifyGodotPath());
@@ -153,14 +153,14 @@ namespace GodotTools.Build
public void UpdateIssuesList()
{
- issuesList.Clear();
+ _issuesList.Clear();
using (var warningIcon = GetThemeIcon("Warning", "EditorIcons"))
using (var errorIcon = GetThemeIcon("Error", "EditorIcons"))
{
- for (int i = 0; i < issues.Count; i++)
+ for (int i = 0; i < _issues.Count; i++)
{
- BuildIssue issue = issues[i];
+ BuildIssue issue = _issues[i];
if (!(issue.Warning ? WarningsVisible : ErrorsVisible))
continue;
@@ -191,11 +191,11 @@ namespace GodotTools.Build
int lineBreakIdx = text.IndexOf("\n", StringComparison.Ordinal);
string itemText = lineBreakIdx == -1 ? text : text.Substring(0, lineBreakIdx);
- issuesList.AddItem(itemText, issue.Warning ? warningIcon : errorIcon);
+ _issuesList.AddItem(itemText, issue.Warning ? warningIcon : errorIcon);
- int index = issuesList.GetItemCount() - 1;
- issuesList.SetItemTooltip(index, tooltip);
- issuesList.SetItemMetadata(index, i);
+ int index = _issuesList.GetItemCount() - 1;
+ _issuesList.SetItemTooltip(index, tooltip);
+ _issuesList.SetItemMetadata(index, i);
}
}
}
@@ -205,12 +205,12 @@ namespace GodotTools.Build
HasBuildExited = true;
BuildResult = Build.BuildResult.Error;
- issuesList.Clear();
+ _issuesList.Clear();
var issue = new BuildIssue {Message = cause, Warning = false};
ErrorCount += 1;
- issues.Add(issue);
+ _issues.Add(issue);
UpdateIssuesList();
@@ -219,13 +219,13 @@ namespace GodotTools.Build
private void BuildStarted(BuildInfo buildInfo)
{
- BuildInfo = buildInfo;
+ _buildInfo = buildInfo;
HasBuildExited = false;
- issues.Clear();
+ _issues.Clear();
WarningCount = 0;
ErrorCount = 0;
- buildLog.Text = string.Empty;
+ _buildLog.Text = string.Empty;
UpdateIssuesList();
@@ -237,7 +237,7 @@ namespace GodotTools.Build
HasBuildExited = true;
BuildResult = result;
- LoadIssuesFromFile(Path.Combine(BuildInfo.LogsDirPath, BuildManager.MsBuildIssuesFileName));
+ LoadIssuesFromFile(Path.Combine(_buildInfo.LogsDirPath, BuildManager.MsBuildIssuesFileName));
UpdateIssuesList();
@@ -246,46 +246,46 @@ namespace GodotTools.Build
private void UpdateBuildLogText()
{
- lock (pendingBuildLogTextLock)
+ lock (_pendingBuildLogTextLock)
{
- buildLog.Text += pendingBuildLogText;
- pendingBuildLogText = string.Empty;
+ _buildLog.Text += _pendingBuildLogText;
+ _pendingBuildLogText = string.Empty;
ScrollToLastNonEmptyLogLine();
}
}
private void StdOutputReceived(string text)
{
- lock (pendingBuildLogTextLock)
+ lock (_pendingBuildLogTextLock)
{
- if (pendingBuildLogText.Length == 0)
+ if (_pendingBuildLogText.Length == 0)
CallDeferred(nameof(UpdateBuildLogText));
- pendingBuildLogText += text + "\n";
+ _pendingBuildLogText += text + "\n";
}
}
private void StdErrorReceived(string text)
{
- lock (pendingBuildLogTextLock)
+ lock (_pendingBuildLogTextLock)
{
- if (pendingBuildLogText.Length == 0)
+ if (_pendingBuildLogText.Length == 0)
CallDeferred(nameof(UpdateBuildLogText));
- pendingBuildLogText += text + "\n";
+ _pendingBuildLogText += text + "\n";
}
}
private void ScrollToLastNonEmptyLogLine()
{
int line;
- for (line = buildLog.GetLineCount(); line > 0; line--)
+ for (line = _buildLog.GetLineCount(); line > 0; line--)
{
- string lineText = buildLog.GetLine(line);
+ string lineText = _buildLog.GetLine(line);
if (!string.IsNullOrEmpty(lineText) || !string.IsNullOrEmpty(lineText?.Trim()))
break;
}
- buildLog.CursorSetLine(line);
+ _buildLog.SetCaretLine(line);
}
public void RestartBuild()
@@ -318,11 +318,11 @@ namespace GodotTools.Build
// We don't allow multi-selection but just in case that changes later...
string text = null;
- foreach (int issueIndex in issuesList.GetSelectedItems())
+ foreach (int issueIndex in _issuesList.GetSelectedItems())
{
if (text != null)
text += "\n";
- text += issuesList.GetItemText(issueIndex);
+ text += _issuesList.GetItemText(issueIndex);
}
if (text != null)
@@ -338,20 +338,20 @@ namespace GodotTools.Build
{
_ = index; // Unused
- issuesListContextMenu.Clear();
- issuesListContextMenu.Size = new Vector2i(1, 1);
+ _issuesListContextMenu.Clear();
+ _issuesListContextMenu.Size = new Vector2i(1, 1);
- if (issuesList.IsAnythingSelected())
+ if (_issuesList.IsAnythingSelected())
{
// Add menu entries for the selected item
- issuesListContextMenu.AddIconItem(GetThemeIcon("ActionCopy", "EditorIcons"),
+ _issuesListContextMenu.AddIconItem(GetThemeIcon("ActionCopy", "EditorIcons"),
label: "Copy Error".TTR(), (int)IssuesContextMenuOption.Copy);
}
- if (issuesListContextMenu.GetItemCount() > 0)
+ if (_issuesListContextMenu.GetItemCount() > 0)
{
- issuesListContextMenu.Position = (Vector2i)(issuesList.RectGlobalPosition + atPosition);
- issuesListContextMenu.Popup();
+ _issuesListContextMenu.Position = (Vector2i)(_issuesList.RectGlobalPosition + atPosition);
+ _issuesListContextMenu.Popup();
}
}
@@ -368,27 +368,27 @@ namespace GodotTools.Build
};
AddChild(hsc);
- issuesList = new ItemList
+ _issuesList = new ItemList
{
SizeFlagsVertical = (int)SizeFlags.ExpandFill,
SizeFlagsHorizontal = (int)SizeFlags.ExpandFill // Avoid being squashed by the build log
};
- issuesList.ItemActivated += IssueActivated;
- issuesList.AllowRmbSelect = true;
- issuesList.ItemRmbSelected += IssuesListRmbSelected;
- hsc.AddChild(issuesList);
+ _issuesList.ItemActivated += IssueActivated;
+ _issuesList.AllowRmbSelect = true;
+ _issuesList.ItemRmbSelected += IssuesListRmbSelected;
+ hsc.AddChild(_issuesList);
- issuesListContextMenu = new PopupMenu();
- issuesListContextMenu.IdPressed += IssuesListContextOptionPressed;
- issuesList.AddChild(issuesListContextMenu);
+ _issuesListContextMenu = new PopupMenu();
+ _issuesListContextMenu.IdPressed += IssuesListContextOptionPressed;
+ _issuesList.AddChild(_issuesListContextMenu);
- buildLog = new TextEdit
+ _buildLog = new TextEdit
{
- Readonly = true,
+ Editable = false,
SizeFlagsVertical = (int)SizeFlags.ExpandFill,
SizeFlagsHorizontal = (int)SizeFlags.ExpandFill // Avoid being squashed by the issues list
};
- hsc.AddChild(buildLog);
+ hsc.AddChild(_buildLog);
AddBuildEventListeners();
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
index 708ec73454..e9cf7911be 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
@@ -11,9 +11,10 @@ namespace GodotTools.Build
{
public BuildOutputView BuildOutputView { get; private set; }
- private Button errorsBtn;
- private Button warningsBtn;
- private Button viewLogBtn;
+ private MenuButton _buildMenuBtn;
+ private Button _errorsBtn;
+ private Button _warningsBtn;
+ private Button _viewLogBtn;
private void WarningsToggled(bool pressed)
{
@@ -43,8 +44,6 @@ namespace GodotTools.Build
GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
}
- BuildManager.GenerateEditorScriptMetadata();
-
if (!BuildManager.BuildProjectBlocking("Debug"))
return; // Build failed
@@ -74,9 +73,7 @@ namespace GodotTools.Build
GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
}
- BuildManager.GenerateEditorScriptMetadata();
-
- if (!BuildManager.BuildProjectBlocking("Debug", targets: new[] {"Rebuild"}))
+ if (!BuildManager.BuildProjectBlocking("Debug", targets: new[] { "Rebuild" }))
return; // Build failed
// Notify running game for hot-reload
@@ -95,7 +92,7 @@ namespace GodotTools.Build
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
return; // No solution to build
- BuildManager.BuildProjectBlocking("Debug", targets: new[] {"Clean"});
+ BuildManager.BuildProjectBlocking("Debug", targets: new[] { "Clean" });
}
private void ViewLogToggled(bool pressed) => BuildOutputView.LogVisible = pressed;
@@ -132,19 +129,19 @@ namespace GodotTools.Build
RectMinSize = new Vector2(0, 228) * EditorScale;
SizeFlagsVertical = (int)SizeFlags.ExpandFill;
- var toolBarHBox = new HBoxContainer {SizeFlagsHorizontal = (int)SizeFlags.ExpandFill};
+ var toolBarHBox = new HBoxContainer { SizeFlagsHorizontal = (int)SizeFlags.ExpandFill };
AddChild(toolBarHBox);
- var buildMenuBtn = new MenuButton {Text = "Build", Icon = GetThemeIcon("Play", "EditorIcons")};
- toolBarHBox.AddChild(buildMenuBtn);
+ _buildMenuBtn = new MenuButton { Text = "Build", Icon = GetThemeIcon("Play", "EditorIcons") };
+ toolBarHBox.AddChild(_buildMenuBtn);
- var buildMenu = buildMenuBtn.GetPopup();
+ var buildMenu = _buildMenuBtn.GetPopup();
buildMenu.AddItem("Build Solution".TTR(), (int)BuildMenuOptions.BuildSolution);
buildMenu.AddItem("Rebuild Solution".TTR(), (int)BuildMenuOptions.RebuildSolution);
buildMenu.AddItem("Clean Solution".TTR(), (int)BuildMenuOptions.CleanSolution);
buildMenu.IdPressed += BuildMenuOptionPressed;
- errorsBtn = new Button
+ _errorsBtn = new Button
{
HintTooltip = "Show Errors".TTR(),
Icon = GetThemeIcon("StatusError", "EditorIcons"),
@@ -153,10 +150,10 @@ namespace GodotTools.Build
Pressed = true,
FocusMode = FocusModeEnum.None
};
- errorsBtn.Toggled += ErrorsToggled;
- toolBarHBox.AddChild(errorsBtn);
+ _errorsBtn.Toggled += ErrorsToggled;
+ toolBarHBox.AddChild(_errorsBtn);
- warningsBtn = new Button
+ _warningsBtn = new Button
{
HintTooltip = "Show Warnings".TTR(),
Icon = GetThemeIcon("NodeWarning", "EditorIcons"),
@@ -165,21 +162,36 @@ namespace GodotTools.Build
Pressed = true,
FocusMode = FocusModeEnum.None
};
- warningsBtn.Toggled += WarningsToggled;
- toolBarHBox.AddChild(warningsBtn);
+ _warningsBtn.Toggled += WarningsToggled;
+ toolBarHBox.AddChild(_warningsBtn);
- viewLogBtn = new Button
+ _viewLogBtn = new Button
{
Text = "Show Output".TTR(),
ToggleMode = true,
Pressed = true,
FocusMode = FocusModeEnum.None
};
- viewLogBtn.Toggled += ViewLogToggled;
- toolBarHBox.AddChild(viewLogBtn);
+ _viewLogBtn.Toggled += ViewLogToggled;
+ toolBarHBox.AddChild(_viewLogBtn);
BuildOutputView = new BuildOutputView();
AddChild(BuildOutputView);
}
+
+ public override void _Notification(int what)
+ {
+ base._Notification(what);
+
+ if (what == NotificationThemeChanged)
+ {
+ if (_buildMenuBtn != null)
+ _buildMenuBtn.Icon = GetThemeIcon("Play", "EditorIcons");
+ if (_errorsBtn != null)
+ _errorsBtn.Icon = GetThemeIcon("StatusError", "EditorIcons");
+ if (_warningsBtn != null)
+ _warningsBtn.Icon = GetThemeIcon("NodeWarning", "EditorIcons");
+ }
+ }
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
index 774c49e705..a859c6f717 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
@@ -61,7 +61,7 @@ namespace GodotTools.Build
}
case BuildTool.JetBrainsMsBuild:
{
- var editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName);
+ string editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName);
if (!File.Exists(editorPath))
throw new FileNotFoundException($"Cannot find Rider executable. Tried with path: {editorPath}");
@@ -165,7 +165,9 @@ namespace GodotTools.Build
// Try to find 15.0 with vswhere
- var envNames = Internal.GodotIs32Bits() ? new[] {"ProgramFiles", "ProgramW6432"} : new[] {"ProgramFiles(x86)", "ProgramFiles"};
+ string[] envNames = Internal.GodotIs32Bits() ?
+ envNames = new[] { "ProgramFiles", "ProgramW6432" } :
+ envNames = new[] { "ProgramFiles(x86)", "ProgramFiles" };
string vsWherePath = null;
foreach (var envName in envNames)
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
index 793ef7fd71..16dd1c8c6b 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
@@ -290,7 +290,8 @@ namespace GodotTools.Build
private static readonly (string packageId, string packageVersion)[] PackagesToAdd =
{
- ("Godot.NET.Sdk", GeneratedGodotNupkgsVersions.GodotNETSdk)
+ ("Godot.NET.Sdk", GeneratedGodotNupkgsVersions.GodotNETSdk),
+ ("Godot.SourceGenerators", GeneratedGodotNupkgsVersions.GodotSourceGenerators),
};
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
index 1d800b8151..e43f10804d 100644
--- a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
@@ -1,11 +1,6 @@
using Godot;
using System;
-using System.Linq;
-using Godot.Collections;
-using GodotTools.Internals;
using GodotTools.ProjectEditor;
-using File = GodotTools.Utils.File;
-using Directory = GodotTools.Utils.Directory;
namespace GodotTools
{
@@ -23,86 +18,5 @@ namespace GodotTools
return string.Empty;
}
}
-
- private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
-
- private static ulong ConvertToTimestamp(this DateTime value)
- {
- TimeSpan elapsedTime = value - Epoch;
- return (ulong)elapsedTime.TotalSeconds;
- }
-
- private static bool TryParseFileMetadata(string includeFile, ulong modifiedTime, out Dictionary fileMetadata)
- {
- fileMetadata = null;
-
- var parseError = ScriptClassParser.ParseFile(includeFile, out var classes, out string errorStr);
-
- if (parseError != Error.Ok)
- {
- GD.PushError($"Failed to determine namespace and class for script: {includeFile}. Parse error: {errorStr ?? parseError.ToString()}");
- return false;
- }
-
- string searchName = System.IO.Path.GetFileNameWithoutExtension(includeFile);
-
- var firstMatch = classes.FirstOrDefault(classDecl =>
- classDecl.BaseCount != 0 && // If it doesn't inherit anything, it can't be a Godot.Object.
- classDecl.SearchName == searchName // Filter by the name we're looking for
- );
-
- if (firstMatch == null)
- return false; // Not found
-
- fileMetadata = new Dictionary
- {
- ["modified_time"] = $"{modifiedTime}",
- ["class"] = new Dictionary
- {
- ["namespace"] = firstMatch.Namespace,
- ["class_name"] = firstMatch.Name,
- ["nested"] = firstMatch.Nested
- }
- };
-
- return true;
- }
-
- public static void GenerateScriptsMetadata(string projectPath, string outputPath)
- {
- var metadataDict = Internal.GetScriptsMetadataOrNothing().Duplicate();
-
- bool IsUpToDate(string includeFile, ulong modifiedTime)
- {
- return metadataDict.TryGetValue(includeFile, out var oldFileVar) &&
- ulong.TryParse(((Dictionary)oldFileVar)["modified_time"] as string,
- out ulong storedModifiedTime) && storedModifiedTime == modifiedTime;
- }
-
- var outdatedFiles = ProjectUtils.GetIncludeFiles(projectPath, "Compile")
- .Select(path => ("res://" + path).SimplifyGodotPath())
- .ToDictionary(path => path, path => File.GetLastWriteTime(path).ConvertToTimestamp())
- .Where(pair => !IsUpToDate(includeFile: pair.Key, modifiedTime: pair.Value))
- .ToArray();
-
- foreach (var pair in outdatedFiles)
- {
- metadataDict.Remove(pair.Key);
-
- string includeFile = pair.Key;
-
- if (TryParseFileMetadata(includeFile, modifiedTime: pair.Value, out var fileMetadata))
- metadataDict[includeFile] = fileMetadata;
- }
-
- string json = metadataDict.Count <= 0 ? "{}" : JSON.Print(metadataDict);
-
- string baseDir = outputPath.GetBaseDir();
-
- if (!Directory.Exists(baseDir))
- Directory.CreateDirectory(baseDir);
-
- File.WriteAllText(outputPath, json);
- }
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
index 5bb8d444c2..37e6a34977 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
@@ -65,12 +65,12 @@ namespace GodotTools.Export
if (platform == OS.Platforms.iOS)
{
- var architectures = GetEnablediOSArchs(features).ToArray();
+ string[] architectures = GetEnablediOSArchs(features).ToArray();
CompileAssembliesForiOS(exporter, isDebug, architectures, aotOpts, aotTempDir, assembliesPrepared, bclDir);
}
else if (platform == OS.Platforms.Android)
{
- var abis = GetEnabledAndroidAbis(features).ToArray();
+ string[] abis = GetEnabledAndroidAbis(features).ToArray();
CompileAssembliesForAndroid(exporter, isDebug, abis, aotOpts, aotTempDir, assembliesPrepared, bclDir);
}
else
@@ -138,7 +138,8 @@ namespace GodotTools.Export
}
else
{
- string outputDataLibDir = Path.Combine(outputDataDir, "Mono", platform == OS.Platforms.Windows ? "bin" : "lib");
+ string libDir = platform == OS.Platforms.Windows ? "bin" : "lib";
+ string outputDataLibDir = Path.Combine(outputDataDir, "Mono", libDir);
File.Copy(tempOutputFilePath, Path.Combine(outputDataLibDir, outputFileName));
}
}
@@ -577,27 +578,27 @@ MONO_AOT_MODE_LAST = 1000,
{
case OS.Platforms.Windows:
case OS.Platforms.UWP:
- {
- string arch = bits == "64" ? "x86_64" : "i686";
- return $"windows-{arch}";
- }
+ {
+ string arch = bits == "64" ? "x86_64" : "i686";
+ return $"windows-{arch}";
+ }
case OS.Platforms.MacOS:
- {
- Debug.Assert(bits == null || bits == "64");
- string arch = "x86_64";
- return $"{platform}-{arch}";
- }
+ {
+ Debug.Assert(bits == null || bits == "64");
+ string arch = "x86_64";
+ return $"{platform}-{arch}";
+ }
case OS.Platforms.LinuxBSD:
case OS.Platforms.Server:
- {
- string arch = bits == "64" ? "x86_64" : "i686";
- return $"linux-{arch}";
- }
+ {
+ string arch = bits == "64" ? "x86_64" : "i686";
+ return $"linux-{arch}";
+ }
case OS.Platforms.Haiku:
- {
- string arch = bits == "64" ? "x86_64" : "i686";
- return $"{platform}-{arch}";
- }
+ {
+ string arch = bits == "64" ? "x86_64" : "i686";
+ return $"{platform}-{arch}";
+ }
default:
throw new NotSupportedException($"Platform not supported: {platform}");
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index e9bb701562..3e46a89b7c 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -20,7 +20,7 @@ namespace GodotTools.Export
public class ExportPlugin : EditorExportPlugin
{
[Flags]
- enum I18NCodesets : long
+ private enum I18NCodesets : long
{
None = 0,
CJK = 1,
@@ -31,6 +31,8 @@ namespace GodotTools.Export
All = CJK | MidEast | Other | Rare | West
}
+ private string _maybeLastExportError;
+
private void AddI18NAssemblies(Godot.Collections.Dictionary<string, string> assemblies, string bclDir)
{
var codesets = (I18NCodesets)ProjectSettings.GetSetting("mono/export/i18n_codesets");
@@ -76,15 +78,13 @@ namespace GodotTools.Export
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", new string[] { });
+ 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", new string[] { });
+ GlobalDef("mono/export/aot/extra_optimizer_options", Array.Empty<string>());
GlobalDef("mono/export/aot/android_toolchain_path", "");
}
- private string maybeLastExportError;
-
private void AddFile(string srcPath, string dstPath, bool remap = false)
{
// Add file to the PCK
@@ -129,14 +129,14 @@ namespace GodotTools.Export
}
catch (Exception e)
{
- maybeLastExportError = e.Message;
+ _maybeLastExportError = e.Message;
// 'maybeLastExportError' cannot be null or empty if there was an error, so we
// must consider the possibility of exceptions being thrown without a message.
- if (string.IsNullOrEmpty(maybeLastExportError))
- maybeLastExportError = $"Exception thrown: {e.GetType().Name}";
+ if (string.IsNullOrEmpty(_maybeLastExportError))
+ _maybeLastExportError = $"Exception thrown: {e.GetType().Name}";
- GD.PushError($"Failed to export project: {maybeLastExportError}");
+ GD.PushError($"Failed to export project: {_maybeLastExportError}");
Console.Error.WriteLine(e);
// TODO: Do something on error once _ExportBegin supports failing.
}
@@ -157,9 +157,6 @@ namespace GodotTools.Export
string buildConfig = isDebug ? "ExportDebug" : "ExportRelease";
- string scriptsMetadataPath = BuildManager.GenerateExportedGameScriptMetadata(isDebug);
- AddFile(scriptsMetadataPath, scriptsMetadataPath);
-
if (!BuildManager.BuildProjectBlocking(buildConfig, platform: platform))
throw new Exception("Failed to build project");
@@ -191,7 +188,7 @@ namespace GodotTools.Export
// However, at least in the case of 'WebAssembly.Net.Http' for some reason the BCL assemblies
// reference a different version even though the assembly is the same, for some weird reason.
- var wasmFrameworkAssemblies = new[] {"WebAssembly.Bindings", "WebAssembly.Net.WebSockets"};
+ var wasmFrameworkAssemblies = new[] { "WebAssembly.Bindings", "WebAssembly.Net.WebSockets" };
foreach (string thisWasmFrameworkAssemblyName in wasmFrameworkAssemblies)
{
@@ -301,8 +298,8 @@ namespace GodotTools.Export
LLVMOutputPath = "",
FullAot = platform == OS.Platforms.iOS || (bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false),
UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"),
- ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? new string[] { },
- ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? new string[] { },
+ ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? Array.Empty<string>(),
+ ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? Array.Empty<string>(),
ToolchainPath = aotToolchainPath
};
@@ -320,10 +317,10 @@ namespace GodotTools.Export
Directory.Delete(aotTempDir, recursive: true);
// TODO: Just a workaround until the export plugins can be made to abort with errors
- if (!string.IsNullOrEmpty(maybeLastExportError)) // Check empty as well, because it's set to empty after hot-reloading
+ if (!string.IsNullOrEmpty(_maybeLastExportError)) // Check empty as well, because it's set to empty after hot-reloading
{
- string lastExportError = maybeLastExportError;
- maybeLastExportError = null;
+ string lastExportError = _maybeLastExportError;
+ _maybeLastExportError = null;
GodotSharpEditor.Instance.ShowErrorDialog(lastExportError, "Failed to export C# project");
}
@@ -384,7 +381,7 @@ namespace GodotTools.Export
private static bool PlatformHasTemplateDir(string platform)
{
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
- return !new[] {OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform);
+ return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform);
}
private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform)
@@ -433,7 +430,7 @@ namespace GodotTools.Export
/// </summary>
private static bool PlatformRequiresCustomBcl(string platform)
{
- if (new[] {OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform))
+ if (new[] { OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform))
return true;
// The 'net_4_x' BCL is not compatible between Windows and the other platforms.
@@ -473,7 +470,7 @@ namespace GodotTools.Export
private static string DetermineDataDirNameForProject()
{
- var appName = (string)ProjectSettings.GetSetting("application/config/name");
+ string appName = (string)ProjectSettings.GetSetting("application/config/name");
string appNameSafe = appName.ToSafeDirName();
return $"data_{appNameSafe}";
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 58561c5097..98c6881166 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -21,20 +21,19 @@ namespace GodotTools
{
public class GodotSharpEditor : EditorPlugin, ISerializationListener
{
- private EditorSettings editorSettings;
+ private EditorSettings _editorSettings;
- private PopupMenu menuPopup;
+ private PopupMenu _menuPopup;
- private AcceptDialog errorDialog;
- private AcceptDialog aboutDialog;
- private CheckBox aboutDialogCheckBox;
+ private AcceptDialog _errorDialog;
- private Button bottomPanelBtn;
- private Button toolBarBuildButton;
+ private Button _bottomPanelBtn;
+ private Button _toolBarBuildButton;
- public GodotIdeManager GodotIdeManager { get; private set; }
+ // TODO Use WeakReference once we have proper serialization.
+ private WeakRef _exportPluginWeak;
- private WeakRef exportPluginWeak; // TODO Use WeakReference once we have proper serialization
+ public GodotIdeManager GodotIdeManager { get; private set; }
public MSBuildPanel MSBuildPanel { get; private set; }
@@ -44,7 +43,7 @@ namespace GodotTools
{
get
{
- var projectAssemblyName = (string)ProjectSettings.GetSetting("application/config/name");
+ string projectAssemblyName = (string)ProjectSettings.GetSetting("application/config/name");
projectAssemblyName = projectAssemblyName.ToSafeDirName();
if (string.IsNullOrEmpty(projectAssemblyName))
projectAssemblyName = "UnnamedProject";
@@ -125,16 +124,9 @@ namespace GodotTools
private void _RemoveCreateSlnMenuOption()
{
- menuPopup.RemoveItem(menuPopup.GetItemIndex((int)MenuOptions.CreateSln));
- bottomPanelBtn.Show();
- toolBarBuildButton.Show();
- }
-
- private void _ShowAboutDialog()
- {
- bool showOnStart = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
- aboutDialogCheckBox.Pressed = showOnStart;
- aboutDialog.PopupCentered();
+ _menuPopup.RemoveItem(_menuPopup.GetItemIndex((int)MenuOptions.CreateSln));
+ _bottomPanelBtn.Show();
+ _toolBarBuildButton.Show();
}
private void _MenuOptionPressed(int id)
@@ -144,9 +136,6 @@ namespace GodotTools
case MenuOptions.CreateSln:
CreateProjectSolution();
break;
- case MenuOptions.AboutCSharp:
- _ShowAboutDialog();
- break;
case MenuOptions.SetupGodotNugetFallbackFolder:
{
try
@@ -183,29 +172,19 @@ namespace GodotTools
base._Ready();
MSBuildPanel.BuildOutputView.BuildStateChanged += BuildStateChanged;
-
- bool showInfoDialog = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
- if (showInfoDialog)
- {
- aboutDialog.Exclusive = true;
- _ShowAboutDialog();
- // Once shown a first time, it can be seen again via the Mono menu - it doesn't have to be exclusive from that time on.
- aboutDialog.Exclusive = false;
- }
}
private enum MenuOptions
{
CreateSln,
- AboutCSharp,
SetupGodotNugetFallbackFolder,
}
public void ShowErrorDialog(string message, string title = "Error")
{
- errorDialog.Title = title;
- errorDialog.DialogText = message;
- errorDialog.PopupCentered();
+ _errorDialog.Title = title;
+ _errorDialog.DialogText = message;
+ _errorDialog.PopupCentered();
}
private static string _vsCodePath = string.Empty;
@@ -218,7 +197,7 @@ namespace GodotTools
[UsedImplicitly]
public Error OpenInExternalEditor(Script script, int line, int col)
{
- var editorId = (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor");
+ var editorId = (ExternalEditorId)_editorSettings.GetSetting("mono/editor/external_editor");
switch (editorId)
{
@@ -309,7 +288,7 @@ namespace GodotTools
}
}
- var resourcePath = ProjectSettings.GlobalizePath("res://");
+ string resourcePath = ProjectSettings.GlobalizePath("res://");
args.Add(resourcePath);
string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath);
@@ -368,10 +347,10 @@ namespace GodotTools
[UsedImplicitly]
public bool OverridesExternalEditor()
{
- return (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor") != ExternalEditorId.None;
+ return (ExternalEditorId)_editorSettings.GetSetting("mono/editor/external_editor") != ExternalEditorId.None;
}
- public override bool Build()
+ public override bool _Build()
{
return BuildManager.EditorBuildCallback();
}
@@ -409,13 +388,13 @@ namespace GodotTools
private void BuildStateChanged()
{
- if (bottomPanelBtn != null)
- bottomPanelBtn.Icon = MSBuildPanel.BuildOutputView.BuildStateIcon;
+ if (_bottomPanelBtn != null)
+ _bottomPanelBtn.Icon = MSBuildPanel.BuildOutputView.BuildStateIcon;
}
- public override void EnablePlugin()
+ public override void _EnablePlugin()
{
- base.EnablePlugin();
+ base._EnablePlugin();
if (Instance != null)
throw new InvalidOperationException();
@@ -424,80 +403,33 @@ namespace GodotTools
var editorInterface = GetEditorInterface();
var editorBaseControl = editorInterface.GetBaseControl();
- editorSettings = editorInterface.GetEditorSettings();
+ _editorSettings = editorInterface.GetEditorSettings();
- errorDialog = new AcceptDialog();
- editorBaseControl.AddChild(errorDialog);
+ _errorDialog = new AcceptDialog();
+ editorBaseControl.AddChild(_errorDialog);
MSBuildPanel = new MSBuildPanel();
- bottomPanelBtn = AddControlToBottomPanel(MSBuildPanel, "MSBuild".TTR());
+ _bottomPanelBtn = AddControlToBottomPanel(MSBuildPanel, "MSBuild".TTR());
AddChild(new HotReloadAssemblyWatcher {Name = "HotReloadAssemblyWatcher"});
- menuPopup = new PopupMenu();
- menuPopup.Hide();
+ _menuPopup = new PopupMenu();
+ _menuPopup.Hide();
- AddToolSubmenuItem("C#", menuPopup);
+ AddToolSubmenuItem("C#", _menuPopup);
- // TODO: Remove or edit this info dialog once Mono support is no longer in alpha
- {
- menuPopup.AddItem("About C# support".TTR(), (int)MenuOptions.AboutCSharp);
- menuPopup.AddItem("Setup Godot NuGet Offline Packages".TTR(), (int)MenuOptions.SetupGodotNugetFallbackFolder);
- aboutDialog = new AcceptDialog();
- editorBaseControl.AddChild(aboutDialog);
- aboutDialog.Title = "Important: C# support is not feature-complete";
-
- // We don't use DialogText as the default AcceptDialog Label doesn't play well with the TextureRect and CheckBox
- // we'll add. Instead we add containers and a new autowrapped Label inside.
-
- // Main VBoxContainer (icon + label on top, checkbox at bottom)
- var aboutVBox = new VBoxContainer();
- aboutDialog.AddChild(aboutVBox);
-
- // HBoxContainer for icon + label
- var aboutHBox = new HBoxContainer();
- aboutVBox.AddChild(aboutHBox);
-
- var aboutIcon = new TextureRect();
- aboutIcon.Texture = aboutIcon.GetThemeIcon("NodeWarning", "EditorIcons");
- aboutHBox.AddChild(aboutIcon);
-
- var aboutLabel = new Label();
- aboutHBox.AddChild(aboutLabel);
- aboutLabel.RectMinSize = new Vector2(600, 150) * EditorScale;
- aboutLabel.SizeFlagsVertical = (int)Control.SizeFlags.ExpandFill;
- aboutLabel.Autowrap = true;
- aboutLabel.Text =
- "C# support in Godot Engine is in late alpha stage and, while already usable, " +
- "it is not meant for use in production.\n\n" +
- "Projects can be exported to Linux, macOS, Windows, Android, iOS and HTML5, but not yet to UWP. " +
- "Bugs and usability issues will be addressed gradually over future releases, " +
- "potentially including compatibility breaking changes as new features are implemented for a better overall C# experience.\n\n" +
- "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, MSBuild version, IDE, etc.:\n\n" +
- " https://github.com/godotengine/godot/issues\n\n" +
- "Your critical feedback at this stage will play a great role in shaping the C# support in future releases, so thank you!";
-
- EditorDef("mono/editor/show_info_on_start", true);
-
- // CheckBox in main container
- aboutDialogCheckBox = new CheckBox {Text = "Show this warning when starting the editor"};
- aboutDialogCheckBox.Toggled += enabled =>
- {
- bool showOnStart = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
- if (showOnStart != enabled)
- editorSettings.SetSetting("mono/editor/show_info_on_start", enabled);
- };
- aboutVBox.AddChild(aboutDialogCheckBox);
- }
+ var buildSolutionShortcut = (Shortcut)EditorShortcut("mono/build_solution");
- toolBarBuildButton = new Button
+ _toolBarBuildButton = new Button
{
Text = "Build",
- HintTooltip = "Build solution",
- FocusMode = Control.FocusModeEnum.None
+ HintTooltip = "Build Solution".TTR(),
+ FocusMode = Control.FocusModeEnum.None,
+ Shortcut = buildSolutionShortcut,
+ ShortcutInTooltip = true
};
- toolBarBuildButton.PressedSignal += BuildSolutionPressed;
- AddControlToContainer(CustomControlContainer.Toolbar, toolBarBuildButton);
+ _toolBarBuildButton.PressedSignal += BuildSolutionPressed;
+ AddControlToContainer(CustomControlContainer.Toolbar, _toolBarBuildButton);
if (File.Exists(GodotSharpDirs.ProjectSlnPath) && File.Exists(GodotSharpDirs.ProjectCsProjPath))
{
@@ -505,12 +437,12 @@ namespace GodotTools
}
else
{
- bottomPanelBtn.Hide();
- toolBarBuildButton.Hide();
- menuPopup.AddItem("Create C# solution".TTR(), (int)MenuOptions.CreateSln);
+ _bottomPanelBtn.Hide();
+ _toolBarBuildButton.Hide();
+ _menuPopup.AddItem("Create C# solution".TTR(), (int)MenuOptions.CreateSln);
}
- menuPopup.IdPressed += _MenuOptionPressed;
+ _menuPopup.IdPressed += _MenuOptionPressed;
// External editor settings
EditorDef("mono/editor/external_editor", ExternalEditorId.None);
@@ -538,7 +470,7 @@ namespace GodotTools
$",JetBrains Rider:{(int)ExternalEditorId.Rider}";
}
- editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
+ _editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
{
["type"] = Variant.Type.Int,
["name"] = "mono/editor/external_editor",
@@ -550,7 +482,7 @@ namespace GodotTools
var exportPlugin = new ExportPlugin();
AddExportPlugin(exportPlugin);
exportPlugin.RegisterExportSettings();
- exportPluginWeak = WeakRef(exportPlugin);
+ _exportPluginWeak = WeakRef(exportPlugin);
try
{
@@ -573,15 +505,15 @@ namespace GodotTools
{
base.Dispose(disposing);
- if (exportPluginWeak != null)
+ if (_exportPluginWeak != null)
{
// We need to dispose our export plugin before the editor destroys EditorSettings.
// Otherwise, if the GC disposes it at a later time, EditorExportPlatformAndroid
// will be freed after EditorSettings already was, and its device polling thread
// will try to access the EditorSettings singleton, resulting in null dereferencing.
- (exportPluginWeak.GetRef() as ExportPlugin)?.Dispose();
+ (_exportPluginWeak.GetRef() as ExportPlugin)?.Dispose();
- exportPluginWeak.Dispose();
+ _exportPluginWeak.Dispose();
}
GodotIdeManager?.Dispose();
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index 3f14629b11..b9aa760f4d 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -3,7 +3,8 @@
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
<TargetFramework>net472</TargetFramework>
<LangVersion>7.2</LangVersion>
- <GodotApiConfiguration>Debug</GodotApiConfiguration> <!-- The Godot editor uses the Debug Godot API assemblies -->
+ <!-- The Godot editor uses the Debug Godot API assemblies -->
+ <GodotApiConfiguration>Debug</GodotApiConfiguration>
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
<GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
<GodotApiAssembliesDir>$(GodotOutputDataDir)/Api/$(GodotApiConfiguration)</GodotApiAssembliesDir>
diff --git a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
index b30c857c64..dd05f28af0 100644
--- a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
@@ -6,7 +6,7 @@ namespace GodotTools
{
public class HotReloadAssemblyWatcher : Node
{
- private Timer watchTimer;
+ private Timer _watchTimer;
public override void _Notification(int what)
{
@@ -27,22 +27,22 @@ namespace GodotTools
public void RestartTimer()
{
- watchTimer.Stop();
- watchTimer.Start();
+ _watchTimer.Stop();
+ _watchTimer.Start();
}
public override void _Ready()
{
base._Ready();
- watchTimer = new Timer
+ _watchTimer = new Timer
{
OneShot = false,
WaitTime = (float)EditorDef("mono/assembly_watch_interval_sec", 0.5)
};
- watchTimer.Timeout += TimerTimeout;
- AddChild(watchTimer);
- watchTimer.Start();
+ _watchTimer.Timeout += TimerTimeout;
+ AddChild(_watchTimer);
+ _watchTimer.Start();
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
index 451ce39f5c..23339fe50b 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
@@ -10,22 +10,22 @@ namespace GodotTools.Ides
{
public sealed class GodotIdeManager : Node, ISerializationListener
{
- private MessagingServer MessagingServer { get; set; }
+ private MessagingServer _messagingServer;
- private MonoDevelop.Instance monoDevelInstance;
- private MonoDevelop.Instance vsForMacInstance;
+ private MonoDevelop.Instance _monoDevelInstance;
+ private MonoDevelop.Instance _vsForMacInstance;
private MessagingServer GetRunningOrNewServer()
{
- if (MessagingServer != null && !MessagingServer.IsDisposed)
- return MessagingServer;
+ if (_messagingServer != null && !_messagingServer.IsDisposed)
+ return _messagingServer;
- MessagingServer?.Dispose();
- MessagingServer = new MessagingServer(OS.GetExecutablePath(), ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir), new GodotLogger());
+ _messagingServer?.Dispose();
+ _messagingServer = new MessagingServer(OS.GetExecutablePath(), ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir), new GodotLogger());
- _ = MessagingServer.Listen();
+ _ = _messagingServer.Listen();
- return MessagingServer;
+ return _messagingServer;
}
public override void _Ready()
@@ -48,7 +48,7 @@ namespace GodotTools.Ides
if (disposing)
{
- MessagingServer?.Dispose();
+ _messagingServer?.Dispose();
}
}
@@ -113,14 +113,14 @@ namespace GodotTools.Ides
{
if (Utils.OS.IsMacOS && editorId == ExternalEditorId.VisualStudioForMac)
{
- vsForMacInstance = (vsForMacInstance?.IsDisposed ?? true ? null : vsForMacInstance) ??
+ _vsForMacInstance = (_vsForMacInstance?.IsDisposed ?? true ? null : _vsForMacInstance) ??
new MonoDevelop.Instance(solutionPath, MonoDevelop.EditorId.VisualStudioForMac);
- return vsForMacInstance;
+ return _vsForMacInstance;
}
- monoDevelInstance = (monoDevelInstance?.IsDisposed ?? true ? null : monoDevelInstance) ??
+ _monoDevelInstance = (_monoDevelInstance?.IsDisposed ?? true ? null : _monoDevelInstance) ??
new MonoDevelop.Instance(solutionPath, MonoDevelop.EditorId.MonoDevelop);
- return monoDevelInstance;
+ return _monoDevelInstance;
}
try
@@ -159,15 +159,15 @@ namespace GodotTools.Ides
public readonly struct EditorPick
{
- private readonly string identity;
+ private readonly string _identity;
public EditorPick(string identity)
{
- this.identity = identity;
+ _identity = identity;
}
public bool IsAnyConnected() =>
- GodotSharpEditor.Instance.GodotIdeManager.GetRunningOrNewServer().IsAnyConnected(identity);
+ GodotSharpEditor.Instance.GodotIdeManager.GetRunningOrNewServer().IsAnyConnected(_identity);
private void SendRequest<TResponse>(Request request)
where TResponse : Response, new()
@@ -175,7 +175,7 @@ namespace GodotTools.Ides
// Logs an error if no client is connected with the specified identity
GodotSharpEditor.Instance.GodotIdeManager
.GetRunningOrNewServer()
- .BroadcastRequest<TResponse>(identity, request);
+ .BroadcastRequest<TResponse>(_identity, request);
}
public void SendOpenFile(string file)
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs
index eb34a2d0f7..6f11831b80 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs
@@ -21,24 +21,26 @@ namespace GodotTools.Ides
{
public sealed class MessagingServer : IDisposable
{
- private readonly ILogger logger;
+ private readonly ILogger _logger;
- private readonly FileStream metaFile;
- private string MetaFilePath { get; }
+ private readonly FileStream _metaFile;
+ private string _metaFilePath;
- private readonly SemaphoreSlim peersSem = new SemaphoreSlim(1);
+ private readonly SemaphoreSlim _peersSem = new SemaphoreSlim(1);
- private readonly TcpListener listener;
+ private readonly TcpListener _listener;
- private readonly Dictionary<string, Queue<NotifyAwaiter<bool>>> clientConnectedAwaiters = new Dictionary<string, Queue<NotifyAwaiter<bool>>>();
- private readonly Dictionary<string, Queue<NotifyAwaiter<bool>>> clientDisconnectedAwaiters = new Dictionary<string, Queue<NotifyAwaiter<bool>>>();
+ private readonly Dictionary<string, Queue<NotifyAwaiter<bool>>> _clientConnectedAwaiters =
+ new Dictionary<string, Queue<NotifyAwaiter<bool>>>();
+ private readonly Dictionary<string, Queue<NotifyAwaiter<bool>>> _clientDisconnectedAwaiters =
+ new Dictionary<string, Queue<NotifyAwaiter<bool>>>();
public async Task<bool> AwaitClientConnected(string identity)
{
- if (!clientConnectedAwaiters.TryGetValue(identity, out var queue))
+ if (!_clientConnectedAwaiters.TryGetValue(identity, out var queue))
{
queue = new Queue<NotifyAwaiter<bool>>();
- clientConnectedAwaiters.Add(identity, queue);
+ _clientConnectedAwaiters.Add(identity, queue);
}
var awaiter = new NotifyAwaiter<bool>();
@@ -48,10 +50,10 @@ namespace GodotTools.Ides
public async Task<bool> AwaitClientDisconnected(string identity)
{
- if (!clientDisconnectedAwaiters.TryGetValue(identity, out var queue))
+ if (!_clientDisconnectedAwaiters.TryGetValue(identity, out var queue))
{
queue = new Queue<NotifyAwaiter<bool>>();
- clientDisconnectedAwaiters.Add(identity, queue);
+ _clientDisconnectedAwaiters.Add(identity, queue);
}
var awaiter = new NotifyAwaiter<bool>();
@@ -77,7 +79,7 @@ namespace GodotTools.Ides
if (IsDisposed)
return;
- using (await peersSem.UseAsync())
+ using (await _peersSem.UseAsync())
{
if (IsDisposed) // lock may not be fair
return;
@@ -95,19 +97,19 @@ namespace GodotTools.Ides
foreach (var connection in Peers)
connection.Dispose();
Peers.Clear();
- listener?.Stop();
+ _listener?.Stop();
- metaFile?.Dispose();
+ _metaFile?.Dispose();
- File.Delete(MetaFilePath);
+ File.Delete(_metaFilePath);
}
}
public MessagingServer(string editorExecutablePath, string projectMetadataDir, ILogger logger)
{
- this.logger = logger;
+ this._logger = logger;
- MetaFilePath = Path.Combine(projectMetadataDir, GodotIdeMetadata.DefaultFileName);
+ _metaFilePath = Path.Combine(projectMetadataDir, GodotIdeMetadata.DefaultFileName);
// Make sure the directory exists
Directory.CreateDirectory(projectMetadataDir);
@@ -115,13 +117,13 @@ namespace GodotTools.Ides
// The Godot editor's file system thread can keep the file open for writing, so we are forced to allow write sharing...
const FileShare metaFileShare = FileShare.ReadWrite;
- metaFile = File.Open(MetaFilePath, FileMode.Create, FileAccess.Write, metaFileShare);
+ _metaFile = File.Open(_metaFilePath, FileMode.Create, FileAccess.Write, metaFileShare);
- listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, port: 0));
- listener.Start();
+ _listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, port: 0));
+ _listener.Start();
- int port = ((IPEndPoint)listener.Server.LocalEndPoint).Port;
- using (var metaFileWriter = new StreamWriter(metaFile, Encoding.UTF8))
+ int port = ((IPEndPoint)_listener.Server.LocalEndPoint).Port;
+ using (var metaFileWriter = new StreamWriter(_metaFile, Encoding.UTF8))
{
metaFileWriter.WriteLine(port);
metaFileWriter.WriteLine(editorExecutablePath);
@@ -130,30 +132,30 @@ namespace GodotTools.Ides
private async Task AcceptClient(TcpClient tcpClient)
{
- logger.LogDebug("Accept client...");
+ _logger.LogDebug("Accept client...");
- using (var peer = new Peer(tcpClient, new ServerHandshake(), new ServerMessageHandler(), logger))
+ using (var peer = new Peer(tcpClient, new ServerHandshake(), new ServerMessageHandler(), _logger))
{
// ReSharper disable AccessToDisposedClosure
peer.Connected += () =>
{
- logger.LogInfo("Connection open with Ide Client");
+ _logger.LogInfo("Connection open with Ide Client");
- if (clientConnectedAwaiters.TryGetValue(peer.RemoteIdentity, out var queue))
+ if (_clientConnectedAwaiters.TryGetValue(peer.RemoteIdentity, out var queue))
{
while (queue.Count > 0)
queue.Dequeue().SetResult(true);
- clientConnectedAwaiters.Remove(peer.RemoteIdentity);
+ _clientConnectedAwaiters.Remove(peer.RemoteIdentity);
}
};
peer.Disconnected += () =>
{
- if (clientDisconnectedAwaiters.TryGetValue(peer.RemoteIdentity, out var queue))
+ if (_clientDisconnectedAwaiters.TryGetValue(peer.RemoteIdentity, out var queue))
{
while (queue.Count > 0)
queue.Dequeue().SetResult(true);
- clientDisconnectedAwaiters.Remove(peer.RemoteIdentity);
+ _clientDisconnectedAwaiters.Remove(peer.RemoteIdentity);
}
};
// ReSharper restore AccessToDisposedClosure
@@ -162,17 +164,17 @@ namespace GodotTools.Ides
{
if (!await peer.DoHandshake("server"))
{
- logger.LogError("Handshake failed");
+ _logger.LogError("Handshake failed");
return;
}
}
catch (Exception e)
{
- logger.LogError("Handshake failed with unhandled exception: ", e);
+ _logger.LogError("Handshake failed with unhandled exception: ", e);
return;
}
- using (await peersSem.UseAsync())
+ using (await _peersSem.UseAsync())
Peers.Add(peer);
try
@@ -181,7 +183,7 @@ namespace GodotTools.Ides
}
finally
{
- using (await peersSem.UseAsync())
+ using (await _peersSem.UseAsync())
Peers.Remove(peer);
}
}
@@ -192,7 +194,7 @@ namespace GodotTools.Ides
try
{
while (!IsDisposed)
- _ = AcceptClient(await listener.AcceptTcpClientAsync());
+ _ = AcceptClient(await _listener.AcceptTcpClientAsync());
}
catch (Exception e)
{
@@ -204,11 +206,11 @@ namespace GodotTools.Ides
public async void BroadcastRequest<TResponse>(string identity, Request request)
where TResponse : Response, new()
{
- using (await peersSem.UseAsync())
+ using (await _peersSem.UseAsync())
{
if (!IsAnyConnected(identity))
{
- logger.LogError("Cannot write request. No client connected to the Godot Ide Server.");
+ _logger.LogError("Cannot write request. No client connected to the Godot Ide Server.");
return;
}
@@ -225,16 +227,19 @@ namespace GodotTools.Ides
private class ServerHandshake : IHandshake
{
- private static readonly string ServerHandshakeBase = $"{Peer.ServerHandshakeName},Version={Peer.ProtocolVersionMajor}.{Peer.ProtocolVersionMinor}.{Peer.ProtocolVersionRevision}";
- private static readonly string ClientHandshakePattern = $@"{Regex.Escape(Peer.ClientHandshakeName)},Version=([0-9]+)\.([0-9]+)\.([0-9]+),([_a-zA-Z][_a-zA-Z0-9]{{0,63}})";
+ private static readonly string _serverHandshakeBase =
+ $"{Peer.ServerHandshakeName},Version={Peer.ProtocolVersionMajor}.{Peer.ProtocolVersionMinor}.{Peer.ProtocolVersionRevision}";
- public string GetHandshakeLine(string identity) => $"{ServerHandshakeBase},{identity}";
+ private static readonly string _clientHandshakePattern =
+ $@"{Regex.Escape(Peer.ClientHandshakeName)},Version=([0-9]+)\.([0-9]+)\.([0-9]+),([_a-zA-Z][_a-zA-Z0-9]{{0,63}})";
+
+ public string GetHandshakeLine(string identity) => $"{_serverHandshakeBase},{identity}";
public bool IsValidPeerHandshake(string handshake, out string identity, ILogger logger)
{
identity = null;
- var match = Regex.Match(handshake, ClientHandshakePattern);
+ var match = Regex.Match(handshake, _clientHandshakePattern);
if (!match.Success)
return false;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
index fd7bbd5578..3f1d5ac3ca 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
@@ -10,17 +10,17 @@ namespace GodotTools.Ides.MonoDevelop
public class Instance : IDisposable
{
public DateTime LaunchTime { get; private set; }
- private readonly string solutionFile;
- private readonly EditorId editorId;
+ private readonly string _solutionFile;
+ private readonly EditorId _editorId;
- private Process process;
+ private Process _process;
- public bool IsRunning => process != null && !process.HasExited;
+ public bool IsRunning => _process != null && !_process.HasExited;
public bool IsDisposed { get; private set; }
public void Execute()
{
- bool newWindow = process == null || process.HasExited;
+ bool newWindow = _process == null || _process.HasExited;
var args = new List<string>();
@@ -28,7 +28,7 @@ namespace GodotTools.Ides.MonoDevelop
if (OS.IsMacOS)
{
- string bundleId = BundleIds[editorId];
+ string bundleId = BundleIds[_editorId];
if (Internal.IsOsxAppBundleInstalled(bundleId))
{
@@ -45,18 +45,18 @@ namespace GodotTools.Ides.MonoDevelop
}
else
{
- command = OS.PathWhich(ExecutableNames[editorId]);
+ command = OS.PathWhich(ExecutableNames[_editorId]);
}
}
else
{
- command = OS.PathWhich(ExecutableNames[editorId]);
+ command = OS.PathWhich(ExecutableNames[_editorId]);
}
args.Add("--ipc-tcp");
if (newWindow)
- args.Add("\"" + Path.GetFullPath(solutionFile) + "\"");
+ args.Add("\"" + Path.GetFullPath(_solutionFile) + "\"");
if (command == null)
throw new FileNotFoundException();
@@ -65,7 +65,7 @@ namespace GodotTools.Ides.MonoDevelop
if (newWindow)
{
- process = Process.Start(new ProcessStartInfo
+ _process = Process.Start(new ProcessStartInfo
{
FileName = command,
Arguments = string.Join(" ", args),
@@ -88,14 +88,14 @@ namespace GodotTools.Ides.MonoDevelop
if (editorId == EditorId.VisualStudioForMac && !OS.IsMacOS)
throw new InvalidOperationException($"{nameof(EditorId.VisualStudioForMac)} not supported on this platform");
- this.solutionFile = solutionFile;
- this.editorId = editorId;
+ _solutionFile = solutionFile;
+ _editorId = editorId;
}
public void Dispose()
{
IsDisposed = true;
- process?.Dispose();
+ _process?.Dispose();
}
private static readonly IReadOnlyDictionary<EditorId, string> ExecutableNames;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
index 94fc5da425..71055f0125 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
@@ -11,6 +11,7 @@ using Environment = System.Environment;
using File = System.IO.File;
using Path = System.IO.Path;
using OS = GodotTools.Utils.OS;
+
// ReSharper disable UnassignedField.Local
// ReSharper disable InconsistentNaming
// ReSharper disable UnassignedField.Global
@@ -47,16 +48,16 @@ namespace GodotTools.Ides.Rider
GD.PushWarning(e.Message);
}
- return new RiderInfo[0];
+ return Array.Empty<RiderInfo>();
}
private static RiderInfo[] CollectAllRiderPathsLinux()
{
var installInfos = new List<RiderInfo>();
- var home = Environment.GetEnvironmentVariable("HOME");
+ string home = Environment.GetEnvironmentVariable("HOME");
if (!string.IsNullOrEmpty(home))
{
- var toolboxRiderRootPath = GetToolboxBaseDir();
+ string toolboxRiderRootPath = GetToolboxBaseDir();
installInfos.AddRange(CollectPathsFromToolbox(toolboxRiderRootPath, "bin", "rider.sh", false)
.Select(a => new RiderInfo(a, true)).ToList());
@@ -65,12 +66,12 @@ namespace GodotTools.Ides.Rider
if (shortcut.Exists)
{
- var lines = File.ReadAllLines(shortcut.FullName);
- foreach (var line in lines)
+ string[] lines = File.ReadAllLines(shortcut.FullName);
+ foreach (string line in lines)
{
if (!line.StartsWith("Exec=\""))
continue;
- var path = line.Split('"').Where((item, index) => index == 1).SingleOrDefault();
+ string path = line.Split('"').Where((item, index) => index == 1).SingleOrDefault();
if (string.IsNullOrEmpty(path))
continue;
@@ -82,7 +83,7 @@ namespace GodotTools.Ides.Rider
}
// snap install
- var snapInstallPath = "/snap/rider/current/bin/rider.sh";
+ string snapInstallPath = "/snap/rider/current/bin/rider.sh";
if (new FileInfo(snapInstallPath).Exists)
installInfos.Add(new RiderInfo(snapInstallPath, false));
@@ -98,15 +99,15 @@ namespace GodotTools.Ides.Rider
if (folder.Exists)
{
installInfos.AddRange(folder.GetDirectories("*Rider*.app")
- .Select(a => new RiderInfo(Path.Combine(a.FullName, "Contents/MacOS/rider"), false))
- .ToList());
+ .Select(a => new RiderInfo(Path.Combine(a.FullName, "Contents/MacOS/rider"), false))
+ .ToList());
}
// /Users/user/Library/Application Support/JetBrains/Toolbox/apps/Rider/ch-1/181.3870.267/Rider EAP.app
// should be combined with "Contents/MacOS/rider"
- var toolboxRiderRootPath = GetToolboxBaseDir();
+ string toolboxRiderRootPath = GetToolboxBaseDir();
var paths = CollectPathsFromToolbox(toolboxRiderRootPath, "", "Rider*.app", true)
- .Select(a => new RiderInfo(Path.Combine(a, "Contents/MacOS/rider"), true));
+ .Select(a => new RiderInfo(Path.Combine(a, "Contents/MacOS/rider"), true));
installInfos.AddRange(paths);
return installInfos.ToArray();
@@ -134,7 +135,7 @@ namespace GodotTools.Ides.Rider
{
if (OS.IsWindows)
{
- var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
return GetToolboxRiderRootPath(localAppData);
}
@@ -249,7 +250,7 @@ namespace GodotTools.Ides.Rider
bool isMac)
{
if (!Directory.Exists(toolboxRiderRootPath))
- return new string[0];
+ return Array.Empty<string>();
var channelDirs = Directory.GetDirectories(toolboxRiderRootPath);
var paths = channelDirs.SelectMany(channelDir =>
@@ -295,7 +296,7 @@ namespace GodotTools.Ides.Rider
Logger.Warn($"Failed to get RiderPath from {channelDir}", e);
}
- return new string[0];
+ return Array.Empty<string>();
})
.Where(c => !string.IsNullOrEmpty(c))
.ToArray();
@@ -306,7 +307,7 @@ namespace GodotTools.Ides.Rider
{
var folder = new DirectoryInfo(Path.Combine(buildDir, dirName));
if (!folder.Exists)
- return new string[0];
+ return Array.Empty<string>();
if (!isMac)
return new[] { Path.Combine(folder.FullName, searchPattern) }.Where(File.Exists).ToArray();
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
index ed25cdaa63..ac29efb716 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
@@ -49,7 +49,7 @@ namespace GodotTools.Ides.Rider
if (!paths.Any())
return;
- var newPath = paths.Last().Path;
+ string newPath = paths.Last().Path;
Globals.EditorDef(EditorPathSettingName, newPath);
editorSettings.SetSetting(EditorPathSettingName, newPath);
}
@@ -57,7 +57,8 @@ namespace GodotTools.Ides.Rider
public static bool IsExternalEditorSetToRider(EditorSettings editorSettings)
{
- return editorSettings.HasSetting(EditorPathSettingName) && IsRider((string) editorSettings.GetSetting(EditorPathSettingName));
+ return editorSettings.HasSetting(EditorPathSettingName) &&
+ IsRider((string)editorSettings.GetSetting(EditorPathSettingName));
}
public static bool IsRider(string path)
@@ -66,7 +67,7 @@ namespace GodotTools.Ides.Rider
return false;
var fileInfo = new FileInfo(path);
- var filename = fileInfo.Name.ToLowerInvariant();
+ string filename = fileInfo.Name.ToLowerInvariant();
return filename.StartsWith("rider", StringComparison.Ordinal);
}
@@ -83,7 +84,7 @@ namespace GodotTools.Ides.Rider
if (!paths.Any())
return null;
- var newPath = paths.Last().Path;
+ string newPath = paths.Last().Path;
editorSettings.SetSetting(EditorPathSettingName, newPath);
Globals.EditorDef(EditorPathSettingName, newPath);
return newPath;
@@ -96,8 +97,8 @@ namespace GodotTools.Ides.Rider
public static void OpenFile(string slnPath, string scriptPath, int line)
{
- var pathFromSettings = GetRiderPathFromSettings();
- var path = CheckAndUpdatePath(pathFromSettings);
+ string pathFromSettings = GetRiderPathFromSettings();
+ string path = CheckAndUpdatePath(pathFromSettings);
var args = new List<string>();
args.Add(slnPath);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
index 793f84fd77..5c5ced8c29 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
@@ -13,6 +13,9 @@ namespace GodotTools.Internals
public static object EditorDef(string setting, object defaultValue, bool restartIfChanged = false) =>
internal_EditorDef(setting, defaultValue, restartIfChanged);
+ public static object EditorShortcut(string setting) =>
+ internal_EditorShortcut(setting);
+
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static string TTR(this string text) => internal_TTR(text);
@@ -28,6 +31,9 @@ namespace GodotTools.Internals
private static extern object internal_EditorDef(string setting, object defaultValue, bool restartIfChanged);
[MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern object internal_EditorShortcut(string setting);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_TTR(string text);
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
index 6893bc1974..5e70c399b2 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
@@ -39,45 +39,57 @@ namespace GodotTools.Internals
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResDataDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResMetadataDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResAssembliesBaseDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResAssembliesDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResConfigDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResTempDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResTempAssembliesBaseDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ResTempAssembliesDir();
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_MonoUserDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_MonoLogsDir();
#region Tools-only
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_MonoSolutionsDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_BuildLogsDirs();
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ProjectSlnPath();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_ProjectCsProjPath();
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_DataEditorToolsDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_DataEditorPrebuiltApiDir();
#endregion
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_DataMonoEtcDir();
+
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_DataMonoLibDir();
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
index 7e5049e4b7..77370090ec 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
@@ -1,7 +1,5 @@
-using System;
using System.Runtime.CompilerServices;
using Godot;
-using Godot.Collections;
using GodotTools.IdeMessaging.Requests;
namespace GodotTools.Internals
@@ -42,9 +40,6 @@ namespace GodotTools.Internals
public static void EditorNodeShowScriptScreen() => internal_EditorNodeShowScriptScreen();
- public static Dictionary<string, object> GetScriptsMetadataOrNothing() =>
- internal_GetScriptsMetadataOrNothing(typeof(Dictionary<string, object>));
-
public static string MonoWindowsInstallRoot => internal_MonoWindowsInstallRoot();
public static void EditorRunPlay() => internal_EditorRunPlay();
@@ -101,9 +96,6 @@ namespace GodotTools.Internals
private static extern void internal_EditorNodeShowScriptScreen();
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern Dictionary<string, object> internal_GetScriptsMetadataOrNothing(Type dictType);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_MonoWindowsInstallRoot();
[MethodImpl(MethodImplOptions.InternalCall)]
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs
deleted file mode 100644
index c72a84c513..0000000000
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using Godot;
-using Godot.Collections;
-
-namespace GodotTools.Internals
-{
- public static class ScriptClassParser
- {
- public class ClassDecl
- {
- public string Name { get; }
- public string Namespace { get; }
- public bool Nested { get; }
- public long BaseCount { get; }
-
- public string SearchName => Nested ?
- Name.Substring(Name.LastIndexOf(".", StringComparison.Ordinal) + 1) :
- Name;
-
- public ClassDecl(string name, string @namespace, bool nested, long baseCount)
- {
- Name = name;
- Namespace = @namespace;
- Nested = nested;
- BaseCount = baseCount;
- }
- }
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern Error internal_ParseFile(string filePath, Array<Dictionary> classes, out string errorStr);
-
- public static Error ParseFile(string filePath, out IEnumerable<ClassDecl> classes, out string errorStr)
- {
- var classesArray = new Array<Dictionary>();
- var error = internal_ParseFile(filePath, classesArray, out errorStr);
- if (error != Error.Ok)
- {
- classes = null;
- return error;
- }
-
- var classesList = new List<ClassDecl>();
-
- foreach (var classDeclDict in classesArray)
- {
- classesList.Add(new ClassDecl(
- (string)classDeclDict["name"],
- (string)classDeclDict["namespace"],
- (bool)classDeclDict["nested"],
- (long)classDeclDict["base_count"]
- ));
- }
-
- classes = classesList;
-
- return Error.Ok;
- }
- }
-}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs
index c6724ccaf7..05499339b1 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs
@@ -8,7 +8,7 @@ namespace GodotTools.Utils
{
public static class FsPathUtils
{
- private static readonly string ResourcePath = ProjectSettings.GlobalizePath("res://");
+ private static readonly string _resourcePath = ProjectSettings.GlobalizePath("res://");
private static bool PathStartsWithAlreadyNorm(this string childPath, string parentPath)
{
@@ -34,7 +34,7 @@ namespace GodotTools.Utils
public static string LocalizePathWithCaseChecked(string path)
{
string pathNorm = path.NormalizePath() + Path.DirectorySeparatorChar;
- string resourcePathNorm = ResourcePath.NormalizePath() + Path.DirectorySeparatorChar;
+ string resourcePathNorm = _resourcePath.NormalizePath() + Path.DirectorySeparatorChar;
if (!pathNorm.PathStartsWithAlreadyNorm(resourcePathNorm))
return null;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
index e745966435..93a1360cb6 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
@@ -13,10 +13,10 @@ namespace GodotTools.Utils
public static class OS
{
[MethodImpl(MethodImplOptions.InternalCall)]
- static extern string GetPlatformName();
+ private static extern string GetPlatformName();
[MethodImpl(MethodImplOptions.InternalCall)]
- static extern bool UnixFileHasExecutableAccess(string filePath);
+ private static extern bool UnixFileHasExecutableAccess(string filePath);
public static class Names
{
@@ -74,10 +74,10 @@ namespace GodotTools.Utils
}
private static readonly IEnumerable<string> LinuxBSDPlatforms =
- new[] {Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD};
+ new[] { Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD };
private static readonly IEnumerable<string> UnixLikePlatforms =
- new[] {Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS}
+ new[] { Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS }
.Concat(LinuxBSDPlatforms).ToArray();
private static readonly Lazy<bool> _isWindows = new Lazy<bool>(() => IsOS(Names.Windows));
@@ -106,21 +106,34 @@ namespace GodotTools.Utils
public static string PathWhich([NotNull] string name)
{
- return IsWindows ? PathWhichWindows(name) : PathWhichUnix(name);
+ if (IsWindows)
+ return PathWhichWindows(name);
+
+ return PathWhichUnix(name);
}
private static string PathWhichWindows([NotNull] string name)
{
- string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? new string[] { };
+ string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>();
string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep);
+ char[] invalidPathChars = Path.GetInvalidPathChars();
var searchDirs = new List<string>();
if (pathDirs != null)
- searchDirs.AddRange(pathDirs);
+ {
+ foreach (var pathDir in pathDirs)
+ {
+ if (pathDir.IndexOfAny(invalidPathChars) != -1)
+ continue;
+
+ searchDirs.Add(pathDir);
+ }
+ }
string nameExt = Path.GetExtension(name);
- bool hasPathExt = !string.IsNullOrEmpty(nameExt) && windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase);
+ bool hasPathExt = !string.IsNullOrEmpty(nameExt) &&
+ windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase);
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
@@ -128,20 +141,29 @@ namespace GodotTools.Utils
return searchDirs.Select(dir => Path.Combine(dir, name)).FirstOrDefault(File.Exists);
return (from dir in searchDirs
- select Path.Combine(dir, name)
+ select Path.Combine(dir, name)
into path
- from ext in windowsExts
- select path + ext).FirstOrDefault(File.Exists);
+ from ext in windowsExts
+ select path + ext).FirstOrDefault(File.Exists);
}
private static string PathWhichUnix([NotNull] string name)
{
string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep);
+ char[] invalidPathChars = Path.GetInvalidPathChars();
var searchDirs = new List<string>();
if (pathDirs != null)
- searchDirs.AddRange(pathDirs);
+ {
+ foreach (var pathDir in pathDirs)
+ {
+ if (pathDir.IndexOfAny(invalidPathChars) != -1)
+ continue;
+
+ searchDirs.Add(pathDir);
+ }
+ }
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
@@ -196,7 +218,7 @@ namespace GodotTools.Utils
startInfo.UseShellExecute = false;
- using (var process = new Process {StartInfo = startInfo})
+ using (var process = new Process { StartInfo = startInfo })
{
process.Start();
process.WaitForExit();
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index b1875aec3f..e03c5fd248 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -35,8 +35,8 @@
#include "core/config/engine.h"
#include "core/core_constants.h"
#include "core/io/compression.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#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"
@@ -387,7 +387,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
xml_output.append(link_target);
xml_output.append("</c>");
}
- } else if (link_tag == "const") {
+ } else if (link_tag == "constant") {
if (!target_itype || !target_itype->is_object_type) {
if (OS::get_singleton()->is_stdout_verbose()) {
if (target_itype) {
@@ -416,8 +416,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
// Try to find as global enum constant
const EnumInterface *target_ienum = nullptr;
- for (const List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
- target_ienum = &E->get();
+ for (const EnumInterface &ienum : global_enums) {
+ target_ienum = &ienum;
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
if (target_iconst) {
break;
@@ -455,8 +455,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
// Try to find as enum constant in the current class
const EnumInterface *target_ienum = nullptr;
- for (const List<EnumInterface>::Element *E = target_itype->enums.front(); E; E = E->next()) {
- target_ienum = &E->get();
+ for (const EnumInterface &ienum : target_itype->enums) {
+ target_ienum = &ienum;
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
if (target_iconst) {
break;
@@ -655,9 +655,7 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
return 0;
}
- for (const List<ConstantInterface>::Element *E = p_ienum.constants.front()->next(); E; E = E->next()) {
- const ConstantInterface &iconstant = E->get();
-
+ for (const ConstantInterface &iconstant : p_ienum.constants) {
Vector<String> parts = iconstant.name.split("_", /* p_allow_empty: */ true);
int i;
@@ -682,12 +680,10 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumInterface &p_ienum, int p_prefix_length) {
if (p_prefix_length > 0) {
- for (List<ConstantInterface>::Element *E = p_ienum.constants.front(); E; E = E->next()) {
+ for (ConstantInterface &iconstant : p_ienum.constants) {
int curr_prefix_length = p_prefix_length;
- ConstantInterface &curr_const = E->get();
-
- String constant_name = curr_const.name;
+ String constant_name = iconstant.name;
Vector<String> parts = constant_name.split("_", /* p_allow_empty: */ true);
@@ -713,15 +709,13 @@ void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumI
constant_name += parts[i];
}
- curr_const.proxy_name = snake_to_pascal_case(constant_name, true);
+ iconstant.proxy_name = snake_to_pascal_case(constant_name, true);
}
}
}
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
- for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
- const MethodInterface &imethod = E->get();
-
+ for (const MethodInterface &imethod : p_itype.methods) {
if (imethod.is_virtual) {
continue;
}
@@ -735,8 +729,8 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
// Get arguments information
int i = 0;
- for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
- const TypeInterface *arg_type = _get_type_or_placeholder(F->get().type);
+ for (const ArgumentInterface &iarg : imethod.arguments) {
+ const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
im_sig += ", ";
im_sig += arg_type->im_type_in;
@@ -776,10 +770,10 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
if (p_itype.api_type != ClassDB::API_EDITOR) {
match->get().editor_only = false;
}
- method_icalls_map.insert(&E->get(), &match->get());
+ method_icalls_map.insert(&imethod, &match->get());
} else {
List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
- method_icalls_map.insert(&E->get(), &added->get());
+ method_icalls_map.insert(&imethod, &added->get());
}
}
}
@@ -859,9 +853,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
p_output.append(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{");
- for (const List<ConstantInterface>::Element *E = global_constants.front(); E; E = E->next()) {
- const ConstantInterface &iconstant = E->get();
-
+ for (const ConstantInterface &iconstant : global_constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -894,9 +886,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
// Enums
- for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
- const EnumInterface &ienum = E->get();
-
+ for (const EnumInterface &ienum : global_enums) {
CRASH_COND(ienum.constants.is_empty());
String enum_proxy_name = ienum.cname.operator String();
@@ -921,9 +911,8 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append(enum_proxy_name);
p_output.append("\n" INDENT1 OPEN_BLOCK);
- for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
- const ConstantInterface &iconstant = F->get();
-
+ const ConstantInterface &last = ienum.constants.back()->get();
+ for (const ConstantInterface &iconstant : ienum.constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -945,7 +934,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append(iconstant.proxy_name);
p_output.append(" = ");
p_output.append(itos(iconstant.value));
- p_output.append(F != ienum.constants.back() ? ",\n" : "\n");
+ p_output.append(&iconstant != &last ? ",\n" : "\n");
}
p_output.append(INDENT1 CLOSE_BLOCK);
@@ -1053,11 +1042,11 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
- for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : core_custom_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : method_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
#undef ADD_INTERNAL_CALL
@@ -1161,11 +1150,11 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
- for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : editor_custom_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : method_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
#undef ADD_INTERNAL_CALL
@@ -1260,7 +1249,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
CRASH_COND(itype.cname != name_cache.type_Object);
CRASH_COND(!itype.is_instantiable);
CRASH_COND(itype.api_type != ClassDB::API_CORE);
- CRASH_COND(itype.is_reference);
+ CRASH_COND(itype.is_ref_counted);
CRASH_COND(itype.is_singleton);
}
@@ -1327,9 +1316,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add constants
- for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) {
- const ConstantInterface &iconstant = E->get();
-
+ for (const ConstantInterface &iconstant : itype.constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -1360,18 +1347,15 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add enums
- for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) {
- const EnumInterface &ienum = E->get();
-
+ for (const EnumInterface &ienum : itype.enums) {
ERR_FAIL_COND_V(ienum.constants.is_empty(), ERR_BUG);
output.append(MEMBER_BEGIN "public enum ");
output.append(ienum.cname.operator String());
output.append(MEMBER_BEGIN OPEN_BLOCK);
- for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
- const ConstantInterface &iconstant = F->get();
-
+ const ConstantInterface &last = ienum.constants.back()->get();
+ for (const ConstantInterface &iconstant : ienum.constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -1393,7 +1377,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.append(iconstant.proxy_name);
output.append(" = ");
output.append(itos(iconstant.value));
- output.append(F != ienum.constants.back() ? ",\n" : "\n");
+ output.append(&iconstant != &last ? ",\n" : "\n");
}
output.append(INDENT2 CLOSE_BLOCK);
@@ -1401,8 +1385,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add properties
- for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) {
- const PropertyInterface &iprop = E->get();
+ for (const PropertyInterface &iprop : itype.properties) {
Error prop_err = _generate_cs_property(itype, iprop, output);
ERR_FAIL_COND_V_MSG(prop_err != OK, prop_err,
"Failed to generate property '" + iprop.cname.operator String() +
@@ -1463,15 +1446,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
int method_bind_count = 0;
- for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
- const MethodInterface &imethod = E->get();
+ for (const MethodInterface &imethod : itype.methods) {
Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'.");
}
- for (const List<SignalInterface>::Element *E = itype.signals_.front(); E; E = E->next()) {
- const SignalInterface &isignal = E->get();
+ for (const SignalInterface &isignal : itype.signals_) {
Error method_err = _generate_cs_signal(itype, isignal, output);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate signal '" + isignal.name + "' for class '" + itype.name + "'.");
@@ -1678,8 +1659,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
StringBuilder default_args_doc;
// Retrieve information from the arguments
- for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
+ const ArgumentInterface &first = p_imethod.arguments.front()->get();
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
@@ -1699,7 +1680,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Add the current arguments to the signature
// If the argument has a default value which is not a constant, we will make it Nullable
{
- if (F != p_imethod.arguments.front()) {
+ if (&iarg != &first) {
arguments_sig += ", ";
}
@@ -1754,7 +1735,12 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
cs_in_statements += " : ";
}
- String def_arg = sformat(iarg.default_argument, arg_type->cs_type);
+ String cs_type = arg_type->cs_type;
+ if (cs_type.ends_with("[]")) {
+ cs_type = cs_type.substr(0, cs_type.length() - 2);
+ }
+
+ String def_arg = sformat(iarg.default_argument, cs_type);
cs_in_statements += def_arg;
cs_in_statements += ";\n" INDENT3;
@@ -1763,8 +1749,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Apparently the name attribute must not include the @
String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name;
+ // Escape < and > in the attribute default value
+ String param_def_arg = def_arg.replacen("<", "&lt;").replacen(">", "&gt;");
- default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>");
+ default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + param_def_arg + "</param>");
} else {
icall_params += arg_type->cs_in.is_empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
}
@@ -1855,9 +1843,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
p_output.append(p_imethod.name);
p_output.append("\"");
- for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
p_output.append(", ");
- p_output.append(F->get().name);
+ p_output.append(iarg.name);
}
p_output.append(");\n" CLOSE_BLOCK_L2);
@@ -1899,8 +1887,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
String arguments_sig;
// Retrieve information from the arguments
- for (const List<ArgumentInterface>::Element *F = p_isignal.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
+ const ArgumentInterface &first = p_isignal.arguments.front()->get();
+ for (const ArgumentInterface &iarg : p_isignal.arguments) {
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
@@ -1914,7 +1902,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
// Add the current arguments to the signature
- if (F != p_isignal.arguments.front()) {
+ if (&iarg != &first) {
arguments_sig += ", ";
}
@@ -2042,8 +2030,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
- for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
- const MethodInterface &imethod = E->get();
+ for (const MethodInterface &imethod : itype.methods) {
Error method_err = _generate_glue_method(itype, imethod, output);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'.");
@@ -2114,20 +2101,20 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
}
bool tools_sequence = false;
- for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) {
+ for (const InternalCall &internal_call : core_custom_icalls) {
if (tools_sequence) {
- if (!E->get().editor_only) {
+ if (!internal_call.editor_only) {
tools_sequence = false;
output.append("#endif\n");
}
} else {
- if (E->get().editor_only) {
+ if (internal_call.editor_only) {
output.append("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ ADD_INTERNAL_CALL_REGISTRATION(internal_call);
}
if (tools_sequence) {
@@ -2136,24 +2123,24 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
}
output.append("#ifdef TOOLS_ENABLED\n");
- for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ for (const InternalCall &internal_call : editor_custom_icalls)
+ ADD_INTERNAL_CALL_REGISTRATION(internal_call);
output.append("#endif // TOOLS_ENABLED\n");
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
+ for (const InternalCall &internal_call : method_icalls) {
if (tools_sequence) {
- if (!E->get().editor_only) {
+ if (!internal_call.editor_only) {
tools_sequence = false;
output.append("#endif\n");
}
} else {
- if (E->get().editor_only) {
+ if (internal_call.editor_only) {
output.append("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ ADD_INTERNAL_CALL_REGISTRATION(internal_call);
}
if (tools_sequence) {
@@ -2209,8 +2196,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
// Get arguments information
int i = 0;
- for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
String c_param_name = "arg" + itos(i + 1);
@@ -2284,8 +2270,8 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
}
if (return_type->is_object_type) {
- ptrcall_return_type = return_type->is_reference ? "Ref<Reference>" : return_type->c_type;
- initialization = return_type->is_reference ? "" : " = nullptr";
+ ptrcall_return_type = return_type->is_ref_counted ? "Ref<RefCounted>" : return_type->c_type;
+ initialization = return_type->is_ref_counted ? "" : " = nullptr";
} else {
ptrcall_return_type = return_type->c_type;
}
@@ -2520,10 +2506,10 @@ bool BindingsGenerator::_arg_default_value_is_assignable_to_type(const Variant &
p_arg_type.name == name_cache.type_NodePath;
case Variant::NODE_PATH:
return p_arg_type.name == name_cache.type_NodePath;
- case Variant::TRANSFORM:
case Variant::TRANSFORM2D:
+ case Variant::TRANSFORM3D:
case Variant::BASIS:
- case Variant::QUAT:
+ case Variant::QUATERNION:
case Variant::PLANE:
case Variant::AABB:
case Variant::COLOR:
@@ -2600,12 +2586,12 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.base_name = ClassDB::get_parent_class(type_cname);
itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name);
itype.is_instantiable = class_info->creation_func && !itype.is_singleton;
- itype.is_reference = ClassDB::is_parent_class(type_cname, name_cache.type_Reference);
- itype.memory_own = itype.is_reference;
+ itype.is_ref_counted = ClassDB::is_parent_class(type_cname, name_cache.type_RefCounted);
+ itype.memory_own = itype.is_ref_counted;
itype.c_out = "\treturn ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
- itype.c_out += itype.is_reference ? "(%1.ptr());\n" : "(%1);\n";
+ itype.c_out += itype.is_ref_counted ? "(%1.ptr());\n" : "(%1);\n";
itype.cs_in = itype.is_singleton ? BINDINGS_PTR_FIELD : "Object." CS_SMETHOD_GETINSTANCE "(%0)";
@@ -2623,10 +2609,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
Map<StringName, StringName> accessor_methods;
- for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- const PropertyInfo &property = E->get();
-
- if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY) {
+ for (const PropertyInfo &property : property_list) {
+ if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY || (property.type == Variant::NIL && property.usage & PROPERTY_USAGE_ARRAY)) {
continue;
}
@@ -2684,9 +2668,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
ClassDB::get_method_list(type_cname, &method_list, true);
method_list.sort();
- for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
- const MethodInfo &method_info = E->get();
-
+ for (const MethodInfo &method_info : method_list) {
int argc = method_info.arguments.size();
if (method_info.name.is_empty()) {
@@ -2741,7 +2723,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
imethod.return_type.cname = return_info.class_name;
bool bad_reference_hint = !imethod.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE &&
- ClassDB::is_parent_class(return_info.class_name, name_cache.type_Reference);
+ ClassDB::is_parent_class(return_info.class_name, name_cache.type_RefCounted);
ERR_FAIL_COND_V_MSG(bad_reference_hint, false,
String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
" Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'.");
@@ -2840,9 +2822,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
// Classes starting with an underscore are ignored unless they're used as a property setter or getter
if (!imethod.is_virtual && imethod.name[0] == '_') {
- for (const List<PropertyInterface>::Element *F = itype.properties.front(); F; F = F->next()) {
- const PropertyInterface &iprop = F->get();
-
+ for (const PropertyInterface &iprop : itype.properties) {
if (iprop.setter == imethod.name || iprop.getter == imethod.name) {
imethod.is_internal = true;
itype.methods.push_back(imethod);
@@ -2952,8 +2932,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
}
EnumInterface ienum(enum_proxy_cname);
const List<StringName> &enum_constants = enum_map.get(*k);
- for (const List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
- const StringName &constant_cname = E->get();
+ for (const StringName &constant_cname : enum_constants) {
String constant_name = constant_cname.operator String();
int *value = class_info->constant_map.getptr(constant_cname);
ERR_FAIL_NULL_V(value, false);
@@ -2989,9 +2968,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
enum_types.insert(enum_itype.cname, enum_itype);
}
- for (const List<String>::Element *E = constants.front(); E; E = E->next()) {
- const String &constant_name = E->get();
- int *value = class_info->constant_map.getptr(StringName(E->get()));
+ for (const String &constant_name : constants) {
+ int *value = class_info->constant_map.getptr(StringName(constant_name));
ERR_FAIL_NULL_V(value, false);
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
@@ -3053,28 +3031,25 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
break;
case Variant::PLANE: {
Plane plane = p_val.operator Plane();
- r_iarg.default_argument = "new Plane(new Vector3(" + plane.normal.operator String() + "), " + rtos(plane.d) + ")";
+ r_iarg.default_argument = "new Plane(new Vector3" + plane.normal.operator String() + ", " + rtos(plane.d) + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} 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.position.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: {
Rect2 rect = p_val.operator Rect2();
- r_iarg.default_argument = "new Rect2(new Vector2(" + rect.position.operator String() + "), new Vector2(" + rect.position.operator String() + "))";
+ r_iarg.default_argument = "new Rect2(new Vector2" + rect.position.operator String() + ", new Vector2" + rect.size.operator String() + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} 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.position.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:
- r_iarg.default_argument = "new %s(" + r_iarg.default_argument + ")";
- r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
- break;
case Variant::VECTOR2:
case Variant::VECTOR2I:
case Variant::VECTOR3:
@@ -3102,6 +3077,9 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
r_iarg.default_argument = "null";
break;
case Variant::ARRAY:
+ r_iarg.default_argument = "new %s { }";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+ break;
case Variant::PACKED_BYTE_ARRAY:
case Variant::PACKED_INT32_ARRAY:
case Variant::PACKED_INT64_ARRAY:
@@ -3111,7 +3089,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
case Variant::PACKED_VECTOR2_ARRAY:
case Variant::PACKED_VECTOR3_ARRAY:
case Variant::PACKED_COLOR_ARRAY:
- r_iarg.default_argument = "new %s {}";
+ r_iarg.default_argument = "Array.Empty<%s>()";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
break;
case Variant::TRANSFORM2D: {
@@ -3123,13 +3101,13 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
- case Variant::TRANSFORM: {
- Transform transform = p_val.operator Transform();
- if (transform == Transform()) {
- r_iarg.default_argument = "Transform.Identity";
+ case Variant::TRANSFORM3D: {
+ Transform3D transform = p_val.operator Transform3D();
+ if (transform == Transform3D()) {
+ r_iarg.default_argument = "Transform3D.Identity";
} else {
Basis basis = transform.basis;
- r_iarg.default_argument = "new Transform(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")";
+ r_iarg.default_argument = "new Transform3D(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")";
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
@@ -3142,18 +3120,28 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
- case Variant::QUAT: {
- Quat quat = p_val.operator Quat();
- if (quat == Quat()) {
- r_iarg.default_argument = "Quat.Identity";
+ case Variant::QUATERNION: {
+ Quaternion quaternion = p_val.operator Quaternion();
+ if (quaternion == Quaternion()) {
+ r_iarg.default_argument = "Quaternion.Identity";
} else {
- r_iarg.default_argument = "new Quat" + quat.operator String();
+ r_iarg.default_argument = "new Quaternion" + quaternion.operator String();
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
case Variant::CALLABLE:
+ ERR_FAIL_COND_V_MSG(r_iarg.type.cname != name_cache.type_Callable, false,
+ "Parameter of type '" + String(r_iarg.type.cname) + "' cannot have a default value of type '" + String(name_cache.type_Callable) + "'.");
+ ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false,
+ "Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value.");
+ r_iarg.default_argument = "default";
+ break;
case Variant::SIGNAL:
- CRASH_NOW_MSG("Parameter of type '" + String(r_iarg.type.cname) + "' cannot have a default value.");
+ ERR_FAIL_COND_V_MSG(r_iarg.type.cname != name_cache.type_Signal, false,
+ "Parameter of type '" + String(r_iarg.type.cname) + "' cannot have a default value of type '" + String(name_cache.type_Signal) + "'.");
+ ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false,
+ "Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value.");
+ r_iarg.default_argument = "default";
break;
default:
CRASH_NOW_MSG("Unexpected Variant type: " + itos(p_val.get_type()));
@@ -3196,8 +3184,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
INSERT_STRUCT_TYPE(Vector3)
INSERT_STRUCT_TYPE(Vector3i)
INSERT_STRUCT_TYPE(Basis)
- INSERT_STRUCT_TYPE(Quat)
- INSERT_STRUCT_TYPE(Transform)
+ INSERT_STRUCT_TYPE(Quaternion)
+ INSERT_STRUCT_TYPE(Transform3D)
INSERT_STRUCT_TYPE(AABB)
INSERT_STRUCT_TYPE(Color)
INSERT_STRUCT_TYPE(Plane)
@@ -3542,9 +3530,7 @@ void BindingsGenerator::_populate_global_constants() {
}
}
- for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
- EnumInterface &ienum = E->get();
-
+ for (EnumInterface &ienum : global_enums) {
TypeInterface enum_itype;
enum_itype.is_enum = true;
enum_itype.name = ienum.cname.operator String();
@@ -3574,13 +3560,13 @@ void BindingsGenerator::_populate_global_constants() {
hardcoded_enums.push_back("Vector2i.Axis");
hardcoded_enums.push_back("Vector3.Axis");
hardcoded_enums.push_back("Vector3i.Axis");
- for (List<StringName>::Element *E = hardcoded_enums.front(); E; E = E->next()) {
+ 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
TypeInterface enum_itype;
enum_itype.is_enum = true;
- enum_itype.name = E->get().operator String();
- enum_itype.cname = E->get();
+ enum_itype.name = enum_cname.operator String();
+ enum_itype.cname = enum_cname;
enum_itype.proxy_name = enum_itype.name;
TypeInterface::postsetup_enum_type(enum_itype);
enum_types.insert(enum_itype.cname, enum_itype);
@@ -3631,11 +3617,44 @@ void BindingsGenerator::_initialize() {
initialized = true;
}
+static String generate_all_glue_option = "--generate-mono-glue";
+static String generate_cs_glue_option = "--generate-mono-cs-glue";
+static String generate_cpp_glue_option = "--generate-mono-cpp-glue";
+
+static void handle_cmdline_options(String glue_dir_path, String cs_dir_path, String cpp_dir_path) {
+ BindingsGenerator bindings_generator;
+ bindings_generator.set_log_print_enabled(true);
+
+ if (!bindings_generator.is_initialized()) {
+ ERR_PRINT("Failed to initialize the bindings generator");
+ return;
+ }
+
+ if (glue_dir_path.length()) {
+ if (bindings_generator.generate_glue(glue_dir_path) != OK) {
+ ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue.");
+ }
+
+ if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) {
+ ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API.");
+ }
+ }
+
+ if (cs_dir_path.length()) {
+ if (bindings_generator.generate_cs_api(cs_dir_path) != OK) {
+ ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API.");
+ }
+ }
+
+ if (cpp_dir_path.length()) {
+ if (bindings_generator.generate_glue(cpp_dir_path) != OK) {
+ ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue.");
+ }
+ }
+}
+
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
const int NUM_OPTIONS = 2;
- String generate_all_glue_option = "--generate-mono-glue";
- String generate_cs_glue_option = "--generate-mono-cs-glue";
- String generate_cpp_glue_option = "--generate-mono-cpp-glue";
String glue_dir_path;
String cs_dir_path;
@@ -3643,6 +3662,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
int options_left = NUM_OPTIONS;
+ bool exit_godot = false;
+
const List<String>::Element *elem = p_cmdline_args.front();
while (elem && options_left) {
@@ -3654,6 +3675,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
} else {
ERR_PRINT(generate_all_glue_option + ": No output directory specified (expected path to '{GODOT_ROOT}/modules/mono/glue').");
+ exit_godot = true;
}
--options_left;
@@ -3665,6 +3687,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
} else {
ERR_PRINT(generate_cs_glue_option + ": No output directory specified.");
+ exit_godot = true;
}
--options_left;
@@ -3676,6 +3699,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
} else {
ERR_PRINT(generate_cpp_glue_option + ": No output directory specified.");
+ exit_godot = true;
}
--options_left;
@@ -3685,37 +3709,11 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
}
if (glue_dir_path.length() || cs_dir_path.length() || cpp_dir_path.length()) {
- BindingsGenerator bindings_generator;
- bindings_generator.set_log_print_enabled(true);
-
- if (!bindings_generator.initialized) {
- ERR_PRINT("Failed to initialize the bindings generator");
- Main::cleanup(true);
- ::exit(0);
- }
-
- if (glue_dir_path.length()) {
- if (bindings_generator.generate_glue(glue_dir_path) != OK) {
- ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue.");
- }
-
- if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) {
- ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API.");
- }
- }
-
- if (cs_dir_path.length()) {
- if (bindings_generator.generate_cs_api(cs_dir_path) != OK) {
- ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API.");
- }
- }
-
- if (cpp_dir_path.length()) {
- if (bindings_generator.generate_glue(cpp_dir_path) != OK) {
- ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue.");
- }
- }
+ handle_cmdline_options(glue_dir_path, cs_dir_path, cpp_dir_path);
+ exit_godot = true;
+ }
+ if (exit_godot) {
// Exit once done
Main::cleanup(true);
::exit(0);
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 876046176b..51a27ee934 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -216,7 +216,7 @@ class BindingsGenerator {
bool is_enum = false;
bool is_object_type = false;
bool is_singleton = false;
- bool is_reference = false;
+ bool is_ref_counted = false;
/**
* Used only by Object-derived types.
@@ -228,7 +228,7 @@ class BindingsGenerator {
/**
* Used only by Object-derived types.
* Determines if the C# class owns the native handle and must free it somehow when disposed.
- * e.g.: Reference types must notify when the C# instance is disposed, for proper refcounting.
+ * e.g.: RefCounted types must notify when the C# instance is disposed, for proper refcounting.
*/
bool memory_own = false;
@@ -295,7 +295,7 @@ class BindingsGenerator {
* VarArg (fictitious type to represent variable arguments): Array
* float: double (because ptrcall only supports double)
* int: int64_t (because ptrcall only supports int64_t and uint64_t)
- * Reference types override this for the type of the return variable: Ref<Reference>
+ * RefCounted types override this for the type of the return variable: Ref<RefCounted>
*/
String c_type;
@@ -357,9 +357,9 @@ class BindingsGenerator {
List<SignalInterface> signals_;
const MethodInterface *find_method_by_name(const StringName &p_cname) const {
- for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().cname == p_cname) {
- return &E->get();
+ for (const MethodInterface &E : methods) {
+ if (E.cname == p_cname) {
+ return &E;
}
}
@@ -367,9 +367,9 @@ class BindingsGenerator {
}
const PropertyInterface *find_property_by_name(const StringName &p_cname) const {
- for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().cname == p_cname) {
- return &E->get();
+ for (const PropertyInterface &E : properties) {
+ if (E.cname == p_cname) {
+ return &E;
}
}
@@ -377,9 +377,9 @@ class BindingsGenerator {
}
const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
- for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().proxy_name == p_proxy_name) {
- return &E->get();
+ for (const PropertyInterface &E : properties) {
+ if (E.proxy_name == p_proxy_name) {
+ return &E;
}
}
@@ -387,9 +387,9 @@ class BindingsGenerator {
}
const MethodInterface *find_method_by_proxy_name(const String &p_proxy_name) const {
- for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().proxy_name == p_proxy_name) {
- return &E->get();
+ for (const MethodInterface &E : methods) {
+ if (E.proxy_name == p_proxy_name) {
+ return &E;
}
}
@@ -534,8 +534,10 @@ class BindingsGenerator {
StringName type_Variant = StaticCString::create("Variant");
StringName type_VarArg = StaticCString::create("VarArg");
StringName type_Object = StaticCString::create("Object");
- StringName type_Reference = StaticCString::create("Reference");
+ StringName type_RefCounted = StaticCString::create("RefCounted");
StringName type_RID = StaticCString::create("RID");
+ StringName type_Callable = StaticCString::create("Callable");
+ StringName type_Signal = StaticCString::create("Signal");
StringName type_String = StaticCString::create("String");
StringName type_StringName = StaticCString::create("StringName");
StringName type_NodePath = StaticCString::create("NodePath");
@@ -573,7 +575,7 @@ class BindingsGenerator {
StaticCString::create(_STR(PackedByteArray)),
StaticCString::create(_STR(PackedInt32Array)),
- StaticCString::create(_STR(PackedInt64rray)),
+ StaticCString::create(_STR(PackedInt64Array)),
StaticCString::create(_STR(PackedFloat32Array)),
StaticCString::create(_STR(PackedFloat64Array)),
StaticCString::create(_STR(PackedStringArray)),
@@ -613,9 +615,9 @@ class BindingsGenerator {
}
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
- for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) {
- if (E->get().name == p_name) {
- return &E->get();
+ for (const ConstantInterface &E : p_constants) {
+ if (E.name == p_name) {
+ return &E;
}
}
@@ -623,7 +625,7 @@ class BindingsGenerator {
}
inline String get_unique_sig(const TypeInterface &p_type) {
- if (p_type.is_reference) {
+ if (p_type.is_ref_counted) {
return "Ref";
} else if (p_type.is_object_type) {
return "Obj";
diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp
index bbfba83e6f..7433c865f5 100644
--- a/modules/mono/editor/code_completion.cpp
+++ b/modules/mono/editor/code_completion.cpp
@@ -109,9 +109,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<PropertyInfo> project_props;
ProjectSettings::get_singleton()->get_property_list(&project_props);
- for (List<PropertyInfo>::Element *E = project_props.front(); E; E = E->next()) {
- const PropertyInfo &prop = E->get();
-
+ for (const PropertyInfo &prop : project_props) {
if (!prop.name.begins_with("input/")) {
continue;
}
@@ -123,10 +121,10 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
case CompletionKind::NODE_PATHS: {
{
// AutoLoads
- Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+ OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
- for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
- const ProjectSettings::AutoloadInfo &info = E->value();
+ for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
+ const ProjectSettings::AutoloadInfo &info = E.value();
suggestions.push_back(quoted("/root/" + String(info.name)));
}
}
@@ -187,8 +185,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
ClassDB::get_signal_list(native, &signals, /* p_no_inheritance: */ false);
}
- for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- const String &signal = E->get().name;
+ for (const MethodInfo &E : signals) {
+ const String &signal = E.name;
suggestions.push_back(quoted(signal));
}
} break;
@@ -199,8 +197,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_color_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -211,8 +209,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_constant_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -223,8 +221,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_font_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -235,8 +233,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_font_size_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -247,8 +245,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_stylebox_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index 667e4a3879..9a61b63c12 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -49,7 +49,6 @@
#include "../utils/osx_utils.h"
#include "code_completion.h"
#include "godotsharp_export.h"
-#include "script_class_parser.h"
MonoString *godot_icall_GodotSharpDirs_ResDataDir() {
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_data_dir());
@@ -172,36 +171,6 @@ MonoBoolean godot_icall_EditorProgress_Step(MonoString *p_task, MonoString *p_st
return EditorNode::progress_task_step(task, state, p_step, (bool)p_force_refresh);
}
-int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObject *p_classes, MonoString **r_error_str) {
- *r_error_str = nullptr;
-
- String filepath = GDMonoMarshal::mono_string_to_godot(p_filepath);
-
- ScriptClassParser scp;
- Error err = scp.parse_file(filepath);
- if (err == OK) {
- Array classes = GDMonoMarshal::mono_object_to_variant(p_classes);
- const Vector<ScriptClassParser::ClassDecl> &class_decls = scp.get_classes();
-
- for (int i = 0; i < class_decls.size(); i++) {
- const ScriptClassParser::ClassDecl &classDecl = class_decls[i];
-
- Dictionary classDeclDict;
- classDeclDict["name"] = classDecl.name;
- classDeclDict["namespace"] = classDecl.namespace_;
- classDeclDict["nested"] = classDecl.nested;
- classDeclDict["base_count"] = classDecl.base.size();
- classes.push_back(classDeclDict);
- }
- } else {
- String error_str = scp.get_error();
- if (!error_str.is_empty()) {
- *r_error_str = GDMonoMarshal::mono_string_from_godot(error_str);
- }
- }
- return err;
-}
-
uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) {
Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies);
@@ -272,7 +241,7 @@ MonoBoolean godot_icall_Internal_IsAssembliesReloadingNeeded() {
void godot_icall_Internal_ReloadAssemblies(MonoBoolean p_soft_reload) {
#ifdef GD_MONO_HOT_RELOAD
- _GodotSharp::get_singleton()->call_deferred("_reload_assemblies", (bool)p_soft_reload);
+ mono_bind::GodotSharp::get_singleton()->call_deferred(SNAME("_reload_assemblies"), (bool)p_soft_reload);
#endif
}
@@ -289,18 +258,6 @@ void godot_icall_Internal_EditorNodeShowScriptScreen() {
EditorNode::get_singleton()->call("_editor_select", EditorNode::EDITOR_SCRIPT);
}
-MonoObject *godot_icall_Internal_GetScriptsMetadataOrNothing(MonoReflectionType *p_dict_reftype) {
- Dictionary maybe_metadata = CSharpLanguage::get_singleton()->get_scripts_metadata_or_nothing();
-
- MonoType *dict_type = mono_reflection_type_get_type(p_dict_reftype);
-
- int type_encoding = mono_type_get_type(dict_type);
- MonoClass *type_class_raw = mono_class_from_mono_type(dict_type);
- GDMonoClass *type_class = GDMono::get_singleton()->get_class(type_class_raw);
-
- return GDMonoMarshal::variant_to_mono_object(maybe_metadata, ManagedType(type_encoding, type_class));
-}
-
MonoString *godot_icall_Internal_MonoWindowsInstallRoot() {
#ifdef WINDOWS_ENABLED
String install_root_dir = GDMono::get_singleton()->get_mono_reg_info().install_root_dir;
@@ -349,6 +306,12 @@ MonoObject *godot_icall_Globals_EditorDef(MonoString *p_setting, MonoObject *p_d
return GDMonoMarshal::variant_to_mono_object(result);
}
+MonoObject *godot_icall_Globals_EditorShortcut(MonoString *p_setting) {
+ String setting = GDMonoMarshal::mono_string_to_godot(p_setting);
+ Ref<Shortcut> result = ED_GET_SHORTCUT(setting);
+ return GDMonoMarshal::variant_to_mono_object(result);
+}
+
MonoString *godot_icall_Globals_TTR(MonoString *p_text) {
String text = GDMonoMarshal::mono_string_to_godot(p_text);
return GDMonoMarshal::mono_string_from_godot(TTR(text));
@@ -395,9 +358,6 @@ void register_editor_internal_calls() {
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Dispose", godot_icall_EditorProgress_Dispose);
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Step", godot_icall_EditorProgress_Step);
- // ScriptClassParser
- GDMonoUtils::add_internal_call("GodotTools.Internals.ScriptClassParser::internal_ParseFile", godot_icall_ScriptClassParser_ParseFile);
-
// ExportPlugin
GDMonoUtils::add_internal_call("GodotTools.Export.ExportPlugin::internal_GetExportedAssemblyDependencies", godot_icall_ExportPlugin_GetExportedAssemblyDependencies);
@@ -416,7 +376,6 @@ void register_editor_internal_calls() {
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorDebuggerNodeReloadScripts", godot_icall_Internal_EditorDebuggerNodeReloadScripts);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ScriptEditorEdit", godot_icall_Internal_ScriptEditorEdit);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorNodeShowScriptScreen", godot_icall_Internal_EditorNodeShowScriptScreen);
- GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GetScriptsMetadataOrNothing", godot_icall_Internal_GetScriptsMetadataOrNothing);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_MonoWindowsInstallRoot", godot_icall_Internal_MonoWindowsInstallRoot);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunPlay", godot_icall_Internal_EditorRunPlay);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunStop", godot_icall_Internal_EditorRunStop);
@@ -427,6 +386,7 @@ void register_editor_internal_calls() {
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_EditorScale", godot_icall_Globals_EditorScale);
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_GlobalDef", godot_icall_Globals_GlobalDef);
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_EditorDef", godot_icall_Globals_EditorDef);
+ GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_EditorShortcut", godot_icall_Globals_EditorShortcut);
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_TTR", godot_icall_Globals_TTR);
// Utils.OS
diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp
index 4b858c0e82..54dbaebf38 100644
--- a/modules/mono/editor/godotsharp_export.cpp
+++ b/modules/mono/editor/godotsharp_export.cpp
@@ -91,7 +91,7 @@ Error get_assembly_dependencies(GDMonoAssembly *p_assembly, MonoAssemblyName *re
mono_assembly_get_assemblyref(image, i, reusable_aname);
- GDMonoAssembly *ref_assembly = NULL;
+ GDMonoAssembly *ref_assembly = nullptr;
if (!GDMono::get_singleton()->load_assembly(ref_name, reusable_aname, &ref_assembly, /* refonly: */ true, p_search_dirs)) {
ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
}
diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp
deleted file mode 100644
index e81cbe4ebd..0000000000
--- a/modules/mono/editor/script_class_parser.cpp
+++ /dev/null
@@ -1,753 +0,0 @@
-/*************************************************************************/
-/* script_class_parser.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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. */
-/*************************************************************************/
-
-#include "script_class_parser.h"
-
-#include "core/os/os.h"
-#include "core/templates/map.h"
-
-#include "../utils/string_utils.h"
-
-const char *ScriptClassParser::token_names[ScriptClassParser::TK_MAX] = {
- "[",
- "]",
- "{",
- "}",
- ".",
- ":",
- ",",
- "Symbol",
- "Identifier",
- "String",
- "Number",
- "<",
- ">",
- "EOF",
- "Error"
-};
-
-String ScriptClassParser::get_token_name(ScriptClassParser::Token p_token) {
- ERR_FAIL_INDEX_V(p_token, TK_MAX, "<error>");
- return token_names[p_token];
-}
-
-ScriptClassParser::Token ScriptClassParser::get_token() {
- while (true) {
- switch (code[idx]) {
- case '\n': {
- line++;
- idx++;
- break;
- };
- case 0: {
- return TK_EOF;
- } break;
- case '{': {
- idx++;
- return TK_CURLY_BRACKET_OPEN;
- };
- case '}': {
- idx++;
- return TK_CURLY_BRACKET_CLOSE;
- };
- case '[': {
- idx++;
- return TK_BRACKET_OPEN;
- };
- case ']': {
- idx++;
- return TK_BRACKET_CLOSE;
- };
- case '<': {
- idx++;
- return TK_OP_LESS;
- };
- case '>': {
- idx++;
- return TK_OP_GREATER;
- };
- case ':': {
- idx++;
- return TK_COLON;
- };
- case ',': {
- idx++;
- return TK_COMMA;
- };
- case '.': {
- idx++;
- return TK_PERIOD;
- };
- case '#': {
- //compiler directive
- while (code[idx] != '\n' && code[idx] != 0) {
- idx++;
- }
- continue;
- } break;
- case '/': {
- switch (code[idx + 1]) {
- case '*': { // block comment
- idx += 2;
- while (true) {
- if (code[idx] == 0) {
- error_str = "Unterminated comment";
- error = true;
- return TK_ERROR;
- } else if (code[idx] == '*' && code[idx + 1] == '/') {
- idx += 2;
- break;
- } else if (code[idx] == '\n') {
- line++;
- }
-
- idx++;
- }
-
- } break;
- case '/': { // line comment skip
- while (code[idx] != '\n' && code[idx] != 0) {
- idx++;
- }
-
- } break;
- default: {
- value = "/";
- idx++;
- return TK_SYMBOL;
- }
- }
-
- continue; // a comment
- } break;
- case '\'':
- case '"': {
- bool verbatim = idx != 0 && code[idx - 1] == '@';
-
- char32_t begin_str = code[idx];
- idx++;
- String tk_string = String();
- while (true) {
- if (code[idx] == 0) {
- error_str = "Unterminated String";
- error = true;
- return TK_ERROR;
- } else if (code[idx] == begin_str) {
- if (verbatim && code[idx + 1] == '"') { // '""' is verbatim string's '\"'
- idx += 2; // skip next '"' as well
- continue;
- }
-
- idx += 1;
- break;
- } else if (code[idx] == '\\' && !verbatim) {
- //escaped characters...
- idx++;
- char32_t next = code[idx];
- if (next == 0) {
- error_str = "Unterminated String";
- error = true;
- return TK_ERROR;
- }
- char32_t res = 0;
-
- switch (next) {
- case 'b':
- res = 8;
- break;
- case 't':
- res = 9;
- break;
- case 'n':
- res = 10;
- break;
- case 'f':
- res = 12;
- break;
- case 'r':
- res = 13;
- break;
- case '\"':
- res = '\"';
- break;
- case '\\':
- res = '\\';
- break;
- default: {
- res = next;
- } break;
- }
-
- tk_string += res;
-
- } else {
- if (code[idx] == '\n') {
- line++;
- }
- tk_string += code[idx];
- }
- idx++;
- }
-
- value = tk_string;
-
- return TK_STRING;
- } break;
- default: {
- if (code[idx] <= 32) {
- idx++;
- break;
- }
-
- if ((code[idx] >= 33 && code[idx] <= 47) || (code[idx] >= 58 && code[idx] <= 63) || (code[idx] >= 91 && code[idx] <= 94) || code[idx] == 96 || (code[idx] >= 123 && code[idx] <= 127)) {
- value = String::chr(code[idx]);
- idx++;
- return TK_SYMBOL;
- }
-
- if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) {
- //a number
- const char32_t *rptr;
- double number = String::to_float(&code[idx], &rptr);
- idx += (rptr - &code[idx]);
- value = number;
- return TK_NUMBER;
-
- } else if ((code[idx] == '@' && code[idx + 1] != '"') || code[idx] == '_' || (code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || code[idx] > 127) {
- String id;
-
- id += code[idx];
- idx++;
-
- while (code[idx] == '_' || (code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || (code[idx] >= '0' && code[idx] <= '9') || code[idx] > 127) {
- id += code[idx];
- idx++;
- }
-
- value = id;
- return TK_IDENTIFIER;
- } else if (code[idx] == '@' && code[idx + 1] == '"') {
- // begin of verbatim string
- idx++;
- } else {
- error_str = "Unexpected character.";
- error = true;
- return TK_ERROR;
- }
- }
- }
- }
-}
-
-Error ScriptClassParser::_skip_generic_type_params() {
- Token tk;
-
- while (true) {
- tk = get_token();
-
- if (tk == TK_IDENTIFIER) {
- tk = get_token();
- // Type specifications can end with "?" to denote nullable types, such as IList<int?>
- if (tk == TK_SYMBOL) {
- tk = get_token();
- if (value.operator String() != "?") {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found unexpected symbol '" + value + "'";
- error = true;
- return ERR_PARSE_ERROR;
- }
- if (tk != TK_OP_GREATER && tk != TK_COMMA) {
- error_str = "Nullable type symbol '?' is only allowed after an identifier, but found " + get_token_name(tk) + " next.";
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-
- if (tk == TK_PERIOD) {
- while (true) {
- tk = get_token();
-
- if (tk != TK_IDENTIFIER) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
-
- if (tk != TK_PERIOD) {
- break;
- }
- }
- }
-
- if (tk == TK_OP_LESS) {
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- tk = get_token();
- }
-
- if (tk == TK_OP_GREATER) {
- return OK;
- } else if (tk != TK_COMMA) {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- } else if (tk == TK_OP_LESS) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found " + get_token_name(TK_OP_LESS);
- error = true;
- return ERR_PARSE_ERROR;
- } else if (tk == TK_OP_GREATER) {
- return OK;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-}
-
-Error ScriptClassParser::_parse_type_full_name(String &r_full_name) {
- Token tk = get_token();
-
- if (tk != TK_IDENTIFIER) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- r_full_name += String(value);
-
- if (code[idx] == '<') {
- idx++;
-
- // We don't mind if the base is generic, but we skip it any ways since this information is not needed
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- }
-
- if (code[idx] != '.') { // We only want to take the next token if it's a period
- return OK;
- }
-
- tk = get_token();
-
- CRASH_COND(tk != TK_PERIOD); // Assertion
-
- r_full_name += ".";
-
- return _parse_type_full_name(r_full_name);
-}
-
-Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
- String name;
-
- Error err = _parse_type_full_name(name);
- if (err) {
- return err;
- }
-
- Token tk = get_token();
-
- if (tk == TK_COMMA) {
- err = _parse_class_base(r_base);
- if (err) {
- return err;
- }
- } else if (tk == TK_IDENTIFIER && String(value) == "where") {
- err = _parse_type_constraints();
- if (err) {
- return err;
- }
-
- // An open curly bracket was parsed by _parse_type_constraints, so we can exit
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- // we are finished when we hit the open curly bracket
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- r_base.push_back(name);
-
- return OK;
-}
-
-Error ScriptClassParser::_parse_type_constraints() {
- Token tk = get_token();
- if (tk != TK_IDENTIFIER) {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
- if (tk != TK_COLON) {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- while (true) {
- tk = get_token();
- if (tk == TK_IDENTIFIER) {
- if (String(value) == "where") {
- return _parse_type_constraints();
- }
-
- tk = get_token();
- if (tk == TK_PERIOD) {
- while (true) {
- tk = get_token();
-
- if (tk != TK_IDENTIFIER) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
-
- if (tk != TK_PERIOD) {
- break;
- }
- }
- }
- }
-
- if (tk == TK_COMMA) {
- continue;
- } else if (tk == TK_IDENTIFIER && String(value) == "where") {
- return _parse_type_constraints();
- } else if (tk == TK_SYMBOL && String(value) == "(") {
- tk = get_token();
- if (tk != TK_SYMBOL || String(value) != ")") {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- } else if (tk == TK_OP_LESS) {
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- return OK;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-}
-
-Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) {
- Token tk = get_token();
-
- if (tk == TK_IDENTIFIER) {
- r_name += String(value);
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
-
- if (tk == TK_PERIOD) {
- r_name += ".";
- return _parse_namespace_name(r_name, r_curly_stack);
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- r_curly_stack++;
- return OK;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-}
-
-Error ScriptClassParser::parse(const String &p_code) {
- code = p_code;
- idx = 0;
- line = 0;
- error_str = String();
- error = false;
- value = Variant();
- classes.clear();
-
- Token tk = get_token();
-
- Map<int, NameDecl> name_stack;
- int curly_stack = 0;
- int type_curly_stack = 0;
-
- while (!error && tk != TK_EOF) {
- String identifier = value;
- if (tk == TK_IDENTIFIER && (identifier == "class" || identifier == "struct")) {
- bool is_class = identifier == "class";
-
- tk = get_token();
-
- if (tk == TK_IDENTIFIER) {
- String name = value;
- int at_level = curly_stack;
-
- ClassDecl class_decl;
-
- for (Map<int, NameDecl>::Element *E = name_stack.front(); E; E = E->next()) {
- const NameDecl &name_decl = E->value();
-
- if (name_decl.type == NameDecl::NAMESPACE_DECL) {
- if (E != name_stack.front()) {
- class_decl.namespace_ += ".";
- }
- class_decl.namespace_ += name_decl.name;
- } else {
- class_decl.name += name_decl.name + ".";
- }
- }
-
- class_decl.name += name;
- class_decl.nested = type_curly_stack > 0;
-
- bool generic = false;
-
- while (true) {
- tk = get_token();
-
- if (tk == TK_COLON) {
- Error err = _parse_class_base(class_decl.base);
- if (err) {
- return err;
- }
-
- curly_stack++;
- type_curly_stack++;
-
- break;
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- curly_stack++;
- type_curly_stack++;
- break;
- } else if (tk == TK_OP_LESS && !generic) {
- generic = true;
-
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- } else if (tk == TK_IDENTIFIER && String(value) == "where") {
- Error err = _parse_type_constraints();
- if (err) {
- return err;
- }
-
- // An open curly bracket was parsed by _parse_type_constraints, so we can exit
- curly_stack++;
- type_curly_stack++;
- break;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-
- NameDecl name_decl;
- name_decl.name = name;
- name_decl.type = is_class ? NameDecl::CLASS_DECL : NameDecl::STRUCT_DECL;
- name_stack[at_level] = name_decl;
-
- if (is_class) {
- if (!generic) { // no generics, thanks
- classes.push_back(class_decl);
- } else if (OS::get_singleton()->is_stdout_verbose()) {
- String full_name = class_decl.namespace_;
- if (full_name.length()) {
- full_name += ".";
- }
- full_name += class_decl.name;
- OS::get_singleton()->print("Ignoring generic class declaration: %s\n", full_name.utf8().get_data());
- }
- }
- }
- } else if (tk == TK_IDENTIFIER && identifier == "namespace") {
- if (type_curly_stack > 0) {
- error_str = "Found namespace nested inside type.";
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- String name;
- int at_level = curly_stack;
-
- Error err = _parse_namespace_name(name, curly_stack);
- if (err) {
- return err;
- }
-
- NameDecl name_decl;
- name_decl.name = name;
- name_decl.type = NameDecl::NAMESPACE_DECL;
- name_stack[at_level] = name_decl;
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- curly_stack++;
- } else if (tk == TK_CURLY_BRACKET_CLOSE) {
- curly_stack--;
- if (name_stack.has(curly_stack)) {
- if (name_stack[curly_stack].type != NameDecl::NAMESPACE_DECL) {
- type_curly_stack--;
- }
- name_stack.erase(curly_stack);
- }
- }
-
- tk = get_token();
- }
-
- if (!error && tk == TK_EOF && curly_stack > 0) {
- error_str = "Reached EOF with missing close curly brackets.";
- error = true;
- }
-
- if (error) {
- return ERR_PARSE_ERROR;
- }
-
- return OK;
-}
-
-static String get_preprocessor_directive(const String &p_line, int p_from) {
- CRASH_COND(p_line[p_from] != '#');
- p_from++;
- int i = p_from;
- while (i < p_line.length() && (p_line[i] == '_' || (p_line[i] >= 'A' && p_line[i] <= 'Z') ||
- (p_line[i] >= 'a' && p_line[i] <= 'z') || p_line[i] > 127)) {
- i++;
- }
- return p_line.substr(p_from, i - p_from);
-}
-
-static void run_dummy_preprocessor(String &r_source, const String &p_filepath) {
- Vector<String> lines = r_source.split("\n", /* p_allow_empty: */ true);
-
- bool *include_lines = memnew_arr(bool, lines.size());
-
- int if_level = -1;
- Vector<bool> is_branch_being_compiled;
-
- for (int i = 0; i < lines.size(); i++) {
- const String &line = lines[i];
-
- const int line_len = line.length();
-
- int j;
- for (j = 0; j < line_len; j++) {
- if (line[j] != ' ' && line[j] != '\t') {
- if (line[j] == '#') {
- // First non-whitespace char of the line is '#'
- include_lines[i] = false;
-
- String directive = get_preprocessor_directive(line, j);
-
- if (directive == "if") {
- if_level++;
- is_branch_being_compiled.push_back(if_level == 0 || is_branch_being_compiled[if_level - 1]);
- } else if (directive == "elif") {
- ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#elif' directive. File: '" + p_filepath + "'.");
- is_branch_being_compiled.write[if_level] = false;
- } else if (directive == "else") {
- ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#else' directive. File: '" + p_filepath + "'.");
- is_branch_being_compiled.write[if_level] = false;
- } else if (directive == "endif") {
- ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#endif' directive. File: '" + p_filepath + "'.");
- is_branch_being_compiled.remove(if_level);
- if_level--;
- }
-
- break;
- } else {
- // First non-whitespace char of the line is not '#'
- include_lines[i] = if_level == -1 || is_branch_being_compiled[if_level];
- break;
- }
- }
- }
-
- if (j == line_len) {
- // Loop ended without finding a non-whitespace character.
- // Either the line was empty or it only contained whitespaces.
- include_lines[i] = if_level == -1 || is_branch_being_compiled[if_level];
- }
- }
-
- r_source.clear();
-
- // Custom join ignoring lines removed by the preprocessor
- for (int i = 0; i < lines.size(); i++) {
- if (i > 0 && include_lines[i - 1]) {
- r_source += '\n';
- }
-
- if (include_lines[i]) {
- r_source += lines[i];
- }
- }
-}
-
-Error ScriptClassParser::parse_file(const String &p_filepath) {
- String source;
-
- Error ferr = read_all_file_utf8(p_filepath, source);
-
- ERR_FAIL_COND_V_MSG(ferr != OK, ferr,
- ferr == ERR_INVALID_DATA ?
- "File '" + p_filepath + "' contains invalid unicode (UTF-8), so it was not loaded."
- " Please ensure that scripts are saved in valid UTF-8 unicode." :
- "Failed to read file: '" + p_filepath + "'.");
-
- run_dummy_preprocessor(source, p_filepath);
-
- return parse(source);
-}
-
-String ScriptClassParser::get_error() {
- return error_str;
-}
-
-Vector<ScriptClassParser::ClassDecl> ScriptClassParser::get_classes() {
- return classes;
-}
diff --git a/modules/mono/editor/script_class_parser.h b/modules/mono/editor/script_class_parser.h
deleted file mode 100644
index 75a46bb4e5..0000000000
--- a/modules/mono/editor/script_class_parser.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************************************/
-/* script_class_parser.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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. */
-/*************************************************************************/
-
-#ifndef SCRIPT_CLASS_PARSER_H
-#define SCRIPT_CLASS_PARSER_H
-
-#include "core/string/ustring.h"
-#include "core/templates/vector.h"
-#include "core/variant/variant.h"
-
-class ScriptClassParser {
-public:
- struct NameDecl {
- enum Type {
- NAMESPACE_DECL,
- CLASS_DECL,
- STRUCT_DECL
- };
-
- String name;
- Type type = NAMESPACE_DECL;
- };
-
- struct ClassDecl {
- String name;
- String namespace_;
- Vector<String> base;
- bool nested = false;
- };
-
-private:
- String code;
- int idx = 0;
- int line = 0;
- String error_str;
- bool error = false;
- Variant value;
-
- Vector<ClassDecl> classes;
-
- enum Token {
- TK_BRACKET_OPEN,
- TK_BRACKET_CLOSE,
- TK_CURLY_BRACKET_OPEN,
- TK_CURLY_BRACKET_CLOSE,
- TK_PERIOD,
- TK_COLON,
- TK_COMMA,
- TK_SYMBOL,
- TK_IDENTIFIER,
- TK_STRING,
- TK_NUMBER,
- TK_OP_LESS,
- TK_OP_GREATER,
- TK_EOF,
- TK_ERROR,
- TK_MAX
- };
-
- static const char *token_names[TK_MAX];
- static String get_token_name(Token p_token);
-
- Token get_token();
-
- Error _skip_generic_type_params();
-
- Error _parse_type_full_name(String &r_full_name);
- Error _parse_class_base(Vector<String> &r_base);
- Error _parse_type_constraints();
- Error _parse_namespace_name(String &r_name, int &r_curly_stack);
-
-public:
- Error parse(const String &p_code);
- Error parse_file(const String &p_filepath);
-
- String get_error();
-
- Vector<ClassDecl> get_classes();
-};
-
-#endif // SCRIPT_CLASS_PARSER_H
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
index 3aecce50f5..8b12537f7f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
@@ -1,16 +1,10 @@
-// file: core/math/aabb.h
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/math/aabb.cpp
-// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
-// file: core/variant_call.cpp
-// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -26,7 +20,7 @@ namespace Godot
private Vector3 _size;
/// <summary>
- /// Beginning corner. Typically has values lower than End.
+ /// Beginning corner. Typically has values lower than <see cref="End"/>.
/// </summary>
/// <value>Directly uses a private field.</value>
public Vector3 Position
@@ -36,7 +30,7 @@ namespace Godot
}
/// <summary>
- /// Size from Position to End. Typically all components are positive.
+ /// Size from <see cref="Position"/> to <see cref="End"/>. Typically all components are positive.
/// If the size is negative, you can use <see cref="Abs"/> to fix it.
/// </summary>
/// <value>Directly uses a private field.</value>
@@ -50,7 +44,10 @@ namespace Godot
/// Ending corner. This is calculated as <see cref="Position"/> plus
/// <see cref="Size"/>. Setting this value will change the size.
/// </summary>
- /// <value>Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`.</value>
+ /// <value>
+ /// 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 Vector3 End
{
get { return _position + _size; }
@@ -58,10 +55,10 @@ namespace Godot
}
/// <summary>
- /// Returns an AABB with equivalent position and size, modified so that
+ /// 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 AABB.</returns>
+ /// <returns>The modified <see cref="AABB"/>.</returns>
public AABB Abs()
{
Vector3 end = End;
@@ -70,30 +67,32 @@ namespace Godot
}
/// <summary>
- /// Returns true if this AABB completely encloses another one.
+ /// Returns <see langword="true"/> if this <see cref="AABB"/> completely encloses another one.
/// </summary>
- /// <param name="with">The other AABB that may be enclosed.</param>
- /// <returns>A bool for whether or not this AABB encloses `b`.</returns>
+ /// <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"/>.
+ /// </returns>
public bool Encloses(AABB with)
{
- Vector3 src_min = _position;
- Vector3 src_max = _position + _size;
- Vector3 dst_min = with._position;
- Vector3 dst_max = with._position + with._size;
+ Vector3 srcMin = _position;
+ Vector3 srcMax = _position + _size;
+ Vector3 dstMin = with._position;
+ Vector3 dstMax = with._position + with._size;
- return src_min.x <= dst_min.x &&
- src_max.x > dst_max.x &&
- src_min.y <= dst_min.y &&
- src_max.y > dst_max.y &&
- src_min.z <= dst_min.z &&
- src_max.z > dst_max.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 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 AABB.</returns>
+ /// <returns>The expanded <see cref="AABB"/>.</returns>
public AABB Expand(Vector3 point)
{
Vector3 begin = _position;
@@ -129,7 +128,7 @@ namespace Godot
}
/// <summary>
- /// Returns the area of the AABB.
+ /// Returns the area of the <see cref="AABB"/>.
/// </summary>
/// <returns>The area.</returns>
public real_t GetArea()
@@ -138,10 +137,10 @@ namespace Godot
}
/// <summary>
- /// Gets the position of one of the 8 endpoints of the AABB.
+ /// Gets the position of one of the 8 endpoints of the <see cref="AABB"/>.
/// </summary>
/// <param name="idx">Which endpoint to get.</param>
- /// <returns>An endpoint of the AABB.</returns>
+ /// <returns>An endpoint of the <see cref="AABB"/>.</returns>
public Vector3 GetEndpoint(int idx)
{
switch (idx)
@@ -163,26 +162,29 @@ namespace Godot
case 7:
return new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z + _size.z);
default:
- throw new ArgumentOutOfRangeException(nameof(idx), String.Format("Index is {0}, but a value from 0 to 7 is expected.", idx));
+ {
+ throw new ArgumentOutOfRangeException(nameof(idx),
+ $"Index is {idx}, but a value from 0 to 7 is expected.");
+ }
}
}
/// <summary>
- /// Returns the normalized longest axis of the AABB.
+ /// Returns the normalized longest axis of the <see cref="AABB"/>.
/// </summary>
- /// <returns>A vector representing the normalized longest axis of the AABB.</returns>
+ /// <returns>A vector representing the normalized longest axis of the <see cref="AABB"/>.</returns>
public Vector3 GetLongestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
- real_t max_size = _size.x;
+ real_t maxSize = _size.x;
- if (_size.y > max_size)
+ if (_size.y > maxSize)
{
axis = new Vector3(0f, 1f, 0f);
- max_size = _size.y;
+ maxSize = _size.y;
}
- if (_size.z > max_size)
+ if (_size.z > maxSize)
{
axis = new Vector3(0f, 0f, 1f);
}
@@ -191,21 +193,21 @@ namespace Godot
}
/// <summary>
- /// Returns the <see cref="Vector3.Axis"/> index of the longest axis of the 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()
{
var axis = Vector3.Axis.X;
- real_t max_size = _size.x;
+ real_t maxSize = _size.x;
- if (_size.y > max_size)
+ if (_size.y > maxSize)
{
axis = Vector3.Axis.Y;
- max_size = _size.y;
+ maxSize = _size.y;
}
- if (_size.z > max_size)
+ if (_size.z > maxSize)
{
axis = Vector3.Axis.Z;
}
@@ -214,38 +216,38 @@ namespace Godot
}
/// <summary>
- /// Returns the scalar length of the longest axis of the 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 AABB.</returns>
+ /// <returns>The scalar length of the longest axis of the <see cref="AABB"/>.</returns>
public real_t GetLongestAxisSize()
{
- real_t max_size = _size.x;
+ real_t maxSize = _size.x;
- if (_size.y > max_size)
- max_size = _size.y;
+ if (_size.y > maxSize)
+ maxSize = _size.y;
- if (_size.z > max_size)
- max_size = _size.z;
+ if (_size.z > maxSize)
+ maxSize = _size.z;
- return max_size;
+ return maxSize;
}
/// <summary>
- /// Returns the normalized shortest axis of the AABB.
+ /// Returns the normalized shortest axis of the <see cref="AABB"/>.
/// </summary>
- /// <returns>A vector representing the normalized shortest axis of the AABB.</returns>
+ /// <returns>A vector representing the normalized shortest axis of the <see cref="AABB"/>.</returns>
public Vector3 GetShortestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
- real_t max_size = _size.x;
+ real_t maxSize = _size.x;
- if (_size.y < max_size)
+ if (_size.y < maxSize)
{
axis = new Vector3(0f, 1f, 0f);
- max_size = _size.y;
+ maxSize = _size.y;
}
- if (_size.z < max_size)
+ if (_size.z < maxSize)
{
axis = new Vector3(0f, 0f, 1f);
}
@@ -254,21 +256,21 @@ namespace Godot
}
/// <summary>
- /// Returns the <see cref="Vector3.Axis"/> index of the shortest axis of the 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()
{
var axis = Vector3.Axis.X;
- real_t max_size = _size.x;
+ real_t maxSize = _size.x;
- if (_size.y < max_size)
+ if (_size.y < maxSize)
{
axis = Vector3.Axis.Y;
- max_size = _size.y;
+ maxSize = _size.y;
}
- if (_size.z < max_size)
+ if (_size.z < maxSize)
{
axis = Vector3.Axis.Z;
}
@@ -277,20 +279,20 @@ namespace Godot
}
/// <summary>
- /// Returns the scalar length of the shortest axis of the 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 AABB.</returns>
+ /// <returns>The scalar length of the shortest axis of the <see cref="AABB"/>.</returns>
public real_t GetShortestAxisSize()
{
- real_t max_size = _size.x;
+ real_t maxSize = _size.x;
- if (_size.y < max_size)
- max_size = _size.y;
+ if (_size.y < maxSize)
+ maxSize = _size.y;
- if (_size.z < max_size)
- max_size = _size.z;
+ if (_size.z < maxSize)
+ maxSize = _size.z;
- return max_size;
+ return maxSize;
}
/// <summary>
@@ -301,23 +303,23 @@ namespace Godot
/// <returns>A vector representing the support.</returns>
public Vector3 GetSupport(Vector3 dir)
{
- Vector3 half_extents = _size * 0.5f;
- Vector3 ofs = _position + half_extents;
+ Vector3 halfExtents = _size * 0.5f;
+ Vector3 ofs = _position + halfExtents;
return ofs + new Vector3(
- dir.x > 0f ? -half_extents.x : half_extents.x,
- dir.y > 0f ? -half_extents.y : half_extents.y,
- dir.z > 0f ? -half_extents.z : half_extents.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 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 AABB.</returns>
+ /// <returns>The grown <see cref="AABB"/>.</returns>
public AABB Grow(real_t by)
{
- var res = this;
+ AABB res = this;
res._position.x -= by;
res._position.y -= by;
@@ -330,28 +332,37 @@ namespace Godot
}
/// <summary>
- /// Returns true if the AABB is flat or empty, or false otherwise.
+ /// Returns <see langword="true"/> if the <see cref="AABB"/> is flat or empty,
+ /// or <see langword="false"/> otherwise.
/// </summary>
- /// <returns>A bool for whether or not the AABB has area.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has area.
+ /// </returns>
public bool HasNoArea()
{
return _size.x <= 0f || _size.y <= 0f || _size.z <= 0f;
}
/// <summary>
- /// Returns true if the AABB has no surface (no size), or false otherwise.
+ /// Returns <see langword="true"/> if the <see cref="AABB"/> has no surface (no size),
+ /// or <see langword="false"/> otherwise.
/// </summary>
- /// <returns>A bool for whether or not the AABB has area.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has area.
+ /// </returns>
public bool HasNoSurface()
{
return _size.x <= 0f && _size.y <= 0f && _size.z <= 0f;
}
/// <summary>
- /// Returns true if the AABB contains a point, or false otherwise.
+ /// 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 bool for whether or not the AABB contains `point`.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> contains <paramref name="point"/>.
+ /// </returns>
public bool HasPoint(Vector3 point)
{
if (point.x < _position.x)
@@ -371,56 +382,59 @@ namespace Godot
}
/// <summary>
- /// Returns the intersection of this AABB and `b`.
+ /// Returns the intersection of this <see cref="AABB"/> and <paramref name="with"/>.
/// </summary>
- /// <param name="with">The other AABB.</param>
- /// <returns>The clipped AABB.</returns>
+ /// <param name="with">The other <see cref="AABB"/>.</param>
+ /// <returns>The clipped <see cref="AABB"/>.</returns>
public AABB Intersection(AABB with)
{
- Vector3 src_min = _position;
- Vector3 src_max = _position + _size;
- Vector3 dst_min = with._position;
- Vector3 dst_max = with._position + with._size;
+ Vector3 srcMin = _position;
+ Vector3 srcMax = _position + _size;
+ Vector3 dstMin = with._position;
+ Vector3 dstMax = with._position + with._size;
Vector3 min, max;
- if (src_min.x > dst_max.x || src_max.x < dst_min.x)
+ if (srcMin.x > dstMax.x || srcMax.x < dstMin.x)
{
return new AABB();
}
- min.x = src_min.x > dst_min.x ? src_min.x : dst_min.x;
- max.x = src_max.x < dst_max.x ? src_max.x : dst_max.x;
+ min.x = srcMin.x > dstMin.x ? srcMin.x : dstMin.x;
+ max.x = srcMax.x < dstMax.x ? srcMax.x : dstMax.x;
- if (src_min.y > dst_max.y || src_max.y < dst_min.y)
+ if (srcMin.y > dstMax.y || srcMax.y < dstMin.y)
{
return new AABB();
}
- min.y = src_min.y > dst_min.y ? src_min.y : dst_min.y;
- max.y = src_max.y < dst_max.y ? src_max.y : dst_max.y;
+ min.y = srcMin.y > dstMin.y ? srcMin.y : dstMin.y;
+ max.y = srcMax.y < dstMax.y ? srcMax.y : dstMax.y;
- if (src_min.z > dst_max.z || src_max.z < dst_min.z)
+ if (srcMin.z > dstMax.z || srcMax.z < dstMin.z)
{
return new AABB();
}
- min.z = src_min.z > dst_min.z ? src_min.z : dst_min.z;
- max.z = src_max.z < dst_max.z ? src_max.z : dst_max.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);
}
/// <summary>
- /// Returns true if the AABB overlaps with `b`
+ /// 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 `includeBorders` is true, they will also be considered overlapping
- /// if their borders touch, even without intersection.
+ /// 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 AABB to check for intersections with.</param>
+ /// <param name="with">The other <see cref="AABB"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
- /// <returns>A bool for whether or not they are intersecting.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not they are intersecting.
+ /// </returns>
public bool Intersects(AABB with, bool includeBorders = false)
{
if (includeBorders)
@@ -458,10 +472,12 @@ namespace Godot
}
/// <summary>
- /// Returns true if the AABB is on both sides of `plane`.
+ /// Returns <see langword="true"/> if the <see cref="AABB"/> is on both sides of <paramref name="plane"/>.
/// </summary>
- /// <param name="plane">The plane to check for intersection.</param>
- /// <returns>A bool for whether or not the AABB intersects the plane.</returns>
+ /// <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"/>.
+ /// </returns>
public bool IntersectsPlane(Plane plane)
{
Vector3[] points =
@@ -495,11 +511,14 @@ namespace Godot
}
/// <summary>
- /// Returns true if the AABB intersects the line segment between `from` and `to`.
+ /// 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 bool for whether or not the AABB intersects the line segment.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the line segment.
+ /// </returns>
public bool IntersectsSegment(Vector3 from, Vector3 to)
{
real_t min = 0f;
@@ -555,10 +574,10 @@ namespace Godot
}
/// <summary>
- /// Returns a larger AABB that contains this AABB and `b`.
+ /// Returns a larger <see cref="AABB"/> that contains this <see cref="AABB"/> and <paramref name="with"/>.
/// </summary>
- /// <param name="with">The other AABB.</param>
- /// <returns>The merged AABB.</returns>
+ /// <param name="with">The other <see cref="AABB"/>.</param>
+ /// <returns>The merged <see cref="AABB"/>.</returns>
public AABB Merge(AABB with)
{
Vector3 beg1 = _position;
@@ -567,22 +586,22 @@ namespace Godot
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);
}
/// <summary>
- /// Constructs an 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>
@@ -593,7 +612,8 @@ namespace Godot
}
/// <summary>
- /// Constructs an AABB from a position, width, height, and depth.
+ /// 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>
@@ -606,7 +626,8 @@ namespace Godot
}
/// <summary>
- /// Constructs an AABB from x, y, z, and size.
+ /// 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>
@@ -619,7 +640,9 @@ namespace Godot
}
/// <summary>
- /// Constructs an AABB from x, y, z, width, height, and depth.
+ /// 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>
/// <param name="x">The position's X coordinate.</param>
/// <param name="y">The position's Y coordinate.</param>
@@ -643,6 +666,11 @@ namespace Godot
return !left.Equals(right);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this AABB and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the AABB structure and the other object are equal.</returns>
public override bool Equals(object obj)
{
if (obj is AABB)
@@ -653,43 +681,52 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this AABB and <paramref name="other"/> are equal
+ /// </summary>
+ /// <param name="other">The other AABB to compare.</param>
+ /// <returns>Whether or not the AABBs are equal.</returns>
public bool Equals(AABB other)
{
return _position == other._position && _size == other._size;
}
/// <summary>
- /// Returns true if this AABB and `other` are approximately equal, by running
- /// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
+ /// Returns <see langword="true"/> if this AABB and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
/// </summary>
/// <param name="other">The other AABB to compare.</param>
- /// <returns>Whether or not the AABBs are approximately equal.</returns>
+ /// <returns>Whether or not the AABBs structures are approximately equal.</returns>
public bool IsEqualApprox(AABB other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size);
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="AABB"/>.
+ /// </summary>
+ /// <returns>A hash code for this AABB.</returns>
public override int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
+ /// <summary>
+ /// Converts this <see cref="AABB"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this AABB.</returns>
public override string ToString()
{
- return String.Format("{0} - {1}", new object[]
- {
- _position.ToString(),
- _size.ToString()
- });
+ return $"{_position}, {_size}";
}
+ /// <summary>
+ /// 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)
{
- return String.Format("{0} - {1}", new object[]
- {
- _position.ToString(format),
- _size.ToString(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 ce613f7ef9..a412047196 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
namespace Godot.Collections
{
- class ArraySafeHandle : SafeHandle
+ internal class ArraySafeHandle : SafeHandle
{
public ArraySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
{
@@ -25,16 +25,30 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Wrapper around Godot's Array class, an array of Variant
+ /// typed elements allocated in the engine in C++. Useful when
+ /// interfacing with the engine. Otherwise prefer .NET collections
+ /// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
+ /// </summary>
public class Array : IList, IDisposable
{
- ArraySafeHandle safeHandle;
- bool disposed = false;
+ private ArraySafeHandle _safeHandle;
+ private bool _disposed = false;
+ /// <summary>
+ /// Constructs a new empty <see cref="Array"/>.
+ /// </summary>
public Array()
{
- safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
+ _safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
}
+ /// <summary>
+ /// Constructs a new <see cref="Array"/> from the given collection's elements.
+ /// </summary>
+ /// <param name="collection">The collection of elements to construct from.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(IEnumerable collection) : this()
{
if (collection == null)
@@ -44,48 +58,72 @@ namespace Godot.Collections
Add(element);
}
+ /// <summary>
+ /// Constructs a new <see cref="Array"/> from the given objects.
+ /// </summary>
+ /// <param name="array">The objects to put in the new array.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(params object[] array) : this()
{
if (array == null)
{
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
}
- safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor_MonoArray(array));
+ _safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor_MonoArray(array));
}
internal Array(ArraySafeHandle handle)
{
- safeHandle = handle;
+ _safeHandle = handle;
}
internal Array(IntPtr handle)
{
- safeHandle = new ArraySafeHandle(handle);
+ _safeHandle = new ArraySafeHandle(handle);
}
internal IntPtr GetPtr()
{
- if (disposed)
+ if (_disposed)
throw new ObjectDisposedException(GetType().FullName);
- return safeHandle.DangerousGetHandle();
+ return _safeHandle.DangerousGetHandle();
}
+ /// <summary>
+ /// Duplicates this <see cref="Array"/>.
+ /// </summary>
+ /// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
+ /// <returns>A new Godot Array.</returns>
public Array Duplicate(bool deep = false)
{
return new Array(godot_icall_Array_Duplicate(GetPtr(), deep));
}
+ /// <summary>
+ /// Resizes this <see cref="Array"/> to the given size.
+ /// </summary>
+ /// <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)
{
return godot_icall_Array_Resize(GetPtr(), newSize);
}
+ /// <summary>
+ /// Shuffles the contents of this <see cref="Array"/> into a random order.
+ /// </summary>
public void Shuffle()
{
godot_icall_Array_Shuffle(GetPtr());
}
+ /// <summary>
+ /// Concatenates these two <see cref="Array"/>s.
+ /// </summary>
+ /// <param name="left">The first array.</param>
+ /// <param name="right">The second array.</param>
+ /// <returns>A new Godot Array with the contents of both arrays.</returns>
public static Array operator +(Array left, Array right)
{
return new Array(godot_icall_Array_Concatenate(left.GetPtr(), right.GetPtr()));
@@ -93,54 +131,109 @@ namespace Godot.Collections
// IDisposable
+ /// <summary>
+ /// Disposes of this <see cref="Array"/>.
+ /// </summary>
public void Dispose()
{
- if (disposed)
+ if (_disposed)
return;
- if (safeHandle != null)
+ if (_safeHandle != null)
{
- safeHandle.Dispose();
- safeHandle = null;
+ _safeHandle.Dispose();
+ _safeHandle = null;
}
- disposed = true;
+ _disposed = true;
}
// IList
- public bool IsReadOnly => false;
+ bool IList.IsReadOnly => false;
- public bool IsFixedSize => false;
+ bool IList.IsFixedSize => false;
+ /// <summary>
+ /// Returns the object at the given <paramref name="index"/>.
+ /// </summary>
+ /// <value>The object at the given <paramref name="index"/>.</value>
public object this[int index]
{
get => godot_icall_Array_At(GetPtr(), index);
set => godot_icall_Array_SetAt(GetPtr(), index, value);
}
+ /// <summary>
+ /// Adds an object to the end of this <see cref="Array"/>.
+ /// This is the same as <c>append</c> or <c>push_back</c> in GDScript.
+ /// </summary>
+ /// <param name="value">The object to add.</param>
+ /// <returns>The new size after adding the object.</returns>
public int Add(object value) => godot_icall_Array_Add(GetPtr(), value);
+ /// <summary>
+ /// Checks if this <see cref="Array"/> contains the given object.
+ /// </summary>
+ /// <param name="value">The item to look for.</param>
+ /// <returns>Whether or not this array contains the given object.</returns>
public bool Contains(object value) => godot_icall_Array_Contains(GetPtr(), value);
+ /// <summary>
+ /// Erases all items from this <see cref="Array"/>.
+ /// </summary>
public void Clear() => godot_icall_Array_Clear(GetPtr());
+ /// <summary>
+ /// Searches this <see cref="Array"/> for an object
+ /// and returns its index or -1 if not found.
+ /// </summary>
+ /// <param name="value">The object to search for.</param>
+ /// <returns>The index of the object, or -1 if not found.</returns>
public int IndexOf(object value) => godot_icall_Array_IndexOf(GetPtr(), value);
+ /// <summary>
+ /// Inserts a new object 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.
+ /// Existing items will be moved to the right.
+ /// </summary>
+ /// <param name="index">The index to insert at.</param>
+ /// <param name="value">The object to insert.</param>
public void Insert(int index, object value) => godot_icall_Array_Insert(GetPtr(), index, value);
+ /// <summary>
+ /// Removes the first occurrence of the specified <paramref name="value"/>
+ /// from this <see cref="Array"/>.
+ /// </summary>
+ /// <param name="value">The value to remove.</param>
public void Remove(object value) => godot_icall_Array_Remove(GetPtr(), value);
+ /// <summary>
+ /// Removes an element from this <see cref="Array"/> by index.
+ /// </summary>
+ /// <param name="index">The index of the element to remove.</param>
public void RemoveAt(int index) => godot_icall_Array_RemoveAt(GetPtr(), index);
// ICollection
+ /// <summary>
+ /// Returns the number of elements in this <see cref="Array"/>.
+ /// This is also known as the size or length of the array.
+ /// </summary>
+ /// <returns>The number of elements.</returns>
public int Count => godot_icall_Array_Count(GetPtr());
- public object SyncRoot => this;
+ object ICollection.SyncRoot => this;
- public bool IsSynchronized => false;
+ bool ICollection.IsSynchronized => false;
+ /// <summary>
+ /// Copies the elements of this <see cref="Array"/> to the given
+ /// untyped C# array, starting at the given index.
+ /// </summary>
+ /// <param name="array">The array to copy to.</param>
+ /// <param name="index">The index to start at.</param>
public void CopyTo(System.Array array, int index)
{
if (array == null)
@@ -155,6 +248,10 @@ namespace Godot.Collections
// IEnumerable
+ /// <summary>
+ /// Gets an enumerator for this <see cref="Array"/>.
+ /// </summary>
+ /// <returns>An enumerator.</returns>
public IEnumerator GetEnumerator()
{
int count = Count;
@@ -165,78 +262,89 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Converts this <see cref="Array"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this array.</returns>
public override string ToString()
{
return godot_icall_Array_ToString(GetPtr());
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Array_Ctor();
+ internal static extern IntPtr godot_icall_Array_Ctor();
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Array_Ctor_MonoArray(System.Array array);
+ internal static extern IntPtr godot_icall_Array_Ctor_MonoArray(System.Array array);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_Dtor(IntPtr ptr);
+ internal static extern void godot_icall_Array_Dtor(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_Array_At(IntPtr ptr, int index);
+ internal static extern object godot_icall_Array_At(IntPtr ptr, int index);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_Array_At_Generic(IntPtr ptr, int index, int elemTypeEncoding, IntPtr elemTypeClass);
+ internal static extern object godot_icall_Array_At_Generic(IntPtr ptr, int index, int elemTypeEncoding, IntPtr elemTypeClass);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
+ internal static extern void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_Array_Count(IntPtr ptr);
+ internal static extern int godot_icall_Array_Count(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_Array_Add(IntPtr ptr, object item);
+ internal static extern int godot_icall_Array_Add(IntPtr ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_Clear(IntPtr ptr);
+ internal static extern void godot_icall_Array_Clear(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Array_Concatenate(IntPtr left, IntPtr right);
+ internal static extern IntPtr godot_icall_Array_Concatenate(IntPtr left, IntPtr right);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item);
+ internal static extern bool godot_icall_Array_Contains(IntPtr ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
+ internal static extern void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep);
+ internal static extern IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item);
+ internal static extern int godot_icall_Array_IndexOf(IntPtr ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_Insert(IntPtr ptr, int index, object item);
+ internal static extern void godot_icall_Array_Insert(IntPtr ptr, int index, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Array_Remove(IntPtr ptr, object item);
+ internal static extern bool godot_icall_Array_Remove(IntPtr ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
+ internal static extern void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static Error godot_icall_Array_Resize(IntPtr ptr, int newSize);
+ internal static extern Error godot_icall_Array_Resize(IntPtr ptr, int newSize);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static Error godot_icall_Array_Shuffle(IntPtr ptr);
+ internal static extern Error godot_icall_Array_Shuffle(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
+ internal static extern void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string godot_icall_Array_ToString(IntPtr ptr);
+ internal static extern string godot_icall_Array_ToString(IntPtr ptr);
}
+ /// <summary>
+ /// Typed wrapper around Godot's Array class, an array of Variant
+ /// typed elements allocated in the engine in C++. Useful when
+ /// interfacing with the engine. Otherwise prefer .NET collections
+ /// such as arrays or <see cref="List{T}"/>.
+ /// </summary>
+ /// <typeparam name="T">The type of the array.</typeparam>
public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
{
- Array objectArray;
+ private Array _objectArray;
internal static int elemTypeEncoding;
internal static IntPtr elemTypeClass;
@@ -246,123 +354,207 @@ namespace Godot.Collections
Array.godot_icall_Array_Generic_GetElementTypeInfo(typeof(T), out elemTypeEncoding, out elemTypeClass);
}
+ /// <summary>
+ /// Constructs a new empty <see cref="Array{T}"/>.
+ /// </summary>
public Array()
{
- objectArray = new Array();
+ _objectArray = new Array();
}
+ /// <summary>
+ /// Constructs a new <see cref="Array{T}"/> from the given collection's elements.
+ /// </summary>
+ /// <param name="collection">The collection of elements to construct from.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(IEnumerable<T> collection)
{
if (collection == null)
throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
- objectArray = new Array(collection);
+ _objectArray = new Array(collection);
}
+ /// <summary>
+ /// Constructs a new <see cref="Array{T}"/> from the given items.
+ /// </summary>
+ /// <param name="array">The items to put in the new array.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(params T[] array) : this()
{
if (array == null)
{
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
}
- objectArray = new Array(array);
+ _objectArray = new Array(array);
}
+ /// <summary>
+ /// Constructs a typed <see cref="Array{T}"/> from an untyped <see cref="Array"/>.
+ /// </summary>
+ /// <param name="array">The untyped array to construct from.</param>
public Array(Array array)
{
- objectArray = array;
+ _objectArray = array;
}
internal Array(IntPtr handle)
{
- objectArray = new Array(handle);
+ _objectArray = new Array(handle);
}
internal Array(ArraySafeHandle handle)
{
- objectArray = new Array(handle);
+ _objectArray = new Array(handle);
}
internal IntPtr GetPtr()
{
- return objectArray.GetPtr();
+ return _objectArray.GetPtr();
}
+ /// <summary>
+ /// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>.
+ /// </summary>
+ /// <param name="from">The typed array to convert.</param>
public static explicit operator Array(Array<T> from)
{
- return from.objectArray;
+ return from._objectArray;
}
+ /// <summary>
+ /// Duplicates this <see cref="Array{T}"/>.
+ /// </summary>
+ /// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
+ /// <returns>A new Godot Array.</returns>
public Array<T> Duplicate(bool deep = false)
{
- return new Array<T>(objectArray.Duplicate(deep));
+ return new Array<T>(_objectArray.Duplicate(deep));
}
+ /// <summary>
+ /// Resizes this <see cref="Array{T}"/> to the given size.
+ /// </summary>
+ /// <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)
{
- return objectArray.Resize(newSize);
+ return _objectArray.Resize(newSize);
}
+ /// <summary>
+ /// Shuffles the contents of this <see cref="Array{T}"/> into a random order.
+ /// </summary>
public void Shuffle()
{
- objectArray.Shuffle();
+ _objectArray.Shuffle();
}
+ /// <summary>
+ /// Concatenates these two <see cref="Array{T}"/>s.
+ /// </summary>
+ /// <param name="left">The first array.</param>
+ /// <param name="right">The second array.</param>
+ /// <returns>A new Godot Array with the contents of both arrays.</returns>
public static Array<T> operator +(Array<T> left, Array<T> right)
{
- return new Array<T>(left.objectArray + right.objectArray);
+ return new Array<T>(left._objectArray + right._objectArray);
}
// IList<T>
+ /// <summary>
+ /// Returns the value at the given <paramref name="index"/>.
+ /// </summary>
+ /// <value>The value at the given <paramref name="index"/>.</value>
public T this[int index]
{
get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); }
- set { objectArray[index] = value; }
+ set { _objectArray[index] = value; }
}
+ /// <summary>
+ /// Searches this <see cref="Array{T}"/> for an item
+ /// and returns its index or -1 if not found.
+ /// </summary>
+ /// <param name="item">The item to search for.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
public int IndexOf(T item)
{
- return objectArray.IndexOf(item);
+ return _objectArray.IndexOf(item);
}
+ /// <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.
+ /// Existing items will be moved to the right.
+ /// </summary>
+ /// <param name="index">The index to insert at.</param>
+ /// <param name="item">The item to insert.</param>
public void Insert(int index, T item)
{
- objectArray.Insert(index, item);
+ _objectArray.Insert(index, item);
}
+ /// <summary>
+ /// Removes an element from this <see cref="Array{T}"/> by index.
+ /// </summary>
+ /// <param name="index">The index of the element to remove.</param>
public void RemoveAt(int index)
{
- objectArray.RemoveAt(index);
+ _objectArray.RemoveAt(index);
}
// ICollection<T>
+ /// <summary>
+ /// Returns the number of elements in this <see cref="Array{T}"/>.
+ /// This is also known as the size or length of the array.
+ /// </summary>
+ /// <returns>The number of elements.</returns>
public int Count
{
- get { return objectArray.Count; }
+ get { return _objectArray.Count; }
}
- public bool IsReadOnly
- {
- get { return objectArray.IsReadOnly; }
- }
+ bool ICollection<T>.IsReadOnly => false;
+ /// <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 void Add(T item)
{
- objectArray.Add(item);
+ _objectArray.Add(item);
}
+ /// <summary>
+ /// Erases all items from this <see cref="Array{T}"/>.
+ /// </summary>
public void Clear()
{
- objectArray.Clear();
+ _objectArray.Clear();
}
+ /// <summary>
+ /// Checks if this <see cref="Array{T}"/> contains the given item.
+ /// </summary>
+ /// <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)
{
- return objectArray.Contains(item);
+ return _objectArray.Contains(item);
}
+ /// <summary>
+ /// Copies the elements of this <see cref="Array{T}"/> to the given
+ /// C# array, starting at the given index.
+ /// </summary>
+ /// <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)
{
if (array == null)
@@ -374,7 +566,7 @@ namespace Godot.Collections
// TODO This may be quite slow because every element access is an internal call.
// It could be moved entirely to an internal call if we find out how to do the cast there.
- int count = objectArray.Count;
+ int count = _objectArray.Count;
if (array.Length < (arrayIndex + count))
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
@@ -386,6 +578,12 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Removes the first occurrence of the specified value
+ /// from this <see cref="Array{T}"/>.
+ /// </summary>
+ /// <param name="item">The value to remove.</param>
+ /// <returns>A <see langword="bool"/> indicating success or failure.</returns>
public bool Remove(T item)
{
return Array.godot_icall_Array_Remove(GetPtr(), item);
@@ -393,9 +591,13 @@ namespace Godot.Collections
// IEnumerable<T>
+ /// <summary>
+ /// Gets an enumerator for this <see cref="Array{T}"/>.
+ /// </summary>
+ /// <returns>An enumerator.</returns>
public IEnumerator<T> GetEnumerator()
{
- int count = objectArray.Count;
+ int count = _objectArray.Count;
for (int i = 0; i < count; i++)
{
@@ -408,6 +610,10 @@ namespace Godot.Collections
return GetEnumerator();
}
- public override string ToString() => objectArray.ToString();
+ /// <summary>
+ /// Converts this <see cref="Array{T}"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this array.</returns>
+ public override string ToString() => _objectArray.ToString();
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
new file mode 100644
index 0000000000..ef135da51a
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public class AssemblyHasScriptsAttribute : Attribute
+ {
+ private readonly bool requiresLookup;
+ private readonly System.Type[] scriptTypes;
+
+ public AssemblyHasScriptsAttribute()
+ {
+ requiresLookup = true;
+ }
+
+ public AssemblyHasScriptsAttribute(System.Type[] scriptTypes)
+ {
+ requiresLookup = false;
+ this.scriptTypes = scriptTypes;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs
new file mode 100644
index 0000000000..e93bc89811
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public class DisableGodotGeneratorsAttribute : Attribute { }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
index 8fc430b6bc..2dedba2be3 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
@@ -2,21 +2,9 @@ using System;
namespace Godot
{
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class RemoteAttribute : Attribute {}
+ [AttributeUsage(AttributeTargets.Method)]
+ public class RemoteAttribute : Attribute { }
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class MasterAttribute : Attribute {}
-
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class PuppetAttribute : Attribute {}
-
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class RemoteSyncAttribute : Attribute {}
-
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class MasterSyncAttribute : Attribute {}
-
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
- public class PuppetSyncAttribute : Attribute {}
+ [AttributeUsage(AttributeTargets.Method)]
+ public class PuppetAttribute : Attribute { }
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
new file mode 100644
index 0000000000..12eb1035c3
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class ScriptPathAttribute : Attribute
+ {
+ private string path;
+
+ public ScriptPathAttribute(string path)
+ {
+ this.path = path;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs
index 39d5782db8..07a214f543 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs
@@ -3,7 +3,5 @@ using System;
namespace Godot
{
[AttributeUsage(AttributeTargets.Delegate | AttributeTargets.Event)]
- public class SignalAttribute : Attribute
- {
- }
+ public 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 d0437409af..d2344389f4 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 class ToolAttribute : Attribute { }
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index 3f1120575f..0fb1df6c2f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -31,7 +31,7 @@ namespace Godot
/// <summary>
/// The basis matrix's X vector (column 0).
/// </summary>
- /// <value>Equivalent to <see cref="Column0"/> and array index `[0]`.</value>
+ /// <value>Equivalent to <see cref="Column0"/> and array index <c>[0]</c>.</value>
public Vector3 x
{
get => Column0;
@@ -41,7 +41,7 @@ namespace Godot
/// <summary>
/// The basis matrix's Y vector (column 1).
/// </summary>
- /// <value>Equivalent to <see cref="Column1"/> and array index `[1]`.</value>
+ /// <value>Equivalent to <see cref="Column1"/> and array index <c>[1]</c>.</value>
public Vector3 y
{
get => Column1;
@@ -51,7 +51,7 @@ namespace Godot
/// <summary>
/// The basis matrix's Z vector (column 2).
/// </summary>
- /// <value>Equivalent to <see cref="Column2"/> and array index `[2]`.</value>
+ /// <value>Equivalent to <see cref="Column2"/> and array index <c>[2]</c>.</value>
public Vector3 z
{
get => Column2;
@@ -82,45 +82,45 @@ namespace Godot
/// <summary>
/// Column 0 of the basis matrix (the X vector).
/// </summary>
- /// <value>Equivalent to <see cref="x"/> and array index `[0]`.</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);
set
{
- this.Row0.x = value.x;
- this.Row1.x = value.y;
- this.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 `[1]`.</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);
set
{
- this.Row0.y = value.x;
- this.Row1.y = value.y;
- this.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 `[2]`.</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);
set
{
- this.Row0.z = value.x;
- this.Row1.z = value.y;
- this.Row2.z = value.z;
+ Row0.z = value.x;
+ Row1.z = value.y;
+ Row2.z = value.z;
}
}
@@ -150,9 +150,10 @@ namespace Godot
}
/// <summary>
- /// Access whole columns in the form of Vector3.
+ /// Access whole columns in the form of <see cref="Vector3"/>.
/// </summary>
/// <param name="column">Which column vector.</param>
+ /// <value>The basis column.</value>
public Vector3 this[int column]
{
get
@@ -193,6 +194,7 @@ namespace Godot
/// </summary>
/// <param name="column">Which column, the matrix horizontal position.</param>
/// <param name="row">Which row, the matrix vertical position.</param>
+ /// <value>The matrix element.</value>
public real_t this[int column, int row]
{
get
@@ -207,7 +209,14 @@ namespace Godot
}
}
- public Quat RotationQuat()
+ /// <summary>
+ /// Returns the <see cref="Basis"/>'s rotation in the form of a
+ /// <see cref="Quaternion"/>. See <see cref="GetEuler"/> if you
+ /// need Euler angles, but keep in mind quaternions should generally
+ /// be preferred to Euler angles.
+ /// </summary>
+ /// <returns>The basis rotation.</returns>
+ public Quaternion GetRotationQuaternion()
{
Basis orthonormalizedBasis = Orthonormalized();
real_t det = orthonormalizedBasis.Determinant();
@@ -218,18 +227,18 @@ namespace Godot
orthonormalizedBasis = orthonormalizedBasis.Scaled(-Vector3.One);
}
- return orthonormalizedBasis.Quat();
+ return orthonormalizedBasis.Quaternion();
}
- internal void SetQuatScale(Quat quat, Vector3 scale)
+ internal void SetQuaternionScale(Quaternion quaternion, Vector3 scale)
{
SetDiagonal(scale);
- Rotate(quat);
+ Rotate(quaternion);
}
- private void Rotate(Quat quat)
+ private void Rotate(Quaternion quaternion)
{
- this *= new Basis(quat);
+ this *= new Basis(quaternion);
}
private void SetDiagonal(Vector3 diagonal)
@@ -263,10 +272,10 @@ namespace Godot
/// The returned vector contains the rotation angles in
/// the format (X angle, Y angle, Z angle).
///
- /// Consider using the <see cref="Basis.Quat()"/> method instead, which
- /// returns a <see cref="Godot.Quat"/> quaternion instead of Euler angles.
+ /// Consider using the <see cref="Quaternion()"/> method instead, which
+ /// returns a <see cref="Godot.Quaternion"/> quaternion instead of Euler angles.
/// </summary>
- /// <returns>A Vector3 representing the basis rotation in Euler angles.</returns>
+ /// <returns>A <see cref="Vector3"/> representing the basis rotation in Euler angles.</returns>
public Vector3 GetEuler()
{
Basis m = Orthonormalized();
@@ -304,7 +313,10 @@ namespace Godot
/// but are more efficient for some internal calculations.
/// </summary>
/// <param name="index">Which row.</param>
- /// <returns>One of `Row0`, `Row1`, or `Row2`.</returns>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the <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)
@@ -326,6 +338,9 @@ namespace Godot
/// </summary>
/// <param name="index">Which row.</param>
/// <param name="value">The vector to set the row to.</param>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the <paramref name="index"/> is not 0, 1 or 2.
+ /// </exception>
public void SetRow(int index, Vector3 value)
{
switch (index)
@@ -452,8 +467,8 @@ namespace Godot
}
/// <summary>
- /// Introduce an additional rotation around the given `axis`
- /// by `phi` (in radians). The axis must be a normalized vector.
+ /// Introduce an additional rotation around the given <paramref name="axis"/>
+ /// by <paramref name="phi"/> (in radians). The axis must be a normalized vector.
/// </summary>
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="phi">The angle to rotate, in radians.</param>
@@ -486,8 +501,8 @@ namespace Godot
/// <returns>The resulting basis matrix of the interpolation.</returns>
public Basis Slerp(Basis target, real_t weight)
{
- Quat from = new Quat(this);
- Quat to = new Quat(target);
+ Quaternion from = new Quaternion(this);
+ Quaternion to = new Quaternion(target);
Basis b = new Basis(from.Slerp(to, weight));
b.Row0 *= Mathf.Lerp(Row0.Length(), target.Row0.Length(), weight);
@@ -504,7 +519,7 @@ namespace Godot
/// <returns>The resulting dot product.</returns>
public real_t Tdotx(Vector3 with)
{
- return this.Row0[0] * with[0] + this.Row1[0] * with[1] + this.Row2[0] * with[2];
+ return Row0[0] * with[0] + Row1[0] * with[1] + Row2[0] * with[2];
}
/// <summary>
@@ -514,7 +529,7 @@ namespace Godot
/// <returns>The resulting dot product.</returns>
public real_t Tdoty(Vector3 with)
{
- return this.Row0[1] * with[0] + this.Row1[1] * with[1] + this.Row2[1] * with[2];
+ return Row0[1] * with[0] + Row1[1] * with[1] + Row2[1] * with[2];
}
/// <summary>
@@ -524,7 +539,7 @@ namespace Godot
/// <returns>The resulting dot product.</returns>
public real_t Tdotz(Vector3 with)
{
- return this.Row0[2] * with[0] + this.Row1[2] * with[1] + this.Row2[2] * with[2];
+ return Row0[2] * with[0] + Row1[2] * with[1] + Row2[2] * with[2];
}
/// <summary>
@@ -533,7 +548,7 @@ namespace Godot
/// <returns>The transposed basis matrix.</returns>
public Basis Transposed()
{
- var tr = this;
+ Basis tr = this;
real_t temp = tr.Row0[1];
tr.Row0[1] = tr.Row1[0];
@@ -553,15 +568,16 @@ namespace Godot
/// <summary>
/// Returns a vector transformed (multiplied) by the basis matrix.
/// </summary>
+ /// <seealso cref="XformInv(Vector3)"/>
/// <param name="v">A vector to transform.</param>
/// <returns>The transformed vector.</returns>
public Vector3 Xform(Vector3 v)
{
return new Vector3
(
- this.Row0.Dot(v),
- this.Row1.Dot(v),
- this.Row2.Dot(v)
+ Row0.Dot(v),
+ Row1.Dot(v),
+ Row2.Dot(v)
);
}
@@ -571,15 +587,16 @@ namespace Godot
/// Note: This results in a multiplication by the inverse of the
/// basis matrix only if it represents a rotation-reflection.
/// </summary>
+ /// <seealso cref="Xform(Vector3)"/>
/// <param name="v">A vector to inversely transform.</param>
/// <returns>The inversely transformed vector.</returns>
public Vector3 XformInv(Vector3 v)
{
return new Vector3
(
- this.Row0[0] * v.x + this.Row1[0] * v.y + this.Row2[0] * v.z,
- this.Row0[1] * v.x + this.Row1[1] * v.y + this.Row2[1] * v.z,
- this.Row0[2] * v.x + this.Row1[2] * v.y + this.Row2[2] * v.z
+ Row0[0] * v.x + Row1[0] * v.y + Row2[0] * v.z,
+ Row0[1] * v.x + Row1[1] * v.y + Row2[1] * v.z,
+ Row0[2] * v.x + Row1[2] * v.y + Row2[2] * v.z
);
}
@@ -588,8 +605,8 @@ namespace Godot
/// 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="Godot.Quat"/> representing the basis's rotation.</returns>
- public Quat Quat()
+ /// <returns>A <see cref="Godot.Quaternion"/> representing the basis's rotation.</returns>
+ public Quaternion Quaternion()
{
real_t trace = Row0[0] + Row1[1] + Row2[2];
@@ -597,7 +614,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
(Row2[1] - Row1[2]) * inv_s,
(Row0[2] - Row2[0]) * inv_s,
(Row1[0] - Row0[1]) * inv_s,
@@ -609,7 +626,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(Row0[0] - Row1[1] - Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
s * 0.25f,
(Row0[1] + Row1[0]) * inv_s,
(Row0[2] + Row2[0]) * inv_s,
@@ -621,7 +638,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(-Row0[0] + Row1[1] - Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
(Row0[1] + Row1[0]) * inv_s,
s * 0.25f,
(Row1[2] + Row2[1]) * inv_s,
@@ -632,7 +649,7 @@ namespace Godot
{
real_t s = Mathf.Sqrt(-Row0[0] - Row1[1] + Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
- return new Quat(
+ return new Quaternion(
(Row0[2] + Row2[0]) * inv_s,
(Row1[2] + Row2[1]) * inv_s,
s * 0.25f,
@@ -675,47 +692,47 @@ namespace Godot
/// <summary>
/// The identity basis, with no rotation or scaling applied.
- /// This is used as a replacement for `Basis()` in GDScript.
- /// Do not use `new Basis()` with no arguments in C#, because it sets all values to zero.
+ /// This is used as a replacement for <c>Basis()</c> in GDScript.
+ /// Do not use <c>new Basis()</c> with no arguments in C#, because it sets all values to zero.
/// </summary>
- /// <value>Equivalent to `new Basis(Vector3.Right, Vector3.Up, Vector3.Back)`.</value>
+ /// <value>Equivalent to <c>new Basis(Vector3.Right, Vector3.Up, Vector3.Back)</c>.</value>
public static Basis Identity { get { return _identity; } }
/// <summary>
/// The basis that will flip something along the X axis when used in a transformation.
/// </summary>
- /// <value>Equivalent to `new Basis(Vector3.Left, Vector3.Up, Vector3.Back)`.</value>
+ /// <value>Equivalent to <c>new Basis(Vector3.Left, Vector3.Up, Vector3.Back)</c>.</value>
public static Basis FlipX { get { return _flipX; } }
/// <summary>
/// The basis that will flip something along the Y axis when used in a transformation.
/// </summary>
- /// <value>Equivalent to `new Basis(Vector3.Right, Vector3.Down, Vector3.Back)`.</value>
+ /// <value>Equivalent to <c>new Basis(Vector3.Right, Vector3.Down, Vector3.Back)</c>.</value>
public static Basis FlipY { get { return _flipY; } }
/// <summary>
/// The basis that will flip something along the Z axis when used in a transformation.
/// </summary>
- /// <value>Equivalent to `new Basis(Vector3.Right, Vector3.Up, Vector3.Forward)`.</value>
+ /// <value>Equivalent to <c>new Basis(Vector3.Right, Vector3.Up, Vector3.Forward)</c>.</value>
public static Basis FlipZ { get { return _flipZ; } }
/// <summary>
/// Constructs a pure rotation basis matrix from the given quaternion.
/// </summary>
- /// <param name="quat">The quaternion to create the basis from.</param>
- public Basis(Quat quat)
+ /// <param name="quaternion">The quaternion to create the basis from.</param>
+ public Basis(Quaternion quaternion)
{
- real_t s = 2.0f / quat.LengthSquared;
+ real_t s = 2.0f / quaternion.LengthSquared;
- real_t xs = quat.x * s;
- real_t ys = quat.y * s;
- real_t zs = quat.z * s;
- real_t wx = quat.w * xs;
- real_t wy = quat.w * ys;
- real_t wz = quat.w * zs;
- real_t xx = quat.x * xs;
- real_t xy = quat.x * ys;
- real_t xz = quat.x * zs;
- real_t yy = quat.y * ys;
- real_t yz = quat.y * zs;
- real_t zz = quat.z * zs;
+ 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);
@@ -727,8 +744,8 @@ namespace Godot
/// (in the YXZ convention: when *composing*, first Y, then X, and Z last),
/// given in the vector format as (X angle, Y angle, Z angle).
///
- /// Consider using the <see cref="Basis(Quat)"/> constructor instead, which
- /// uses a <see cref="Godot.Quat"/> quaternion instead of Euler angles.
+ /// Consider using the <see cref="Basis(Quaternion)"/> constructor instead, which
+ /// uses a <see cref="Godot.Quaternion"/> quaternion instead of Euler angles.
/// </summary>
/// <param name="eulerYXZ">The Euler angles to create the basis from.</param>
public Basis(Vector3 eulerYXZ)
@@ -752,8 +769,8 @@ namespace Godot
}
/// <summary>
- /// Constructs a pure rotation basis matrix, rotated around the given `axis`
- /// by `phi` (in radians). The axis must be a normalized vector.
+ /// Constructs a pure rotation basis matrix, rotated around the given <paramref name="axis"/>
+ /// by <paramref name="phi"/> (in radians). The axis must be a normalized vector.
/// </summary>
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="phi">The angle to rotate, in radians.</param>
@@ -830,6 +847,11 @@ namespace Godot
return !left.Equals(right);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this basis and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the basis and the other object are equal.</returns>
public override bool Equals(object obj)
{
if (obj is Basis)
@@ -840,45 +862,52 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this basis and <paramref name="other"/> are equal
+ /// </summary>
+ /// <param name="other">The other basis to compare.</param>
+ /// <returns>Whether or not the bases are equal.</returns>
public bool Equals(Basis other)
{
return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2);
}
/// <summary>
- /// Returns true if this basis and `other` are approximately equal, by running
- /// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
+ /// Returns <see langword="true"/> if this basis and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
/// </summary>
/// <param name="other">The other basis to compare.</param>
- /// <returns>Whether or not the matrices are approximately equal.</returns>
+ /// <returns>Whether or not the bases are approximately equal.</returns>
public bool IsEqualApprox(Basis other)
{
return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2);
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Basis"/>.
+ /// </summary>
+ /// <returns>A hash code for this basis.</returns>
public override int GetHashCode()
{
return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode();
}
+ /// <summary>
+ /// Converts this <see cref="Basis"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this basis.</returns>
public override string ToString()
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- Row0.ToString(),
- Row1.ToString(),
- Row2.ToString()
- });
+ 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)
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- Row0.ToString(format),
- Row1.ToString(format),
- Row2.ToString(format)
- });
+ return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, Z: {z.ToString(format)}]";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
index c85cc1884c..a28a46896b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
@@ -2,18 +2,58 @@ using System;
namespace Godot
{
+ /// <summary>
+ /// Callable is a first class object which can be held in variables and passed to functions.
+ /// It represents a given method in an Object, and is typically used for signal callbacks.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// public void PrintArgs(object ar1, object arg2, object arg3 = null)
+ /// {
+ /// GD.PrintS(arg1, arg2, arg3);
+ /// }
+ ///
+ /// public void Test()
+ /// {
+ /// // This Callable object will call the PrintArgs method defined above.
+ /// Callable callable = new Callable(this, nameof(PrintArgs));
+ /// callable.Call("hello", "world"); // Prints "hello world null".
+ /// callable.Call(Vector2.Up, 42, callable); // Prints "(0, -1) 42 Node(Node.cs)::PrintArgs".
+ /// callable.Call("invalid"); // Invalid call, should have at least 2 arguments.
+ /// }
+ /// </code>
+ /// </example>
public struct Callable
{
private readonly Object _target;
private readonly StringName _method;
private readonly Delegate _delegate;
+ /// <summary>
+ /// Object that contains the method.
+ /// </summary>
public Object Target => _target;
+ /// <summary>
+ /// Name of the method that will be called.
+ /// </summary>
public StringName Method => _method;
+ /// <summary>
+ /// Delegate of the method that will be called.
+ /// </summary>
public Delegate Delegate => _delegate;
+ /// <summary>
+ /// Converts a <see cref="Delegate"/> to a <see cref="Callable"/>.
+ /// </summary>
+ /// <param name="delegate">The delegate to convert.</param>
public static implicit operator Callable(Delegate @delegate) => new Callable(@delegate);
+ /// <summary>
+ /// Constructs a new <see cref="Callable"/> for the method called <paramref name="method"/>
+ /// in the specified <paramref name="target"/>.
+ /// </summary>
+ /// <param name="target">Object that contains the method.</param>
+ /// <param name="method">Name of the method that will be called.</param>
public Callable(Object target, StringName method)
{
_target = target;
@@ -21,6 +61,10 @@ namespace Godot
_delegate = null;
}
+ /// <summary>
+ /// Constructs a new <see cref="Callable"/> for the given <paramref name="delegate"/>.
+ /// </summary>
+ /// <param name="delegate">Delegate method that will be called.</param>
public Callable(Delegate @delegate)
{
_target = null;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index 0c333d06ef..2a869bc335 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -7,11 +7,11 @@ namespace Godot
/// A color represented by red, green, blue, and alpha (RGBA) components.
/// The alpha component is often used for transparency.
/// Values are in floating-point and usually range from 0 to 1.
- /// Some properties (such as CanvasItem.modulate) may accept values
+ /// Some properties (such as <see cref="CanvasItem.Modulate"/>) may accept values
/// greater than 1 (overbright or HDR colors).
///
/// If you want to supply values in a range of 0 to 255, you should use
- /// <see cref="Color8"/> and the `r8`/`g8`/`b8`/`a8` properties.
+ /// <see cref="Color8"/> and the <c>r8</c>/<c>g8</c>/<c>b8</c>/<c>a8</c> properties.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
@@ -127,11 +127,11 @@ namespace Godot
}
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;
@@ -173,7 +173,7 @@ namespace Godot
/// <summary>
/// The HSV value (brightness) of this color, on the range 0 to 1.
/// </summary>
- /// <value>Getting is equivalent to using `Max()` on the RGB components. Setting uses <see cref="FromHSV"/>.</value>
+ /// <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
@@ -189,7 +189,12 @@ namespace Godot
/// <summary>
/// Access color components using their index.
/// </summary>
- /// <value>`[0]` is equivalent to `.r`, `[1]` is equivalent to `.g`, `[2]` is equivalent to `.b`, `[3]` is equivalent to `.a`.</value>
+ /// <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"/>.
+ /// </value>
public float this[int index]
{
get
@@ -236,27 +241,48 @@ namespace Godot
/// The second color may have a range of alpha values.
/// </summary>
/// <param name="over">The color to blend over.</param>
- /// <returns>This color blended over `over`.</returns>
+ /// <returns>This color blended over <paramref name="over"/>.</returns>
public Color Blend(Color over)
{
Color res;
float sa = 1.0f - over.a;
- res.a = a * sa + over.a;
+ res.a = (a * sa) + over.a;
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;
}
/// <summary>
+ /// Returns a new color with all components clamped between the
+ /// components of <paramref name="min"/> and <paramref name="max"/>
+ /// using <see cref="Mathf.Clamp(float, float, float)"/>.
+ /// </summary>
+ /// <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)
+ {
+ 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)
+ );
+ }
+
+ /// <summary>
/// Returns a new color resulting from making this color darker
/// by the specified ratio (on the range of 0 to 1).
/// </summary>
@@ -265,14 +291,14 @@ namespace Godot
public Color Darkened(float amount)
{
Color res = this;
- res.r = res.r * (1.0f - amount);
- res.g = res.g * (1.0f - amount);
- res.b = res.b * (1.0f - amount);
+ res.r *= 1.0f - amount;
+ res.g *= 1.0f - amount;
+ res.b *= 1.0f - amount;
return res;
}
/// <summary>
- /// Returns the inverted color: `(1 - r, 1 - g, 1 - b, a)`.
+ /// Returns the inverted color: <c>(1 - r, 1 - g, 1 - b, a)</c>.
/// </summary>
/// <returns>The inverted color.</returns>
public Color Inverted()
@@ -294,15 +320,15 @@ namespace Godot
public Color Lightened(float amount)
{
Color res = this;
- res.r = res.r + (1.0f - res.r) * amount;
- res.g = res.g + (1.0f - res.g) * amount;
- res.b = 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;
}
/// <summary>
/// Returns the result of the linear interpolation between
- /// this color and `to` by amount `weight`.
+ /// this color and <paramref name="to"/> by amount <paramref name="weight"/>.
/// </summary>
/// <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>
@@ -320,7 +346,7 @@ namespace Godot
/// <summary>
/// Returns the result of the linear interpolation between
- /// this color and `to` by color amount `weight`.
+ /// this color and <paramref name="to"/> by color amount <paramref name="weight"/>.
/// </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>
@@ -341,7 +367,7 @@ namespace Godot
/// format (each byte represents a color channel).
/// ABGR is the reversed version of the default format.
/// </summary>
- /// <returns>A uint representing this color in ABGR32 format.</returns>
+ /// <returns>A <see langword="uint"/> representing this color in ABGR32 format.</returns>
public uint ToAbgr32()
{
uint c = (byte)Math.Round(a * 255);
@@ -360,7 +386,7 @@ namespace Godot
/// format (each word represents a color channel).
/// ABGR is the reversed version of the default format.
/// </summary>
- /// <returns>A ulong representing this color in ABGR64 format.</returns>
+ /// <returns>A <see langword="ulong"/> representing this color in ABGR64 format.</returns>
public ulong ToAbgr64()
{
ulong c = (ushort)Math.Round(a * 65535);
@@ -379,7 +405,7 @@ namespace Godot
/// format (each byte represents a color channel).
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
- /// <returns>A uint representing this color in ARGB32 format.</returns>
+ /// <returns>A <see langword="uint"/> representing this color in ARGB32 format.</returns>
public uint ToArgb32()
{
uint c = (byte)Math.Round(a * 255);
@@ -398,7 +424,7 @@ namespace Godot
/// format (each word represents a color channel).
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
- /// <returns>A ulong representing this color in ARGB64 format.</returns>
+ /// <returns>A <see langword="ulong"/> representing this color in ARGB64 format.</returns>
public ulong ToArgb64()
{
ulong c = (ushort)Math.Round(a * 65535);
@@ -417,7 +443,7 @@ namespace Godot
/// format (each byte represents a color channel).
/// RGBA is Godot's default and recommended format.
/// </summary>
- /// <returns>A uint representing this color in RGBA32 format.</returns>
+ /// <returns>A <see langword="uint"/> representing this color in RGBA32 format.</returns>
public uint ToRgba32()
{
uint c = (byte)Math.Round(r * 255);
@@ -436,7 +462,7 @@ namespace Godot
/// format (each word represents a color channel).
/// RGBA is Godot's default and recommended format.
/// </summary>
- /// <returns>A ulong representing this color in RGBA64 format.</returns>
+ /// <returns>A <see langword="ulong"/> representing this color in RGBA64 format.</returns>
public ulong ToRgba64()
{
ulong c = (ushort)Math.Round(r * 65535);
@@ -453,11 +479,13 @@ namespace Godot
/// <summary>
/// Returns the color's HTML hexadecimal color string in RGBA format.
/// </summary>
- /// <param name="includeAlpha">Whether or not to include alpha. If false, the color is RGB instead of RGBA.</param>
+ /// <param name="includeAlpha">
+ /// 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)
{
- var txt = string.Empty;
+ string txt = string.Empty;
txt += ToHex32(r);
txt += ToHex32(g);
@@ -472,7 +500,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a color from RGBA values, typically on the range of 0 to 1.
+ /// Constructs a <see cref="Color"/> from RGBA values, typically on the range of 0 to 1.
/// </summary>
/// <param name="r">The color's red component, typically on the range of 0 to 1.</param>
/// <param name="g">The color's green component, typically on the range of 0 to 1.</param>
@@ -487,7 +515,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a color from an existing color and an alpha value.
+ /// Constructs a <see cref="Color"/> from an existing color and an alpha value.
/// </summary>
/// <param name="c">The color to construct from. Only its RGB values are used.</param>
/// <param name="a">The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1.</param>
@@ -500,10 +528,10 @@ namespace Godot
}
/// <summary>
- /// Constructs a color from an unsigned 32-bit integer in RGBA format
+ /// Constructs a <see cref="Color"/> from an unsigned 32-bit integer in RGBA format
/// (each byte represents a color channel).
/// </summary>
- /// <param name="rgba">The uint representing the color.</param>
+ /// <param name="rgba">The <see langword="uint"/> representing the color.</param>
public Color(uint rgba)
{
a = (rgba & 0xFF) / 255.0f;
@@ -516,10 +544,10 @@ namespace Godot
}
/// <summary>
- /// Constructs a color from an unsigned 64-bit integer in RGBA format
+ /// Constructs a <see cref="Color"/> from an unsigned 64-bit integer in RGBA format
/// (each word represents a color channel).
/// </summary>
- /// <param name="rgba">The ulong representing the color.</param>
+ /// <param name="rgba">The <see langword="ulong"/> representing the color.</param>
public Color(ulong rgba)
{
a = (rgba & 0xFFFF) / 65535.0f;
@@ -532,9 +560,9 @@ namespace Godot
}
/// <summary>
- /// Constructs a color either from an HTML color code or from a
- /// standardized color name. Supported
- /// color names are the same as the <see cref="Colors"/> constants.
+ /// Constructs a <see cref="Color"/> either from an HTML color code or from a
+ /// standardized color name. Supported color names are the same as the
+ /// <see cref="Colors"/> constants.
/// </summary>
/// <param name="code">The HTML color code or color name to construct from.</param>
public Color(string code)
@@ -550,8 +578,8 @@ namespace Godot
}
/// <summary>
- /// Constructs a color either from an HTML color code or from a
- /// standardized color name, with `alpha` on the range of 0 to 1. Supported
+ /// Constructs a <see cref="Color"/> either from an HTML color code or from a
+ /// standardized color name, with <paramref name="alpha"/> on the range of 0 to 1. Supported
/// color names are the same as the <see cref="Colors"/> constants.
/// </summary>
/// <param name="code">The HTML color code or color name to construct from.</param>
@@ -563,9 +591,12 @@ namespace Godot
}
/// <summary>
- /// Constructs a color from the HTML hexadecimal color string in RGBA format.
+ /// Constructs a <see cref="Color"/> from the HTML hexadecimal color string in RGBA format.
/// </summary>
/// <param name="rgba">A string for the HTML hexadecimal representation of this color.</param>
+ /// <exception name="ArgumentOutOfRangeException">
+ /// Thrown when the given <paramref name="rgba"/> color code is invalid.
+ /// </exception>
private static Color FromHTML(string rgba)
{
Color c;
@@ -606,7 +637,8 @@ namespace Godot
}
else
{
- throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba);
+ throw new ArgumentOutOfRangeException(
+ $"Invalid color code. Length is {rgba.Length}, but a length of 6 or 8 is expected: {rgba}");
}
c.a = 1.0f;
@@ -676,12 +708,12 @@ namespace Godot
/// <returns>The constructed color.</returns>
private static Color Named(string name)
{
- 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.ToLower();
+ 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))
{
@@ -694,7 +726,7 @@ namespace Godot
/// <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 `h`/`s`/`v` properties, but much more efficient.
+ /// the <c>h</c>/<c>s</c>/<c>v</c> properties, but much more efficient.
/// </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>
@@ -718,8 +750,8 @@ namespace Godot
f = hue - i;
p = value * (1 - saturation);
- q = value * (1 - saturation * f);
- t = value * (1 - saturation * (1 - f));
+ q = value * (1 - (saturation * f));
+ t = value * (1 - (saturation * (1 - f)));
switch (i)
{
@@ -740,7 +772,7 @@ namespace Godot
/// <summary>
/// Converts a color to HSV values. This is equivalent to using each of
- /// the `h`/`s`/`v` properties, but much more efficient.
+ /// the <c>h</c>/<c>s</c>/<c>v</c> properties, but much more efficient.
/// </summary>
/// <param name="hue">Output parameter for the HSV hue.</param>
/// <param name="saturation">Output parameter for the HSV saturation.</param>
@@ -764,22 +796,24 @@ namespace Godot
}
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;
if (hue < 0)
- {
hue += 1.0f;
- }
}
- saturation = max == 0 ? 0 : 1f - 1f * min / max;
+ if (max == 0)
+ saturation = 0;
+ else
+ saturation = 1 - (min / max);
+
value = max;
}
@@ -956,6 +990,11 @@ namespace Godot
return left.r > right.r;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this color 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 bool Equals(object obj)
{
if (obj is Color)
@@ -966,14 +1005,19 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this color and <paramref name="other"/> are equal
+ /// </summary>
+ /// <param name="other">The other color to compare.</param>
+ /// <returns>Whether or not the colors are equal.</returns>
public bool Equals(Color other)
{
return r == other.r && g == other.g && b == other.b && a == other.a;
}
/// <summary>
- /// Returns true if this color and `other` are approximately equal, by running
- /// <see cref="Godot.Mathf.IsEqualApprox(float, float)"/> on each component.
+ /// Returns <see langword="true"/> if this color and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Mathf.IsEqualApprox(float, float)"/> on each component.
/// </summary>
/// <param name="other">The other color to compare.</param>
/// <returns>Whether or not the colors are approximately equal.</returns>
@@ -982,19 +1026,31 @@ namespace Godot
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()
{
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()
{
- return String.Format("{0},{1},{2},{3}", r.ToString(), g.ToString(), b.ToString(), a.ToString());
+ 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)
{
- return String.Format("{0},{1},{2},{3}", 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/Colors.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
index d05a0414aa..d64c8b563e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
namespace Godot
@@ -9,301 +8,301 @@ namespace Godot
/// </summary>
public static class Colors
{
- // Color names and values are derived from core/color_names.inc
+ // Color names and values are derived from core/math/color_names.inc
internal static readonly Dictionary<string, Color> namedColors = new Dictionary<string, Color> {
- {"aliceblue", new Color(0.94f, 0.97f, 1.00f)},
- {"antiquewhite", new Color(0.98f, 0.92f, 0.84f)},
- {"aqua", new Color(0.00f, 1.00f, 1.00f)},
- {"aquamarine", new Color(0.50f, 1.00f, 0.83f)},
- {"azure", new Color(0.94f, 1.00f, 1.00f)},
- {"beige", new Color(0.96f, 0.96f, 0.86f)},
- {"bisque", new Color(1.00f, 0.89f, 0.77f)},
- {"black", new Color(0.00f, 0.00f, 0.00f)},
- {"blanchedalmond", new Color(1.00f, 0.92f, 0.80f)},
- {"blue", new Color(0.00f, 0.00f, 1.00f)},
- {"blueviolet", new Color(0.54f, 0.17f, 0.89f)},
- {"brown", new Color(0.65f, 0.16f, 0.16f)},
- {"burlywood", new Color(0.87f, 0.72f, 0.53f)},
- {"cadetblue", new Color(0.37f, 0.62f, 0.63f)},
- {"chartreuse", new Color(0.50f, 1.00f, 0.00f)},
- {"chocolate", new Color(0.82f, 0.41f, 0.12f)},
- {"coral", new Color(1.00f, 0.50f, 0.31f)},
- {"cornflower", new Color(0.39f, 0.58f, 0.93f)},
- {"cornsilk", new Color(1.00f, 0.97f, 0.86f)},
- {"crimson", new Color(0.86f, 0.08f, 0.24f)},
- {"cyan", new Color(0.00f, 1.00f, 1.00f)},
- {"darkblue", new Color(0.00f, 0.00f, 0.55f)},
- {"darkcyan", new Color(0.00f, 0.55f, 0.55f)},
- {"darkgoldenrod", new Color(0.72f, 0.53f, 0.04f)},
- {"darkgray", new Color(0.66f, 0.66f, 0.66f)},
- {"darkgreen", new Color(0.00f, 0.39f, 0.00f)},
- {"darkkhaki", new Color(0.74f, 0.72f, 0.42f)},
- {"darkmagenta", new Color(0.55f, 0.00f, 0.55f)},
- {"darkolivegreen", new Color(0.33f, 0.42f, 0.18f)},
- {"darkorange", new Color(1.00f, 0.55f, 0.00f)},
- {"darkorchid", new Color(0.60f, 0.20f, 0.80f)},
- {"darkred", new Color(0.55f, 0.00f, 0.00f)},
- {"darksalmon", new Color(0.91f, 0.59f, 0.48f)},
- {"darkseagreen", new Color(0.56f, 0.74f, 0.56f)},
- {"darkslateblue", new Color(0.28f, 0.24f, 0.55f)},
- {"darkslategray", new Color(0.18f, 0.31f, 0.31f)},
- {"darkturquoise", new Color(0.00f, 0.81f, 0.82f)},
- {"darkviolet", new Color(0.58f, 0.00f, 0.83f)},
- {"deeppink", new Color(1.00f, 0.08f, 0.58f)},
- {"deepskyblue", new Color(0.00f, 0.75f, 1.00f)},
- {"dimgray", new Color(0.41f, 0.41f, 0.41f)},
- {"dodgerblue", new Color(0.12f, 0.56f, 1.00f)},
- {"firebrick", new Color(0.70f, 0.13f, 0.13f)},
- {"floralwhite", new Color(1.00f, 0.98f, 0.94f)},
- {"forestgreen", new Color(0.13f, 0.55f, 0.13f)},
- {"fuchsia", new Color(1.00f, 0.00f, 1.00f)},
- {"gainsboro", new Color(0.86f, 0.86f, 0.86f)},
- {"ghostwhite", new Color(0.97f, 0.97f, 1.00f)},
- {"gold", new Color(1.00f, 0.84f, 0.00f)},
- {"goldenrod", new Color(0.85f, 0.65f, 0.13f)},
- {"gray", new Color(0.75f, 0.75f, 0.75f)},
- {"green", new Color(0.00f, 1.00f, 0.00f)},
- {"greenyellow", new Color(0.68f, 1.00f, 0.18f)},
- {"honeydew", new Color(0.94f, 1.00f, 0.94f)},
- {"hotpink", new Color(1.00f, 0.41f, 0.71f)},
- {"indianred", new Color(0.80f, 0.36f, 0.36f)},
- {"indigo", new Color(0.29f, 0.00f, 0.51f)},
- {"ivory", new Color(1.00f, 1.00f, 0.94f)},
- {"khaki", new Color(0.94f, 0.90f, 0.55f)},
- {"lavender", new Color(0.90f, 0.90f, 0.98f)},
- {"lavenderblush", new Color(1.00f, 0.94f, 0.96f)},
- {"lawngreen", new Color(0.49f, 0.99f, 0.00f)},
- {"lemonchiffon", new Color(1.00f, 0.98f, 0.80f)},
- {"lightblue", new Color(0.68f, 0.85f, 0.90f)},
- {"lightcoral", new Color(0.94f, 0.50f, 0.50f)},
- {"lightcyan", new Color(0.88f, 1.00f, 1.00f)},
- {"lightgoldenrod", new Color(0.98f, 0.98f, 0.82f)},
- {"lightgray", new Color(0.83f, 0.83f, 0.83f)},
- {"lightgreen", new Color(0.56f, 0.93f, 0.56f)},
- {"lightpink", new Color(1.00f, 0.71f, 0.76f)},
- {"lightsalmon", new Color(1.00f, 0.63f, 0.48f)},
- {"lightseagreen", new Color(0.13f, 0.70f, 0.67f)},
- {"lightskyblue", new Color(0.53f, 0.81f, 0.98f)},
- {"lightslategray", new Color(0.47f, 0.53f, 0.60f)},
- {"lightsteelblue", new Color(0.69f, 0.77f, 0.87f)},
- {"lightyellow", new Color(1.00f, 1.00f, 0.88f)},
- {"lime", new Color(0.00f, 1.00f, 0.00f)},
- {"limegreen", new Color(0.20f, 0.80f, 0.20f)},
- {"linen", new Color(0.98f, 0.94f, 0.90f)},
- {"magenta", new Color(1.00f, 0.00f, 1.00f)},
- {"maroon", new Color(0.69f, 0.19f, 0.38f)},
- {"mediumaquamarine", new Color(0.40f, 0.80f, 0.67f)},
- {"mediumblue", new Color(0.00f, 0.00f, 0.80f)},
- {"mediumorchid", new Color(0.73f, 0.33f, 0.83f)},
- {"mediumpurple", new Color(0.58f, 0.44f, 0.86f)},
- {"mediumseagreen", new Color(0.24f, 0.70f, 0.44f)},
- {"mediumslateblue", new Color(0.48f, 0.41f, 0.93f)},
- {"mediumspringgreen", new Color(0.00f, 0.98f, 0.60f)},
- {"mediumturquoise", new Color(0.28f, 0.82f, 0.80f)},
- {"mediumvioletred", new Color(0.78f, 0.08f, 0.52f)},
- {"midnightblue", new Color(0.10f, 0.10f, 0.44f)},
- {"mintcream", new Color(0.96f, 1.00f, 0.98f)},
- {"mistyrose", new Color(1.00f, 0.89f, 0.88f)},
- {"moccasin", new Color(1.00f, 0.89f, 0.71f)},
- {"navajowhite", new Color(1.00f, 0.87f, 0.68f)},
- {"navyblue", new Color(0.00f, 0.00f, 0.50f)},
- {"oldlace", new Color(0.99f, 0.96f, 0.90f)},
- {"olive", new Color(0.50f, 0.50f, 0.00f)},
- {"olivedrab", new Color(0.42f, 0.56f, 0.14f)},
- {"orange", new Color(1.00f, 0.65f, 0.00f)},
- {"orangered", new Color(1.00f, 0.27f, 0.00f)},
- {"orchid", new Color(0.85f, 0.44f, 0.84f)},
- {"palegoldenrod", new Color(0.93f, 0.91f, 0.67f)},
- {"palegreen", new Color(0.60f, 0.98f, 0.60f)},
- {"paleturquoise", new Color(0.69f, 0.93f, 0.93f)},
- {"palevioletred", new Color(0.86f, 0.44f, 0.58f)},
- {"papayawhip", new Color(1.00f, 0.94f, 0.84f)},
- {"peachpuff", new Color(1.00f, 0.85f, 0.73f)},
- {"peru", new Color(0.80f, 0.52f, 0.25f)},
- {"pink", new Color(1.00f, 0.75f, 0.80f)},
- {"plum", new Color(0.87f, 0.63f, 0.87f)},
- {"powderblue", new Color(0.69f, 0.88f, 0.90f)},
- {"purple", new Color(0.63f, 0.13f, 0.94f)},
- {"rebeccapurple", new Color(0.40f, 0.20f, 0.60f)},
- {"red", new Color(1.00f, 0.00f, 0.00f)},
- {"rosybrown", new Color(0.74f, 0.56f, 0.56f)},
- {"royalblue", new Color(0.25f, 0.41f, 0.88f)},
- {"saddlebrown", new Color(0.55f, 0.27f, 0.07f)},
- {"salmon", new Color(0.98f, 0.50f, 0.45f)},
- {"sandybrown", new Color(0.96f, 0.64f, 0.38f)},
- {"seagreen", new Color(0.18f, 0.55f, 0.34f)},
- {"seashell", new Color(1.00f, 0.96f, 0.93f)},
- {"sienna", new Color(0.63f, 0.32f, 0.18f)},
- {"silver", new Color(0.75f, 0.75f, 0.75f)},
- {"skyblue", new Color(0.53f, 0.81f, 0.92f)},
- {"slateblue", new Color(0.42f, 0.35f, 0.80f)},
- {"slategray", new Color(0.44f, 0.50f, 0.56f)},
- {"snow", new Color(1.00f, 0.98f, 0.98f)},
- {"springgreen", new Color(0.00f, 1.00f, 0.50f)},
- {"steelblue", new Color(0.27f, 0.51f, 0.71f)},
- {"tan", new Color(0.82f, 0.71f, 0.55f)},
- {"teal", new Color(0.00f, 0.50f, 0.50f)},
- {"thistle", new Color(0.85f, 0.75f, 0.85f)},
- {"tomato", new Color(1.00f, 0.39f, 0.28f)},
- {"transparent", new Color(1.00f, 1.00f, 1.00f, 0.00f)},
- {"turquoise", new Color(0.25f, 0.88f, 0.82f)},
- {"violet", new Color(0.93f, 0.51f, 0.93f)},
- {"webgreen", new Color(0.00f, 0.50f, 0.00f)},
- {"webgray", new Color(0.50f, 0.50f, 0.50f)},
- {"webmaroon", new Color(0.50f, 0.00f, 0.00f)},
- {"webpurple", new Color(0.50f, 0.00f, 0.50f)},
- {"wheat", new Color(0.96f, 0.87f, 0.70f)},
- {"white", new Color(1.00f, 1.00f, 1.00f)},
- {"whitesmoke", new Color(0.96f, 0.96f, 0.96f)},
- {"yellow", new Color(1.00f, 1.00f, 0.00f)},
- {"yellowgreen", new Color(0.60f, 0.80f, 0.20f)},
+ {"ALICEBLUE", new Color(0.94f, 0.97f, 1.00f)},
+ {"ANTIQUEWHITE", new Color(0.98f, 0.92f, 0.84f)},
+ {"AQUA", new Color(0.00f, 1.00f, 1.00f)},
+ {"AQUAMARINE", new Color(0.50f, 1.00f, 0.83f)},
+ {"AZURE", new Color(0.94f, 1.00f, 1.00f)},
+ {"BEIGE", new Color(0.96f, 0.96f, 0.86f)},
+ {"BISQUE", new Color(1.00f, 0.89f, 0.77f)},
+ {"BLACK", new Color(0.00f, 0.00f, 0.00f)},
+ {"BLANCHEDALMOND", new Color(1.00f, 0.92f, 0.80f)},
+ {"BLUE", new Color(0.00f, 0.00f, 1.00f)},
+ {"BLUEVIOLET", new Color(0.54f, 0.17f, 0.89f)},
+ {"BROWN", new Color(0.65f, 0.16f, 0.16f)},
+ {"BURLYWOOD", new Color(0.87f, 0.72f, 0.53f)},
+ {"CADETBLUE", new Color(0.37f, 0.62f, 0.63f)},
+ {"CHARTREUSE", new Color(0.50f, 1.00f, 0.00f)},
+ {"CHOCOLATE", new Color(0.82f, 0.41f, 0.12f)},
+ {"CORAL", new Color(1.00f, 0.50f, 0.31f)},
+ {"CORNFLOWERBLUE", new Color(0.39f, 0.58f, 0.93f)},
+ {"CORNSILK", new Color(1.00f, 0.97f, 0.86f)},
+ {"CRIMSON", new Color(0.86f, 0.08f, 0.24f)},
+ {"CYAN", new Color(0.00f, 1.00f, 1.00f)},
+ {"DARKBLUE", new Color(0.00f, 0.00f, 0.55f)},
+ {"DARKCYAN", new Color(0.00f, 0.55f, 0.55f)},
+ {"DARKGOLDENROD", new Color(0.72f, 0.53f, 0.04f)},
+ {"DARKGRAY", new Color(0.66f, 0.66f, 0.66f)},
+ {"DARKGREEN", new Color(0.00f, 0.39f, 0.00f)},
+ {"DARKKHAKI", new Color(0.74f, 0.72f, 0.42f)},
+ {"DARKMAGENTA", new Color(0.55f, 0.00f, 0.55f)},
+ {"DARKOLIVEGREEN", new Color(0.33f, 0.42f, 0.18f)},
+ {"DARKORANGE", new Color(1.00f, 0.55f, 0.00f)},
+ {"DARKORCHID", new Color(0.60f, 0.20f, 0.80f)},
+ {"DARKRED", new Color(0.55f, 0.00f, 0.00f)},
+ {"DARKSALMON", new Color(0.91f, 0.59f, 0.48f)},
+ {"DARKSEAGREEN", new Color(0.56f, 0.74f, 0.56f)},
+ {"DARKSLATEBLUE", new Color(0.28f, 0.24f, 0.55f)},
+ {"DARKSLATEGRAY", new Color(0.18f, 0.31f, 0.31f)},
+ {"DARKTURQUOISE", new Color(0.00f, 0.81f, 0.82f)},
+ {"DARKVIOLET", new Color(0.58f, 0.00f, 0.83f)},
+ {"DEEPPINK", new Color(1.00f, 0.08f, 0.58f)},
+ {"DEEPSKYBLUE", new Color(0.00f, 0.75f, 1.00f)},
+ {"DIMGRAY", new Color(0.41f, 0.41f, 0.41f)},
+ {"DODGERBLUE", new Color(0.12f, 0.56f, 1.00f)},
+ {"FIREBRICK", new Color(0.70f, 0.13f, 0.13f)},
+ {"FLORALWHITE", new Color(1.00f, 0.98f, 0.94f)},
+ {"FORESTGREEN", new Color(0.13f, 0.55f, 0.13f)},
+ {"FUCHSIA", new Color(1.00f, 0.00f, 1.00f)},
+ {"GAINSBORO", new Color(0.86f, 0.86f, 0.86f)},
+ {"GHOSTWHITE", new Color(0.97f, 0.97f, 1.00f)},
+ {"GOLD", new Color(1.00f, 0.84f, 0.00f)},
+ {"GOLDENROD", new Color(0.85f, 0.65f, 0.13f)},
+ {"GRAY", new Color(0.75f, 0.75f, 0.75f)},
+ {"GREEN", new Color(0.00f, 1.00f, 0.00f)},
+ {"GREENYELLOW", new Color(0.68f, 1.00f, 0.18f)},
+ {"HONEYDEW", new Color(0.94f, 1.00f, 0.94f)},
+ {"HOTPINK", new Color(1.00f, 0.41f, 0.71f)},
+ {"INDIANRED", new Color(0.80f, 0.36f, 0.36f)},
+ {"INDIGO", new Color(0.29f, 0.00f, 0.51f)},
+ {"IVORY", new Color(1.00f, 1.00f, 0.94f)},
+ {"KHAKI", new Color(0.94f, 0.90f, 0.55f)},
+ {"LAVENDER", new Color(0.90f, 0.90f, 0.98f)},
+ {"LAVENDERBLUSH", new Color(1.00f, 0.94f, 0.96f)},
+ {"LAWNGREEN", new Color(0.49f, 0.99f, 0.00f)},
+ {"LEMONCHIFFON", new Color(1.00f, 0.98f, 0.80f)},
+ {"LIGHTBLUE", new Color(0.68f, 0.85f, 0.90f)},
+ {"LIGHTCORAL", new Color(0.94f, 0.50f, 0.50f)},
+ {"LIGHTCYAN", new Color(0.88f, 1.00f, 1.00f)},
+ {"LIGHTGOLDENROD", new Color(0.98f, 0.98f, 0.82f)},
+ {"LIGHTGRAY", new Color(0.83f, 0.83f, 0.83f)},
+ {"LIGHTGREEN", new Color(0.56f, 0.93f, 0.56f)},
+ {"LIGHTPINK", new Color(1.00f, 0.71f, 0.76f)},
+ {"LIGHTSALMON", new Color(1.00f, 0.63f, 0.48f)},
+ {"LIGHTSEAGREEN", new Color(0.13f, 0.70f, 0.67f)},
+ {"LIGHTSKYBLUE", new Color(0.53f, 0.81f, 0.98f)},
+ {"LIGHTSLATEGRAY", new Color(0.47f, 0.53f, 0.60f)},
+ {"LIGHTSTEELBLUE", new Color(0.69f, 0.77f, 0.87f)},
+ {"LIGHTYELLOW", new Color(1.00f, 1.00f, 0.88f)},
+ {"LIME", new Color(0.00f, 1.00f, 0.00f)},
+ {"LIMEGREEN", new Color(0.20f, 0.80f, 0.20f)},
+ {"LINEN", new Color(0.98f, 0.94f, 0.90f)},
+ {"MAGENTA", new Color(1.00f, 0.00f, 1.00f)},
+ {"MAROON", new Color(0.69f, 0.19f, 0.38f)},
+ {"MEDIUMAQUAMARINE", new Color(0.40f, 0.80f, 0.67f)},
+ {"MEDIUMBLUE", new Color(0.00f, 0.00f, 0.80f)},
+ {"MEDIUMORCHID", new Color(0.73f, 0.33f, 0.83f)},
+ {"MEDIUMPURPLE", new Color(0.58f, 0.44f, 0.86f)},
+ {"MEDIUMSEAGREEN", new Color(0.24f, 0.70f, 0.44f)},
+ {"MEDIUMSLATEBLUE", new Color(0.48f, 0.41f, 0.93f)},
+ {"MEDIUMSPRINGGREEN", new Color(0.00f, 0.98f, 0.60f)},
+ {"MEDIUMTURQUOISE", new Color(0.28f, 0.82f, 0.80f)},
+ {"MEDIUMVIOLETRED", new Color(0.78f, 0.08f, 0.52f)},
+ {"MIDNIGHTBLUE", new Color(0.10f, 0.10f, 0.44f)},
+ {"MINTCREAM", new Color(0.96f, 1.00f, 0.98f)},
+ {"MISTYROSE", new Color(1.00f, 0.89f, 0.88f)},
+ {"MOCCASIN", new Color(1.00f, 0.89f, 0.71f)},
+ {"NAVAJOWHITE", new Color(1.00f, 0.87f, 0.68f)},
+ {"NAVYBLUE", new Color(0.00f, 0.00f, 0.50f)},
+ {"OLDLACE", new Color(0.99f, 0.96f, 0.90f)},
+ {"OLIVE", new Color(0.50f, 0.50f, 0.00f)},
+ {"OLIVEDRAB", new Color(0.42f, 0.56f, 0.14f)},
+ {"ORANGE", new Color(1.00f, 0.65f, 0.00f)},
+ {"ORANGERED", new Color(1.00f, 0.27f, 0.00f)},
+ {"ORCHID", new Color(0.85f, 0.44f, 0.84f)},
+ {"PALEGOLDENROD", new Color(0.93f, 0.91f, 0.67f)},
+ {"PALEGREEN", new Color(0.60f, 0.98f, 0.60f)},
+ {"PALETURQUOISE", new Color(0.69f, 0.93f, 0.93f)},
+ {"PALEVIOLETRED", new Color(0.86f, 0.44f, 0.58f)},
+ {"PAPAYAWHIP", new Color(1.00f, 0.94f, 0.84f)},
+ {"PEACHPUFF", new Color(1.00f, 0.85f, 0.73f)},
+ {"PERU", new Color(0.80f, 0.52f, 0.25f)},
+ {"PINK", new Color(1.00f, 0.75f, 0.80f)},
+ {"PLUM", new Color(0.87f, 0.63f, 0.87f)},
+ {"POWDERBLUE", new Color(0.69f, 0.88f, 0.90f)},
+ {"PURPLE", new Color(0.63f, 0.13f, 0.94f)},
+ {"REBECCAPURPLE", new Color(0.40f, 0.20f, 0.60f)},
+ {"RED", new Color(1.00f, 0.00f, 0.00f)},
+ {"ROSYBROWN", new Color(0.74f, 0.56f, 0.56f)},
+ {"ROYALBLUE", new Color(0.25f, 0.41f, 0.88f)},
+ {"SADDLEBROWN", new Color(0.55f, 0.27f, 0.07f)},
+ {"SALMON", new Color(0.98f, 0.50f, 0.45f)},
+ {"SANDYBROWN", new Color(0.96f, 0.64f, 0.38f)},
+ {"SEAGREEN", new Color(0.18f, 0.55f, 0.34f)},
+ {"SEASHELL", new Color(1.00f, 0.96f, 0.93f)},
+ {"SIENNA", new Color(0.63f, 0.32f, 0.18f)},
+ {"SILVER", new Color(0.75f, 0.75f, 0.75f)},
+ {"SKYBLUE", new Color(0.53f, 0.81f, 0.92f)},
+ {"SLATEBLUE", new Color(0.42f, 0.35f, 0.80f)},
+ {"SLATEGRAY", new Color(0.44f, 0.50f, 0.56f)},
+ {"SNOW", new Color(1.00f, 0.98f, 0.98f)},
+ {"SPRINGGREEN", new Color(0.00f, 1.00f, 0.50f)},
+ {"STEELBLUE", new Color(0.27f, 0.51f, 0.71f)},
+ {"TAN", new Color(0.82f, 0.71f, 0.55f)},
+ {"TEAL", new Color(0.00f, 0.50f, 0.50f)},
+ {"THISTLE", new Color(0.85f, 0.75f, 0.85f)},
+ {"TOMATO", new Color(1.00f, 0.39f, 0.28f)},
+ {"TRANSPARENT", new Color(1.00f, 1.00f, 1.00f, 0.00f)},
+ {"TURQUOISE", new Color(0.25f, 0.88f, 0.82f)},
+ {"VIOLET", new Color(0.93f, 0.51f, 0.93f)},
+ {"WEBGRAY", new Color(0.50f, 0.50f, 0.50f)},
+ {"WEBGREEN", new Color(0.00f, 0.50f, 0.00f)},
+ {"WEBMAROON", new Color(0.50f, 0.00f, 0.00f)},
+ {"WEBPURPLE", new Color(0.50f, 0.00f, 0.50f)},
+ {"WHEAT", new Color(0.96f, 0.87f, 0.70f)},
+ {"WHITE", new Color(1.00f, 1.00f, 1.00f)},
+ {"WHITESMOKE", new Color(0.96f, 0.96f, 0.96f)},
+ {"YELLOW", new Color(1.00f, 1.00f, 0.00f)},
+ {"YELLOWGREEN", new Color(0.60f, 0.80f, 0.20f)},
};
- public static Color AliceBlue { get { return namedColors["aliceblue"]; } }
- public static Color AntiqueWhite { get { return namedColors["antiquewhite"]; } }
- public static Color Aqua { get { return namedColors["aqua"]; } }
- public static Color Aquamarine { get { return namedColors["aquamarine"]; } }
- public static Color Azure { get { return namedColors["azure"]; } }
- public static Color Beige { get { return namedColors["beige"]; } }
- public static Color Bisque { get { return namedColors["bisque"]; } }
- public static Color Black { get { return namedColors["black"]; } }
- public static Color BlanchedAlmond { get { return namedColors["blanchedalmond"]; } }
- public static Color Blue { get { return namedColors["blue"]; } }
- public static Color BlueViolet { get { return namedColors["blueviolet"]; } }
- public static Color Brown { get { return namedColors["brown"]; } }
- public static Color BurlyWood { get { return namedColors["burlywood"]; } }
- public static Color CadetBlue { get { return namedColors["cadetblue"]; } }
- public static Color Chartreuse { get { return namedColors["chartreuse"]; } }
- public static Color Chocolate { get { return namedColors["chocolate"]; } }
- public static Color Coral { get { return namedColors["coral"]; } }
- public static Color Cornflower { get { return namedColors["cornflower"]; } }
- public static Color Cornsilk { get { return namedColors["cornsilk"]; } }
- public static Color Crimson { get { return namedColors["crimson"]; } }
- public static Color Cyan { get { return namedColors["cyan"]; } }
- public static Color DarkBlue { get { return namedColors["darkblue"]; } }
- public static Color DarkCyan { get { return namedColors["darkcyan"]; } }
- public static Color DarkGoldenrod { get { return namedColors["darkgoldenrod"]; } }
- public static Color DarkGray { get { return namedColors["darkgray"]; } }
- public static Color DarkGreen { get { return namedColors["darkgreen"]; } }
- public static Color DarkKhaki { get { return namedColors["darkkhaki"]; } }
- public static Color DarkMagenta { get { return namedColors["darkmagenta"]; } }
- public static Color DarkOliveGreen { get { return namedColors["darkolivegreen"]; } }
- public static Color DarkOrange { get { return namedColors["darkorange"]; } }
- public static Color DarkOrchid { get { return namedColors["darkorchid"]; } }
- public static Color DarkRed { get { return namedColors["darkred"]; } }
- public static Color DarkSalmon { get { return namedColors["darksalmon"]; } }
- public static Color DarkSeaGreen { get { return namedColors["darkseagreen"]; } }
- public static Color DarkSlateBlue { get { return namedColors["darkslateblue"]; } }
- public static Color DarkSlateGray { get { return namedColors["darkslategray"]; } }
- public static Color DarkTurquoise { get { return namedColors["darkturquoise"]; } }
- public static Color DarkViolet { get { return namedColors["darkviolet"]; } }
- public static Color DeepPink { get { return namedColors["deeppink"]; } }
- public static Color DeepSkyBlue { get { return namedColors["deepskyblue"]; } }
- public static Color DimGray { get { return namedColors["dimgray"]; } }
- public static Color DodgerBlue { get { return namedColors["dodgerblue"]; } }
- public static Color Firebrick { get { return namedColors["firebrick"]; } }
- public static Color FloralWhite { get { return namedColors["floralwhite"]; } }
- public static Color ForestGreen { get { return namedColors["forestgreen"]; } }
- public static Color Fuchsia { get { return namedColors["fuchsia"]; } }
- public static Color Gainsboro { get { return namedColors["gainsboro"]; } }
- public static Color GhostWhite { get { return namedColors["ghostwhite"]; } }
- public static Color Gold { get { return namedColors["gold"]; } }
- public static Color Goldenrod { get { return namedColors["goldenrod"]; } }
- public static Color Gray { get { return namedColors["gray"]; } }
- public static Color Green { get { return namedColors["green"]; } }
- public static Color GreenYellow { get { return namedColors["greenyellow"]; } }
- public static Color Honeydew { get { return namedColors["honeydew"]; } }
- public static Color HotPink { get { return namedColors["hotpink"]; } }
- public static Color IndianRed { get { return namedColors["indianred"]; } }
- public static Color Indigo { get { return namedColors["indigo"]; } }
- public static Color Ivory { get { return namedColors["ivory"]; } }
- public static Color Khaki { get { return namedColors["khaki"]; } }
- public static Color Lavender { get { return namedColors["lavender"]; } }
- public static Color LavenderBlush { get { return namedColors["lavenderblush"]; } }
- public static Color LawnGreen { get { return namedColors["lawngreen"]; } }
- public static Color LemonChiffon { get { return namedColors["lemonchiffon"]; } }
- public static Color LightBlue { get { return namedColors["lightblue"]; } }
- public static Color LightCoral { get { return namedColors["lightcoral"]; } }
- public static Color LightCyan { get { return namedColors["lightcyan"]; } }
- public static Color LightGoldenrod { get { return namedColors["lightgoldenrod"]; } }
- public static Color LightGray { get { return namedColors["lightgray"]; } }
- public static Color LightGreen { get { return namedColors["lightgreen"]; } }
- public static Color LightPink { get { return namedColors["lightpink"]; } }
- public static Color LightSalmon { get { return namedColors["lightsalmon"]; } }
- public static Color LightSeaGreen { get { return namedColors["lightseagreen"]; } }
- public static Color LightSkyBlue { get { return namedColors["lightskyblue"]; } }
- public static Color LightSlateGray { get { return namedColors["lightslategray"]; } }
- public static Color LightSteelBlue { get { return namedColors["lightsteelblue"]; } }
- public static Color LightYellow { get { return namedColors["lightyellow"]; } }
- public static Color Lime { get { return namedColors["lime"]; } }
- public static Color Limegreen { get { return namedColors["limegreen"]; } }
- public static Color Linen { get { return namedColors["linen"]; } }
- public static Color Magenta { get { return namedColors["magenta"]; } }
- public static Color Maroon { get { return namedColors["maroon"]; } }
- public static Color MediumAquamarine { get { return namedColors["mediumaquamarine"]; } }
- public static Color MediumBlue { get { return namedColors["mediumblue"]; } }
- public static Color MediumOrchid { get { return namedColors["mediumorchid"]; } }
- public static Color MediumPurple { get { return namedColors["mediumpurple"]; } }
- public static Color MediumSeaGreen { get { return namedColors["mediumseagreen"]; } }
- public static Color MediumSlateBlue { get { return namedColors["mediumslateblue"]; } }
- public static Color MediumSpringGreen { get { return namedColors["mediumspringgreen"]; } }
- public static Color MediumTurquoise { get { return namedColors["mediumturquoise"]; } }
- public static Color MediumVioletRed { get { return namedColors["mediumvioletred"]; } }
- public static Color MidnightBlue { get { return namedColors["midnightblue"]; } }
- public static Color MintCream { get { return namedColors["mintcream"]; } }
- public static Color MistyRose { get { return namedColors["mistyrose"]; } }
- public static Color Moccasin { get { return namedColors["moccasin"]; } }
- public static Color NavajoWhite { get { return namedColors["navajowhite"]; } }
- public static Color NavyBlue { get { return namedColors["navyblue"]; } }
- public static Color OldLace { get { return namedColors["oldlace"]; } }
- public static Color Olive { get { return namedColors["olive"]; } }
- public static Color OliveDrab { get { return namedColors["olivedrab"]; } }
- public static Color Orange { get { return namedColors["orange"]; } }
- public static Color OrangeRed { get { return namedColors["orangered"]; } }
- public static Color Orchid { get { return namedColors["orchid"]; } }
- public static Color PaleGoldenrod { get { return namedColors["palegoldenrod"]; } }
- public static Color PaleGreen { get { return namedColors["palegreen"]; } }
- public static Color PaleTurquoise { get { return namedColors["paleturquoise"]; } }
- public static Color PaleVioletRed { get { return namedColors["palevioletred"]; } }
- public static Color PapayaWhip { get { return namedColors["papayawhip"]; } }
- public static Color PeachPuff { get { return namedColors["peachpuff"]; } }
- public static Color Peru { get { return namedColors["peru"]; } }
- public static Color Pink { get { return namedColors["pink"]; } }
- public static Color Plum { get { return namedColors["plum"]; } }
- public static Color PowderBlue { get { return namedColors["powderblue"]; } }
- public static Color Purple { get { return namedColors["purple"]; } }
- public static Color RebeccaPurple { get { return namedColors["rebeccapurple"]; } }
- public static Color Red { get { return namedColors["red"]; } }
- public static Color RosyBrown { get { return namedColors["rosybrown"]; } }
- public static Color RoyalBlue { get { return namedColors["royalblue"]; } }
- public static Color SaddleBrown { get { return namedColors["saddlebrown"]; } }
- public static Color Salmon { get { return namedColors["salmon"]; } }
- public static Color SandyBrown { get { return namedColors["sandybrown"]; } }
- public static Color SeaGreen { get { return namedColors["seagreen"]; } }
- public static Color SeaShell { get { return namedColors["seashell"]; } }
- public static Color Sienna { get { return namedColors["sienna"]; } }
- public static Color Silver { get { return namedColors["silver"]; } }
- public static Color SkyBlue { get { return namedColors["skyblue"]; } }
- public static Color SlateBlue { get { return namedColors["slateblue"]; } }
- public static Color SlateGray { get { return namedColors["slategray"]; } }
- public static Color Snow { get { return namedColors["snow"]; } }
- public static Color SpringGreen { get { return namedColors["springgreen"]; } }
- public static Color SteelBlue { get { return namedColors["steelblue"]; } }
- public static Color Tan { get { return namedColors["tan"]; } }
- public static Color Teal { get { return namedColors["teal"]; } }
- public static Color Thistle { get { return namedColors["thistle"]; } }
- public static Color Tomato { get { return namedColors["tomato"]; } }
- public static Color Transparent { get { return namedColors["transparent"]; } }
- public static Color Turquoise { get { return namedColors["turquoise"]; } }
- public static Color Violet { get { return namedColors["violet"]; } }
- public static Color WebGreen { get { return namedColors["webgreen"]; } }
- public static Color WebGray { get { return namedColors["webgray"]; } }
- public static Color WebMaroon { get { return namedColors["webmaroon"]; } }
- public static Color WebPurple { get { return namedColors["webpurple"]; } }
- public static Color Wheat { get { return namedColors["wheat"]; } }
- public static Color White { get { return namedColors["white"]; } }
- public static Color WhiteSmoke { get { return namedColors["whitesmoke"]; } }
- public static Color Yellow { get { return namedColors["yellow"]; } }
- public static Color YellowGreen { get { return namedColors["yellowgreen"]; } }
+ public static Color AliceBlue { get { return namedColors["ALICEBLUE"]; } }
+ public static Color AntiqueWhite { get { return namedColors["ANTIQUEWHITE"]; } }
+ public static Color Aqua { get { return namedColors["AQUA"]; } }
+ public static Color Aquamarine { get { return namedColors["AQUAMARINE"]; } }
+ public static Color Azure { get { return namedColors["AZURE"]; } }
+ public static Color Beige { get { return namedColors["BEIGE"]; } }
+ public static Color Bisque { get { return namedColors["BISQUE"]; } }
+ public static Color Black { get { return namedColors["BLACK"]; } }
+ public static Color BlanchedAlmond { get { return namedColors["BLANCHEDALMOND"]; } }
+ public static Color Blue { get { return namedColors["BLUE"]; } }
+ public static Color BlueViolet { get { return namedColors["BLUEVIOLET"]; } }
+ public static Color Brown { get { return namedColors["BROWN"]; } }
+ public static Color Burlywood { get { return namedColors["BURLYWOOD"]; } }
+ public static Color CadetBlue { get { return namedColors["CADETBLUE"]; } }
+ public static Color Chartreuse { get { return namedColors["CHARTREUSE"]; } }
+ public static Color Chocolate { get { return namedColors["CHOCOLATE"]; } }
+ public static Color Coral { get { return namedColors["CORAL"]; } }
+ public static Color CornflowerBlue { get { return namedColors["CORNFLOWERBLUE"]; } }
+ public static Color Cornsilk { get { return namedColors["CORNSILK"]; } }
+ public static Color Crimson { get { return namedColors["CRIMSON"]; } }
+ public static Color Cyan { get { return namedColors["CYAN"]; } }
+ public static Color DarkBlue { get { return namedColors["DARKBLUE"]; } }
+ public static Color DarkCyan { get { return namedColors["DARKCYAN"]; } }
+ public static Color DarkGoldenrod { get { return namedColors["DARKGOLDENROD"]; } }
+ public static Color DarkGray { get { return namedColors["DARKGRAY"]; } }
+ public static Color DarkGreen { get { return namedColors["DARKGREEN"]; } }
+ public static Color DarkKhaki { get { return namedColors["DARKKHAKI"]; } }
+ public static Color DarkMagenta { get { return namedColors["DARKMAGENTA"]; } }
+ public static Color DarkOliveGreen { get { return namedColors["DARKOLIVEGREEN"]; } }
+ public static Color DarkOrange { get { return namedColors["DARKORANGE"]; } }
+ public static Color DarkOrchid { get { return namedColors["DARKORCHID"]; } }
+ public static Color DarkRed { get { return namedColors["DARKRED"]; } }
+ public static Color DarkSalmon { get { return namedColors["DARKSALMON"]; } }
+ public static Color DarkSeaGreen { get { return namedColors["DARKSEAGREEN"]; } }
+ public static Color DarkSlateBlue { get { return namedColors["DARKSLATEBLUE"]; } }
+ public static Color DarkSlateGray { get { return namedColors["DARKSLATEGRAY"]; } }
+ public static Color DarkTurquoise { get { return namedColors["DARKTURQUOISE"]; } }
+ public static Color DarkViolet { get { return namedColors["DARKVIOLET"]; } }
+ public static Color DeepPink { get { return namedColors["DEEPPINK"]; } }
+ public static Color DeepSkyBlue { get { return namedColors["DEEPSKYBLUE"]; } }
+ public static Color DimGray { get { return namedColors["DIMGRAY"]; } }
+ public static Color DodgerBlue { get { return namedColors["DODGERBLUE"]; } }
+ public static Color Firebrick { get { return namedColors["FIREBRICK"]; } }
+ public static Color FloralWhite { get { return namedColors["FLORALWHITE"]; } }
+ public static Color ForestGreen { get { return namedColors["FORESTGREEN"]; } }
+ public static Color Fuchsia { get { return namedColors["FUCHSIA"]; } }
+ public static Color Gainsboro { get { return namedColors["GAINSBORO"]; } }
+ public static Color GhostWhite { get { return namedColors["GHOSTWHITE"]; } }
+ public static Color Gold { get { return namedColors["GOLD"]; } }
+ public static Color Goldenrod { get { return namedColors["GOLDENROD"]; } }
+ public static Color Gray { get { return namedColors["GRAY"]; } }
+ public static Color Green { get { return namedColors["GREEN"]; } }
+ public static Color GreenYellow { get { return namedColors["GREENYELLOW"]; } }
+ public static Color Honeydew { get { return namedColors["HONEYDEW"]; } }
+ public static Color HotPink { get { return namedColors["HOTPINK"]; } }
+ public static Color IndianRed { get { return namedColors["INDIANRED"]; } }
+ public static Color Indigo { get { return namedColors["INDIGO"]; } }
+ public static Color Ivory { get { return namedColors["IVORY"]; } }
+ public static Color Khaki { get { return namedColors["KHAKI"]; } }
+ public static Color Lavender { get { return namedColors["LAVENDER"]; } }
+ public static Color LavenderBlush { get { return namedColors["LAVENDERBLUSH"]; } }
+ public static Color LawnGreen { get { return namedColors["LAWNGREEN"]; } }
+ public static Color LemonChiffon { get { return namedColors["LEMONCHIFFON"]; } }
+ public static Color LightBlue { get { return namedColors["LIGHTBLUE"]; } }
+ public static Color LightCoral { get { return namedColors["LIGHTCORAL"]; } }
+ public static Color LightCyan { get { return namedColors["LIGHTCYAN"]; } }
+ public static Color LightGoldenrod { get { return namedColors["LIGHTGOLDENROD"]; } }
+ public static Color LightGray { get { return namedColors["LIGHTGRAY"]; } }
+ public static Color LightGreen { get { return namedColors["LIGHTGREEN"]; } }
+ public static Color LightPink { get { return namedColors["LIGHTPINK"]; } }
+ public static Color LightSalmon { get { return namedColors["LIGHTSALMON"]; } }
+ public static Color LightSeaGreen { get { return namedColors["LIGHTSEAGREEN"]; } }
+ public static Color LightSkyBlue { get { return namedColors["LIGHTSKYBLUE"]; } }
+ public static Color LightSlateGray { get { return namedColors["LIGHTSLATEGRAY"]; } }
+ public static Color LightSteelBlue { get { return namedColors["LIGHTSTEELBLUE"]; } }
+ public static Color LightYellow { get { return namedColors["LIGHTYELLOW"]; } }
+ public static Color Lime { get { return namedColors["LIME"]; } }
+ public static Color LimeGreen { get { return namedColors["LIMEGREEN"]; } }
+ public static Color Linen { get { return namedColors["LINEN"]; } }
+ public static Color Magenta { get { return namedColors["MAGENTA"]; } }
+ public static Color Maroon { get { return namedColors["MAROON"]; } }
+ public static Color MediumAquamarine { get { return namedColors["MEDIUMAQUAMARINE"]; } }
+ public static Color MediumBlue { get { return namedColors["MEDIUMBLUE"]; } }
+ public static Color MediumOrchid { get { return namedColors["MEDIUMORCHID"]; } }
+ public static Color MediumPurple { get { return namedColors["MEDIUMPURPLE"]; } }
+ public static Color MediumSeaGreen { get { return namedColors["MEDIUMSEAGREEN"]; } }
+ public static Color MediumSlateBlue { get { return namedColors["MEDIUMSLATEBLUE"]; } }
+ public static Color MediumSpringGreen { get { return namedColors["MEDIUMSPRINGGREEN"]; } }
+ public static Color MediumTurquoise { get { return namedColors["MEDIUMTURQUOISE"]; } }
+ public static Color MediumVioletRed { get { return namedColors["MEDIUMVIOLETRED"]; } }
+ public static Color MidnightBlue { get { return namedColors["MIDNIGHTBLUE"]; } }
+ public static Color MintCream { get { return namedColors["MINTCREAM"]; } }
+ public static Color MistyRose { get { return namedColors["MISTYROSE"]; } }
+ public static Color Moccasin { get { return namedColors["MOCCASIN"]; } }
+ public static Color NavajoWhite { get { return namedColors["NAVAJOWHITE"]; } }
+ public static Color NavyBlue { get { return namedColors["NAVYBLUE"]; } }
+ public static Color OldLace { get { return namedColors["OLDLACE"]; } }
+ public static Color Olive { get { return namedColors["OLIVE"]; } }
+ public static Color OliveDrab { get { return namedColors["OLIVEDRAB"]; } }
+ public static Color Orange { get { return namedColors["ORANGE"]; } }
+ public static Color OrangeRed { get { return namedColors["ORANGERED"]; } }
+ public static Color Orchid { get { return namedColors["ORCHID"]; } }
+ public static Color PaleGoldenrod { get { return namedColors["PALEGOLDENROD"]; } }
+ public static Color PaleGreen { get { return namedColors["PALEGREEN"]; } }
+ public static Color PaleTurquoise { get { return namedColors["PALETURQUOISE"]; } }
+ public static Color PaleVioletRed { get { return namedColors["PALEVIOLETRED"]; } }
+ public static Color PapayaWhip { get { return namedColors["PAPAYAWHIP"]; } }
+ public static Color PeachPuff { get { return namedColors["PEACHPUFF"]; } }
+ public static Color Peru { get { return namedColors["PERU"]; } }
+ public static Color Pink { get { return namedColors["PINK"]; } }
+ public static Color Plum { get { return namedColors["PLUM"]; } }
+ public static Color PowderBlue { get { return namedColors["POWDERBLUE"]; } }
+ public static Color Purple { get { return namedColors["PURPLE"]; } }
+ public static Color RebeccaPurple { get { return namedColors["REBECCAPURPLE"]; } }
+ public static Color Red { get { return namedColors["RED"]; } }
+ public static Color RosyBrown { get { return namedColors["ROSYBROWN"]; } }
+ public static Color RoyalBlue { get { return namedColors["ROYALBLUE"]; } }
+ public static Color SaddleBrown { get { return namedColors["SADDLEBROWN"]; } }
+ public static Color Salmon { get { return namedColors["SALMON"]; } }
+ public static Color SandyBrown { get { return namedColors["SANDYBROWN"]; } }
+ public static Color SeaGreen { get { return namedColors["SEAGREEN"]; } }
+ public static Color Seashell { get { return namedColors["SEASHELL"]; } }
+ public static Color Sienna { get { return namedColors["SIENNA"]; } }
+ public static Color Silver { get { return namedColors["SILVER"]; } }
+ public static Color SkyBlue { get { return namedColors["SKYBLUE"]; } }
+ public static Color SlateBlue { get { return namedColors["SLATEBLUE"]; } }
+ public static Color SlateGray { get { return namedColors["SLATEGRAY"]; } }
+ public static Color Snow { get { return namedColors["SNOW"]; } }
+ public static Color SpringGreen { get { return namedColors["SPRINGGREEN"]; } }
+ public static Color SteelBlue { get { return namedColors["STEELBLUE"]; } }
+ public static Color Tan { get { return namedColors["TAN"]; } }
+ public static Color Teal { get { return namedColors["TEAL"]; } }
+ public static Color Thistle { get { return namedColors["THISTLE"]; } }
+ public static Color Tomato { get { return namedColors["TOMATO"]; } }
+ public static Color Transparent { get { return namedColors["TRANSPARENT"]; } }
+ public static Color Turquoise { get { return namedColors["TURQUOISE"]; } }
+ public static Color Violet { get { return namedColors["VIOLET"]; } }
+ public static Color WebGray { get { return namedColors["WEBGRAY"]; } }
+ public static Color WebGreen { get { return namedColors["WEBGREEN"]; } }
+ public static Color WebMaroon { get { return namedColors["WEBMAROON"]; } }
+ public static Color WebPurple { get { return namedColors["WEBPURPLE"]; } }
+ public static Color Wheat { get { return namedColors["WHEAT"]; } }
+ public static Color White { get { return namedColors["WHITE"]; } }
+ public static Color WhiteSmoke { get { return namedColors["WHITESMOKE"]; } }
+ public static Color Yellow { get { return namedColors["YELLOW"]; } }
+ public static Color YellowGreen { get { return namedColors["YELLOWGREEN"]; } }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
index 785e87a043..1dca9e6ea7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
@@ -61,7 +61,7 @@ namespace Godot
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
- writer.Write((ulong) TargetKind.Static);
+ writer.Write((ulong)TargetKind.Static);
SerializeType(writer, @delegate.GetType());
@@ -77,8 +77,8 @@ namespace Godot
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
- writer.Write((ulong) TargetKind.GodotObject);
- writer.Write((ulong) godotObject.GetInstanceId());
+ writer.Write((ulong)TargetKind.GodotObject);
+ writer.Write((ulong)godotObject.GetInstanceId());
SerializeType(writer, @delegate.GetType());
@@ -100,7 +100,7 @@ namespace Godot
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
- writer.Write((ulong) TargetKind.CompilerGenerated);
+ writer.Write((ulong)TargetKind.CompilerGenerated);
SerializeType(writer, targetType);
SerializeType(writer, @delegate.GetType());
@@ -149,14 +149,14 @@ namespace Godot
int flags = 0;
if (methodInfo.IsPublic)
- flags |= (int) BindingFlags.Public;
+ flags |= (int)BindingFlags.Public;
else
- flags |= (int) BindingFlags.NonPublic;
+ flags |= (int)BindingFlags.NonPublic;
if (methodInfo.IsStatic)
- flags |= (int) BindingFlags.Static;
+ flags |= (int)BindingFlags.Static;
else
- flags |= (int) BindingFlags.Instance;
+ flags |= (int)BindingFlags.Instance;
writer.Write(flags);
@@ -238,7 +238,7 @@ namespace Godot
}
else
{
- if (TryDeserializeSingleDelegate((byte[]) elem, out Delegate oneDelegate))
+ if (TryDeserializeSingleDelegate((byte[])elem, out Delegate oneDelegate))
delegates.Add(oneDelegate);
}
}
@@ -257,7 +257,7 @@ namespace Godot
using (var stream = new MemoryStream(buffer, writable: false))
using (var reader = new BinaryReader(stream))
{
- var targetKind = (TargetKind) reader.ReadUInt64();
+ var targetKind = (TargetKind)reader.ReadUInt64();
switch (targetKind)
{
@@ -353,11 +353,11 @@ namespace Godot
parameterTypes[i] = parameterType;
}
- methodInfo = declaringType.GetMethod(methodName, (BindingFlags) flags, null, parameterTypes, null);
+ methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags, null, parameterTypes, null);
return methodInfo != null && methodInfo.ReturnType == returnType;
}
- methodInfo = declaringType.GetMethod(methodName, (BindingFlags) flags);
+ methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags);
return methodInfo != null && methodInfo.ReturnType == returnType;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index 213fc181c1..2dfe304aaa 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
namespace Godot.Collections
{
- class DictionarySafeHandle : SafeHandle
+ internal class DictionarySafeHandle : SafeHandle
{
public DictionarySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
{
@@ -25,18 +26,29 @@ namespace Godot.Collections
}
}
- public class Dictionary :
- IDictionary,
- IDisposable
+ /// <summary>
+ /// Wrapper around Godot's Dictionary class, a dictionary of Variant
+ /// typed elements allocated in the engine in C++. Useful when
+ /// interfacing with the engine.
+ /// </summary>
+ public class Dictionary : IDictionary, IDisposable
{
- DictionarySafeHandle safeHandle;
- bool disposed = false;
+ private DictionarySafeHandle _safeHandle;
+ private bool _disposed = false;
+ /// <summary>
+ /// Constructs a new empty <see cref="Dictionary"/>.
+ /// </summary>
public Dictionary()
{
- safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
+ _safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
}
+ /// <summary>
+ /// Constructs a new <see cref="Dictionary"/> from the given dictionary's elements.
+ /// </summary>
+ /// <param name="dictionary">The dictionary to construct from.</param>
+ /// <returns>A new Godot Dictionary.</returns>
public Dictionary(IDictionary dictionary) : this()
{
if (dictionary == null)
@@ -48,36 +60,44 @@ namespace Godot.Collections
internal Dictionary(DictionarySafeHandle handle)
{
- safeHandle = handle;
+ _safeHandle = handle;
}
internal Dictionary(IntPtr handle)
{
- safeHandle = new DictionarySafeHandle(handle);
+ _safeHandle = new DictionarySafeHandle(handle);
}
internal IntPtr GetPtr()
{
- if (disposed)
+ if (_disposed)
throw new ObjectDisposedException(GetType().FullName);
- return safeHandle.DangerousGetHandle();
+ return _safeHandle.DangerousGetHandle();
}
+ /// <summary>
+ /// Disposes of this <see cref="Dictionary"/>.
+ /// </summary>
public void Dispose()
{
- if (disposed)
+ if (_disposed)
return;
- if (safeHandle != null)
+ if (_safeHandle != null)
{
- safeHandle.Dispose();
- safeHandle = null;
+ _safeHandle.Dispose();
+ _safeHandle = null;
}
- disposed = true;
+ _disposed = true;
}
+ /// <summary>
+ /// Duplicates this <see cref="Dictionary"/>.
+ /// </summary>
+ /// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
+ /// <returns>A new Godot Dictionary.</returns>
public Dictionary Duplicate(bool deep = false)
{
return new Dictionary(godot_icall_Dictionary_Duplicate(GetPtr(), deep));
@@ -85,6 +105,9 @@ namespace Godot.Collections
// IDictionary
+ /// <summary>
+ /// Gets the collection of keys in this <see cref="Dictionary"/>.
+ /// </summary>
public ICollection Keys
{
get
@@ -94,6 +117,9 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Gets the collection of elements in this <see cref="Dictionary"/>.
+ /// </summary>
public ICollection Values
{
get
@@ -103,47 +129,88 @@ namespace Godot.Collections
}
}
- public bool IsFixedSize => false;
+ private (Array keys, Array values, int count) GetKeyValuePairs()
+ {
+ int count = godot_icall_Dictionary_KeyValuePairs(GetPtr(), out IntPtr keysHandle, out IntPtr valuesHandle);
+ Array keys = new Array(new ArraySafeHandle(keysHandle));
+ Array values = new Array(new ArraySafeHandle(valuesHandle));
+ return (keys, values, count);
+ }
+
+ bool IDictionary.IsFixedSize => false;
- public bool IsReadOnly => false;
+ bool IDictionary.IsReadOnly => false;
+ /// <summary>
+ /// Returns the object at the given <paramref name="key"/>.
+ /// </summary>
+ /// <value>The object at the given <paramref name="key"/>.</value>
public object this[object key]
{
get => godot_icall_Dictionary_GetValue(GetPtr(), key);
set => godot_icall_Dictionary_SetValue(GetPtr(), key, value);
}
+ /// <summary>
+ /// Adds an object <paramref name="value"/> at key <paramref name="key"/>
+ /// to this <see cref="Dictionary"/>.
+ /// </summary>
+ /// <param name="key">The key at which to add the object.</param>
+ /// <param name="value">The object to add.</param>
public void Add(object key, object value) => godot_icall_Dictionary_Add(GetPtr(), key, value);
+ /// <summary>
+ /// Erases all items from this <see cref="Dictionary"/>.
+ /// </summary>
public void Clear() => godot_icall_Dictionary_Clear(GetPtr());
+ /// <summary>
+ /// Checks if this <see cref="Dictionary"/> contains the given key.
+ /// </summary>
+ /// <param name="key">The key to look for.</param>
+ /// <returns>Whether or not this dictionary contains the given key.</returns>
public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(GetPtr(), key);
+ /// <summary>
+ /// Gets an enumerator for this <see cref="Dictionary"/>.
+ /// </summary>
+ /// <returns>An enumerator.</returns>
public IDictionaryEnumerator GetEnumerator() => new DictionaryEnumerator(this);
+ /// <summary>
+ /// Removes an element from this <see cref="Dictionary"/> by key.
+ /// </summary>
+ /// <param name="key">The key of the element to remove.</param>
public void Remove(object key) => godot_icall_Dictionary_RemoveKey(GetPtr(), key);
// ICollection
- public object SyncRoot => this;
+ object ICollection.SyncRoot => this;
- public bool IsSynchronized => false;
+ bool ICollection.IsSynchronized => false;
+ /// <summary>
+ /// Returns the number of elements in this <see cref="Dictionary"/>.
+ /// This is also known as the size or length of the dictionary.
+ /// </summary>
+ /// <returns>The number of elements.</returns>
public int Count => godot_icall_Dictionary_Count(GetPtr());
+ /// <summary>
+ /// Copies the elements of this <see cref="Dictionary"/> to the given
+ /// untyped C# array, starting at the given index.
+ /// </summary>
+ /// <param name="array">The array to copy to.</param>
+ /// <param name="index">The index to start at.</param>
public void CopyTo(System.Array array, int index)
{
- // TODO Can be done with single internal call
-
if (array == null)
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
if (index < 0)
throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
- Array keys = (Array)Keys;
- Array values = (Array)Values;
- int count = Count;
+ var (keys, values, count) = GetKeyValuePairs();
if (array.Length < (index + count))
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
@@ -161,24 +228,39 @@ namespace Godot.Collections
private class DictionaryEnumerator : IDictionaryEnumerator
{
- Array keys;
- Array values;
- int count;
- int index = -1;
+ private readonly Dictionary _dictionary;
+ private readonly int _count;
+ private int _index = -1;
+ private bool _dirty = true;
+
+ private DictionaryEntry _entry;
public DictionaryEnumerator(Dictionary dictionary)
{
- // TODO 3 internal calls, can reduce to 1
- keys = (Array)dictionary.Keys;
- values = (Array)dictionary.Values;
- count = dictionary.Count;
+ _dictionary = dictionary;
+ _count = dictionary.Count;
}
public object Current => Entry;
- public DictionaryEntry Entry =>
- // TODO 2 internal calls, can reduce to 1
- new DictionaryEntry(keys[index], values[index]);
+ public DictionaryEntry Entry
+ {
+ get
+ {
+ if (_dirty)
+ {
+ UpdateEntry();
+ }
+ return _entry;
+ }
+ }
+
+ private void UpdateEntry()
+ {
+ _dirty = false;
+ godot_icall_Dictionary_KeyValuePairAt(_dictionary.GetPtr(), _index, out object key, out object value);
+ _entry = new DictionaryEntry(key, value);
+ }
public object Key => Entry.Key;
@@ -186,83 +268,102 @@ namespace Godot.Collections
public bool MoveNext()
{
- index++;
- return index < count;
+ _index++;
+ _dirty = true;
+ return _index < _count;
}
public void Reset()
{
- index = -1;
+ _index = -1;
+ _dirty = true;
}
}
+ /// <summary>
+ /// Converts this <see cref="Dictionary"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this dictionary.</returns>
public override string ToString()
{
return godot_icall_Dictionary_ToString(GetPtr());
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Dictionary_Ctor();
+ internal static extern IntPtr godot_icall_Dictionary_Ctor();
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Dictionary_Dtor(IntPtr ptr);
+ internal static extern void godot_icall_Dictionary_Dtor(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
+ internal static extern object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_Dictionary_GetValue_Generic(IntPtr ptr, object key, int valTypeEncoding, IntPtr valTypeClass);
+ internal static extern object godot_icall_Dictionary_GetValue_Generic(IntPtr ptr, object key, int valTypeEncoding, IntPtr valTypeClass);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
+ internal static extern void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Dictionary_Keys(IntPtr ptr);
+ internal static extern IntPtr godot_icall_Dictionary_Keys(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Dictionary_Values(IntPtr ptr);
+ internal static extern IntPtr godot_icall_Dictionary_Values(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_Dictionary_Count(IntPtr ptr);
+ internal static extern int godot_icall_Dictionary_Count(IntPtr ptr);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value);
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Dictionary_Clear(IntPtr ptr);
+ internal static extern void godot_icall_Dictionary_Clear(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value);
+ internal static extern bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
+ internal static extern bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep);
+ internal static extern IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
+ internal static extern bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value);
+ internal static extern bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
+ internal static extern bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_Dictionary_TryGetValue_Generic(IntPtr ptr, object key, out object value, int valTypeEncoding, IntPtr valTypeClass);
+ internal static extern bool godot_icall_Dictionary_TryGetValue_Generic(IntPtr ptr, object key, out object value, int valTypeEncoding, IntPtr valTypeClass);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
+ internal static extern void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string godot_icall_Dictionary_ToString(IntPtr ptr);
+ internal static extern string godot_icall_Dictionary_ToString(IntPtr ptr);
}
- public class Dictionary<TKey, TValue> :
- IDictionary<TKey, TValue>
+ /// <summary>
+ /// Typed wrapper around Godot's Dictionary class, a dictionary of Variant
+ /// typed elements allocated in the engine in C++. Useful when
+ /// interfacing with the engine. Otherwise prefer .NET collections
+ /// such as <see cref="System.Collections.Generic.Dictionary{TKey, TValue}"/>.
+ /// </summary>
+ /// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
+ /// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
+ public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
- Dictionary objectDict;
+ private readonly Dictionary _objectDict;
internal static int valTypeEncoding;
internal static IntPtr valTypeClass;
@@ -272,14 +373,22 @@ namespace Godot.Collections
Dictionary.godot_icall_Dictionary_Generic_GetValueTypeInfo(typeof(TValue), out valTypeEncoding, out valTypeClass);
}
+ /// <summary>
+ /// Constructs a new empty <see cref="Dictionary{TKey, TValue}"/>.
+ /// </summary>
public Dictionary()
{
- objectDict = new Dictionary();
+ _objectDict = new Dictionary();
}
+ /// <summary>
+ /// Constructs a new <see cref="Dictionary{TKey, TValue}"/> from the given dictionary's elements.
+ /// </summary>
+ /// <param name="dictionary">The dictionary to construct from.</param>
+ /// <returns>A new Godot Dictionary.</returns>
public Dictionary(IDictionary<TKey, TValue> dictionary)
{
- objectDict = new Dictionary();
+ _objectDict = new Dictionary();
if (dictionary == null)
throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
@@ -294,112 +403,173 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Constructs a new <see cref="Dictionary{TKey, TValue}"/> from the given dictionary's elements.
+ /// </summary>
+ /// <param name="dictionary">The dictionary to construct from.</param>
+ /// <returns>A new Godot Dictionary.</returns>
public Dictionary(Dictionary dictionary)
{
- objectDict = dictionary;
+ _objectDict = dictionary;
}
internal Dictionary(IntPtr handle)
{
- objectDict = new Dictionary(handle);
+ _objectDict = new Dictionary(handle);
}
internal Dictionary(DictionarySafeHandle handle)
{
- objectDict = new Dictionary(handle);
+ _objectDict = new Dictionary(handle);
}
+ /// <summary>
+ /// Converts this typed <see cref="Dictionary{TKey, TValue}"/> to an untyped <see cref="Dictionary"/>.
+ /// </summary>
+ /// <param name="from">The typed dictionary to convert.</param>
public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
{
- return from.objectDict;
+ return from._objectDict;
}
internal IntPtr GetPtr()
{
- return objectDict.GetPtr();
+ return _objectDict.GetPtr();
}
+ /// <summary>
+ /// Duplicates this <see cref="Dictionary{TKey, TValue}"/>.
+ /// </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>(objectDict.Duplicate(deep));
+ return new Dictionary<TKey, TValue>(_objectDict.Duplicate(deep));
}
// IDictionary<TKey, TValue>
+ /// <summary>
+ /// Returns the value at the given <paramref name="key"/>.
+ /// </summary>
+ /// <value>The value at the given <paramref name="key"/>.</value>
public TValue this[TKey key]
{
- get { return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); }
- set { objectDict[key] = value; }
+ get { return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(_objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); }
+ set { _objectDict[key] = value; }
}
+ /// <summary>
+ /// Gets the collection of keys in this <see cref="Dictionary{TKey, TValue}"/>.
+ /// </summary>
public ICollection<TKey> Keys
{
get
{
- IntPtr handle = Dictionary.godot_icall_Dictionary_Keys(objectDict.GetPtr());
+ IntPtr handle = Dictionary.godot_icall_Dictionary_Keys(_objectDict.GetPtr());
return new Array<TKey>(new ArraySafeHandle(handle));
}
}
+ /// <summary>
+ /// Gets the collection of elements in this <see cref="Dictionary{TKey, TValue}"/>.
+ /// </summary>
public ICollection<TValue> Values
{
get
{
- IntPtr handle = Dictionary.godot_icall_Dictionary_Values(objectDict.GetPtr());
+ IntPtr handle = Dictionary.godot_icall_Dictionary_Values(_objectDict.GetPtr());
return new Array<TValue>(new ArraySafeHandle(handle));
}
}
+ private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
+ {
+ Dictionary.godot_icall_Dictionary_KeyValuePairAt(GetPtr(), index, out object key, out object value);
+ return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
+ }
+
+ /// <summary>
+ /// Adds an object <paramref name="value"/> at key <paramref name="key"/>
+ /// to this <see cref="Dictionary{TKey, TValue}"/>.
+ /// </summary>
+ /// <param name="key">The key at which to add the object.</param>
+ /// <param name="value">The object to add.</param>
public void Add(TKey key, TValue value)
{
- objectDict.Add(key, value);
+ _objectDict.Add(key, value);
}
+ /// <summary>
+ /// Checks if this <see cref="Dictionary{TKey, TValue}"/> contains the given key.
+ /// </summary>
+ /// <param name="key">The key to look for.</param>
+ /// <returns>Whether or not this dictionary contains the given key.</returns>
public bool ContainsKey(TKey key)
{
- return objectDict.Contains(key);
+ return _objectDict.Contains(key);
}
+ /// <summary>
+ /// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
+ /// </summary>
+ /// <param name="key">The key of the element to remove.</param>
public bool Remove(TKey key)
{
return Dictionary.godot_icall_Dictionary_RemoveKey(GetPtr(), key);
}
- public bool TryGetValue(TKey key, out TValue value)
+ /// <summary>
+ /// Gets the object at the given <paramref name="key"/>.
+ /// </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 bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
- object retValue;
- bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out retValue, valTypeEncoding, valTypeClass);
- value = found ? (TValue)retValue : default(TValue);
+ bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out object retValue, valTypeEncoding, valTypeClass);
+ value = found ? (TValue)retValue : default;
return found;
}
// ICollection<KeyValuePair<TKey, TValue>>
+ /// <summary>
+ /// Returns the number of elements in this <see cref="Dictionary{TKey, TValue}"/>.
+ /// This is also known as the size or length of the dictionary.
+ /// </summary>
+ /// <returns>The number of elements.</returns>
public int Count
{
- get { return objectDict.Count; }
+ get { return _objectDict.Count; }
}
- public bool IsReadOnly
- {
- get { return objectDict.IsReadOnly; }
- }
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
- public void Add(KeyValuePair<TKey, TValue> item)
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
- objectDict.Add(item.Key, item.Value);
+ _objectDict.Add(item.Key, item.Value);
}
+ /// <summary>
+ /// Erases all the items from this <see cref="Dictionary{TKey, TValue}"/>.
+ /// </summary>
public void Clear()
{
- objectDict.Clear();
+ _objectDict.Clear();
}
- public bool Contains(KeyValuePair<TKey, TValue> item)
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
- return objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
+ return _objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
}
+ /// <summary>
+ /// Copies the elements of this <see cref="Dictionary{TKey, TValue}"/> to the given
+ /// untyped C# array, starting at the given index.
+ /// </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)
{
if (array == null)
@@ -408,9 +578,6 @@ namespace Godot.Collections
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
- // TODO 3 internal calls, can reduce to 1
- Array<TKey> keys = (Array<TKey>)Keys;
- Array<TValue> values = (Array<TValue>)Values;
int count = Count;
if (array.Length < (arrayIndex + count))
@@ -418,13 +585,12 @@ namespace Godot.Collections
for (int i = 0; i < count; i++)
{
- // TODO 2 internal calls, can reduce to 1
- array[arrayIndex] = new KeyValuePair<TKey, TValue>(keys[i], values[i]);
+ array[arrayIndex] = GetKeyValuePair(i);
arrayIndex++;
}
}
- public bool Remove(KeyValuePair<TKey, TValue> item)
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
;
@@ -432,17 +598,15 @@ namespace Godot.Collections
// IEnumerable<KeyValuePair<TKey, TValue>>
+ /// <summary>
+ /// Gets an enumerator for this <see cref="Dictionary{TKey, TValue}"/>.
+ /// </summary>
+ /// <returns>An enumerator.</returns>
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
- // TODO 3 internal calls, can reduce to 1
- Array<TKey> keys = (Array<TKey>)Keys;
- Array<TValue> values = (Array<TValue>)Values;
- int count = Count;
-
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < Count; i++)
{
- // TODO 2 internal calls, can reduce to 1
- yield return new KeyValuePair<TKey, TValue>(keys[i], values[i]);
+ yield return GetKeyValuePair(i);
}
}
@@ -451,6 +615,10 @@ namespace Godot.Collections
return GetEnumerator();
}
- public override string ToString() => objectDict.ToString();
+ /// <summary>
+ /// Converts this <see cref="Dictionary{TKey, TValue}"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this dictionary.</returns>
+ public override string ToString() => _objectDict.ToString();
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs
index c4c911b863..26d5f9c796 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs
@@ -1,4 +1,3 @@
-
using System;
using System.Collections.Generic;
using System.Dynamic;
@@ -8,20 +7,20 @@ using System.Runtime.CompilerServices;
namespace Godot
{
/// <summary>
- /// Represents an <see cref="Godot.Object"/> whose members can be dynamically accessed at runtime through the Variant API.
+ /// Represents an <see cref="Object"/> whose members can be dynamically accessed at runtime through the Variant API.
/// </summary>
/// <remarks>
/// <para>
- /// The <see cref="Godot.DynamicGodotObject"/> class enables access to the Variant
- /// members of a <see cref="Godot.Object"/> instance at runtime.
+ /// The <see cref="DynamicGodotObject"/> class enables access to the Variant
+ /// members of a <see cref="Object"/> instance at runtime.
/// </para>
/// <para>
/// This allows accessing the class members using their original names in the engine as well as the members from the
- /// script attached to the <see cref="Godot.Object"/>, regardless of the scripting language it was written in.
+ /// script attached to the <see cref="Object"/>, regardless of the scripting language it was written in.
/// </para>
/// </remarks>
/// <example>
- /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Godot.Object"/>.
+ /// This sample shows how to use <see cref="DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Object"/>.
/// <code>
/// dynamic sprite = GetNode("Sprite2D").DynamicGodotObject;
/// sprite.add_child(this);
@@ -31,7 +30,7 @@ namespace Godot
/// </code>
/// </example>
/// <example>
- /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the members of the script attached to a <see cref="Godot.Object"/>.
+ /// This sample shows how to use <see cref="DynamicGodotObject"/> to dynamically access the members of the script attached to a <see cref="Object"/>.
/// <code>
/// dynamic childNode = GetNode("ChildNode").DynamicGodotObject;
///
@@ -55,32 +54,34 @@ namespace Godot
public class DynamicGodotObject : DynamicObject
{
/// <summary>
- /// Gets the <see cref="Godot.Object"/> associated with this <see cref="Godot.DynamicGodotObject"/>.
+ /// Gets the <see cref="Object"/> associated with this <see cref="DynamicGodotObject"/>.
/// </summary>
public Object Value { get; }
/// <summary>
- /// Initializes a new instance of the <see cref="Godot.DynamicGodotObject"/> class.
+ /// Initializes a new instance of the <see cref="DynamicGodotObject"/> class.
/// </summary>
/// <param name="godotObject">
- /// The <see cref="Godot.Object"/> that will be associated with this <see cref="Godot.DynamicGodotObject"/>.
+ /// The <see cref="Object"/> that will be associated with this <see cref="DynamicGodotObject"/>.
/// </param>
- /// <exception cref="System.ArgumentNullException">
- /// Thrown when the <paramref name="godotObject"/> parameter is null.
+ /// <exception cref="ArgumentNullException">
+ /// Thrown when the <paramref name="godotObject"/> parameter is <see langword="null"/>.
/// </exception>
public DynamicGodotObject(Object godotObject)
{
if (godotObject == null)
throw new ArgumentNullException(nameof(godotObject));
- this.Value = godotObject;
+ Value = godotObject;
}
+ /// <inheritdoc/>
public override IEnumerable<string> GetDynamicMemberNames()
{
return godot_icall_DynamicGodotObject_SetMemberList(Object.GetPtr(Value));
}
+ /// <inheritdoc/>
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
{
switch (binder.Operation)
@@ -122,6 +123,7 @@ namespace Godot
return base.TryBinaryOperation(binder, arg, out result);
}
+ /// <inheritdoc/>
public override bool TryConvert(ConvertBinder binder, out object result)
{
if (binder.Type == typeof(Object))
@@ -140,6 +142,7 @@ namespace Godot
return base.TryConvert(binder, out result);
}
+ /// <inheritdoc/>
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
if (indexes.Length == 1)
@@ -153,16 +156,19 @@ namespace Godot
return base.TryGetIndex(binder, indexes, out result);
}
+ /// <inheritdoc/>
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), binder.Name, out result);
}
+ /// <inheritdoc/>
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
return godot_icall_DynamicGodotObject_InvokeMember(Object.GetPtr(Value), binder.Name, args, out result);
}
+ /// <inheritdoc/>
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
{
if (indexes.Length == 1)
@@ -176,22 +182,23 @@ namespace Godot
return base.TrySetIndex(binder, indexes, value);
}
+ /// <inheritdoc/>
public override bool TrySetMember(SetMemberBinder binder, object value)
{
return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), binder.Name, value);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string[] godot_icall_DynamicGodotObject_SetMemberList(IntPtr godotObject);
+ internal static extern string[] godot_icall_DynamicGodotObject_SetMemberList(IntPtr godotObject);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_DynamicGodotObject_InvokeMember(IntPtr godotObject, string name, object[] args, out object result);
+ internal static extern bool godot_icall_DynamicGodotObject_InvokeMember(IntPtr godotObject, string name, object[] args, out object result);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_DynamicGodotObject_GetMember(IntPtr godotObject, string name, out object result);
+ internal static extern bool godot_icall_DynamicGodotObject_GetMember(IntPtr godotObject, string name, out object result);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_DynamicGodotObject_SetMember(IntPtr godotObject, string name, object value);
+ internal static extern bool godot_icall_DynamicGodotObject_SetMember(IntPtr godotObject, string name, object value);
#region We don't override these methods
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs
index 5d16260f5d..658582960f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs
@@ -1,42 +1,190 @@
+using System;
+
namespace Godot
{
public partial class Node
{
+ /// <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"/>).
+ /// </summary>
+ /// <example>
+ /// Example: Assume your current node is Character and the following tree:
+ /// <code>
+ /// /root
+ /// /root/Character
+ /// /root/Character/Sword
+ /// /root/Character/Backpack/Dagger
+ /// /root/MyGame
+ /// /root/Swamp/Alligator
+ /// /root/Swamp/Mosquito
+ /// /root/Swamp/Goblin
+ /// </code>
+ /// Possible paths are:
+ /// <code>
+ /// GetNode("Sword");
+ /// GetNode("Backpack/Dagger");
+ /// GetNode("../Swamp/Alligator");
+ /// GetNode("/root/MyGame");
+ /// </code>
+ /// </example>
+ /// <seealso cref="GetNodeOrNull{T}(NodePath)"/>
+ /// <param name="path">The path to the node to fetch.</param>
+ /// <exception cref="InvalidCastException">
+ /// Thrown when the given the fetched node can't be casted to the given type <typeparamref name="T"/>.
+ /// </exception>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>
+ /// The <see cref="Node"/> at the given <paramref name="path"/>.
+ /// </returns>
public T GetNode<T>(NodePath path) where T : class
{
return (T)(object)GetNode(path);
}
+ /// <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"/>).
+ /// </summary>
+ /// <example>
+ /// Example: Assume your current node is Character and the following tree:
+ /// <code>
+ /// /root
+ /// /root/Character
+ /// /root/Character/Sword
+ /// /root/Character/Backpack/Dagger
+ /// /root/MyGame
+ /// /root/Swamp/Alligator
+ /// /root/Swamp/Mosquito
+ /// /root/Swamp/Goblin
+ /// </code>
+ /// Possible paths are:
+ /// <code>
+ /// GetNode("Sword");
+ /// GetNode("Backpack/Dagger");
+ /// GetNode("../Swamp/Alligator");
+ /// GetNode("/root/MyGame");
+ /// </code>
+ /// </example>
+ /// <seealso cref="GetNode{T}(NodePath)"/>
+ /// <param name="path">The path to the node to fetch.</param>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>/// ///////// <returns>
+ /// The <see cref="Node"/> at the given <paramref name="path"/>, or <see langword="null"/> if not found.
+ /// </returns>
public T GetNodeOrNull<T>(NodePath path) where T : class
{
return GetNodeOrNull(path) as T;
}
+ /// <summary>
+ /// Returns a child node by its index (see <see cref="GetChildCount"/>).
+ /// This method is often used for iterating all children of a node.
+ /// Negative indices access the children from the last one.
+ /// To access a child node via its name, use <see cref="GetNode"/>.
+ /// </summary>
+ /// <seealso cref="GetChildOrNull{T}(int)"/>
+ /// <param name="idx">Child index.</param>
+ /// <exception cref="InvalidCastException">
+ /// Thrown when the given the fetched node can't be casted to the given type <typeparamref name="T"/>.
+ /// </exception>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>/// ///////// <returns>
+ /// The child <see cref="Node"/> at the given index <paramref name="idx"/>.
+ /// </returns>
public T GetChild<T>(int idx) where T : class
{
return (T)(object)GetChild(idx);
}
+ /// <summary>
+ /// Returns a child node by its index (see <see cref="GetChildCount"/>).
+ /// This method is often used for iterating all children of a node.
+ /// Negative indices access the children from the last one.
+ /// To access a child node via its name, use <see cref="GetNode"/>.
+ /// </summary>
+ /// <seealso cref="GetChild{T}(int)"/>
+ /// <param name="idx">Child index.</param>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>
+ /// The child <see cref="Node"/> at the given index <paramref name="idx"/>, or <see langword="null"/> if not found.
+ /// </returns>
public T GetChildOrNull<T>(int idx) where T : class
{
return GetChild(idx) as T;
}
+ /// <summary>
+ /// The node owner. A node can have any other node as owner (as long as it is
+ /// a valid parent, grandparent, etc. ascending in the tree). When saving a
+ /// node (using <see cref="PackedScene"/>), all the nodes it owns will be saved
+ /// with it. This allows for the creation of complex <see cref="SceneTree"/>s,
+ /// with instancing and subinstancing.
+ /// </summary>
+ /// <seealso cref="GetOwnerOrNull{T}"/>
+ /// <exception cref="InvalidCastException">
+ /// Thrown when the given the fetched node can't be casted to the given type <typeparamref name="T"/>.
+ /// </exception>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>
+ /// The owner <see cref="Node"/>.
+ /// </returns>
public T GetOwner<T>() where T : class
{
return (T)(object)Owner;
}
+ /// <summary>
+ /// The node owner. A node can have any other node as owner (as long as it is
+ /// a valid parent, grandparent, etc. ascending in the tree). When saving a
+ /// node (using <see cref="PackedScene"/>), all the nodes it owns will be saved
+ /// with it. This allows for the creation of complex <see cref="SceneTree"/>s,
+ /// with instancing and subinstancing.
+ /// </summary>
+ /// <seealso cref="GetOwner{T}"/>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>
+ /// The owner <see cref="Node"/>, or <see langword="null"/> if there is no owner.
+ /// </returns>
public T GetOwnerOrNull<T>() where T : class
{
return Owner as T;
}
+ /// <summary>
+ /// Returns the parent node of the current node, or a <see langword="null"/> instance
+ /// if the node lacks a parent.
+ /// </summary>
+ /// <seealso cref="GetParentOrNull{T}"/>
+ /// <exception cref="InvalidCastException">
+ /// Thrown when the given the fetched node can't be casted to the given type <typeparamref name="T"/>.
+ /// </exception>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>
+ /// The parent <see cref="Node"/>.
+ /// </returns>
public T GetParent<T>() where T : class
{
return (T)(object)GetParent();
}
+ /// <summary>
+ /// Returns the parent node of the current node, or a <see langword="null"/> instance
+ /// if the node lacks a parent.
+ /// </summary>
+ /// <seealso cref="GetParent{T}"/>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>
+ /// The parent <see cref="Node"/>, or <see langword="null"/> if the node has no parent.
+ /// </returns>
public T GetParentOrNull<T>() where T : class
{
return GetParent() as T;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
index 9ef0959750..691fd85964 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
@@ -5,17 +5,37 @@ 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)
{
- return godot_icall_Object_weakref(Object.GetPtr(obj));
+ return godot_icall_Object_weakref(GetPtr(obj));
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static WeakRef godot_icall_Object_weakref(IntPtr obj);
+ internal static extern WeakRef godot_icall_Object_weakref(IntPtr obj);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
index 763f470504..435b59d5f3 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace Godot
{
public partial class PackedScene
@@ -5,23 +7,30 @@ namespace Godot
/// <summary>
/// Instantiates the scene's node hierarchy, erroring on failure.
/// Triggers child scene instantiation(s). Triggers a
- /// `Node.NotificationInstanced` notification on the root node.
+ /// <see cref="Node.NotificationInstanced"/> notification on the root node.
/// </summary>
- /// <typeparam name="T">The type to cast to. Should be a descendant of Node.</typeparam>
- public T Instance<T>(PackedScene.GenEditState editState = (PackedScene.GenEditState)0) where T : class
+ /// <seealso cref="InstantiateOrNull{T}(GenEditState)"/>
+ /// <exception cref="InvalidCastException">
+ /// Thrown when the given the instantiated node can't be casted to the given type <typeparamref name="T"/>.
+ /// </exception>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>The instantiated scene.</returns>
+ public T Instantiate<T>(PackedScene.GenEditState editState = (PackedScene.GenEditState)0) where T : class
{
- return (T)(object)Instance(editState);
+ return (T)(object)Instantiate(editState);
}
/// <summary>
- /// Instantiates the scene's node hierarchy, returning null on failure.
+ /// Instantiates the scene's node hierarchy, returning <see langword="null"/> on failure.
/// Triggers child scene instantiation(s). Triggers a
- /// `Node.NotificationInstanced` notification on the root node.
+ /// <see cref="Node.NotificationInstanced"/> notification on the root node.
/// </summary>
- /// <typeparam name="T">The type to cast to. Should be a descendant of Node.</typeparam>
- public T InstanceOrNull<T>(PackedScene.GenEditState editState = (PackedScene.GenEditState)0) where T : class
+ /// <seealso cref="Instantiate{T}(GenEditState)"/>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
+ /// <returns>The instantiated scene.</returns>
+ public T InstantiateOrNull<T>(PackedScene.GenEditState editState = (PackedScene.GenEditState)0) where T : class
{
- return Instance(editState) as T;
+ return Instantiate(editState) as T;
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs
index 74fa05d1fd..25c11d5cf6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs
@@ -1,10 +1,30 @@
+using System;
+
namespace Godot
{
public static partial class ResourceLoader
{
- public static T Load<T>(string path, string typeHint = null, CacheMode noCache = CacheMode.Reuse) where T : class
+ /// <summary>
+ /// Loads a resource at the given <paramref name="path"/>, caching the result
+ /// for further access.
+ /// The registered <see cref="ResourceFormatLoader"/> instances are queried sequentially
+ /// to find the first one which can handle the file's extension, and then attempt
+ /// loading. If loading fails, the remaining ResourceFormatLoaders are also attempted.
+ /// An optional <paramref name="typeHint"/> can be used to further specify the
+ /// <see cref="Resource"/> type that should be handled by the <see cref="ResourceFormatLoader"/>.
+ /// Anything that inherits from <see cref="Resource"/> can be used as a type hint,
+ /// for example <see cref="Image"/>.
+ /// The <paramref name="cacheMode"/> property defines whether and how the cache should
+ /// be used or updated when loading the resource. See <see cref="CacheMode"/> for details.
+ /// Returns an empty resource if no <see cref="ResourceFormatLoader"/> could handle the file.
+ /// </summary>
+ /// <exception cref="InvalidCastException">
+ /// Thrown when the given the loaded resource can't be casted to the given type <typeparamref name="T"/>.
+ /// </exception>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Resource"/>.</typeparam>
+ public static T Load<T>(string path, string typeHint = null, CacheMode cacheMode = CacheMode.Reuse) where T : class
{
- return (T)(object)Load(path, typeHint, noCache);
+ return (T)(object)Load(path, typeHint, cacheMode);
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs
index 20b11a48dd..df130a5c77 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs
@@ -6,12 +6,16 @@ namespace Godot
{
public partial class SceneTree
{
+ /// <summary>
+ /// Returns a list of all nodes assigned to the given <paramref name="group"/>.
+ /// </summary>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
public Array<T> GetNodesInGroup<T>(StringName group) where T : class
{
- return new Array<T>(godot_icall_SceneTree_get_nodes_in_group_Generic(Object.GetPtr(this), StringName.GetPtr(group), typeof(T)));
+ return new Array<T>(godot_icall_SceneTree_get_nodes_in_group_Generic(GetPtr(this), StringName.GetPtr(group), typeof(T)));
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, IntPtr group, Type elemType);
+ internal static extern IntPtr godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, IntPtr group, Type elemType);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index 6699c5992c..ef42374041 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -1,149 +1,431 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
-
#endif
-
-// TODO: Add comments describing what this class does. It is not obvious.
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
namespace Godot
{
+ /// <summary>
+ /// Godot's global functions.
+ /// </summary>
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).
+ /// </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 object Bytes2Var(byte[] bytes, bool allowObjects = false)
{
return godot_icall_GD_bytes2var(bytes, allowObjects);
}
+ /// <summary>
+ /// Converts from a <c>Variant</c> type to another 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);
+ /// </code>
+ /// </example>
+ /// <returns>The <c>Variant</c> converted to the given <paramref name="type"/>.</returns>
public static object Convert(object what, Variant.Type type)
{
return godot_icall_GD_convert(what, type);
}
+ /// <summary>
+ /// Converts from decibels to linear energy (audio).
+ /// </summary>
+ /// <seealso cref="Linear2Db(real_t)"/>
+ /// <param name="db">Decibels to convert.</param>
+ /// <returns>Audio volume as linear energy.</returns>
public static real_t Db2Linear(real_t db)
{
- return (real_t) Math.Exp(db * 0.11512925464970228420089957273422);
+ return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
}
- public static real_t DecTime(real_t value, real_t amount, real_t step)
+ private static object[] GetPrintParams(object[] parameters)
{
- real_t sgn = Mathf.Sign(value);
- real_t val = Mathf.Abs(value);
- val -= amount * step;
- if (val < 0)
- val = 0;
- return val * sgn;
+ if (parameters == null)
+ {
+ return new[] { "null" };
+ }
+
+ return Array.ConvertAll(parameters, x => x?.ToString() ?? "null");
}
+ /// <summary>
+ /// Returns the integer hash of the variable passed.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print(GD.Hash("a")); // Prints 177670
+ /// </code>
+ /// </example>
+ /// <param name="var">Variable that will be hashed.</param>
+ /// <returns>Hash of the variable passed.</returns>
public static int Hash(object var)
{
return godot_icall_GD_hash(var);
}
+ /// <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 godot_icall_GD_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="Db2Linear(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.Linear2Db(slider.value));
+ /// </code>
+ /// </example>
+ /// <param name="linear">The linear energy to convert.</param>
+ /// <returns>Audio as decibels</returns>
public static real_t Linear2Db(real_t linear)
{
- return (real_t) (Math.Log(linear) * 8.6858896380650365530225783783321);
- }
-
+ 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,
+ /// especially when loading scenes. To avoid unnecessary delays when loading something
+ /// multiple times, either store the resource in a variable.
+ ///
+ /// Note: Resource paths can be obtained by right-clicking on a resource in the FileSystem
+ /// dock and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script.
+ ///
+ /// Important: The path must be absolute, a local path will just return <see langword="null"/>.
+ /// This method is a simplified version of <see cref="ResourceLoader.Load"/>, which can be used
+ /// for more advanced scenarios.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// // Load a scene called main located in the root of the project directory and cache it in a variable.
+ /// var main = GD.Load("res://main.tscn"); // main will contain a PackedScene resource.
+ /// </code>
+ /// </example>
+ /// <param name="path">Path of the <see cref="Resource"/> to load.</param>
+ /// <returns>The loaded <see cref="Resource"/>.</returns>
public static Resource Load(string path)
{
return ResourceLoader.Load(path);
}
+ /// <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,
+ /// especially when loading scenes. To avoid unnecessary delays when loading something
+ /// multiple times, either store the resource in a variable.
+ ///
+ /// Note: Resource paths can be obtained by right-clicking on a resource in the FileSystem
+ /// dock and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script.
+ ///
+ /// Important: The path must be absolute, a local path will just return <see langword="null"/>.
+ /// This method is a simplified version of <see cref="ResourceLoader.Load"/>, which can be used
+ /// for more advanced scenarios.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// // Load a scene called main located in the root of the project directory and cache it in a variable.
+ /// var main = GD.Load&lt;PackedScene&gt;("res://main.tscn"); // main will contain a PackedScene resource.
+ /// </code>
+ /// </example>
+ /// <param name="path">Path of the <see cref="Resource"/> to load.</param>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Resource"/>.</typeparam>
public static T Load<T>(string path) where T : class
{
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.
+ /// To print an error message and pause project execution in debug builds,
+ /// use [code]assert(false, "test error")[/code] instead.
+ /// </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)
{
godot_icall_GD_pusherror(message);
}
+ /// <summary>
+ /// Pushes a warning message to Godot's built-in debugger and to the OS terminal.
+ /// </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)
{
godot_icall_GD_pushwarning(message);
}
+ /// <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)"/>
+ /// 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 };
+ /// 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)
{
- godot_icall_GD_print(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_print(GetPrintParams(what));
}
+ /// <summary>
+ /// Prints the current stack trace information to the console.
+ /// </summary>
public static void PrintStack()
{
Print(System.Environment.StackTrace);
}
+ /// <summary>
+ /// Prints one or more arguments to strings in the best way possible to standard error line.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PrintErr("prints to stderr");
+ /// </code>
+ /// </example>
+ /// <param name="what">Arguments that will be printed.</param>
public static void PrintErr(params object[] what)
{
- godot_icall_GD_printerr(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
- }
-
+ godot_icall_GD_printerr(GetPrintParams(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[])"/>.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PrintRaw("A");
+ /// GD.PrintRaw("B");
+ /// // Prints AB
+ /// </code>
+ /// </example>
+ /// <param name="what">Arguments that will be printed.</param>
public static void PrintRaw(params object[] what)
{
- godot_icall_GD_printraw(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_printraw(GetPrintParams(what));
}
+ /// <summary>
+ /// Prints one or more arguments to the console with a space between each argument.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PrintS("A", "B", "C"); // Prints A B C
+ /// </code>
+ /// </example>
+ /// <param name="what">Arguments that will be printed.</param>
public static void PrintS(params object[] what)
{
- godot_icall_GD_prints(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_prints(GetPrintParams(what));
}
+ /// <summary>
+ /// Prints one or more arguments to the console with a tab between each argument.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.PrintT("A", "B", "C"); // Prints A B C
+ /// </code>
+ /// </example>
+ /// <param name="what">Arguments that will be printed.</param>
public static void PrintT(params object[] what)
{
- godot_icall_GD_printt(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_printt(GetPrintParams(what));
}
+ /// <summary>
+ /// Returns a random floating point value between <c>0.0</c> and <c>1.0</c> (inclusive).
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Randf(); // Returns e.g. 0.375671
+ /// </code>
+ /// </example>
+ /// <returns>A random <see langword="float"/> number.</returns>
public static float Randf()
{
return godot_icall_GD_randf();
}
+ /// <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).
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Randi(); // Returns random integer between 0 and 2^32 - 1
+ /// GD.Randi() % 20; // Returns random integer between 0 and 19
+ /// GD.Randi() % 100; // Returns random integer between 0 and 99
+ /// GD.Randi() % 100 + 1; // Returns random integer between 1 and 100
+ /// </code>
+ /// </example>
+ /// <returns>A random <see langword="uint"/> number.</returns>
public static uint Randi()
{
return godot_icall_GD_randi();
}
+ /// <summary>
+ /// Randomizes the seed (or the internal state) of the random number generator.
+ /// Current implementation reseeds using a number based on 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.
+ /// </summary>
public static void Randomize()
{
godot_icall_GD_randomize();
}
+ /// <summary>
+ /// Returns a random floating point value on the interval 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
+ /// </code>
+ /// </example>
+ /// <returns>A random <see langword="double"/> number inside the given range.</returns>
public static double RandRange(double from, double to)
{
return godot_icall_GD_randf_range(from, to);
}
+ /// <summary>
+ /// Returns a random signed 32-bit integer between <paramref name="from"/>
+ /// and <paramref name="to"/> (inclusive). If <paramref name="to"/> is lesser than
+ /// <paramref name="from"/>, they are swapped.
+ /// </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
+ /// </code>
+ /// </example>
+ /// <returns>A random <see langword="int"/> number inside the given range.</returns>
public static int RandRange(int from, int to)
{
return godot_icall_GD_randi_range(from, to);
}
- public static uint RandSeed(ulong seed, out ulong newSeed)
+ /// <summary>
+ /// Returns a random unsigned 32-bit integer, using the given <paramref name="seed"/>.
+ /// </summary>
+ /// <param name="seed">
+ /// Seed to use to generate the random number.
+ /// If a different seed is used, its value will be modfied.
+ /// </param>
+ /// <returns>A random <see langword="uint"/> number.</returns>
+ public static uint RandFromSeed(ref ulong seed)
{
- return godot_icall_GD_rand_seed(seed, out newSeed);
+ return godot_icall_GD_rand_seed(seed, out seed);
}
+ /// <summary>
+ /// Returns a <see cref="IEnumerable{T}"/> that iterates from
+ /// <c>0</c> to <paramref name="end"/> in steps of <c>1</c>.
+ /// </summary>
+ /// <param name="end">The last index.</param>
public static IEnumerable<int> Range(int end)
{
return Range(0, end, 1);
}
+ /// <summary>
+ /// Returns a <see cref="IEnumerable{T}"/> that iterates from
+ /// <paramref name="start"/> to <paramref name="end"/> in steps of <c>1</c>.
+ /// </summary>
+ /// <param name="start">The first index.</param>
+ /// <param name="end">The last index.</param>
public static IEnumerable<int> Range(int start, int end)
{
return Range(start, end, 1);
}
+ /// <summary>
+ /// Returns a <see cref="IEnumerable{T}"/> that iterates from
+ /// <paramref name="start"/> to <paramref name="end"/> in steps of <paramref name="step"/>.
+ /// </summary>
+ /// <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 (end < start && step > 0)
@@ -164,109 +446,164 @@ namespace Godot
}
}
+ /// <summary>
+ /// Sets seed for the random number generator.
+ /// </summary>
+ /// <param name="seed">Seed that will be used.</param>
public static void Seed(ulong seed)
{
godot_icall_GD_seed(seed);
}
+ /// <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 object[] what)
{
return godot_icall_GD_str(what);
}
+ /// <summary>
+ /// Converts a formatted string that was returned by <see cref="Var2Str(object)"/> to the original value.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// string a = "{\"a\": 1, \"b\": 2 }";
+ /// var b = (Godot.Collections.Dictionary)GD.Str2Var(a);
+ /// GD.Print(b["a"]); // Prints 1
+ /// </code>
+ /// </example>
+ /// <param name="str">String that will be converted to Variant.</param>
+ /// <returns>The decoded <c>Variant</c>.</returns>
public static object Str2Var(string str)
{
return godot_icall_GD_str2var(str);
}
+ /// <summary>
+ /// Returns whether the given class exists in <see cref="ClassDB"/>.
+ /// </summary>
+ /// <returns>If the class exists in <see cref="ClassDB"/>.</returns>
public static bool TypeExists(StringName type)
{
return godot_icall_GD_type_exists(StringName.GetPtr(type));
}
+ /// <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="Bytes2Var(byte[], bool)"/>.
+ /// </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[] Var2Bytes(object var, bool fullObjects = false)
{
return godot_icall_GD_var2bytes(var, fullObjects);
}
+ /// <summary>
+ /// Converts a <c>Variant</c> <paramref name="var"/> to a formatted string that
+ /// can later be parsed using <see cref="Str2Var(string)"/>.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var a = new Godot.Collections.Dictionary { ["a"] = 1, ["b"] = 2 };
+ /// GD.Print(GD.Var2Str(a));
+ /// // Prints
+ /// // {
+ /// // "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>
public static string Var2Str(object var)
{
return godot_icall_GD_var2str(var);
}
+ /// <summary>
+ /// Get the <see cref="Variant.Type"/> that corresponds for the given <see cref="Type"/>.
+ /// </summary>
+ /// <returns>The <see cref="Variant.Type"/> for the given <paramref name="type"/>.</returns>
public static Variant.Type TypeToVariantType(Type type)
{
return godot_icall_TypeToVariantType(type);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allowObjects);
+ internal static extern object godot_icall_GD_bytes2var(byte[] bytes, bool allowObjects);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_GD_convert(object what, Variant.Type type);
+ internal static extern object godot_icall_GD_convert(object what, Variant.Type type);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_GD_hash(object var);
+ internal static extern int godot_icall_GD_hash(object var);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static Object godot_icall_GD_instance_from_id(ulong instanceId);
+ internal static extern Object godot_icall_GD_instance_from_id(ulong instanceId);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_print(object[] what);
+ internal static extern void godot_icall_GD_print(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_printerr(object[] what);
+ internal static extern void godot_icall_GD_printerr(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_printraw(object[] what);
+ internal static extern void godot_icall_GD_printraw(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_prints(object[] what);
+ internal static extern void godot_icall_GD_prints(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_printt(object[] what);
+ internal static extern void godot_icall_GD_printt(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static float godot_icall_GD_randf();
+ internal static extern float godot_icall_GD_randf();
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static uint godot_icall_GD_randi();
+ internal static extern uint godot_icall_GD_randi();
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_randomize();
+ internal static extern void godot_icall_GD_randomize();
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static double godot_icall_GD_randf_range(double from, double to);
+ internal static extern double godot_icall_GD_randf_range(double from, double to);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_GD_randi_range(int from, int to);
+ internal static extern int godot_icall_GD_randi_range(int from, int to);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed);
+ internal static extern uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_seed(ulong seed);
+ internal static extern void godot_icall_GD_seed(ulong seed);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string godot_icall_GD_str(object[] what);
+ internal static extern string godot_icall_GD_str(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_GD_str2var(string str);
+ internal static extern object godot_icall_GD_str2var(string str);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static bool godot_icall_GD_type_exists(IntPtr type);
+ internal static extern bool godot_icall_GD_type_exists(IntPtr type);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static byte[] godot_icall_GD_var2bytes(object what, bool fullObjects);
+ internal static extern byte[] godot_icall_GD_var2bytes(object what, bool fullObjects);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string godot_icall_GD_var2str(object var);
+ internal static extern string godot_icall_GD_var2str(object var);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_pusherror(string type);
+ internal static extern void godot_icall_GD_pusherror(string type);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_GD_pushwarning(string type);
+ internal static extern void godot_icall_GD_pushwarning(string type);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern Variant.Type godot_icall_TypeToVariantType(Type type);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
index 4b5e3f8761..c01c926e82 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
@@ -6,7 +6,8 @@ namespace Godot
{
public class GodotSynchronizationContext : SynchronizationContext
{
- private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> _queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
+ private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> _queue =
+ new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
public override void Post(SendOrPostCallback d, object state)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs
index f1a00ae0fa..9ccac1faaf 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs
@@ -1,4 +1,3 @@
-using System;
using System.Diagnostics;
namespace Godot
@@ -25,7 +24,7 @@ namespace Godot
try
{
- var stackTrace = new StackTrace(true).ToString();
+ string stackTrace = new StackTrace(true).ToString();
GD.PrintErr(stackTrace);
}
catch
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs
new file mode 100644
index 0000000000..729529d093
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Godot
+{
+ public static partial class GD
+ {
+ /// <summary>
+ /// Fires when an unhandled exception occurs, regardless of project settings.
+ /// </summary>
+ public static event EventHandler<UnhandledExceptionArgs> UnhandledException;
+
+ private static void OnUnhandledException(Exception e)
+ {
+ UnhandledException?.Invoke(null, new UnhandledExceptionArgs(e));
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
index c59d083080..3051bcedc7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
@@ -1,66 +1,137 @@
using System;
-using System.Collections;
using System.Collections.Generic;
namespace Godot
{
- using Array = Godot.Collections.Array;
- using Dictionary = Godot.Collections.Dictionary;
-
- static class MarshalUtils
+ internal static class MarshalUtils
{
/// <summary>
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="Godot.Collections.Array{T}"/>; otherwise returns <see langword="false"/>.
+ /// is <see cref="Collections.Array{T}"/>; otherwise returns <see langword="false"/>.
/// </summary>
- /// <exception cref="System.InvalidOperationException">
- /// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="type"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
/// </exception>
- static bool TypeIsGenericArray(Type type) =>
- type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>);
+ private static bool TypeIsGenericArray(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(Collections.Array<>);
/// <summary>
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="Godot.Collections.Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
+ /// is <see cref="Collections.Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
/// </summary>
- /// <exception cref="System.InvalidOperationException">
- /// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="type"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
/// </exception>
- static bool TypeIsGenericDictionary(Type type) =>
- type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
+ private static bool TypeIsGenericDictionary(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(Collections.Dictionary<,>);
- static bool TypeIsSystemGenericList(Type type) =>
- type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>);
+ /// <summary>
+ /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
+ /// is <see cref="List{T}"/>; otherwise returns <see langword="false"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="type"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
+ /// </exception>
+ private static bool TypeIsSystemGenericList(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(List<>);
- static bool TypeIsSystemGenericDictionary(Type type) =>
- type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.Dictionary<,>);
+ /// <summary>
+ /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
+ /// is <see cref="Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="type"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
+ /// </exception>
+ private static bool TypeIsSystemGenericDictionary(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
- static bool TypeIsGenericIEnumerable(Type type) => type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
+ /// <summary>
+ /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
+ /// is <see cref="IEnumerable{T}"/>; otherwise returns <see langword="false"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="type"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
+ /// </exception>
+ private static bool TypeIsGenericIEnumerable(Type type) => type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
- static bool TypeIsGenericICollection(Type type) => type.GetGenericTypeDefinition() == typeof(ICollection<>);
+ /// <summary>
+ /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
+ /// is <see cref="ICollection{T}"/>; otherwise returns <see langword="false"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="type"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
+ /// </exception>
+ private static bool TypeIsGenericICollection(Type type) => type.GetGenericTypeDefinition() == typeof(ICollection<>);
- static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>);
+ /// <summary>
+ /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
+ /// is <see cref="IDictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="type"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
+ /// </exception>
+ private static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>);
- static void ArrayGetElementType(Type arrayType, out Type elementType)
+ /// <summary>
+ /// Gets the element type for the given <paramref name="arrayType"/>.
+ /// </summary>
+ /// <param name="arrayType">Type for the generic array.</param>
+ /// <param name="elementType">Element type for the generic array.</param>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="arrayType"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
+ /// </exception>
+ private static void ArrayGetElementType(Type arrayType, out Type elementType)
{
elementType = arrayType.GetGenericArguments()[0];
}
- static void DictionaryGetKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
+ /// <summary>
+ /// Gets the key type and the value type for the given <paramref name="dictionaryType"/>.
+ /// </summary>
+ /// <param name="dictionaryType">The type for the generic dictionary.</param>
+ /// <param name="keyType">Key type for the generic dictionary.</param>
+ /// <param name="valueType">Value type for the generic dictionary.</param>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown when the given <paramref name="dictionaryType"/> is not a generic type.
+ /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
+ /// </exception>
+ private static void DictionaryGetKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
{
var genericArgs = dictionaryType.GetGenericArguments();
keyType = genericArgs[0];
valueType = genericArgs[1];
}
- static Type MakeGenericArrayType(Type elemType)
+ /// <summary>
+ /// Constructs a new <see cref="Type"/> from <see cref="Collections.Array{T}"/>
+ /// where the generic type for the elements is <paramref name="elemType"/>.
+ /// </summary>
+ /// <param name="elemType">Element type for the array.</param>
+ /// <returns>The generic array type with the specified element type.</returns>
+ private static Type MakeGenericArrayType(Type elemType)
{
- return typeof(Godot.Collections.Array<>).MakeGenericType(elemType);
+ return typeof(Collections.Array<>).MakeGenericType(elemType);
}
- static Type MakeGenericDictionaryType(Type keyType, Type valueType)
+ /// <summary>
+ /// Constructs a new <see cref="Type"/> from <see cref="Collections.Dictionary{TKey, TValue}"/>
+ /// where the generic type for the keys is <paramref name="keyType"/> and
+ /// for the values is <paramref name="valueType"/>.
+ /// </summary>
+ /// <param name="keyType">Key type for the dictionary.</param>
+ /// <param name="valueType">Key type for the dictionary.</param>
+ /// <returns>The generic dictionary type with the specified key and value types.</returns>
+ private static Type MakeGenericDictionaryType(Type keyType, Type valueType)
{
- return typeof(Godot.Collections.Dictionary<,>).MakeGenericType(keyType, valueType);
+ return typeof(Collections.Dictionary<,>).MakeGenericType(keyType, valueType);
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index c3f372d415..6f7fac7429 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -1,12 +1,15 @@
-using System;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
namespace Godot
{
+ /// <summary>
+ /// Provides constants and static methods for common mathematical functions.
+ /// </summary>
public static partial class Mathf
{
// Define constants with Decimal precision and cast down to double or float.
@@ -14,122 +17,125 @@ namespace Godot
/// <summary>
/// The circle constant, the circumference of the unit circle in radians.
/// </summary>
- public const real_t Tau = (real_t) 6.2831853071795864769252867666M; // 6.2831855f and 6.28318530717959
+ // 6.2831855f and 6.28318530717959
+ public const real_t Tau = (real_t)6.2831853071795864769252867666M;
/// <summary>
/// Constant that represents how many times the diameter of a circle
- /// fits around its perimeter. This is equivalent to `Mathf.Tau / 2`.
+ /// fits around its perimeter. This is equivalent to <c>Mathf.Tau / 2</c>.
/// </summary>
- public const real_t Pi = (real_t) 3.1415926535897932384626433833M; // 3.1415927f and 3.14159265358979
+ // 3.1415927f and 3.14159265358979
+ public const real_t Pi = (real_t)3.1415926535897932384626433833M;
/// <summary>
- /// Positive infinity. For negative infinity, use `-Mathf.Inf`.
+ /// Positive infinity. For negative infinity, use <c>-Mathf.Inf</c>.
/// </summary>
public const real_t Inf = real_t.PositiveInfinity;
/// <summary>
- /// "Not a Number", an invalid value. `NaN` has special properties, including
+ /// "Not a Number", an invalid value. <c>NaN</c> has special properties, including
/// that it is not equal to itself. It is output by some invalid operations,
/// such as dividing zero by zero.
/// </summary>
public const real_t NaN = real_t.NaN;
- private const real_t Deg2RadConst = (real_t) 0.0174532925199432957692369077M; // 0.0174532924f and 0.0174532925199433
- private const real_t Rad2DegConst = (real_t) 57.295779513082320876798154814M; // 57.29578f and 57.2957795130823
+ // 0.0174532924f and 0.0174532925199433
+ private const real_t _deg2RadConst = (real_t)0.0174532925199432957692369077M;
+ // 57.29578f and 57.2957795130823
+ private const real_t _rad2DegConst = (real_t)57.295779513082320876798154814M;
/// <summary>
- /// Returns the absolute value of `s` (i.e. positive value).
+ /// 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 `s`.</returns>
+ /// <returns>The absolute value of <paramref name="s"/>.</returns>
public static int Abs(int s)
{
return Math.Abs(s);
}
/// <summary>
- /// Returns the absolute value of `s` (i.e. positive value).
+ /// 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 `s`.</returns>
+ /// <returns>The absolute value of <paramref name="s"/>.</returns>
public static real_t Abs(real_t s)
{
return Math.Abs(s);
}
/// <summary>
- /// Returns the arc cosine of `s` in radians. Use to get the angle of cosine s.
+ /// 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 `0` to `Tau/2`.</returns>
+ /// <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)
{
return (real_t)Math.Acos(s);
}
/// <summary>
- /// Returns the arc sine of `s` in radians. Use to get the angle of sine s.
+ /// 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 `-Tau/4` to `Tau/4`.</returns>
+ /// <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)
{
return (real_t)Math.Asin(s);
}
/// <summary>
- /// Returns the arc tangent of `s` in radians. Use to get the angle of tangent s.
+ /// 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(real_t, real_t)"/> if you have both `y` and `x`.
+ /// See <see cref="Atan2(real_t, real_t)"/> 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 `-Tau/4` to `Tau/4`.</returns>
+ /// <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)
{
return (real_t)Math.Atan(s);
}
/// <summary>
- /// Returns the arc tangent of `y` and `x` in radians. Use to get the angle
- /// of the tangent of `y/x`. To compute the value, the method takes into
+ /// 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 `-Tau/2` to `Tau/2`.</returns>
+ /// <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)
{
return (real_t)Math.Atan2(y, x);
}
/// <summary>
- /// Converts a 2D point expressed in the cartesian coordinate
- /// system (X and Y axis) to the polar coordinate system
- /// (a distance from the origin and an angle).
- /// </summary>
- /// <param name="x">The input X coordinate.</param>
- /// <param name="y">The input Y coordinate.</param>
- /// <returns>A <see cref="Vector2"/> with X representing the distance and Y representing the angle.</returns>
- public static Vector2 Cartesian2Polar(real_t x, real_t y)
- {
- return new Vector2(Sqrt(x * x + y * y), Atan2(y, x));
- }
-
- /// <summary>
- /// Rounds `s` upward (towards positive infinity).
+ /// 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 `s`.</returns>
+ /// <returns>The smallest whole number that is not less than <paramref name="s"/>.</returns>
public static real_t Ceil(real_t s)
{
return (real_t)Math.Ceiling(s);
}
/// <summary>
- /// Clamps a `value` so that it is not less than `min` and not more than `max`.
+ /// 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>
@@ -141,7 +147,8 @@ namespace Godot
}
/// <summary>
- /// Clamps a `value` so that it is not less than `min` and not more than `max`.
+ /// 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>
@@ -153,7 +160,7 @@ namespace Godot
}
/// <summary>
- /// Returns the cosine of angle `s` in radians.
+ /// 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>
@@ -163,7 +170,7 @@ namespace Godot
}
/// <summary>
- /// Returns the hyperbolic cosine of angle `s` in radians.
+ /// 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>
@@ -179,16 +186,18 @@ namespace Godot
/// <returns>The same angle expressed in radians.</returns>
public static real_t Deg2Rad(real_t deg)
{
- return deg * Deg2RadConst;
+ return deg * _deg2RadConst;
}
/// <summary>
- /// Easing function, based on exponent. The curve values are:
- /// `0` is constant, `1` is linear, `0` to `1` is ease-in, `1` or more is ease-out.
+ /// 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">`0` is constant, `1` is linear, `0` to `1` is ease-in, `1` or more is ease-out.</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 real_t Ease(real_t s, real_t curve)
{
@@ -218,7 +227,7 @@ namespace Godot
return 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 - Pow(1.0f - ((s - 0.5f) * 2.0f), -curve)) * 0.5f) + 0.5f;
}
return 0f;
@@ -226,20 +235,20 @@ namespace Godot
/// <summary>
/// The natural exponential function. It raises the mathematical
- /// constant `e` to the power of `s` and returns it.
+ /// constant <c>e</c> to the power of <paramref name="s"/> and returns it.
/// </summary>
- /// <param name="s">The exponent to raise `e` to.</param>
- /// <returns>`e` raised to the power of `s`.</returns>
+ /// <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)
{
return (real_t)Math.Exp(s);
}
/// <summary>
- /// Rounds `s` downward (towards negative infinity).
+ /// 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 `s`.</returns>
+ /// <returns>The largest whole number that is not more than <paramref name="s"/>.</returns>
public static real_t Floor(real_t s)
{
return (real_t)Math.Floor(s);
@@ -259,12 +268,13 @@ namespace Godot
}
/// <summary>
- /// Returns true if `a` and `b` are approximately equal to each other.
+ /// 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 bool for whether or not the two values are approximately equal.</returns>
+ /// <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)
{
// Check for exact equality first, required to handle "infinity" values.
@@ -282,33 +292,33 @@ namespace Godot
}
/// <summary>
- /// Returns whether `s` is an infinity value (either positive infinity or negative infinity).
+ /// 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 bool for whether or not the value is an infinity value.</returns>
+ /// <returns>A <see langword="bool"/> for whether or not the value is an infinity value.</returns>
public static bool IsInf(real_t s)
{
return real_t.IsInfinity(s);
}
/// <summary>
- /// Returns whether `s` is a `NaN` ("Not a Number" or invalid) value.
+ /// 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 bool for whether or not the value is a `NaN` value.</returns>
+ /// <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)
{
return real_t.IsNaN(s);
}
/// <summary>
- /// Returns true if `s` is approximately zero.
+ /// Returns <see langword="true"/> if <paramref name="s"/> is approximately 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.
/// </summary>
/// <param name="s">The value to check.</param>
- /// <returns>A bool for whether or not the value is nearly zero.</returns>
+ /// <returns>A <see langword="bool"/> for whether or not the value is nearly zero.</returns>
public static bool IsZeroApprox(real_t s)
{
return Abs(s) < Epsilon;
@@ -324,7 +334,7 @@ namespace Godot
/// <returns>The resulting value of the interpolation.</returns>
public static real_t Lerp(real_t from, real_t to, real_t weight)
{
- return from + (to - from) * weight;
+ return from + ((to - from) * weight);
}
/// <summary>
@@ -341,7 +351,7 @@ namespace Godot
{
real_t difference = (to - from) % Mathf.Tau;
real_t distance = ((2 * difference) % Mathf.Tau) - difference;
- return from + distance * weight;
+ return from + (distance * weight);
}
/// <summary>
@@ -350,7 +360,7 @@ namespace Godot
/// 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 `s`.</returns>
+ /// <returns>The natural log of <paramref name="s"/>.</returns>
public static real_t Log(real_t s)
{
return (real_t)Math.Log(s);
@@ -401,9 +411,9 @@ namespace Godot
}
/// <summary>
- /// Moves `from` toward `to` by the `delta` value.
+ /// Moves <paramref name="from"/> toward <paramref name="to"/> by the <paramref name="delta"/> value.
///
- /// Use a negative delta value to move away.
+ /// 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>
@@ -411,11 +421,14 @@ namespace Godot
/// <returns>The value after moving.</returns>
public static real_t MoveToward(real_t from, real_t to, real_t delta)
{
- return Abs(to - from) <= delta ? to : from + Sign(to - from) * delta;
+ if (Abs(to - from) <= delta)
+ return to;
+
+ return from + (Sign(to - from) * delta);
}
/// <summary>
- /// Returns the nearest larger power of 2 for the integer `value`.
+ /// Returns the nearest larger power of 2 for the integer <paramref name="value"/>.
/// </summary>
/// <param name="value">The input value.</param>
/// <returns>The nearest larger power of 2.</returns>
@@ -432,23 +445,10 @@ namespace Godot
}
/// <summary>
- /// Converts a 2D point expressed in the polar coordinate
- /// system (a distance from the origin `r` and an angle `th`)
- /// to the cartesian coordinate system (X and Y axis).
- /// </summary>
- /// <param name="r">The distance from the origin.</param>
- /// <param name="th">The angle of the point.</param>
- /// <returns>A <see cref="Vector2"/> representing the cartesian coordinate.</returns>
- public static Vector2 Polar2Cartesian(real_t r, real_t th)
- {
- return new Vector2(r * Cos(th), r * Sin(th));
- }
-
- /// <summary>
- /// Performs a canonical Modulus operation, where the output is on the range `[0, b)`.
+ /// 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, b)`.</param>
+ /// <param name="b">The divisor. The output is on the range [0, <paramref name="b"/>).</param>
/// <returns>The resulting output.</returns>
public static int PosMod(int a, int b)
{
@@ -461,10 +461,10 @@ namespace Godot
}
/// <summary>
- /// Performs a canonical Modulus operation, where the output is on the range `[0, b)`.
+ /// 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, b)`.</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)
{
@@ -477,11 +477,11 @@ namespace Godot
}
/// <summary>
- /// Returns the result of `x` raised to the power of `y`.
+ /// 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>`x` raised to the power of `y`.</returns>
+ /// <returns><paramref name="x"/> raised to the power of <paramref name="y"/>.</returns>
public static real_t Pow(real_t x, real_t y)
{
return (real_t)Math.Pow(x, y);
@@ -494,11 +494,11 @@ namespace Godot
/// <returns>The same angle expressed in degrees.</returns>
public static real_t Rad2Deg(real_t rad)
{
- return rad * Rad2DegConst;
+ return rad * _rad2DegConst;
}
/// <summary>
- /// Rounds `s` to the nearest whole number,
+ /// 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>
@@ -509,29 +509,33 @@ namespace Godot
}
/// <summary>
- /// Returns the sign of `s`: `-1` or `1`. Returns `0` if `s` is `0`.
+ /// 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: `1`, `-1`, or `0`.</returns>
+ /// <returns>One of three possible values: <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
public static int Sign(int s)
{
- if (s == 0) return 0;
+ if (s == 0)
+ return 0;
return s < 0 ? -1 : 1;
}
/// <summary>
- /// Returns the sign of `s`: `-1` or `1`. Returns `0` if `s` is `0`.
+ /// 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: `1`, `-1`, or `0`.</returns>
+ /// <returns>One of three possible values: <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
public static int Sign(real_t s)
{
- if (s == 0) return 0;
+ if (s == 0)
+ return 0;
return s < 0 ? -1 : 1;
}
/// <summary>
- /// Returns the sine of angle `s` in radians.
+ /// 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>
@@ -541,7 +545,7 @@ namespace Godot
}
/// <summary>
- /// Returns the hyperbolic sine of angle `s` in radians.
+ /// 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>
@@ -551,8 +555,8 @@ namespace Godot
}
/// <summary>
- /// Returns a number smoothly interpolated between `from` and `to`,
- /// based on the `weight`. Similar to <see cref="Lerp(real_t, real_t, real_t)"/>,
+ /// 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)"/>,
/// but interpolates faster at the beginning and slower at the end.
/// </summary>
/// <param name="from">The start value for interpolation.</param>
@@ -566,16 +570,16 @@ namespace Godot
return from;
}
real_t x = Clamp((weight - from) / (to - from), (real_t)0.0, (real_t)1.0);
- return x * x * (3 - 2 * x);
+ return x * x * (3 - (2 * x));
}
/// <summary>
- /// Returns the square root of `s`, where `s` is a non-negative number.
+ /// Returns the square root of <paramref name="s"/>, where <paramref name="s"/> is a non-negative number.
///
- /// If you need negative inputs, use `System.Numerics.Complex`.
+ /// 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 `s`.</returns>
+ /// <returns>The square root of <paramref name="s"/>.</returns>
public static real_t Sqrt(real_t s)
{
return (real_t)Math.Sqrt(s);
@@ -590,7 +594,8 @@ namespace Godot
/// <returns>The position of the first non-zero digit.</returns>
public static int StepDecimals(real_t step)
{
- double[] sd = new double[] {
+ double[] sd = new double[]
+ {
0.9999,
0.09999,
0.009999,
@@ -601,7 +606,7 @@ namespace Godot
0.00000009999,
0.000000009999,
};
- double abs = Mathf.Abs(step);
+ double abs = Abs(step);
double decs = abs - (int)abs; // Strip away integer part
for (int i = 0; i < sd.Length; i++)
{
@@ -614,9 +619,8 @@ namespace Godot
}
/// <summary>
- /// Snaps float value `s` to a given `step`.
- /// This can also be used to round a floating point
- /// number to an arbitrary number of decimals.
+ /// 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>
@@ -625,14 +629,14 @@ namespace Godot
{
if (step != 0f)
{
- return Floor(s / step + 0.5f) * step;
+ return Floor((s / step) + 0.5f) * step;
}
return s;
}
/// <summary>
- /// Returns the tangent of angle `s` in radians.
+ /// 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>
@@ -642,7 +646,7 @@ namespace Godot
}
/// <summary>
- /// Returns the hyperbolic tangent of angle `s` in radians.
+ /// 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>
@@ -652,8 +656,9 @@ namespace Godot
}
/// <summary>
- /// Wraps `value` between `min` and `max`. Usable for creating loop-alike
- /// behavior or infinite surfaces. If `min` is `0`, this is equivalent
+ /// 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(int, int)"/>, so prefer using that instead.
/// </summary>
/// <param name="value">The value to wrap.</param>
@@ -663,12 +668,16 @@ namespace Godot
public static int Wrap(int value, int min, int max)
{
int range = max - min;
- return range == 0 ? min : min + ((value - min) % range + range) % range;
+ if (range == 0)
+ return min;
+
+ return min + ((((value - min) % range) + range) % range);
}
/// <summary>
- /// Wraps `value` between `min` and `max`. Usable for creating loop-alike
- /// behavior or infinite surfaces. If `min` is `0`, this is equivalent
+ /// 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.
/// </summary>
/// <param name="value">The value to wrap.</param>
@@ -678,7 +687,11 @@ namespace Godot
public static real_t Wrap(real_t value, real_t min, real_t max)
{
real_t range = max - min;
- return IsZeroApprox(range) ? min : min + ((value - min) % range + range) % range;
+ if (IsZeroApprox(range))
+ {
+ return min;
+ }
+ return min + ((((value - min) % range) + range) % range);
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
index c2f4701b5f..9bb73ce7dd 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
@@ -1,10 +1,9 @@
-using System;
-
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
namespace Godot
{
@@ -13,18 +12,18 @@ namespace Godot
// Define constants with Decimal precision and cast down to double or float.
/// <summary>
- /// The natural number `e`.
+ /// The natural number <c>e</c>.
/// </summary>
- public const real_t E = (real_t) 2.7182818284590452353602874714M; // 2.7182817f and 2.718281828459045
+ public const real_t E = (real_t)2.7182818284590452353602874714M; // 2.7182817f and 2.718281828459045
/// <summary>
/// The square root of 2.
/// </summary>
- public const real_t Sqrt2 = (real_t) 1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095
+ public const real_t Sqrt2 = (real_t)1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095
/// <summary>
/// A very small number used for float comparison with error tolerance.
- /// 1e-06 with single-precision floats, but 1e-14 if `REAL_T_IS_DOUBLE`.
+ /// 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.
@@ -45,7 +44,7 @@ namespace Godot
/// <summary>
/// Returns the amount of digits after the decimal place.
/// </summary>
- /// <param name="s">The input <see cref="System.Decimal"/> value.</param>
+ /// <param name="s">The input <see cref="decimal"/> value.</param>
/// <returns>The amount of digits.</returns>
public static int DecimalCount(decimal s)
{
@@ -53,48 +52,51 @@ namespace Godot
}
/// <summary>
- /// Rounds `s` upward (towards positive infinity).
+ /// Rounds <paramref name="s"/> upward (towards positive infinity).
///
- /// This is the same as <see cref="Ceil(real_t)"/>, but returns an `int`.
+ /// This is the same as <see cref="Ceil(real_t)"/>, but returns an <c>int</c>.
/// </summary>
/// <param name="s">The number to ceil.</param>
- /// <returns>The smallest whole number that is not less than `s`.</returns>
+ /// <returns>The smallest whole number that is not less than <paramref name="s"/>.</returns>
public static int CeilToInt(real_t s)
{
return (int)Math.Ceiling(s);
}
/// <summary>
- /// Rounds `s` downward (towards negative infinity).
+ /// Rounds <paramref name="s"/> downward (towards negative infinity).
///
- /// This is the same as <see cref="Floor(real_t)"/>, but returns an `int`.
+ /// This is the same as <see cref="Floor(real_t)"/>, but returns an <c>int</c>.
/// </summary>
/// <param name="s">The number to floor.</param>
- /// <returns>The largest whole number that is not more than `s`.</returns>
+ /// <returns>The largest whole number that is not more than <paramref name="s"/>.</returns>
public static int FloorToInt(real_t s)
{
return (int)Math.Floor(s);
}
/// <summary>
+ /// Rounds <paramref name="s"/> to the nearest whole number.
///
+ /// This is the same as <see cref="Round(real_t)"/>, but returns an <c>int</c>.
/// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
+ /// <param name="s">The number to round.</param>
+ /// <returns>The rounded number.</returns>
public static int RoundToInt(real_t s)
{
return (int)Math.Round(s);
}
/// <summary>
- /// Returns true if `a` and `b` are approximately equal to each other.
+ /// 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)"/>.
/// </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 bool for whether or not the two values are equal.</returns>
+ /// <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)
{
// Check for exact equality first, required to handle "infinity" values.
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
index 4ecc55f94e..f53b5dc904 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
@@ -3,9 +3,45 @@ using System.Runtime.CompilerServices;
namespace Godot
{
+ /// <summary>
+ /// A pre-parsed relative or absolute path in a scene tree,
+ /// for use with <see cref="Node.GetNode(NodePath)"/> and similar functions.
+ /// It can reference a node, a resource within a node, or a property
+ /// of a node or resource.
+ /// For instance, <c>"Path2D/PathFollow2D/Sprite2D:texture:size"</c>
+ /// would refer to the <c>size</c> property of the <c>texture</c>
+ /// resource on the node named <c>"Sprite2D"</c> which is a child of
+ /// the other named nodes in the path.
+ /// You will usually just pass a string to <see cref="Node.GetNode(NodePath)"/>
+ /// and it will be automatically converted, but you may occasionally
+ /// want to parse a path ahead of time with NodePath.
+ /// Exporting a NodePath variable will give you a node selection widget
+ /// in the properties panel of the editor, which can often be useful.
+ /// A NodePath is composed of a list of slash-separated node names
+ /// (like a filesystem path) and an optional colon-separated list of
+ /// "subnames" which can be resources or properties.
+ ///
+ /// Note: In the editor, NodePath properties are automatically updated when moving,
+ /// renaming or deleting a node in the scene tree, but they are never updated at runtime.
+ /// </summary>
+ /// <example>
+ /// Some examples of NodePaths include the following:
+ /// <code>
+ /// // No leading slash means it is relative to the current node.
+ /// new NodePath("A"); // Immediate child A.
+ /// new NodePath("A/B"); // A's child B.
+ /// new NodePath("."); // The current node.
+ /// new NodePath(".."); // The parent node.
+ /// new NodePath("../C"); // A sibling node C.
+ /// // A leading slash means it is absolute from the SceneTree.
+ /// new NodePath("/root"); // Equivalent to GetTree().Root
+ /// new NodePath("/root/Main"); // If your main scene's root node were named "Main".
+ /// new NodePath("/root/MyAutoload"); // If you have an autoloaded node or scene.
+ /// </code>
+ /// </example>
public sealed partial class NodePath : IDisposable
{
- private bool disposed = false;
+ private bool _disposed = false;
private IntPtr ptr;
@@ -14,7 +50,7 @@ namespace Godot
if (instance == null)
throw new NullReferenceException($"The instance of type {nameof(NodePath)} is null.");
- if (instance.disposed)
+ if (instance._disposed)
throw new ObjectDisposedException(instance.GetType().FullName);
return instance.ptr;
@@ -25,6 +61,9 @@ namespace Godot
Dispose(false);
}
+ /// <summary>
+ /// Disposes of this <see cref="NodePath"/>.
+ /// </summary>
public void Dispose()
{
Dispose(true);
@@ -33,7 +72,7 @@ namespace Godot
private void Dispose(bool disposing)
{
- if (disposed)
+ if (_disposed)
return;
if (ptr != IntPtr.Zero)
@@ -42,7 +81,7 @@ namespace Godot
ptr = IntPtr.Zero;
}
- disposed = true;
+ _disposed = true;
}
internal NodePath(IntPtr ptr)
@@ -50,57 +89,168 @@ namespace Godot
this.ptr = ptr;
}
- public NodePath() : this(string.Empty) {}
-
+ /// <summary>
+ /// Constructs an empty <see cref="NodePath"/>.
+ /// </summary>
+ public NodePath() : this(string.Empty) { }
+
+ /// <summary>
+ /// Constructs a <see cref="NodePath"/> from a string <paramref name="path"/>,
+ /// e.g.: <c>"Path2D/PathFollow2D/Sprite2D:texture:size"</c>.
+ /// A path is absolute if it starts with a slash. Absolute paths
+ /// are only valid in the global scene tree, not within individual
+ /// scenes. In a relative path, <c>"."</c> and <c>".."</c> indicate
+ /// the current node and its parent.
+ /// The "subnames" optionally included after the path to the target
+ /// node can point to resources or properties, and can also be nested.
+ /// </summary>
+ /// <example>
+ /// Examples of valid NodePaths (assuming that those nodes exist and
+ /// have the referenced resources or properties):
+ /// <code>
+ /// // Points to the Sprite2D node.
+ /// "Path2D/PathFollow2D/Sprite2D"
+ /// // Points to the Sprite2D node and its "texture" resource.
+ /// // GetNode() would retrieve "Sprite2D", while GetNodeAndResource()
+ /// // would retrieve both the Sprite2D node and the "texture" resource.
+ /// "Path2D/PathFollow2D/Sprite2D:texture"
+ /// // Points to the Sprite2D node and its "position" property.
+ /// "Path2D/PathFollow2D/Sprite2D:position"
+ /// // Points to the Sprite2D node and the "x" component of its "position" property.
+ /// "Path2D/PathFollow2D/Sprite2D:position:x"
+ /// // Absolute path (from "root")
+ /// "/root/Level/Path2D"
+ /// </code>
+ /// </example>
+ /// <param name="path"></param>
public NodePath(string path)
{
ptr = godot_icall_NodePath_Ctor(path);
}
+ /// <summary>
+ /// Converts a string to a <see cref="NodePath"/>.
+ /// </summary>
+ /// <param name="from">The string to convert.</param>
public static implicit operator NodePath(string from) => new NodePath(from);
+ /// <summary>
+ /// Converts this <see cref="NodePath"/> to a string.
+ /// </summary>
+ /// <param name="from">The <see cref="NodePath"/> to convert.</param>
public static implicit operator string(NodePath from) => from.ToString();
+ /// <summary>
+ /// Converts this <see cref="NodePath"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this <see cref="NodePath"/>.</returns>
public override string ToString()
{
return godot_icall_NodePath_operator_String(GetPtr(this));
}
+ /// <summary>
+ /// Returns a node path with a colon character (<c>:</c>) prepended,
+ /// transforming it to a pure property path with no node name (defaults
+ /// to resolving from the current node).
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// // This will be parsed as a node path to the "x" property in the "position" node.
+ /// var nodePath = new NodePath("position:x");
+ /// // This will be parsed as a node path to the "x" component of the "position" property in the current node.
+ /// NodePath propertyPath = nodePath.GetAsPropertyPath();
+ /// GD.Print(propertyPath); // :position:x
+ /// </code>
+ /// </example>
+ /// <returns>The <see cref="NodePath"/> as a pure property path.</returns>
public NodePath GetAsPropertyPath()
{
return new NodePath(godot_icall_NodePath_get_as_property_path(GetPtr(this)));
}
+ /// <summary>
+ /// Returns all subnames concatenated with a colon character (<c>:</c>)
+ /// as separator, i.e. the right side of the first colon in a node path.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var nodepath = new NodePath("Path2D/PathFollow2D/Sprite2D:texture:load_path");
+ /// GD.Print(nodepath.GetConcatenatedSubnames()); // texture:load_path
+ /// </code>
+ /// </example>
+ /// <returns>The subnames concatenated with <c>:</c>.</returns>
public string GetConcatenatedSubnames()
{
return godot_icall_NodePath_get_concatenated_subnames(GetPtr(this));
}
+ /// <summary>
+ /// Gets the node name indicated by <paramref name="idx"/> (0 to <see cref="GetNameCount"/>).
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var nodePath = new NodePath("Path2D/PathFollow2D/Sprite2D");
+ /// GD.Print(nodePath.GetName(0)); // Path2D
+ /// GD.Print(nodePath.GetName(1)); // PathFollow2D
+ /// GD.Print(nodePath.GetName(2)); // Sprite
+ /// </code>
+ /// </example>
+ /// <param name="idx">The name index.</param>
+ /// <returns>The name at the given index <paramref name="idx"/>.</returns>
public string GetName(int idx)
{
return godot_icall_NodePath_get_name(GetPtr(this), idx);
}
+ /// <summary>
+ /// Gets the number of node names which make up the path.
+ /// Subnames (see <see cref="GetSubnameCount"/>) are not included.
+ /// For example, <c>"Path2D/PathFollow2D/Sprite2D"</c> has 3 names.
+ /// </summary>
+ /// <returns>The number of node names which make up the path.</returns>
public int GetNameCount()
{
return godot_icall_NodePath_get_name_count(GetPtr(this));
}
+ /// <summary>
+ /// Gets the resource or property name indicated by <paramref name="idx"/> (0 to <see cref="GetSubnameCount"/>).
+ /// </summary>
+ /// <param name="idx">The subname index.</param>
+ /// <returns>The subname at the given index <paramref name="idx"/>.</returns>
public string GetSubname(int idx)
{
return godot_icall_NodePath_get_subname(GetPtr(this), idx);
}
+ /// <summary>
+ /// Gets the number of resource or property names ("subnames") in the path.
+ /// Each subname is listed after a colon character (<c>:</c>) in the node path.
+ /// For example, <c>"Path2D/PathFollow2D/Sprite2D:texture:load_path"</c> has 2 subnames.
+ /// </summary>
+ /// <returns>The number of subnames in the path.</returns>
public int GetSubnameCount()
{
return godot_icall_NodePath_get_subname_count(GetPtr(this));
}
+ /// <summary>
+ /// Returns <see langword="true"/> if the node path is absolute (as opposed to relative),
+ /// which means that it starts with a slash character (<c>/</c>). Absolute node paths can
+ /// be used to access the root node (<c>"/root"</c>) or autoloads (e.g. <c>"/global"</c>
+ /// if a "global" autoload was registered).
+ /// </summary>
+ /// <returns>If the <see cref="NodePath"/> is an absolute path.</returns>
public bool IsAbsolute()
{
return godot_icall_NodePath_is_absolute(GetPtr(this));
}
+ /// <summary>
+ /// Returns <see langword="true"/> if the node path is empty.
+ /// </summary>
+ /// <returns>If the <see cref="NodePath"/> is empty.</returns>
public bool IsEmpty()
{
return godot_icall_NodePath_is_empty(GetPtr(this));
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
index 48582d5ad8..8fe08e7e1d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
@@ -5,13 +5,16 @@ namespace Godot
{
public partial class Object : IDisposable
{
- private bool disposed = false;
+ private bool _disposed = false;
private static StringName nativeName = "Object";
internal IntPtr ptr;
internal bool memoryOwn;
+ /// <summary>
+ /// Constructs a new <see cref="Object"/>.
+ /// </summary>
public Object() : this(false)
{
if (ptr == IntPtr.Zero)
@@ -29,6 +32,9 @@ namespace Godot
this.memoryOwn = memoryOwn;
}
+ /// <summary>
+ /// The pointer to the native instance of this <see cref="Object"/>.
+ /// </summary>
public IntPtr NativeInstance
{
get { return ptr; }
@@ -39,7 +45,7 @@ namespace Godot
if (instance == null)
return IntPtr.Zero;
- if (instance.disposed)
+ if (instance._disposed)
throw new ObjectDisposedException(instance.GetType().FullName);
return instance.ptr;
@@ -50,15 +56,21 @@ namespace Godot
Dispose(false);
}
+ /// <summary>
+ /// Disposes of this <see cref="Object"/>.
+ /// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
+ /// <summary>
+ /// Disposes implementation of this <see cref="Object"/>.
+ /// </summary>
protected virtual void Dispose(bool disposing)
{
- if (disposed)
+ if (_disposed)
return;
if (ptr != IntPtr.Zero)
@@ -66,26 +78,30 @@ namespace Godot
if (memoryOwn)
{
memoryOwn = false;
- godot_icall_Reference_Disposed(this, ptr, !disposing);
+ godot_icall_RefCounted_Disposed(this, ptr, !disposing);
}
else
{
godot_icall_Object_Disposed(this, ptr);
}
- this.ptr = IntPtr.Zero;
+ ptr = IntPtr.Zero;
}
- disposed = true;
+ _disposed = true;
}
+ /// <summary>
+ /// Converts this <see cref="Object"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this object.</returns>
public override string ToString()
{
return godot_icall_Object_ToString(GetPtr(this));
}
/// <summary>
- /// Returns a new <see cref="Godot.SignalAwaiter"/> awaiter configured to complete when the instance
+ /// Returns a new <see cref="SignalAwaiter"/> awaiter configured to complete when the instance
/// <paramref name="source"/> emits the signal specified by the <paramref name="signal"/> parameter.
/// </summary>
/// <param name="source">
@@ -107,13 +123,17 @@ namespace Godot
/// }
/// </code>
/// </example>
+ /// <returns>
+ /// A <see cref="SignalAwaiter"/> that completes when
+ /// <paramref name="source"/> emits the <paramref name="signal"/>.
+ /// </returns>
public SignalAwaiter ToSignal(Object source, StringName signal)
{
return new SignalAwaiter(source, signal, this);
}
/// <summary>
- /// Gets a new <see cref="Godot.DynamicGodotObject"/> associated with this instance.
+ /// Gets a new <see cref="DynamicGodotObject"/> associated with this instance.
/// </summary>
public dynamic DynamicObject => new DynamicGodotObject(this);
@@ -129,7 +149,7 @@ namespace Godot
internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Reference_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
+ internal static extern void godot_icall_RefCounted_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void godot_icall_Object_ConnectEventSignals(IntPtr obj);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index 2f8b5f297c..66f7b745f7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -21,10 +21,10 @@ namespace Godot
/// <summary>
/// The normal of the plane, which must be normalized.
- /// In the scalar equation of the plane `ax + by + cz = d`, this is
- /// the vector `(a, b, c)`, where `d` is the <see cref="D"/> property.
+ /// 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 `x`, `y`, and `z`.</value>
+ /// <value>Equivalent to <see cref="x"/>, <see cref="y"/>, and <see cref="z"/>.</value>
public Vector3 Normal
{
get { return _normal; }
@@ -82,8 +82,8 @@ namespace Godot
/// <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 `ax + by + cz = d`,
- /// this is `d`, while the `(a, b, c)` coordinates are represented
+ /// 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>
@@ -92,7 +92,7 @@ namespace Godot
/// <summary>
/// The center of the plane, the point where the normal line intersects the plane.
/// </summary>
- /// <value>Equivalent to <see cref="Normal"/> multiplied by `D`.</value>
+ /// <value>Equivalent to <see cref="Normal"/> multiplied by <see cref="D"/>.</value>
public Vector3 Center
{
get
@@ -107,7 +107,7 @@ namespace Godot
}
/// <summary>
- /// Returns the shortest distance from this plane to the position `point`.
+ /// Returns the shortest distance from this plane to the position <paramref name="point"/>.
/// </summary>
/// <param name="point">The position to use for the calculation.</param>
/// <returns>The shortest distance.</returns>
@@ -117,12 +117,12 @@ namespace Godot
}
/// <summary>
- /// Returns true if point is inside the plane.
+ /// Returns <see langword="true"/> if point is inside the plane.
/// Comparison uses a custom minimum epsilon threshold.
/// </summary>
/// <param name="point">The point to check.</param>
/// <param name="epsilon">The tolerance threshold.</param>
- /// <returns>A bool for whether or not the plane has the point.</returns>
+ /// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns>
public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon)
{
real_t dist = _normal.Dot(point) - D;
@@ -130,12 +130,12 @@ namespace Godot
}
/// <summary>
- /// Returns the intersection point of the three planes: `b`, `c`,
- /// and this plane. If no intersection is found, `null` is returned.
+ /// Returns the intersection point of the three planes: <paramref name="b"/>, <paramref name="c"/>,
+ /// and this plane. If no intersection is found, <see langword="null"/> is returned.
/// </summary>
/// <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 `null` if none is found.</returns>
+ /// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
public Vector3? Intersect3(Plane b, Plane c)
{
real_t denom = _normal.Cross(b._normal).Dot(c._normal);
@@ -145,21 +145,21 @@ 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;
}
/// <summary>
- /// Returns the intersection point of a ray consisting of the
- /// position `from` and the direction normal `dir` with this plane.
- /// If no intersection is found, `null` is returned.
+ /// Returns the intersection point of a ray consisting of the position <paramref name="from"/>
+ /// and the direction normal <paramref name="dir"/> with this plane.
+ /// If no intersection is found, <see langword="null"/> is returned.
/// </summary>
/// <param name="from">The start of the ray.</param>
/// <param name="dir">The direction of the ray, normalized.</param>
- /// <returns>The intersection, or `null` if none is found.</returns>
+ /// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
public Vector3? IntersectRay(Vector3 from, Vector3 dir)
{
real_t den = _normal.Dot(dir);
@@ -177,17 +177,17 @@ namespace Godot
return null;
}
- return from + dir * -dist;
+ return from - (dir * dist);
}
/// <summary>
/// Returns the intersection point of a line segment from
- /// position `begin` to position `end` with this plane.
- /// If no intersection is found, `null` is returned.
+ /// position <paramref name="begin"/> to position <paramref name="end"/> with this plane.
+ /// If no intersection is found, <see langword="null"/> is returned.
/// </summary>
/// <param name="begin">The start of the line segment.</param>
/// <param name="end">The end of the line segment.</param>
- /// <returns>The intersection, or `null` if none is found.</returns>
+ /// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
public Vector3? IntersectSegment(Vector3 begin, Vector3 end)
{
Vector3 segment = begin - end;
@@ -206,14 +206,14 @@ namespace Godot
return null;
}
- return begin + segment * -dist;
+ return begin - (segment * dist);
}
/// <summary>
- /// Returns true if `point` is located above the plane.
+ /// Returns <see langword="true"/> if <paramref name="point"/> is located above the plane.
/// </summary>
/// <param name="point">The point to check.</param>
- /// <returns>A bool for whether or not the point is above the plane.</returns>
+ /// <returns>A <see langword="bool"/> for whether or not the point is above the plane.</returns>
public bool IsPointOver(Vector3 point)
{
return _normal.Dot(point) > D;
@@ -236,13 +236,13 @@ namespace Godot
}
/// <summary>
- /// Returns the orthogonal projection of `point` into the plane.
+ /// Returns the orthogonal projection of <paramref name="point"/> into the plane.
/// </summary>
/// <param name="point">The point to project.</param>
/// <returns>The projected point.</returns>
public Vector3 Project(Vector3 point)
{
- return point - _normal * DistanceTo(point);
+ return point - (_normal * DistanceTo(point));
}
// Constants
@@ -251,27 +251,28 @@ namespace Godot
private static readonly Plane _planeXY = new Plane(0, 0, 1, 0);
/// <summary>
- /// A plane that extends in the Y and Z axes (normal vector points +X).
+ /// A <see cref="Plane"/> that extends in the Y and Z axes (normal vector points +X).
/// </summary>
- /// <value>Equivalent to `new Plane(1, 0, 0, 0)`.</value>
+ /// <value>Equivalent to <c>new Plane(1, 0, 0, 0)</c>.</value>
public static Plane PlaneYZ { get { return _planeYZ; } }
/// <summary>
- /// A plane that extends in the X and Z axes (normal vector points +Y).
+ /// A <see cref="Plane"/> that extends in the X and Z axes (normal vector points +Y).
/// </summary>
- /// <value>Equivalent to `new Plane(0, 1, 0, 0)`.</value>
+ /// <value>Equivalent to <c>new Plane(0, 1, 0, 0)</c>.</value>
public static Plane PlaneXZ { get { return _planeXZ; } }
/// <summary>
- /// A plane that extends in the X and Y axes (normal vector points +Z).
+ /// A <see cref="Plane"/> that extends in the X and Y axes (normal vector points +Z).
/// </summary>
- /// <value>Equivalent to `new Plane(0, 0, 1, 0)`.</value>
+ /// <value>Equivalent to <c>new Plane(0, 0, 1, 0)</c>.</value>
public static Plane PlaneXY { get { return _planeXY; } }
/// <summary>
- /// Constructs a plane from four values. `a`, `b` and `c` become the
+ /// Constructs a <see cref="Plane"/> from four values.
+ /// <paramref name="a"/>, <paramref name="b"/> and <paramref name="c"/> become the
/// components of the resulting plane's <see cref="Normal"/> vector.
- /// `d` becomes the plane's distance from the origin.
+ /// <paramref name="d"/> becomes the plane's distance from the origin.
/// </summary>
/// <param name="a">The X component of the plane's normal vector.</param>
/// <param name="b">The Y component of the plane's normal vector.</param>
@@ -280,22 +281,23 @@ namespace Godot
public Plane(real_t a, real_t b, real_t c, real_t d)
{
_normal = new Vector3(a, b, c);
- this.D = d;
+ D = d;
}
/// <summary>
- /// Constructs a plane from a normal vector and the plane's distance to the origin.
+ /// 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="d">The plane's distance from the origin. This value is typically non-negative.</param>
public Plane(Vector3 normal, real_t d)
{
- this._normal = normal;
- this.D = d;
+ _normal = normal;
+ D = d;
}
/// <summary>
- /// Constructs a plane from the three points, given in clockwise order.
+ /// Constructs a <see cref="Plane"/> from the three points, given in clockwise order.
/// </summary>
/// <param name="v1">The first point.</param>
/// <param name="v2">The second point.</param>
@@ -322,6 +324,11 @@ namespace Godot
return !left.Equals(right);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this plane and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the plane and the other object are equal.</returns>
public override bool Equals(object obj)
{
if (obj is Plane)
@@ -332,14 +339,19 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this plane and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other plane to compare.</param>
+ /// <returns>Whether or not the planes are equal.</returns>
public bool Equals(Plane other)
{
return _normal == other._normal && D == other.D;
}
/// <summary>
- /// Returns true if this plane and `other` are approximately equal, by running
- /// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
+ /// Returns <see langword="true"/> if this plane and <paramref name="other"/> are
+ /// approximately equal, by running <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
/// </summary>
/// <param name="other">The other plane to compare.</param>
/// <returns>Whether or not the planes are approximately equal.</returns>
@@ -348,27 +360,31 @@ namespace Godot
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()
{
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()
{
- return String.Format("({0}, {1})", new object[]
- {
- _normal.ToString(),
- D.ToString()
- });
+ 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)
{
- return String.Format("({0}, {1})", new object[]
- {
- _normal.ToString(format),
- D.ToString(format)
- });
+ return $"{_normal.ToString(format)}, {D.ToString(format)}";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
index bd3bcb0c58..1694ac0320 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -12,10 +12,10 @@ namespace Godot
/// A unit quaternion used for representing 3D rotations.
/// Quaternions need to be normalized to be used for rotation.
///
- /// It is similar to Basis, which implements matrix representation of
- /// rotations, and can be parametrized using both an axis-angle pair
- /// or Euler angles. Basis stores rotation, scale, and shearing,
- /// while Quat only stores rotation.
+ /// It is similar to <see cref="Basis"/>, which implements matrix
+ /// representation of rotations, and can be parametrized using both
+ /// an axis-angle pair or Euler angles. Basis stores rotation, scale,
+ /// and shearing, while Quaternion only stores rotation.
///
/// Due to its compactness and the way it is stored in memory, certain
/// operations (obtaining axis-angle and performing SLERP, in particular)
@@ -23,22 +23,22 @@ namespace Godot
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- public struct Quat : IEquatable<Quat>
+ public struct Quaternion : IEquatable<Quaternion>
{
/// <summary>
- /// X component of the quaternion (imaginary `i` axis part).
+ /// X component of the quaternion (imaginary <c>i</c> axis part).
/// Quaternion components should usually not be manipulated directly.
/// </summary>
public real_t x;
/// <summary>
- /// Y component of the quaternion (imaginary `j` axis part).
+ /// Y component of the quaternion (imaginary <c>j</c> axis part).
/// Quaternion components should usually not be manipulated directly.
/// </summary>
public real_t y;
/// <summary>
- /// Z component of the quaternion (imaginary `k` axis part).
+ /// Z component of the quaternion (imaginary <c>k</c> axis part).
/// Quaternion components should usually not be manipulated directly.
/// </summary>
public real_t z;
@@ -52,7 +52,12 @@ namespace Godot
/// <summary>
/// Access quaternion components using their index.
/// </summary>
- /// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`, `[3]` is equivalent to `.w`.</value>
+ /// <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"/>.
+ /// </value>
public real_t this[int index]
{
get
@@ -96,7 +101,8 @@ namespace Godot
/// <summary>
/// Returns the length (magnitude) of the quaternion.
/// </summary>
- /// <value>Equivalent to `Mathf.Sqrt(LengthSquared)`.</value>
+ /// <seealso cref="LengthSquared"/>
+ /// <value>Equivalent to <c>Mathf.Sqrt(LengthSquared)</c>.</value>
public real_t Length
{
get { return Mathf.Sqrt(LengthSquared); }
@@ -107,26 +113,43 @@ namespace Godot
/// 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 `Dot(this)`.</value>
+ /// <value>Equivalent to <c>Dot(this)</c>.</value>
public real_t LengthSquared
{
get { return Dot(this); }
}
/// <summary>
- /// Performs a cubic spherical interpolation between quaternions `preA`,
- /// this vector, `b`, and `postB`, by the given amount `t`.
+ /// 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.
+ ///
+ /// Note: This method has an abnormally high amount
+ /// of floating-point error, so methods such as
+ /// <see cref="Mathf.IsZeroApprox"/> will not work reliably.
+ /// </summary>
+ /// <param name="to">The other quaternion.</param>
+ /// <returns>The angle between the quaternions.</returns>
+ public real_t AngleTo(Quaternion to)
+ {
+ real_t dot = Dot(to);
+ return Mathf.Acos(Mathf.Clamp(dot * dot * 2 - 1, -1, 1));
+ }
+
+ /// <summary>
+ /// Performs a cubic spherical interpolation between quaternions <paramref name="preA"/>, this quaternion,
+ /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
/// </summary>
/// <param name="b">The destination quaternion.</param>
/// <param name="preA">A quaternion before this quaternion.</param>
- /// <param name="postB">A quaternion after `b`.</param>
+ /// <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 Quat CubicSlerp(Quat b, Quat preA, Quat postB, real_t weight)
+ public Quaternion CubicSlerp(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
{
real_t t2 = (1.0f - weight) * weight * 2f;
- Quat sp = Slerp(b, weight);
- Quat sq = preA.Slerpni(postB, weight);
+ Quaternion sp = Slerp(b, weight);
+ Quaternion sq = preA.Slerpni(postB, weight);
return sp.Slerpni(sq, t2);
}
@@ -135,9 +158,9 @@ namespace Godot
/// </summary>
/// <param name="b">The other quaternion.</param>
/// <returns>The dot product.</returns>
- public real_t Dot(Quat b)
+ public 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);
}
/// <summary>
@@ -152,7 +175,7 @@ namespace Godot
#if DEBUG
if (!IsNormalized())
{
- throw new InvalidOperationException("Quat is not normalized");
+ throw new InvalidOperationException("Quaternion is not normalized");
}
#endif
var basis = new Basis(this);
@@ -163,21 +186,21 @@ namespace Godot
/// Returns the inverse of the quaternion.
/// </summary>
/// <returns>The inverse quaternion.</returns>
- public Quat Inverse()
+ public Quaternion Inverse()
{
#if DEBUG
if (!IsNormalized())
{
- throw new InvalidOperationException("Quat is not normalized");
+ throw new InvalidOperationException("Quaternion is not normalized");
}
#endif
- return new Quat(-x, -y, -z, w);
+ return new Quaternion(-x, -y, -z, w);
}
/// <summary>
/// Returns whether the quaternion is normalized or not.
/// </summary>
- /// <returns>A bool for whether the quaternion is normalized or not.</returns>
+ /// <returns>A <see langword="bool"/> for whether the quaternion is normalized or not.</returns>
public bool IsNormalized()
{
return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
@@ -187,26 +210,26 @@ namespace Godot
/// Returns a copy of the quaternion, normalized to unit length.
/// </summary>
/// <returns>The normalized quaternion.</returns>
- public Quat Normalized()
+ public Quaternion Normalized()
{
return this / Length;
}
/// <summary>
/// Returns the result of the spherical linear interpolation between
- /// this quaternion and `to` by amount `weight`.
+ /// this quaternion and <paramref name="to"/> by amount <paramref name="weight"/>.
///
/// Note: Both quaternions must be normalized.
/// </summary>
/// <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 Quat Slerp(Quat to, real_t weight)
+ public Quaternion Slerp(Quaternion to, real_t weight)
{
#if DEBUG
if (!IsNormalized())
{
- throw new InvalidOperationException("Quat is not normalized");
+ throw new InvalidOperationException("Quaternion is not normalized");
}
if (!to.IsNormalized())
{
@@ -217,7 +240,7 @@ namespace Godot
// Calculate cosine.
real_t cosom = x * to.x + y * to.y + z * to.z + w * to.w;
- var to1 = new Quat();
+ var to1 = new Quaternion();
// Adjust signs if necessary.
if (cosom < 0.0)
@@ -255,24 +278,24 @@ namespace Godot
}
// Calculate final values.
- return new Quat
+ 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)
);
}
/// <summary>
/// Returns the result of the spherical linear interpolation between
- /// this quaternion and `to` by amount `weight`, but without
+ /// this quaternion and <paramref name="to"/> by amount <paramref name="weight"/>, but without
/// checking if the rotation path is not bigger than 90 degrees.
/// </summary>
/// <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 Quat Slerpni(Quat to, real_t weight)
+ public Quaternion Slerpni(Quaternion to, real_t weight)
{
real_t dot = Dot(to);
@@ -286,12 +309,12 @@ namespace Godot
real_t newFactor = Mathf.Sin(weight * theta) * sinT;
real_t invFactor = Mathf.Sin((1.0f - weight) * theta) * sinT;
- return new Quat
+ 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)
);
}
@@ -305,33 +328,33 @@ namespace Godot
#if DEBUG
if (!IsNormalized())
{
- throw new InvalidOperationException("Quat is not normalized");
+ throw new InvalidOperationException("Quaternion is not normalized");
}
#endif
var u = new Vector3(x, y, z);
Vector3 uv = u.Cross(v);
- return v + ((uv * w) + u.Cross(uv)) * 2;
+ return v + (((uv * w) + u.Cross(uv)) * 2);
}
// Constants
- private static readonly Quat _identity = new Quat(0, 0, 0, 1);
+ private static readonly Quaternion _identity = new Quaternion(0, 0, 0, 1);
/// <summary>
/// The identity quaternion, representing no rotation.
/// Equivalent to an identity <see cref="Basis"/> matrix. If a vector is transformed by
/// an identity quaternion, it will not change.
/// </summary>
- /// <value>Equivalent to `new Quat(0, 0, 0, 1)`.</value>
- public static Quat Identity { get { return _identity; } }
+ /// <value>Equivalent to <c>new Quaternion(0, 0, 0, 1)</c>.</value>
+ public static Quaternion Identity { get { return _identity; } }
/// <summary>
- /// Constructs a quaternion defined by the given values.
+ /// Constructs a <see cref="Quaternion"/> defined by the given values.
/// </summary>
- /// <param name="x">X component of the quaternion (imaginary `i` axis part).</param>
- /// <param name="y">Y component of the quaternion (imaginary `j` axis part).</param>
- /// <param name="z">Z component of the quaternion (imaginary `k` axis part).</param>
+ /// <param name="x">X component of the quaternion (imaginary <c>i</c> axis part).</param>
+ /// <param name="y">Y component of the quaternion (imaginary <c>j</c> axis part).</param>
+ /// <param name="z">Z component of the quaternion (imaginary <c>k</c> axis part).</param>
/// <param name="w">W component of the quaternion (real part).</param>
- public Quat(real_t x, real_t y, real_t z, real_t w)
+ public Quaternion(real_t x, real_t y, real_t z, real_t w)
{
this.x = x;
this.y = y;
@@ -340,60 +363,59 @@ namespace Godot
}
/// <summary>
- /// Constructs a quaternion from the given quaternion.
+ /// Constructs a <see cref="Quaternion"/> from the given <see cref="Quaternion"/>.
/// </summary>
/// <param name="q">The existing quaternion.</param>
- public Quat(Quat q)
+ public Quaternion(Quaternion q)
{
this = q;
}
/// <summary>
- /// Constructs a quaternion from the given <see cref="Basis"/>.
+ /// Constructs a <see cref="Quaternion"/> from the given <see cref="Basis"/>.
/// </summary>
- /// <param name="basis">The basis to construct from.</param>
- public Quat(Basis basis)
+ /// <param name="basis">The <see cref="Basis"/> to construct from.</param>
+ public Quaternion(Basis basis)
{
- this = basis.Quat();
+ this = basis.Quaternion();
}
/// <summary>
- /// Constructs a quaternion that will perform a rotation specified by
- /// Euler angles (in the YXZ convention: when decomposing,
- /// first Z, then X, and Y last),
+ /// Constructs a <see cref="Quaternion"/> that will perform a rotation specified by
+ /// Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last),
/// given in the vector format as (X angle, Y angle, Z angle).
/// </summary>
- /// <param name="eulerYXZ"></param>
- public Quat(Vector3 eulerYXZ)
+ /// <param name="eulerYXZ">Euler angles that the quaternion will be rotated by.</param>
+ public Quaternion(Vector3 eulerYXZ)
{
- real_t half_a1 = eulerYXZ.y * 0.5f;
- real_t half_a2 = eulerYXZ.x * 0.5f;
- real_t half_a3 = 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 cos_a1 = Mathf.Cos(half_a1);
- real_t sin_a1 = Mathf.Sin(half_a1);
- real_t cos_a2 = Mathf.Cos(half_a2);
- real_t sin_a2 = Mathf.Sin(half_a2);
- real_t cos_a3 = Mathf.Cos(half_a3);
- real_t sin_a3 = Mathf.Sin(half_a3);
+ 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);
- x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
- y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
- z = cos_a1 * cos_a2 * sin_a3 - sin_a1 * sin_a2 * cos_a3;
- w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
+ x = (sinA1 * cosA2 * sinA3) + (cosA1 * sinA2 * cosA3);
+ y = (sinA1 * cosA2 * cosA3) - (cosA1 * sinA2 * sinA3);
+ z = (cosA1 * cosA2 * sinA3) - (sinA1 * sinA2 * cosA3);
+ w = (sinA1 * sinA2 * sinA3) + (cosA1 * cosA2 * cosA3);
}
/// <summary>
- /// Constructs a quaternion that will rotate around the given axis
+ /// Constructs a <see cref="Quaternion"/> that will rotate around the given axis
/// by the specified angle. The axis must be a normalized vector.
/// </summary>
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
- public Quat(Vector3 axis, real_t angle)
+ public Quaternion(Vector3 axis, real_t angle)
{
#if DEBUG
if (!axis.IsNormalized())
@@ -424,118 +446,140 @@ namespace Godot
}
}
- public static Quat operator *(Quat left, Quat right)
+ public static Quaternion operator *(Quaternion left, Quaternion right)
{
- return new Quat
+ 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)
);
}
- public static Quat operator +(Quat left, Quat right)
+ public static Quaternion operator +(Quaternion left, Quaternion right)
{
- return new Quat(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);
}
- public static Quat operator -(Quat left, Quat right)
+ public static Quaternion operator -(Quaternion left, Quaternion right)
{
- return new Quat(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);
}
- public static Quat operator -(Quat left)
+ public static Quaternion operator -(Quaternion left)
{
- return new Quat(-left.x, -left.y, -left.z, -left.w);
+ return new Quaternion(-left.x, -left.y, -left.z, -left.w);
}
- public static Quat operator *(Quat left, Vector3 right)
+ public static Quaternion operator *(Quaternion left, Vector3 right)
{
- return new Quat
+ return new Quaternion
(
- left.w * right.x + left.y * right.z - left.z * right.y,
- left.w * right.y + left.z * right.x - left.x * right.z,
- left.w * right.z + left.x * right.y - left.y * right.x,
- -left.x * right.x - left.y * right.y - left.z * right.z
+ (left.w * right.x) + (left.y * right.z) - (left.z * right.y),
+ (left.w * right.y) + (left.z * right.x) - (left.x * right.z),
+ (left.w * right.z) + (left.x * right.y) - (left.y * right.x),
+ -(left.x * right.x) - (left.y * right.y) - (left.z * right.z)
);
}
- public static Quat operator *(Vector3 left, Quat right)
+ public static Quaternion operator *(Vector3 left, Quaternion right)
{
- return new Quat
+ return new Quaternion
(
- right.w * left.x + right.y * left.z - right.z * left.y,
- right.w * left.y + right.z * left.x - right.x * left.z,
- right.w * left.z + right.x * left.y - right.y * left.x,
- -right.x * left.x - right.y * left.y - right.z * left.z
+ (right.w * left.x) + (right.y * left.z) - (right.z * left.y),
+ (right.w * left.y) + (right.z * left.x) - (right.x * left.z),
+ (right.w * left.z) + (right.x * left.y) - (right.y * left.x),
+ -(right.x * left.x) - (right.y * left.y) - (right.z * left.z)
);
}
- public static Quat operator *(Quat left, real_t right)
+ public static Quaternion operator *(Quaternion left, real_t right)
{
- return new Quat(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);
}
- public static Quat operator *(real_t left, Quat right)
+ public static Quaternion operator *(real_t left, Quaternion right)
{
- return new Quat(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);
}
- public static Quat operator /(Quat left, real_t right)
+ public static Quaternion operator /(Quaternion left, real_t right)
{
return left * (1.0f / right);
}
- public static bool operator ==(Quat left, Quat right)
+ public static bool operator ==(Quaternion left, Quaternion right)
{
return left.Equals(right);
}
- public static bool operator !=(Quat left, Quat right)
+ public static bool operator !=(Quaternion left, Quaternion right)
{
return !left.Equals(right);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this quaternion and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the quaternion and the other object are equal.</returns>
public override bool Equals(object obj)
{
- if (obj is Quat)
+ if (obj is Quaternion)
{
- return Equals((Quat)obj);
+ return Equals((Quaternion)obj);
}
return false;
}
- public bool Equals(Quat other)
+ /// <summary>
+ /// Returns <see langword="true"/> if this quaternion and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other quaternion to compare.</param>
+ /// <returns>Whether or not the quaternions are equal.</returns>
+ public bool Equals(Quaternion other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
/// <summary>
- /// Returns true if this quaternion and `other` are approximately equal, by running
- /// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
+ /// Returns <see langword="true"/> if this quaternion and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
/// </summary>
/// <param name="other">The other quaternion to compare.</param>
/// <returns>Whether or not the quaternions are approximately equal.</returns>
- public bool IsEqualApprox(Quat other)
+ public 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);
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Quaternion"/>.
+ /// </summary>
+ /// <returns>A hash code for this quaternion.</returns>
public override int 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()
{
- return String.Format("({0}, {1}, {2}, {3})", x.ToString(), y.ToString(), z.ToString(), w.ToString());
+ 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)
{
- return String.Format("({0}, {1}, {2}, {3})", 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
index 94761531b1..1588869ec0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
@@ -3,9 +3,15 @@ using System.Runtime.CompilerServices;
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>
public sealed partial class RID : IDisposable
{
- private bool disposed = false;
+ private bool _disposed = false;
internal IntPtr ptr;
@@ -14,7 +20,7 @@ namespace Godot
if (instance == null)
throw new NullReferenceException($"The instance of type {nameof(RID)} is null.");
- if (instance.disposed)
+ if (instance._disposed)
throw new ObjectDisposedException(instance.GetType().FullName);
return instance.ptr;
@@ -25,6 +31,9 @@ namespace Godot
Dispose(false);
}
+ /// <summary>
+ /// Disposes of this <see cref="RID"/>.
+ /// </summary>
public void Dispose()
{
Dispose(true);
@@ -33,7 +42,7 @@ namespace Godot
private void Dispose(bool disposing)
{
- if (disposed)
+ if (_disposed)
return;
if (ptr != IntPtr.Zero)
@@ -42,7 +51,7 @@ namespace Godot
ptr = IntPtr.Zero;
}
- disposed = true;
+ _disposed = true;
}
internal RID(IntPtr ptr)
@@ -50,6 +59,9 @@ namespace Godot
this.ptr = ptr;
}
+ /// <summary>
+ /// The pointer to the native instance of this <see cref="RID"/>.
+ /// </summary>
public IntPtr NativeInstance
{
get { return ptr; }
@@ -60,25 +72,36 @@ namespace Godot
this.ptr = IntPtr.Zero;
}
+ /// <summary>
+ /// Constructs a new <see cref="RID"/> for the given <see cref="Object"/> <paramref name="from"/>.
+ /// </summary>
public RID(Object from)
{
this.ptr = godot_icall_RID_Ctor(Object.GetPtr(from));
}
+ /// <summary>
+ /// Returns the ID of the referenced resource.
+ /// </summary>
+ /// <returns>The ID of the referenced resource.</returns>
public int GetId()
{
- return godot_icall_RID_get_id(RID.GetPtr(this));
+ return godot_icall_RID_get_id(GetPtr(this));
}
+ /// <summary>
+ /// Converts this <see cref="RID"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this RID.</returns>
public override string ToString() => "[RID]";
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static IntPtr godot_icall_RID_Ctor(IntPtr from);
+ internal static extern IntPtr godot_icall_RID_Ctor(IntPtr from);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_RID_Dtor(IntPtr ptr);
+ internal static extern void godot_icall_RID_Dtor(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_RID_get_id(IntPtr ptr);
+ internal static extern int godot_icall_RID_get_id(IntPtr ptr);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index 868c3536fe..1d001fba2d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -20,7 +20,7 @@ namespace Godot
private Vector2 _size;
/// <summary>
- /// Beginning corner. Typically has values lower than End.
+ /// Beginning corner. Typically has values lower than <see cref="End"/>.
/// </summary>
/// <value>Directly uses a private field.</value>
public Vector2 Position
@@ -30,7 +30,7 @@ namespace Godot
}
/// <summary>
- /// Size from Position to End. Typically all components are positive.
+ /// Size from <see cref="Position"/> to <see cref="End"/>. Typically all components are positive.
/// If the size is negative, you can use <see cref="Abs"/> to fix it.
/// </summary>
/// <value>Directly uses a private field.</value>
@@ -41,10 +41,13 @@ namespace Godot
}
/// <summary>
- /// Ending corner. This is calculated as <see cref="Position"/> plus
- /// <see cref="Size"/>. Setting this value will change the size.
+ /// Ending corner. This is calculated as <see cref="Position"/> plus <see cref="Size"/>.
+ /// Setting this value will change the size.
/// </summary>
- /// <value>Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`.</value>
+ /// <value>
+ /// 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 Vector2 End
{
get { return _position + _size; }
@@ -52,7 +55,7 @@ namespace Godot
}
/// <summary>
- /// The area of this Rect2.
+ /// The area of this <see cref="Rect2"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
public real_t Area
@@ -61,10 +64,10 @@ namespace Godot
}
/// <summary>
- /// Returns a Rect2 with equivalent position and size, modified so that
+ /// Returns a <see cref="Rect2"/> 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 Rect2.</returns>
+ /// <returns>The modified <see cref="Rect2"/>.</returns>
public Rect2 Abs()
{
Vector2 end = End;
@@ -73,14 +76,17 @@ namespace Godot
}
/// <summary>
- /// Returns the intersection of this Rect2 and `b`.
- /// If the rectangles do not intersect, an empty Rect2 is returned.
+ /// Returns the intersection of this <see cref="Rect2"/> and <paramref name="b"/>.
+ /// If the rectangles do not intersect, an empty <see cref="Rect2"/> is returned.
/// </summary>
- /// <param name="b">The other Rect2.</param>
- /// <returns>The intersection of this Rect2 and `b`, or an empty Rect2 if they do not intersect.</returns>
+ /// <param name="b">The other <see cref="Rect2"/>.</param>
+ /// <returns>
+ /// 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)
{
- var newRect = b;
+ Rect2 newRect = b;
if (!Intersects(newRect))
{
@@ -100,10 +106,12 @@ namespace Godot
}
/// <summary>
- /// Returns true if this Rect2 completely encloses another one.
+ /// Returns <see langword="true"/> if this <see cref="Rect2"/> completely encloses another one.
/// </summary>
- /// <param name="b">The other Rect2 that may be enclosed.</param>
- /// <returns>A bool for whether or not this Rect2 encloses `b`.</returns>
+ /// <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)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
@@ -112,13 +120,13 @@ namespace Godot
}
/// <summary>
- /// Returns this Rect2 expanded to include a given point.
+ /// Returns this <see cref="Rect2"/> expanded to include a given point.
/// </summary>
/// <param name="to">The point to include.</param>
- /// <returns>The expanded Rect2.</returns>
+ /// <returns>The expanded <see cref="Rect2"/>.</returns>
public Rect2 Expand(Vector2 to)
{
- var expanded = this;
+ Rect2 expanded = this;
Vector2 begin = expanded._position;
Vector2 end = expanded._position + expanded._size;
@@ -148,7 +156,7 @@ namespace Godot
}
/// <summary>
- /// Returns the area of the Rect2.
+ /// Returns the area of the <see cref="Rect2"/>.
/// </summary>
/// <returns>The area.</returns>
public real_t GetArea()
@@ -157,13 +165,16 @@ namespace Godot
}
/// <summary>
- /// Returns a copy of the Rect2 grown by the specified amount on all sides.
+ /// Returns a copy of the <see cref="Rect2"/> grown by the specified amount
+ /// on all sides.
/// </summary>
+ /// <seealso cref="GrowIndividual(real_t, real_t, real_t, real_t)"/>
+ /// <seealso cref="GrowSide(Side, real_t)"/>
/// <param name="by">The amount to grow by.</param>
- /// <returns>The grown Rect2.</returns>
+ /// <returns>The grown <see cref="Rect2"/>.</returns>
public Rect2 Grow(real_t by)
{
- var g = this;
+ Rect2 g = this;
g._position.x -= by;
g._position.y -= by;
@@ -174,16 +185,19 @@ namespace Godot
}
/// <summary>
- /// Returns a copy of the Rect2 grown by the specified amount on each side individually.
+ /// Returns a copy of the <see cref="Rect2"/> grown by the specified amount
+ /// on each side individually.
/// </summary>
+ /// <seealso cref="Grow(real_t)"/>
+ /// <seealso cref="GrowSide(Side, real_t)"/>
/// <param name="left">The amount to grow by on the left side.</param>
/// <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 Rect2.</returns>
+ /// <returns>The grown <see cref="Rect2"/>.</returns>
public Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
{
- var g = this;
+ Rect2 g = this;
g._position.x -= left;
g._position.y -= top;
@@ -194,14 +208,17 @@ namespace Godot
}
/// <summary>
- /// Returns a copy of the Rect2 grown by the specified amount on the specified Side.
+ /// Returns a copy of the <see cref="Rect2"/> grown by the specified amount
+ /// on the specified <see cref="Side"/>.
/// </summary>
+ /// <seealso cref="Grow(real_t)"/>
+ /// <seealso cref="GrowIndividual(real_t, real_t, real_t, real_t)"/>
/// <param name="side">The side to grow.</param>
/// <param name="by">The amount to grow by.</param>
- /// <returns>The grown Rect2.</returns>
+ /// <returns>The grown <see cref="Rect2"/>.</returns>
public Rect2 GrowSide(Side side, real_t by)
{
- var g = this;
+ Rect2 g = this;
g = g.GrowIndividual(Side.Left == side ? by : 0,
Side.Top == side ? by : 0,
@@ -212,19 +229,25 @@ namespace Godot
}
/// <summary>
- /// Returns true if the Rect2 is flat or empty, or false otherwise.
+ /// Returns <see langword="true"/> if the <see cref="Rect2"/> is flat or empty,
+ /// or <see langword="false"/> otherwise.
/// </summary>
- /// <returns>A bool for whether or not the Rect2 has area.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> has area.
+ /// </returns>
public bool HasNoArea()
{
return _size.x <= 0 || _size.y <= 0;
}
/// <summary>
- /// Returns true if the Rect2 contains a point, or false otherwise.
+ /// Returns <see langword="true"/> if the <see cref="Rect2"/> contains a point,
+ /// or <see langword="false"/> otherwise.
/// </summary>
/// <param name="point">The point to check.</param>
- /// <returns>A bool for whether or not the Rect2 contains `point`.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> contains <paramref name="point"/>.
+ /// </returns>
public bool HasPoint(Vector2 point)
{
if (point.x < _position.x)
@@ -241,15 +264,16 @@ namespace Godot
}
/// <summary>
- /// Returns true if the Rect2 overlaps with `b`
+ /// Returns <see langword="true"/> if the <see cref="Rect2"/> overlaps with <paramref name="b"/>
/// (i.e. they have at least one point in common).
///
- /// If `includeBorders` is true, they will also be considered overlapping
- /// if their borders touch, even without intersection.
+ /// 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 Rect2 to check for intersections with.</param>
+ /// <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 bool for whether or not they are intersecting.</returns>
+ /// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
public bool Intersects(Rect2 b, bool includeBorders = false)
{
if (includeBorders)
@@ -295,10 +319,10 @@ namespace Godot
}
/// <summary>
- /// Returns a larger Rect2 that contains this Rect2 and `b`.
+ /// Returns a larger <see cref="Rect2"/> that contains this <see cref="Rect2"/> and <paramref name="b"/>.
/// </summary>
- /// <param name="b">The other Rect2.</param>
- /// <returns>The merged Rect2.</returns>
+ /// <param name="b">The other <see cref="Rect2"/>.</param>
+ /// <returns>The merged <see cref="Rect2"/>.</returns>
public Rect2 Merge(Rect2 b)
{
Rect2 newRect;
@@ -315,7 +339,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a Rect2 from a position and size.
+ /// Constructs a <see cref="Rect2"/> from a position and size.
/// </summary>
/// <param name="position">The position.</param>
/// <param name="size">The size.</param>
@@ -326,7 +350,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a Rect2 from a position, width, and height.
+ /// Constructs a <see cref="Rect2"/> from a position, width, and height.
/// </summary>
/// <param name="position">The position.</param>
/// <param name="width">The width.</param>
@@ -338,7 +362,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a Rect2 from x, y, and size.
+ /// Constructs a <see cref="Rect2"/> from x, y, and size.
/// </summary>
/// <param name="x">The position's X coordinate.</param>
/// <param name="y">The position's Y coordinate.</param>
@@ -350,7 +374,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a Rect2 from x, y, width, and height.
+ /// Constructs a <see cref="Rect2"/> 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>
@@ -372,6 +396,11 @@ namespace Godot
return !left.Equals(right);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this rect and <paramref name="obj"/> are equal.
+ /// </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)
{
if (obj is Rect2)
@@ -382,43 +411,52 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this rect and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other rect to compare.</param>
+ /// <returns>Whether or not the rects are equal.</returns>
public bool Equals(Rect2 other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
/// <summary>
- /// Returns true if this Rect2 and `other` are approximately equal, by running
- /// <see cref="Vector2.IsEqualApprox(Vector2)"/> on each component.
+ /// Returns <see langword="true"/> if this rect and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Vector2.IsEqualApprox(Vector2)"/> on each component.
/// </summary>
- /// <param name="other">The other Rect2 to compare.</param>
- /// <returns>Whether or not the Rect2s are approximately equal.</returns>
+ /// <param name="other">The other rect to compare.</param>
+ /// <returns>Whether or not the rects are approximately equal.</returns>
public bool IsEqualApprox(Rect2 other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size);
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Rect2"/>.
+ /// </summary>
+ /// <returns>A hash code for this rect.</returns>
public override int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
+ /// <summary>
+ /// Converts this <see cref="Rect2"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this rect.</returns>
public override string ToString()
{
- return String.Format("({0}, {1})", new object[]
- {
- _position.ToString(),
- _size.ToString()
- });
+ return $"{_position}, {_size}";
}
+ /// <summary>
+ /// 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)
{
- return String.Format("({0}, {1})", new object[]
- {
- _position.ToString(format),
- _size.ToString(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 c27af74866..250b0d0baf 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
@@ -15,7 +15,7 @@ namespace Godot
private Vector2i _size;
/// <summary>
- /// Beginning corner. Typically has values lower than End.
+ /// Beginning corner. Typically has values lower than <see cref="End"/>.
/// </summary>
/// <value>Directly uses a private field.</value>
public Vector2i Position
@@ -25,7 +25,7 @@ namespace Godot
}
/// <summary>
- /// Size from Position to End. Typically all components are positive.
+ /// Size from <see cref="Position"/> to <see cref="End"/>. Typically all components are positive.
/// If the size is negative, you can use <see cref="Abs"/> to fix it.
/// </summary>
/// <value>Directly uses a private field.</value>
@@ -36,10 +36,13 @@ namespace Godot
}
/// <summary>
- /// Ending corner. This is calculated as <see cref="Position"/> plus
- /// <see cref="Size"/>. Setting this value will change the size.
+ /// Ending corner. This is calculated as <see cref="Position"/> plus <see cref="Size"/>.
+ /// Setting this value will change the size.
/// </summary>
- /// <value>Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`.</value>
+ /// <value>
+ /// 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
{
get { return _position + _size; }
@@ -47,7 +50,7 @@ namespace Godot
}
/// <summary>
- /// The area of this Rect2i.
+ /// The area of this <see cref="Rect2i"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
public int Area
@@ -56,10 +59,10 @@ namespace Godot
}
/// <summary>
- /// Returns a 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 Rect2i.</returns>
+ /// <returns>The modified <see cref="Rect2i"/>.</returns>
public Rect2i Abs()
{
Vector2i end = End;
@@ -68,14 +71,17 @@ namespace Godot
}
/// <summary>
- /// Returns the intersection of this Rect2i and `b`.
- /// If the rectangles do not intersect, an empty 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 Rect2i.</param>
- /// <returns>The intersection of this Rect2i and `b`, or an empty Rect2i if they do not intersect.</returns>
+ /// <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.
+ /// </returns>
public Rect2i Intersection(Rect2i b)
{
- var newRect = b;
+ Rect2i newRect = b;
if (!Intersects(newRect))
{
@@ -95,10 +101,12 @@ namespace Godot
}
/// <summary>
- /// Returns true if this Rect2i completely encloses another one.
+ /// Returns <see langword="true"/> if this <see cref="Rect2i"/> completely encloses another one.
/// </summary>
- /// <param name="b">The other Rect2i that may be enclosed.</param>
- /// <returns>A bool for whether or not this Rect2i encloses `b`.</returns>
+ /// <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"/>.
+ /// </returns>
public bool Encloses(Rect2i b)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
@@ -107,13 +115,13 @@ namespace Godot
}
/// <summary>
- /// Returns this 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 Rect2i.</returns>
+ /// <returns>The expanded <see cref="Rect2i"/>.</returns>
public Rect2i Expand(Vector2i to)
{
- var expanded = this;
+ Rect2i expanded = this;
Vector2i begin = expanded._position;
Vector2i end = expanded._position + expanded._size;
@@ -143,7 +151,7 @@ namespace Godot
}
/// <summary>
- /// Returns the area of the Rect2.
+ /// Returns the area of the <see cref="Rect2"/>.
/// </summary>
/// <returns>The area.</returns>
public int GetArea()
@@ -152,13 +160,16 @@ namespace Godot
}
/// <summary>
- /// Returns a copy of the Rect2i grown by the specified amount on all sides.
+ /// 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 Rect2i.</returns>
+ /// <returns>The grown <see cref="Rect2i"/>.</returns>
public Rect2i Grow(int by)
{
- var g = this;
+ Rect2i g = this;
g._position.x -= by;
g._position.y -= by;
@@ -169,16 +180,19 @@ namespace Godot
}
/// <summary>
- /// Returns a copy of the Rect2i grown by the specified amount on each side individually.
+ /// Returns a copy of the <see cref="Rect2i"/> grown by the specified amount
+ /// on each side individually.
/// </summary>
+ /// <seealso cref="Grow(int)"/>
+ /// <seealso cref="GrowSide(Side, int)"/>
/// <param name="left">The amount to grow by on the left side.</param>
/// <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 Rect2i.</returns>
+ /// <returns>The grown <see cref="Rect2i"/>.</returns>
public Rect2i GrowIndividual(int left, int top, int right, int bottom)
{
- var g = this;
+ Rect2i g = this;
g._position.x -= left;
g._position.y -= top;
@@ -189,14 +203,17 @@ namespace Godot
}
/// <summary>
- /// Returns a copy of the Rect2i grown by the specified amount on the specified Side.
+ /// 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 Rect2i.</returns>
+ /// <returns>The grown <see cref="Rect2i"/>.</returns>
public Rect2i GrowSide(Side side, int by)
{
- var g = this;
+ Rect2i g = this;
g = g.GrowIndividual(Side.Left == side ? by : 0,
Side.Top == side ? by : 0,
@@ -207,19 +224,25 @@ namespace Godot
}
/// <summary>
- /// Returns true if the Rect2i is flat or empty, or false otherwise.
+ /// Returns <see langword="true"/> if the <see cref="Rect2i"/> is flat or empty,
+ /// or <see langword="false"/> otherwise.
/// </summary>
- /// <returns>A bool for whether or not the Rect2i has area.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> has area.
+ /// </returns>
public bool HasNoArea()
{
return _size.x <= 0 || _size.y <= 0;
}
/// <summary>
- /// Returns true if the Rect2i contains a point, or false otherwise.
+ /// 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 bool for whether or not the Rect2i contains `point`.</returns>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> contains <paramref name="point"/>.
+ /// </returns>
public bool HasPoint(Vector2i point)
{
if (point.x < _position.x)
@@ -236,15 +259,16 @@ namespace Godot
}
/// <summary>
- /// Returns true if the Rect2i overlaps with `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 `includeBorders` is true, they will also be considered overlapping
- /// if their borders touch, even without intersection.
+ /// 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 Rect2i to check for intersections with.</param>
+ /// <param name="b">The other <see cref="Rect2i"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
- /// <returns>A bool for whether or not they are intersecting.</returns>
+ /// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
public bool Intersects(Rect2i b, bool includeBorders = false)
{
if (includeBorders)
@@ -274,10 +298,10 @@ namespace Godot
}
/// <summary>
- /// Returns a larger Rect2i that contains this Rect2i and `b`.
+ /// Returns a larger <see cref="Rect2i"/> that contains this <see cref="Rect2i"/> and <paramref name="b"/>.
/// </summary>
- /// <param name="b">The other Rect2i.</param>
- /// <returns>The merged Rect2i.</returns>
+ /// <param name="b">The other <see cref="Rect2i"/>.</param>
+ /// <returns>The merged <see cref="Rect2i"/>.</returns>
public Rect2i Merge(Rect2i b)
{
Rect2i newRect;
@@ -294,7 +318,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a 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>
@@ -305,7 +329,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a 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>
@@ -317,7 +341,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a 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>
@@ -329,7 +353,7 @@ namespace Godot
}
/// <summary>
- /// Constructs a 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>
@@ -351,16 +375,29 @@ namespace Godot
return !left.Equals(right);
}
+ /// <summary>
+ /// 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)
{
return new Rect2(value._position, value._size);
}
+ /// <summary>
+ /// 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)
{
return new Rect2i((Vector2i)value.Position, (Vector2i)value.Size);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this rect and <paramref name="obj"/> are equal.
+ /// </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)
{
if (obj is Rect2i)
@@ -371,32 +408,41 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this rect and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other rect to compare.</param>
+ /// <returns>Whether or not the rects are equal.</returns>
public bool Equals(Rect2i other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Rect2i"/>.
+ /// </summary>
+ /// <returns>A hash code for this rect.</returns>
public override int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
+ /// <summary>
+ /// Converts this <see cref="Rect2i"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this rect.</returns>
public override string ToString()
{
- return String.Format("{0}, {1}", new object[]
- {
- _position.ToString(),
- _size.ToString()
- });
+ return $"{_position}, {_size}";
}
+ /// <summary>
+ /// 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)
{
- return String.Format("{0}, {1}", new object[]
- {
- _position.ToString(format),
- _size.ToString(format)
- });
+ return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
index 4dc630238b..2ba0493002 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
@@ -5,9 +5,9 @@ namespace Godot
{
public class SignalAwaiter : IAwaiter<object[]>, IAwaitable<object[]>
{
- private bool completed;
- private object[] result;
- private Action action;
+ private bool _completed;
+ private object[] _result;
+ private Action _action;
public SignalAwaiter(Object source, StringName signal, Object target)
{
@@ -15,24 +15,24 @@ namespace Godot
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static Error godot_icall_SignalAwaiter_connect(IntPtr source, IntPtr signal, IntPtr target, SignalAwaiter awaiter);
+ internal static extern Error godot_icall_SignalAwaiter_connect(IntPtr source, IntPtr signal, IntPtr target, SignalAwaiter awaiter);
public bool IsCompleted
{
get
{
- return completed;
+ return _completed;
}
}
public void OnCompleted(Action action)
{
- this.action = action;
+ this._action = action;
}
public object[] GetResult()
{
- return result;
+ return _result;
}
public IAwaiter<object[]> GetAwaiter()
@@ -42,13 +42,9 @@ namespace Godot
internal void SignalCallback(object[] args)
{
- completed = true;
- result = args;
-
- if (action != null)
- {
- action();
- }
+ _completed = true;
+ _result = args;
+ _action?.Invoke();
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
index dc92de7a61..5680c9d55a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
@@ -1,13 +1,28 @@
namespace Godot
{
+ /// <summary>
+ /// Represents a signal defined in an object.
+ /// </summary>
public struct SignalInfo
{
private readonly Object _owner;
private readonly StringName _signalName;
+ /// <summary>
+ /// Object that contains the signal.
+ /// </summary>
public Object Owner => _owner;
+ /// <summary>
+ /// Name of the signal.
+ /// </summary>
public StringName Name => _signalName;
+ /// <summary>
+ /// 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)
{
_owner = owner;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index 98efa89ef0..6b3eb09581 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -8,6 +8,9 @@ using System.Text.RegularExpressions;
namespace Godot
{
+ /// <summary>
+ /// Extension methods to manipulate strings.
+ /// </summary>
public static class StringExtensions
{
private static int GetSliceCount(this string instance, string splitter)
@@ -61,10 +64,15 @@ namespace Godot
return string.Empty;
}
- // <summary>
- // If the string is a path to a file, return the path to the file without the extension.
- // </summary>
- public static string BaseName(this string instance)
+ /// <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('.');
@@ -74,20 +82,26 @@ namespace Godot
return instance;
}
- // <summary>
- // Return true if the strings begins with the given string.
- // </summary>
+ /// <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>
- // Return the bigrams (pairs of consecutive letters) of this string.
- // </summary>
+ /// <summary>
+ /// Returns the bigrams (pairs of consecutive letters) of this string.
+ /// </summary>
+ /// <param name="instance">The string that will be used.</param>
+ /// <returns>The bigrams of this string.</returns>
public static string[] Bigrams(this string instance)
{
- var b = new string[instance.Length - 1];
+ string[] b = new string[instance.Length - 1];
for (int i = 0; i < b.Length; i++)
{
@@ -99,8 +113,8 @@ namespace Godot
/// <summary>
/// Converts a string containing a binary number into an integer.
- /// Binary strings can either be prefixed with `0b` or not,
- /// and they can also start with a `-` before the optional prefix.
+ /// Binary strings can either be prefixed with <c>0b</c> or not,
+ /// and they can also start with a <c>-</c> before the optional prefix.
/// </summary>
/// <param name="instance">The string to convert.</param>
/// <returns>The converted string.</returns>
@@ -124,12 +138,18 @@ namespace Godot
instance = instance.Substring(2);
}
- return sign * Convert.ToInt32(instance, 2);;
+ return sign * Convert.ToInt32(instance, 2);
}
- // <summary>
- // Return the amount of substrings in string.
- // </summary>
+ /// <summary>
+ /// Returns the amount of substrings <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)
{
if (what.Length == 0)
@@ -187,9 +207,11 @@ namespace Godot
return c;
}
- // <summary>
- // Return a copy of the string with special characters escaped using the C language standard.
- // </summary>
+ /// <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>
+ /// <returns>The escaped string.</returns>
public static string CEscape(this string instance)
{
var sb = new StringBuilder(string.Copy(instance));
@@ -209,9 +231,12 @@ namespace Godot
return sb.ToString();
}
- // <summary>
- // Return a copy of the string with escaped characters replaced by their meanings according to the C language standard.
- // </summary>
+ /// <summary>
+ /// Returns a copy of the string with escaped characters replaced by their meanings
+ /// according to the C language standard.
+ /// </summary>
+ /// <param name="instance">The string to unescape.</param>
+ /// <returns>The unescaped string.</returns>
public static string CUnescape(this string instance)
{
var sb = new StringBuilder(string.Copy(instance));
@@ -231,13 +256,18 @@ namespace Godot
return sb.ToString();
}
- // <summary>
- // Change the case of some letters. Replace underscores with spaces, convert all letters to lowercase then capitalize first and every letter following the space character. For [code]capitalize camelCase mixed_with_underscores[/code] it will return [code]Capitalize Camelcase Mixed With Underscores[/code].
- // </summary>
+ /// <summary>
+ /// Changes the case of some letters. Replace underscores with spaces, convert all letters
+ /// to lowercase then capitalize first and every letter following the space character.
+ /// For <c>capitalize camelCase mixed_with_underscores</c> it will return
+ /// <c>Capitalize Camelcase Mixed With Underscores</c>.
+ /// </summary>
+ /// <param name="instance">The string to capitalize.</param>
+ /// <returns>The capitalized string.</returns>
public static string Capitalize(this string instance)
{
string aux = instance.Replace("_", " ").ToLower();
- var cap = string.Empty;
+ string cap = string.Empty;
for (int i = 0; i < aux.GetSliceCount(" "); i++)
{
@@ -254,17 +284,28 @@ namespace Godot
return cap;
}
- // <summary>
- // Perform a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
- // </summary>
+ /// <summary>
+ /// Performs a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// </summary>
+ /// <seealso cref="NocasecmpTo(string, string)"/>
+ /// <seealso cref="CompareTo(string, string, bool)"/>
+ /// <param name="instance">The string to compare.</param>
+ /// <param name="to">The other string to compare.</param>
+ /// <returns>-1 if less, 0 if equal and +1 if greater.</returns>
public static int CasecmpTo(this string instance, string to)
{
return instance.CompareTo(to, caseSensitive: true);
}
- // <summary>
- // Perform a comparison to another string, return -1 if less, 0 if equal and +1 if greater.
- // </summary>
+ /// <summary>
+ /// Performs a comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// </summary>
+ /// <param name="instance">The string to compare.</param>
+ /// <param name="to">The other string to compare.</param>
+ /// <param name="caseSensitive">
+ /// If <see langword="true"/>, the comparison will be case sensitive.
+ /// </param>
+ /// <returns>-1 if less, 0 if equal and +1 if greater.</returns>
public static int CompareTo(this string instance, string to, bool caseSensitive = true)
{
if (string.IsNullOrEmpty(instance))
@@ -316,26 +357,52 @@ namespace Godot
}
}
- // <summary>
- // Return true if the strings ends with the given string.
- // </summary>
+ /// <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 [code]chars[/code] characters from the string starting from [code]pos[/code].
- // </summary>
+ /// <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>
- // If the string is a path to a file, return the extension.
- // </summary>
- public static string Extension(this string instance)
+ /// <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.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print("/path/to/file.txt".GetExtension()) // "txt"
+ /// GD.Print("file.txt".GetExtension()) // "txt"
+ /// GD.Print("file.sample.txt".GetExtension()) // "txt"
+ /// GD.Print(".txt".GetExtension()) // "txt"
+ /// GD.Print("file.txt.".GetExtension()) // "" (empty string)
+ /// GD.Print("file.txt..".GetExtension()) // "" (empty string)
+ /// GD.Print("txt".GetExtension()) // "" (empty string)
+ /// GD.Print("".GetExtension()) // "" (empty string)
+ /// </code>
+ /// </example>
+ /// <seealso cref="GetBaseName(string)"/>
+ /// <seealso cref="GetBaseDir(string)"/>
+ /// <seealso cref="GetFile(string)"/>
+ /// <param name="instance">The path to a file.</param>
+ /// <returns>The extension of the file or an empty string.</returns>
+ public static string GetExtension(this string instance)
{
int pos = instance.FindLast(".");
@@ -345,14 +412,30 @@ namespace Godot
return instance.Substring(pos + 1);
}
- /// <summary>Find the first occurrence of a substring. Optionally, the search starting position can be passed.</summary>
+ /// <summary>
+ /// Find the first occurrence of a substring. Optionally, the search starting position can be passed.
+ /// </summary>
+ /// <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 Find(this string instance, string what, int from = 0, bool caseSensitive = true)
{
return instance.IndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
- /// <summary>Find the first occurrence of a char. Optionally, the search starting position can be passed.</summary>
+ /// <summary>
+ /// 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)"/>
+ /// <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 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)
{
@@ -362,6 +445,13 @@ namespace Godot
}
/// <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)
{
@@ -369,41 +459,64 @@ namespace Godot
}
/// <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);
}
- /// <summary>Find the first occurrence of a substring but search as case-insensitive. Optionally, the search starting position can be passed.</summary>
+ /// <summary>
+ /// Find the first occurrence of a substring but search as case-insensitive.
+ /// Optionally, the search starting position can be passed.
+ /// </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)"/>
+ /// <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>
/// <returns>The starting position of the substring, or -1 if not found.</returns>
public static int FindN(this string instance, string what, int from = 0)
{
return instance.IndexOf(what, from, StringComparison.OrdinalIgnoreCase);
}
- // <summary>
- // If the string is a path to a file, return the base directory.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file, return the base directory.
+ /// </summary>
+ /// <seealso cref="GetBaseName(string)"/>
+ /// <seealso cref="GetExtension(string)"/>
+ /// <seealso cref="GetFile(string)"/>
+ /// <param name="instance">The path to a file.</param>
+ /// <returns>The base directory.</returns>
public static string GetBaseDir(this string instance)
{
int basepos = instance.Find("://");
string rs;
- var @base = string.Empty;
+ string directory = string.Empty;
if (basepos != -1)
{
- var end = basepos + 3;
+ int end = basepos + 3;
rs = instance.Substring(end);
- @base = instance.Substring(0, end);
+ directory = instance.Substring(0, end);
}
else
{
if (instance.BeginsWith("/"))
{
rs = instance.Substring(1);
- @base = "/";
+ directory = "/";
}
else
{
@@ -414,14 +527,19 @@ namespace Godot
int sep = Mathf.Max(rs.FindLast("/"), rs.FindLast("\\"));
if (sep == -1)
- return @base;
+ return directory;
- return @base + rs.Substr(0, sep);
+ return directory + rs.Substr(0, sep);
}
- // <summary>
- // If the string is a path to a file, return the file and ignore the base directory.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file, return the file and ignore the base directory.
+ /// </summary>
+ /// <seealso cref="GetBaseName(string)"/>
+ /// <seealso cref="GetExtension(string)"/>
+ /// <seealso cref="GetBaseDir(string)"/>
+ /// <param name="instance">The path to a file.</param>
+ /// <returns>The file name.</returns>
public static string GetFile(this string instance)
{
int sep = Mathf.Max(instance.FindLast("/"), instance.FindLast("\\"));
@@ -461,14 +579,16 @@ namespace Godot
return Encoding.UTF8.GetString(bytes);
}
- // <summary>
- // Hash the string and return a 32 bits unsigned integer.
- // </summary>
+ /// <summary>
+ /// Hash the string and return a 32 bits unsigned integer.
+ /// </summary>
+ /// <param name="instance">The string to hash.</param>
+ /// <returns>The calculated hash of the string.</returns>
public static uint Hash(this string instance)
{
uint hash = 5381;
- foreach(uint c in instance)
+ foreach (uint c in instance)
{
hash = (hash << 5) + hash + c; // hash * 33 + c
}
@@ -483,7 +603,7 @@ namespace Godot
/// <returns>The hexadecimal representation of this byte.</returns>
internal static string HexEncode(this byte b)
{
- var ret = string.Empty;
+ string ret = string.Empty;
for (int i = 0; i < 2; i++)
{
@@ -513,7 +633,7 @@ namespace Godot
/// <returns>The hexadecimal representation of this byte array.</returns>
public static string HexEncode(this byte[] bytes)
{
- var ret = string.Empty;
+ string ret = string.Empty;
foreach (byte b in bytes)
{
@@ -525,8 +645,8 @@ namespace Godot
/// <summary>
/// Converts a string containing a hexadecimal number into an integer.
- /// Hexadecimal strings can either be prefixed with `0x` or not,
- /// and they can also start with a `-` before the optional prefix.
+ /// Hexadecimal strings can either be prefixed with <c>0x</c> or not,
+ /// and they can also start with a <c>-</c> before the optional prefix.
/// </summary>
/// <param name="instance">The string to convert.</param>
/// <returns>The converted string.</returns>
@@ -553,18 +673,30 @@ namespace Godot
return sign * int.Parse(instance, NumberStyles.HexNumber);
}
- // <summary>
- // Insert a substring at a given position.
- // </summary>
+ /// <summary>
+ /// Inserts a substring at a given position.
+ /// </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)
{
return instance.Insert(pos, what);
}
- // <summary>
- // If the string is a path to a file or directory, return true if the path is absolute.
- // </summary>
- public static bool IsAbsPath(this string instance)
+ /// <summary>
+ /// Returns <see langword="true"/> if the string is a path to a file or
+ /// directory and its startign point is explicitly defined. This includes
+ /// <c>res://</c>, <c>user://</c>, <c>C:\</c>, <c>/</c>, etc.
+ /// </summary>
+ /// <seealso cref="IsRelativePath(string)"/>
+ /// <param name="instance">The string to check.</param>
+ /// <returns>If the string is an absolute path.</returns>
+ public static bool IsAbsolutePath(this string instance)
{
if (string.IsNullOrEmpty(instance))
return false;
@@ -574,17 +706,28 @@ namespace Godot
return instance[0] == '/' || instance[0] == '\\';
}
- // <summary>
- // If the string is a path to a file or directory, return true if the path is relative.
- // </summary>
- public static bool IsRelPath(this string instance)
+ /// <summary>
+ /// Returns <see langword="true"/> if the string is a path to a file or
+ /// directory and its starting point is implicitly defined within the
+ /// context it is being used. The starting point may refer to the current
+ /// directory (<c>./</c>), or the current <see cref="Node"/>.
+ /// </summary>
+ /// <seealso cref="IsAbsolutePath(string)"/>
+ /// <param name="instance">The string to check.</param>
+ /// <returns>If the string is a relative path.</returns>
+ public static bool IsRelativePath(this string instance)
{
- return !IsAbsPath(instance);
+ return !IsAbsolutePath(instance);
}
- // <summary>
- // Check whether this string is a subsequence of the given string.
- // </summary>
+ /// <summary>
+ /// Check whether this string is a subsequence of the given string.
+ /// </summary>
+ /// <seealso cref="IsSubsequenceOfI(string, string)"/>
+ /// <param name="instance">The subsequence to search.</param>
+ /// <param name="text">The string that contains the subsequence.</param>
+ /// <param name="caseSensitive">If <see langword="true"/>, the check is case sensitive.</param>
+ /// <returns>If the string is a subsequence of the given string.</returns>
public static bool IsSubsequenceOf(this string instance, string text, bool caseSensitive = true)
{
int len = instance.Length;
@@ -625,34 +768,46 @@ namespace Godot
return false;
}
- // <summary>
- // Check whether this string is a subsequence of the given string, ignoring case differences.
- // </summary>
+ /// <summary>
+ /// Check whether this string is a subsequence of the given string, ignoring case differences.
+ /// </summary>
+ /// <seealso cref="IsSubsequenceOf(string, string, bool)"/>
+ /// <param name="instance">The subsequence to search.</param>
+ /// <param name="text">The string that contains the subsequence.</param>
+ /// <returns>If the string is a subsequence of the given string.</returns>
public static bool IsSubsequenceOfI(this string instance, string text)
{
return instance.IsSubsequenceOf(text, caseSensitive: false);
}
- // <summary>
- // Check whether the string contains a valid float.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid <see langword="float"/>.
+ /// </summary>
+ /// <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);
}
- // <summary>
- // Check whether the string contains a valid color in HTML notation.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid color in HTML notation.
+ /// </summary>
+ /// <param name="instance">The string to check.</param>
+ /// <returns>If the string contains a valid HTML color.</returns>
public static bool IsValidHtmlColor(this string instance)
{
return Color.HtmlIsValid(instance);
}
- // <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.
- // </summary>
+ /// <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.
+ /// </summary>
+ /// <param name="instance">The string to check.</param>
+ /// <returns>If the string contains a valid identifier.</returns>
public static bool IsValidIdentifier(this string instance)
{
int len = instance.Length;
@@ -660,18 +815,15 @@ namespace Godot
if (len == 0)
return false;
+ if (instance[0] >= '0' && instance[0] <= '9')
+ return false; // Identifiers cannot start with numbers.
+
for (int i = 0; i < len; i++)
{
- if (i == 0)
- {
- if (instance[0] >= '0' && instance[0] <= '9')
- return false; // Don't start with number plz
- }
-
- bool validChar = instance[i] >= '0' &&
- instance[i] <= '9' || instance[i] >= 'a' &&
- instance[i] <= 'z' || instance[i] >= 'A' &&
- instance[i] <= 'Z' || instance[i] == '_';
+ bool validChar = instance[i] == '_' ||
+ (instance[i] >= 'a' && instance[i] <= 'z') ||
+ (instance[i] >= 'A' && instance[i] <= 'Z') ||
+ (instance[i] >= '0' && instance[i] <= '9');
if (!validChar)
return false;
@@ -680,18 +832,22 @@ namespace Godot
return true;
}
- // <summary>
- // Check whether the string contains a valid integer.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid integer.
+ /// </summary>
+ /// <param name="instance">The string to check.</param>
+ /// <returns>If the string contains a valid integer.</returns>
public static bool IsValidInteger(this string instance)
{
int f;
return int.TryParse(instance, out f);
}
- // <summary>
- // Check whether the string contains a valid IP address.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid IP address.
+ /// </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
@@ -714,9 +870,11 @@ namespace Godot
return true;
}
- // <summary>
- // Return a copy of the string with special characters escaped using the JSON standard.
- // </summary>
+ /// <summary>
+ /// Returns a copy of the string with special characters escaped using the JSON standard.
+ /// </summary>
+ /// <param name="instance">The string to escape.</param>
+ /// <returns>The escaped string.</returns>
public static string JSONEscape(this string instance)
{
var sb = new StringBuilder(string.Copy(instance));
@@ -733,9 +891,13 @@ namespace Godot
return sb.ToString();
}
- // <summary>
- // Return an amount of characters from the left of the string.
- // </summary>
+ /// <summary>
+ /// Returns an amount of characters from the left of the string.
+ /// </summary>
+ /// <seealso cref="Right(string, int)"/>
+ /// <param name="instance">The original string.</param>
+ /// <param name="pos">The position in the string where the left side ends.</param>
+ /// <returns>The left side of the string from the given position.</returns>
public static string Left(this string instance, int pos)
{
if (pos <= 0)
@@ -748,8 +910,10 @@ namespace Godot
}
/// <summary>
- /// Return the length of the string in characters.
+ /// 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;
@@ -758,6 +922,7 @@ namespace Godot
/// <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>
@@ -783,8 +948,15 @@ namespace Godot
}
/// <summary>
- /// Do a simple expression match, where '*' matches zero or more arbitrary characters and '?' matches any single character except '.'.
+ /// Do a simple expression match, where '*' matches zero or more
+ /// arbitrary characters and '?' matches any single character except '.'.
/// </summary>
+ /// <param name="instance">The string to check.</param>
+ /// <param name="expr">Expression to check.</param>
+ /// <param name="caseSensitive">
+ /// If <see langword="true"/>, the check will be case sensitive.
+ /// </param>
+ /// <returns>If the expression has any matches.</returns>
private static bool ExprMatch(this string instance, string expr, bool caseSensitive)
{
// case '\0':
@@ -798,14 +970,25 @@ namespace Godot
case '?':
return instance.Length > 0 && instance[0] != '.' && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
default:
- if (instance.Length == 0) return false;
- return (caseSensitive ? instance[0] == expr[0] : char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
+ if (instance.Length == 0)
+ return false;
+ if (caseSensitive)
+ return instance[0] == expr[0];
+ return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
}
}
/// <summary>
- /// Do a simple case sensitive expression match, using ? and * wildcards (see [method expr_match]).
+ /// Do a simple case sensitive expression match, using ? and * wildcards
+ /// (see <see cref="ExprMatch(string, string, bool)"/>).
/// </summary>
+ /// <seealso cref="MatchN(string, string)"/>
+ /// <param name="instance">The string to check.</param>
+ /// <param name="expr">Expression to check.</param>
+ /// <param name="caseSensitive">
+ /// If <see langword="true"/>, the check will be case sensitive.
+ /// </param>
+ /// <returns>If the expression has any matches.</returns>
public static bool Match(this string instance, string expr, bool caseSensitive = true)
{
if (instance.Length == 0 || expr.Length == 0)
@@ -815,8 +998,13 @@ namespace Godot
}
/// <summary>
- /// Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]).
+ /// Do a simple case insensitive expression match, using ? and * wildcards
+ /// (see <see cref="ExprMatch(string, string, bool)"/>).
/// </summary>
+ /// <seealso cref="Match(string, string, bool)"/>
+ /// <param name="instance">The string to check.</param>
+ /// <param name="expr">Expression to check.</param>
+ /// <returns>If the expression has any matches.</returns>
public static bool MatchN(this string instance, string expr)
{
if (instance.Length == 0 || expr.Length == 0)
@@ -825,47 +1013,66 @@ namespace Godot
return instance.ExprMatch(expr, caseSensitive: false);
}
- // <summary>
- // Return the MD5 hash of the string as an array of bytes.
- // </summary>
+ /// <summary>
+ /// Returns the MD5 hash of the string as an array of bytes.
+ /// </summary>
+ /// <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)
{
return godot_icall_String_md5_buffer(instance);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static byte[] godot_icall_String_md5_buffer(string str);
+ internal static extern byte[] godot_icall_String_md5_buffer(string str);
- // <summary>
- // Return the MD5 hash of the string as a string.
- // </summary>
+ /// <summary>
+ /// Returns the MD5 hash of the string as a string.
+ /// </summary>
+ /// <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)
{
return godot_icall_String_md5_text(instance);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string godot_icall_String_md5_text(string str);
+ internal static extern string godot_icall_String_md5_text(string str);
- // <summary>
- // Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
- // </summary>
+ /// <summary>
+ /// Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// </summary>
+ /// <seealso cref="CasecmpTo(string, string)"/>
+ /// <seealso cref="CompareTo(string, string, bool)"/>
+ /// <param name="instance">The string to compare.</param>
+ /// <param name="to">The other string to compare.</param>
+ /// <returns>-1 if less, 0 if equal and +1 if greater.</returns>
public static int NocasecmpTo(this string instance, string to)
{
return instance.CompareTo(to, caseSensitive: false);
}
- // <summary>
- // Return the character code at position [code]at[/code].
- // </summary>
+ /// <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 [code]digits[/code] after the decimal point.
- // </summary>
+ /// <summary>
+ /// Format a number to have an exact number of <paramref name="digits"/>
+ /// after the decimal point.
+ /// </summary>
+ /// <seealso cref="PadZeros(string, int)"/>
+ /// <param name="instance">The string to pad.</param>
+ /// <param name="digits">Amount of digits after the decimal point.</param>
+ /// <returns>The string padded with zeroes.</returns>
public static string PadDecimals(this string instance, int digits)
{
int c = instance.Find(".");
@@ -899,9 +1106,14 @@ namespace Godot
return instance;
}
- // <summary>
- // Format a number to have an exact number of [code]digits[/code] before the decimal point.
- // </summary>
+ /// <summary>
+ /// Format a number to have an exact number of <paramref name="digits"/>
+ /// before the decimal point.
+ /// </summary>
+ /// <seealso cref="PadDecimals(string, int)"/>
+ /// <param name="instance">The string to pad.</param>
+ /// <param name="digits">Amount of digits before the decimal point.</param>
+ /// <returns>The string padded with zeroes.</returns>
public static string PadZeros(this string instance, int digits)
{
string s = instance;
@@ -932,9 +1144,14 @@ namespace Godot
return s;
}
- // <summary>
- // If the string is a path, this concatenates [code]file[/code] at the end of the string as a subpath. E.g. [code]"this/is".plus_file("path") == "this/is/path"[/code].
- // </summary>
+ /// <summary>
+ /// If the string is a path, this concatenates <paramref name="file"/>
+ /// at the end of the string as a subpath.
+ /// E.g. <c>"this/is".PlusFile("path") == "this/is/path"</c>.
+ /// </summary>
+ /// <param name="instance">The path that will be concatenated.</param>
+ /// <param name="file">File name to concatenate with the path.</param>
+ /// <returns>The concatenated path with the given file name.</returns>
public static string PlusFile(this string instance, string file)
{
if (instance.Length > 0 && instance[instance.Length - 1] == '/')
@@ -942,47 +1159,72 @@ namespace Godot
return instance + "/" + file;
}
- // <summary>
- // Replace occurrences of a substring for different ones inside the string.
- // </summary>
+ /// <summary>
+ /// Replace occurrences of a substring for different ones inside the string.
+ /// </summary>
+ /// <seealso cref="ReplaceN(string, string, string)"/>
+ /// <param name="instance">The string to modify.</param>
+ /// <param name="what">The substring to be replaced in the string.</param>
+ /// <param name="forwhat">The substring that replaces <paramref name="what"/>.</param>
+ /// <returns>The string with the substring occurrences replaced.</returns>
public static string Replace(this string instance, string what, string forwhat)
{
return instance.Replace(what, forwhat);
}
- // <summary>
- // Replace occurrences of a substring for different ones inside the string, but search case-insensitive.
- // </summary>
+ /// <summary>
+ /// Replace occurrences of a substring for different ones inside the string, but search case-insensitive.
+ /// </summary>
+ /// <seealso cref="Replace(string, string, string)"/>
+ /// <param name="instance">The string to modify.</param>
+ /// <param name="what">The substring to be replaced in the string.</param>
+ /// <param name="forwhat">The substring that replaces <paramref name="what"/>.</param>
+ /// <returns>The string with the substring occurrences replaced.</returns>
public static string ReplaceN(this string instance, string what, string forwhat)
{
return Regex.Replace(instance, what, forwhat, RegexOptions.IgnoreCase);
}
- // <summary>
- // Perform a search for a substring, but start from the end of the string instead of the beginning.
- // </summary>
+ /// <summary>
+ /// Perform a search for a substring, but start from the end of the string instead of the beginning.
+ /// </summary>
+ /// <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>
+ /// <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)
{
return godot_icall_String_rfind(instance, what, from);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_String_rfind(string str, string what, int from);
+ internal static extern int godot_icall_String_rfind(string str, string what, int from);
- // <summary>
- // Perform a search for a substring, but start from the end of the string instead of the beginning. Also search case-insensitive.
- // </summary>
+ /// <summary>
+ /// Perform a search for a substring, but start from the end of the string instead of the beginning.
+ /// Also search case-insensitive.
+ /// </summary>
+ /// <seealso cref="RFind(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>
+ /// <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)
{
return godot_icall_String_rfindn(instance, what, from);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static int godot_icall_String_rfindn(string str, string what, int from);
+ internal static extern int godot_icall_String_rfindn(string str, string what, int from);
- // <summary>
- // Return the right side of the string from a given position.
- // </summary>
+ /// <summary>
+ /// Returns the right side of the string from a given position.
+ /// </summary>
+ /// <seealso cref="Left(string, int)"/>
+ /// <param name="instance">The original string.</param>
+ /// <param name="pos">The position in the string from which the right side starts.</param>
+ /// <returns>The right side of the string from the given position.</returns>
public static string Right(this string instance, int pos)
{
if (pos >= instance.Length)
@@ -997,6 +1239,7 @@ namespace Godot
/// <summary>
/// Returns a copy of the string with characters removed from the right.
/// </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>
@@ -1021,28 +1264,41 @@ namespace Godot
return instance.Substr(0, end + 1);
}
+ /// <summary>
+ /// Returns the SHA-256 hash of the string as an array of bytes.
+ /// </summary>
+ /// <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)
{
return godot_icall_String_sha256_buffer(instance);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static byte[] godot_icall_String_sha256_buffer(string str);
+ internal static extern byte[] godot_icall_String_sha256_buffer(string str);
- // <summary>
- // Return the SHA-256 hash of the string as a string.
- // </summary>
+ /// <summary>
+ /// Returns the SHA-256 hash of the string as a string.
+ /// </summary>
+ /// <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)
{
return godot_icall_String_sha256_text(instance);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string godot_icall_String_sha256_text(string str);
+ internal static extern string godot_icall_String_sha256_text(string str);
- // <summary>
- // Return the similarity index of the text compared to this string. 1 means totally similar and 0 means totally dissimilar.
- // </summary>
+ /// <summary>
+ /// Returns the similarity index of the text compared to this string.
+ /// 1 means totally similar and 0 means totally dissimilar.
+ /// </summary>
+ /// <param name="instance">The string to compare.</param>
+ /// <param name="text">The other string to compare.</param>
+ /// <returns>The similarity index.</returns>
public static float Similarity(this string instance, string text)
{
if (instance == text)
@@ -1080,17 +1336,44 @@ namespace Godot
return 2.0f * inter / sum;
}
- // <summary>
- // Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
- // </summary>
+ /// <summary>
+ /// Returns a simplified canonical path.
+ /// </summary>
+ public static string SimplifyPath(this string instance)
+ {
+ return godot_icall_String_simplify_path(instance);
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string godot_icall_String_simplify_path(string str);
+
+ /// <summary>
+ /// Split the string by a divisor string, return an array of the substrings.
+ /// Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
+ /// </summary>
+ /// <seealso cref="SplitFloats(string, string, bool)"/>
+ /// <param name="instance">The string to split.</param>
+ /// <param name="divisor">The divisor string that splits the string.</param>
+ /// <param name="allowEmpty">
+ /// If <see langword="true"/>, the array may include empty strings.
+ /// </param>
+ /// <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 }, StringSplitOptions.RemoveEmptyEntries);
+ return instance.Split(new[] { divisor }, allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
}
- // <summary>
- // Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",".
- // </summary>
+ /// <summary>
+ /// Split the string in floats by using a divisor string, return an array of the substrings.
+ /// Example "1,2.5,3" will return [1,2.5,3] if split by ",".
+ /// </summary>
+ /// <seealso cref="Split(string, string, bool)"/>
+ /// <param name="instance">The string to split.</param>
+ /// <param name="divisor">The divisor string that splits the string.</param>
+ /// <param name="allowEmpty">
+ /// If <see langword="true"/>, the array may include empty floats.
+ /// </param>
+ /// <returns>The array of floats split from the string.</returns>
public static float[] SplitFloats(this string instance, string divisor, bool allowEmpty = true)
{
var ret = new List<float>();
@@ -1113,7 +1396,8 @@ namespace Godot
return ret.ToArray();
}
- private static readonly char[] _nonPrintable = {
+ private static readonly char[] _nonPrintable =
+ {
(char)00, (char)01, (char)02, (char)03, (char)04, (char)05,
(char)06, (char)07, (char)08, (char)09, (char)10, (char)11,
(char)12, (char)13, (char)14, (char)15, (char)16, (char)17,
@@ -1122,9 +1406,14 @@ namespace Godot
(char)30, (char)31, (char)32
};
- // <summary>
- // Return 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.
- // </summary>
+ /// <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.
+ /// </summary>
+ /// <param name="instance">The string to strip.</param>
+ /// <param name="left">If the left side should be stripped.</param>
+ /// <param name="right">If the right side should be stripped.</param>
+ /// <returns>The string stripped of any non-printable characters.</returns>
public static string StripEdges(this string instance, bool left = true, bool right = true)
{
if (left)
@@ -1137,58 +1426,86 @@ namespace Godot
return instance.TrimEnd(_nonPrintable);
}
- // <summary>
- // Return part of the string from the position [code]from[/code], with length [code]len[/code].
- // </summary>
+ /// <summary>
+ /// Returns part of the string from the position <paramref name="from"/>, with length <paramref name="len"/>.
+ /// </summary>
+ /// <param name="instance">The string to slice.</param>
+ /// <param name="from">The position in the string that the part starts from.</param>
+ /// <param name="len">The length of the returned part.</param>
+ /// <returns>
+ /// Part of the string from the position <paramref name="from"/>, with length <paramref name="len"/>.
+ /// </returns>
public static string Substr(this string instance, int from, int len)
{
int max = instance.Length - from;
return instance.Substring(from, len > max ? max : len);
}
- // <summary>
- // Convert the String (which is a character array) to PackedByteArray (which is an array of bytes). The conversion is speeded up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters.
- // </summary>
+ /// <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.
+ /// </summary>
+ /// <seealso cref="ToUTF8(string)"/>
+ /// <param name="instance">The string to convert.</param>
+ /// <returns>The string as ASCII encoded bytes.</returns>
public static byte[] ToAscii(this string instance)
{
return Encoding.ASCII.GetBytes(instance);
}
- // <summary>
- // Convert a string, containing a decimal number, into a [code]float[/code].
- // </summary>
+ /// <summary>
+ /// Converts a string, containing a decimal number, into a <see langword="float" />.
+ /// </summary>
+ /// <seealso cref="ToInt(string)"/>
+ /// <param name="instance">The string to convert.</param>
+ /// <returns>The number representation of the string.</returns>
public static float ToFloat(this string instance)
{
return float.Parse(instance);
}
- // <summary>
- // Convert a string, containing an integer number, into an [code]int[/code].
- // </summary>
+ /// <summary>
+ /// Converts a string, containing an integer number, into an <see langword="int" />.
+ /// </summary>
+ /// <seealso cref="ToFloat(string)"/>
+ /// <param name="instance">The string to convert.</param>
+ /// <returns>The number representation of the string.</returns>
public static int ToInt(this string instance)
{
return int.Parse(instance);
}
- // <summary>
- // Return the string converted to lowercase.
- // </summary>
+ /// <summary>
+ /// Returns the string converted to lowercase.
+ /// </summary>
+ /// <seealso cref="ToUpper(string)"/>
+ /// <param name="instance">The string to convert.</param>
+ /// <returns>The string converted to lowercase.</returns>
public static string ToLower(this string instance)
{
return instance.ToLower();
}
- // <summary>
- // Return the string converted to uppercase.
- // </summary>
+ /// <summary>
+ /// Returns the string converted to uppercase.
+ /// </summary>
+ /// <seealso cref="ToLower(string)"/>
+ /// <param name="instance">The string to convert.</param>
+ /// <returns>The string converted to uppercase.</returns>
public static string ToUpper(this string instance)
{
return instance.ToUpper();
}
- // <summary>
- // Convert the String (which is an array of characters) to PackedByteArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii().
- // </summary>
+ /// <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)"/>.
+ /// </summary>
+ /// <seealso cref="ToAscii(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)
{
return Encoding.UTF8.GetBytes(instance);
@@ -1197,8 +1514,8 @@ namespace Godot
/// <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 `System.Uri.UnescapeDataString()`,
- /// but also handles `+`.
+ /// This mostly wraps around <see cref="Uri.UnescapeDataString"/>,
+ /// but also handles <c>+</c>.
/// See <see cref="URIEncode"/> for encoding.
/// </summary>
/// <param name="instance">The string to decode.</param>
@@ -1211,7 +1528,7 @@ namespace Godot
/// <summary>
/// Encodes a string to URL friendly format. This is meant to
/// encode parameters in a URL when sending an HTTP request.
- /// This wraps around `System.Uri.EscapeDataString()`.
+ /// This wraps around <see cref="Uri.EscapeDataString"/>.
/// See <see cref="URIDecode"/> for decoding.
/// </summary>
/// <param name="instance">The string to encode.</param>
@@ -1221,17 +1538,24 @@ namespace Godot
return Uri.EscapeDataString(instance);
}
- // <summary>
- // Return a copy of the string with special characters escaped using the XML standard.
- // </summary>
+ /// <summary>
+ /// Returns a copy of the string with special characters escaped using the XML standard.
+ /// </summary>
+ /// <seealso cref="XMLUnescape(string)"/>
+ /// <param name="instance">The string to escape.</param>
+ /// <returns>The escaped string.</returns>
public static string XMLEscape(this string instance)
{
return SecurityElement.Escape(instance);
}
- // <summary>
- // Return a copy of the string with escaped characters replaced by their meanings according to the XML standard.
- // </summary>
+ /// <summary>
+ /// Returns a copy of the string with escaped characters replaced by their meanings
+ /// according to the XML standard.
+ /// </summary>
+ /// <seealso cref="XMLEscape(string)"/>
+ /// <param name="instance">The string to unescape.</param>
+ /// <returns>The unescaped string.</returns>
public static string XMLUnescape(this string instance)
{
return SecurityElement.FromString(instance).Text;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
index 7700b6d4ed..b1d504410b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
@@ -3,6 +3,13 @@ using System.Runtime.CompilerServices;
namespace Godot
{
+ /// <summary>
+ /// StringNames are immutable strings designed for general-purpose representation of unique names.
+ /// StringName ensures that only one instance of a given name exists (so two StringNames with the
+ /// same value are the same object).
+ /// Comparing them is much faster than with regular strings, because only the pointers are compared,
+ /// not the whole strings.
+ /// </summary>
public sealed partial class StringName : IDisposable
{
private IntPtr ptr;
@@ -23,6 +30,9 @@ namespace Godot
Dispose(false);
}
+ /// <summary>
+ /// Disposes of this <see cref="StringName"/>.
+ /// </summary>
public void Dispose()
{
Dispose(true);
@@ -43,25 +53,48 @@ namespace Godot
this.ptr = ptr;
}
+ /// <summary>
+ /// Constructs an empty <see cref="StringName"/>.
+ /// </summary>
public StringName()
{
ptr = IntPtr.Zero;
}
+ /// <summary>
+ /// Constructs a <see cref="StringName"/> from the given <paramref name="path"/> string.
+ /// </summary>
+ /// <param name="path">String to construct the <see cref="StringName"/> from.</param>
public StringName(string path)
{
ptr = path == null ? IntPtr.Zero : godot_icall_StringName_Ctor(path);
}
+ /// <summary>
+ /// Converts a string to a <see cref="StringName"/>.
+ /// </summary>
+ /// <param name="from">The string to convert.</param>
public static implicit operator StringName(string from) => new StringName(from);
+ /// <summary>
+ /// Converts a <see cref="StringName"/> to a string.
+ /// </summary>
+ /// <param name="from">The <see cref="StringName"/> to convert.</param>
public static implicit operator string(StringName from) => from.ToString();
+ /// <summary>
+ /// Converts this <see cref="StringName"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this <see cref="StringName"/>.</returns>
public override string ToString()
{
return ptr == IntPtr.Zero ? string.Empty : godot_icall_StringName_operator_String(GetPtr(this));
}
+ /// <summary>
+ /// Check whether this <see cref="StringName"/> is empty.
+ /// </summary>
+ /// <returns>If the <see cref="StringName"/> is empty.</returns>
public bool IsEmpty()
{
return ptr == IntPtr.Zero || godot_icall_StringName_is_empty(GetPtr(this));
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index bc0f81b2a7..daea09ba72 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -21,18 +21,18 @@ namespace Godot
public struct Transform2D : IEquatable<Transform2D>
{
/// <summary>
- /// The basis matrix's X vector (column 0). Equivalent to array index `[0]`.
+ /// The basis matrix's X vector (column 0). Equivalent to array index <c>[0]</c>.
/// </summary>
/// <value></value>
public Vector2 x;
/// <summary>
- /// The basis matrix's Y vector (column 1). Equivalent to array index `[1]`.
+ /// The basis matrix's Y vector (column 1). Equivalent to array index <c>[1]</c>.
/// </summary>
public Vector2 y;
/// <summary>
- /// The origin vector (column 2, the third column). Equivalent to array index `[2]`.
+ /// The origin vector (column 2, the third column). Equivalent to array index <c>[2]</c>.
/// The origin vector represents translation.
/// </summary>
public Vector2 origin;
@@ -77,7 +77,8 @@ namespace Godot
}
/// <summary>
- /// Access whole columns in the form of Vector2. The third column is the origin vector.
+ /// Access whole columns in the form of <see cref="Vector2"/>.
+ /// The third column is the <see cref="origin"/> vector.
/// </summary>
/// <param name="column">Which column vector.</param>
public Vector2 this[int column]
@@ -116,7 +117,8 @@ namespace Godot
}
/// <summary>
- /// Access matrix elements in column-major order. The third column is the origin vector.
+ /// Access matrix elements in column-major order.
+ /// 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>
@@ -138,6 +140,7 @@ namespace Godot
/// Returns the inverse of the transform, under the assumption that
/// the transformation is composed of rotation, scaling, and translation.
/// </summary>
+ /// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
public Transform2D AffineInverse()
{
@@ -146,7 +149,7 @@ namespace Godot
if (det == 0)
throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
- var inv = this;
+ Transform2D inv = this;
real_t temp = inv[0, 0];
inv[0, 0] = inv[1, 1];
@@ -173,13 +176,14 @@ namespace Godot
/// <returns>The determinant of the basis matrix.</returns>
private 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 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)
@@ -189,11 +193,12 @@ namespace Godot
/// <summary>
/// Returns a vector transformed (multiplied) by the inverse basis matrix.
- /// This method does not account for translation (the 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.
/// </summary>
+ /// <seealso cref="BasisXform(Vector2)"/>
/// <param name="v">A vector to inversely transform.</param>
/// <returns>The inversely transformed vector.</returns>
public Vector2 BasisXformInv(Vector2 v)
@@ -202,7 +207,7 @@ namespace Godot
}
/// <summary>
- /// Interpolates this transform to the other `transform` by `weight`.
+ /// Interpolates this transform to the other <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>
@@ -233,8 +238,8 @@ namespace Godot
else
{
real_t angle = weight * Mathf.Acos(dot);
- Vector2 v3 = (v2 - v1 * dot).Normalized();
- v = v1 * Mathf.Cos(angle) + v3 * Mathf.Sin(angle);
+ Vector2 v3 = (v2 - (v1 * dot)).Normalized();
+ v = (v1 * Mathf.Cos(angle)) + (v3 * Mathf.Sin(angle));
}
// Extract parameters
@@ -258,7 +263,7 @@ namespace Godot
/// <returns>The inverse matrix.</returns>
public Transform2D Inverse()
{
- var inv = this;
+ Transform2D inv = this;
// Swap
real_t temp = inv.x.y;
@@ -277,13 +282,13 @@ namespace Godot
/// <returns>The orthonormalized transform.</returns>
public Transform2D Orthonormalized()
{
- var on = this;
+ Transform2D on = this;
Vector2 onX = on.x;
Vector2 onY = on.y;
onX.Normalize();
- onY = onY - onX * onX.Dot(onY);
+ onY = onY - (onX * onX.Dot(onY));
onY.Normalize();
on.x = onX;
@@ -293,7 +298,7 @@ namespace Godot
}
/// <summary>
- /// Rotates the transform by `phi` (in radians), using matrix multiplication.
+ /// Rotates the transform by <paramref name="phi"/> (in radians), using matrix multiplication.
/// </summary>
/// <param name="phi">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
@@ -309,7 +314,7 @@ namespace Godot
/// <returns>The scaled transformation matrix.</returns>
public Transform2D Scaled(Vector2 scale)
{
- var copy = this;
+ Transform2D copy = this;
copy.x *= scale;
copy.y *= scale;
copy.origin *= scale;
@@ -326,16 +331,16 @@ namespace Godot
private real_t Tdotx(Vector2 with)
{
- return this[0, 0] * with[0] + this[1, 0] * with[1];
+ return (this[0, 0] * with[0]) + (this[1, 0] * with[1]);
}
private real_t Tdoty(Vector2 with)
{
- return this[0, 1] * with[0] + this[1, 1] * with[1];
+ return (this[0, 1] * with[0]) + (this[1, 1] * with[1]);
}
/// <summary>
- /// Translates the transform by the given `offset`,
+ /// Translates the transform by the given <paramref name="offset"/>,
/// relative to the transform's basis vectors.
///
/// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
@@ -345,7 +350,7 @@ namespace Godot
/// <returns>The translated matrix.</returns>
public Transform2D Translated(Vector2 offset)
{
- var copy = this;
+ Transform2D copy = this;
copy.origin += copy.BasisXform(offset);
return copy;
}
@@ -353,6 +358,7 @@ namespace Godot
/// <summary>
/// Returns a vector transformed (multiplied) by this transformation matrix.
/// </summary>
+ /// <seealso cref="XformInv(Vector2)"/>
/// <param name="v">A vector to transform.</param>
/// <returns>The transformed vector.</returns>
public Vector2 Xform(Vector2 v)
@@ -363,6 +369,7 @@ namespace Godot
/// <summary>
/// Returns a vector transformed (multiplied) by the inverse transformation matrix.
/// </summary>
+ /// <seealso cref="Xform(Vector2)"/>
/// <param name="v">A vector to inversely transform.</param>
/// <returns>The inversely transformed vector.</returns>
public Vector2 XformInv(Vector2 v)
@@ -378,20 +385,20 @@ namespace Godot
/// <summary>
/// The identity transform, with no translation, rotation, or scaling applied.
- /// This is used as a replacement for `Transform2D()` in GDScript.
- /// Do not use `new Transform2D()` with no arguments in C#, because it sets all values to zero.
+ /// This is used as a replacement for <c>Transform2D()</c> in GDScript.
+ /// Do not use <c>new Transform2D()</c> with no arguments in C#, because it sets all values to zero.
/// </summary>
- /// <value>Equivalent to `new Transform2D(Vector2.Right, Vector2.Down, Vector2.Zero)`.</value>
+ /// <value>Equivalent to <c>new Transform2D(Vector2.Right, Vector2.Down, Vector2.Zero)</c>.</value>
public static Transform2D Identity { get { return _identity; } }
/// <summary>
/// The transform that will flip something along the X axis.
/// </summary>
- /// <value>Equivalent to `new Transform2D(Vector2.Left, Vector2.Down, Vector2.Zero)`.</value>
+ /// <value>Equivalent to <c>new Transform2D(Vector2.Left, Vector2.Down, Vector2.Zero)</c>.</value>
public static Transform2D FlipX { get { return _flipX; } }
/// <summary>
/// The transform that will flip something along the Y axis.
/// </summary>
- /// <value>Equivalent to `new Transform2D(Vector2.Right, Vector2.Up, Vector2.Zero)`.</value>
+ /// <value>Equivalent to <c>new Transform2D(Vector2.Right, Vector2.Up, Vector2.Zero)</c>.</value>
public static Transform2D FlipY { get { return _flipY; } }
/// <summary>
@@ -411,12 +418,12 @@ namespace Godot
/// 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 `t.x.x` or `[0][0]`</param>
- /// <param name="xy">The Y component of the X column vector, accessed via `t.x.y` or `[0][1]`</param>
- /// <param name="yx">The X component of the Y column vector, accessed via `t.y.x` or `[1][0]`</param>
- /// <param name="yy">The Y component of the Y column vector, accessed via `t.y.y` or `[1][1]`</param>
- /// <param name="ox">The X component of the origin vector, accessed via `t.origin.x` or `[2][0]`</param>
- /// <param name="oy">The Y component of the origin vector, accessed via `t.origin.y` or `[2][1]`</param>
+ /// <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);
@@ -425,16 +432,17 @@ namespace Godot
}
/// <summary>
- /// Constructs a transformation matrix from a rotation value and origin vector.
+ /// Constructs a transformation matrix from a <paramref name="rotation"/> value and
+ /// <paramref name="origin"/> vector.
/// </summary>
- /// <param name="rot">The rotation of the new transform, in radians.</param>
- /// <param name="pos">The origin vector, or column index 2.</param>
- public Transform2D(real_t rot, Vector2 pos)
+ /// <param name="rotation">The rotation of the new transform, in radians.</param>
+ /// <param name="origin">The origin vector, or column index 2.</param>
+ public Transform2D(real_t rotation, Vector2 origin)
{
- x.x = y.y = Mathf.Cos(rot);
- x.y = y.x = Mathf.Sin(rot);
+ x.x = y.y = Mathf.Cos(rotation);
+ x.y = y.x = Mathf.Sin(rotation);
y.x *= -1;
- origin = pos;
+ this.origin = origin;
}
public static Transform2D operator *(Transform2D left, Transform2D right)
@@ -464,19 +472,29 @@ namespace Godot
return !left.Equals(right);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this transform and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the transform and the other object are equal.</returns>
public override bool Equals(object obj)
{
return obj is Transform2D transform2D && Equals(transform2D);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this transform and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other transform to compare.</param>
+ /// <returns>Whether or not the matrices are equal.</returns>
public bool Equals(Transform2D other)
{
return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin);
}
/// <summary>
- /// Returns true if this transform and `other` are approximately equal, by running
- /// <see cref="Vector2.IsEqualApprox(Vector2)"/> on each component.
+ /// Returns <see langword="true"/> if this transform and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Vector2.IsEqualApprox(Vector2)"/> on each component.
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
@@ -485,29 +503,31 @@ namespace Godot
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()
{
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()
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- x.ToString(),
- y.ToString(),
- origin.ToString()
- });
+ 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)
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- x.ToString(format),
- y.ToString(format),
- 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/Transform.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index ac47f6029f..7176cd60dc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -19,7 +19,7 @@ namespace Godot
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- public struct Transform : IEquatable<Transform>
+ public struct Transform3D : IEquatable<Transform3D>
{
/// <summary>
/// The <see cref="Basis"/> of this transform. Contains the X, Y, and Z basis
@@ -28,12 +28,13 @@ namespace Godot
public Basis basis;
/// <summary>
- /// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`.
+ /// The origin vector (column 3, the fourth column). Equivalent to array index <c>[3]</c>.
/// </summary>
public Vector3 origin;
/// <summary>
- /// Access whole columns in the form of Vector3. The fourth column is the origin vector.
+ /// Access whole columns in the form of <see cref="Vector3"/>.
+ /// The fourth column is the <see cref="origin"/> vector.
/// </summary>
/// <param name="column">Which column vector.</param>
public Vector3 this[int column]
@@ -77,7 +78,8 @@ namespace Godot
}
/// <summary>
- /// Access matrix elements in column-major order. The fourth column is the origin vector.
+ /// Access matrix elements in column-major order.
+ /// 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>
@@ -106,33 +108,36 @@ namespace Godot
/// Returns the inverse of the transform, under the assumption that
/// the transformation is composed of rotation, scaling, and translation.
/// </summary>
+ /// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
- public Transform AffineInverse()
+ public Transform3D AffineInverse()
{
Basis basisInv = basis.Inverse();
- return new Transform(basisInv, basisInv.Xform(-origin));
+ return new Transform3D(basisInv, basisInv.Xform(-origin));
}
/// <summary>
- /// Interpolates this transform to the other `transform` by `weight`.
+ /// Interpolates this transform to the other <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 Transform InterpolateWith(Transform transform, real_t weight)
+ public Transform3D InterpolateWith(Transform3D transform, real_t weight)
{
/* not sure if very "efficient" but good enough? */
Vector3 sourceScale = basis.Scale;
- Quat sourceRotation = basis.RotationQuat();
+ Quaternion sourceRotation = basis.GetRotationQuaternion();
Vector3 sourceLocation = origin;
Vector3 destinationScale = transform.basis.Scale;
- Quat destinationRotation = transform.basis.RotationQuat();
+ Quaternion destinationRotation = transform.basis.GetRotationQuaternion();
Vector3 destinationLocation = transform.origin;
- var interpolated = new Transform();
- interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.Lerp(destinationScale, weight));
+ 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;
@@ -144,28 +149,28 @@ namespace Godot
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Transform Inverse()
+ public Transform3D Inverse()
{
Basis basisTr = basis.Transposed();
- return new Transform(basisTr, basisTr.Xform(-origin));
+ return new Transform3D(basisTr, basisTr.Xform(-origin));
}
/// <summary>
/// Returns a copy of the transform rotated such that its
- /// -Z axis (forward) points towards the target position.
+ /// -Z axis (forward) points towards the <paramref name="target"/> position.
///
- /// The transform will first be rotated around the given up vector,
- /// and then fully aligned to the target by a further rotation around
- /// an axis perpendicular to both the target and up vectors.
+ /// The transform will first be rotated around the given <paramref name="up"/> vector,
+ /// and then fully aligned to the <paramref name="target"/> by a further rotation around
+ /// an axis perpendicular to both the <paramref name="target"/> and <paramref name="up"/> vectors.
///
/// Operations take place in global space.
/// </summary>
/// <param name="target">The object to look at.</param>
/// <param name="up">The relative up direction</param>
/// <returns>The resulting transform.</returns>
- public Transform LookingAt(Vector3 target, Vector3 up)
+ public Transform3D LookingAt(Vector3 target, Vector3 up)
{
- var t = this;
+ Transform3D t = this;
t.SetLookAt(origin, target, up);
return t;
}
@@ -175,21 +180,21 @@ namespace Godot
/// and normalized axis vectors (scale of 1 or -1).
/// </summary>
/// <returns>The orthonormalized transform.</returns>
- public Transform Orthonormalized()
+ public Transform3D Orthonormalized()
{
- return new Transform(basis.Orthonormalized(), origin);
+ return new Transform3D(basis.Orthonormalized(), origin);
}
/// <summary>
- /// Rotates the transform around the given `axis` by `phi` (in radians),
+ /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="phi"/> (in radians),
/// using matrix multiplication. The axis must be a normalized vector.
/// </summary>
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="phi">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform Rotated(Vector3 axis, real_t phi)
+ public Transform3D Rotated(Vector3 axis, real_t phi)
{
- return new Transform(new Basis(axis, phi), new Vector3()) * this;
+ return new Transform3D(new Basis(axis, phi), new Vector3()) * this;
}
/// <summary>
@@ -197,9 +202,9 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform Scaled(Vector3 scale)
+ public Transform3D Scaled(Vector3 scale)
{
- return new Transform(basis.Scaled(scale), origin * scale);
+ return new Transform3D(basis.Scaled(scale), origin * scale);
}
private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
@@ -226,7 +231,7 @@ namespace Godot
}
/// <summary>
- /// Translates the transform by the given `offset`,
+ /// Translates the transform by the given <paramref name="offset"/>,
/// relative to the transform's basis vectors.
///
/// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
@@ -234,9 +239,9 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform Translated(Vector3 offset)
+ public Transform3D Translated(Vector3 offset)
{
- return new Transform(basis, new Vector3
+ return new Transform3D(basis, new Vector3
(
origin[0] += basis.Row0.Dot(offset),
origin[1] += basis.Row1.Dot(offset),
@@ -247,6 +252,7 @@ namespace Godot
/// <summary>
/// Returns a vector transformed (multiplied) by this transformation matrix.
/// </summary>
+ /// <seealso cref="XformInv(Vector3)"/>
/// <param name="v">A vector to transform.</param>
/// <returns>The transformed vector.</returns>
public Vector3 Xform(Vector3 v)
@@ -265,6 +271,7 @@ namespace Godot
/// Note: This results in a multiplication by the inverse of the
/// transformation matrix only if it represents a rotation-reflection.
/// </summary>
+ /// <seealso cref="Xform(Vector3)"/>
/// <param name="v">A vector to inversely transform.</param>
/// <returns>The inversely transformed vector.</returns>
public Vector3 XformInv(Vector3 v)
@@ -273,40 +280,40 @@ namespace Godot
return new Vector3
(
- basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z,
- basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z,
- basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z
+ (basis.Row0[0] * vInv.x) + (basis.Row1[0] * vInv.y) + (basis.Row2[0] * vInv.z),
+ (basis.Row0[1] * vInv.x) + (basis.Row1[1] * vInv.y) + (basis.Row2[1] * vInv.z),
+ (basis.Row0[2] * vInv.x) + (basis.Row1[2] * vInv.y) + (basis.Row2[2] * vInv.z)
);
}
// Constants
- private static readonly Transform _identity = new Transform(Basis.Identity, Vector3.Zero);
- private static readonly Transform _flipX = new Transform(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
- private static readonly Transform _flipY = new Transform(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
- private static readonly Transform _flipZ = new Transform(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
+ private static readonly Transform3D _identity = new Transform3D(Basis.Identity, Vector3.Zero);
+ private static readonly Transform3D _flipX = new Transform3D(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform3D _flipY = new Transform3D(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform3D _flipZ = new Transform3D(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
/// <summary>
/// The identity transform, with no translation, rotation, or scaling applied.
- /// This is used as a replacement for `Transform()` in GDScript.
- /// Do not use `new Transform()` with no arguments in C#, because it sets all values to zero.
+ /// This is used as a replacement for <c>Transform()</c> in GDScript.
+ /// Do not use <c>new Transform()</c> with no arguments in C#, because it sets all values to zero.
/// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
- public static Transform Identity { get { return _identity; } }
+ /// <value>Equivalent to <c>new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)</c>.</value>
+ public static Transform3D Identity { get { return _identity; } }
/// <summary>
/// The transform that will flip something along the X axis.
/// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
- public static Transform FlipX { get { return _flipX; } }
+ /// <value>Equivalent to <c>new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)</c>.</value>
+ public static Transform3D FlipX { get { return _flipX; } }
/// <summary>
/// The transform that will flip something along the Y axis.
/// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)`.</value>
- public static Transform FlipY { get { return _flipY; } }
+ /// <value>Equivalent to <c>new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)</c>.</value>
+ public static Transform3D FlipY { get { return _flipY; } }
/// <summary>
/// The transform that will flip something along the Z axis.
/// </summary>
- /// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)`.</value>
- public static Transform FlipZ { get { return _flipZ; } }
+ /// <value>Equivalent to <c>new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)</c>.</value>
+ public static Transform3D FlipZ { get { return _flipZ; } }
/// <summary>
/// Constructs a transformation matrix from 4 vectors (matrix columns).
@@ -315,98 +322,114 @@ namespace Godot
/// <param name="column1">The Y vector, or column index 1.</param>
/// <param name="column2">The Z vector, or column index 2.</param>
/// <param name="origin">The origin vector, or column index 3.</param>
- public Transform(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
+ public Transform3D(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
{
basis = new Basis(column0, column1, column2);
this.origin = origin;
}
/// <summary>
- /// Constructs a transformation matrix from the given quaternion and origin vector.
+ /// Constructs a transformation matrix from the given <paramref name="quaternion"/>
+ /// and <paramref name="origin"/> vector.
/// </summary>
- /// <param name="quat">The <see cref="Godot.Quat"/> to create the basis from.</param>
+ /// <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 Transform(Quat quat, Vector3 origin)
+ public Transform3D(Quaternion quaternion, Vector3 origin)
{
- basis = new Basis(quat);
+ basis = new Basis(quaternion);
this.origin = origin;
}
/// <summary>
- /// Constructs a transformation matrix from the given basis and origin vector.
+ /// Constructs a transformation matrix from the given <paramref name="basis"/> and
+ /// <paramref name="origin"/> vector.
/// </summary>
- /// <param name="basis">The <see cref="Godot.Basis"/> to create the basis from.</param>
+ /// <param name="basis">The <see cref="Basis"/> to create the basis from.</param>
/// <param name="origin">The origin vector, or column index 3.</param>
- public Transform(Basis basis, Vector3 origin)
+ public Transform3D(Basis basis, Vector3 origin)
{
this.basis = basis;
this.origin = origin;
}
- public static Transform operator *(Transform left, Transform right)
+ public static Transform3D operator *(Transform3D left, Transform3D right)
{
left.origin = left.Xform(right.origin);
left.basis *= right.basis;
return left;
}
- public static bool operator ==(Transform left, Transform right)
+ public static bool operator ==(Transform3D left, Transform3D right)
{
return left.Equals(right);
}
- public static bool operator !=(Transform left, Transform right)
+ public static bool operator !=(Transform3D left, Transform3D right)
{
return !left.Equals(right);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this transform and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the transform and the other object are equal.</returns>
public override bool Equals(object obj)
{
- if (obj is Transform)
+ if (obj is Transform3D)
{
- return Equals((Transform)obj);
+ return Equals((Transform3D)obj);
}
return false;
}
- public bool Equals(Transform other)
+ /// <summary>
+ /// Returns <see langword="true"/> if this transform and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other transform to compare.</param>
+ /// <returns>Whether or not the matrices are equal.</returns>
+ public bool Equals(Transform3D other)
{
return basis.Equals(other.basis) && origin.Equals(other.origin);
}
/// <summary>
- /// Returns true if this transform and `other` are approximately equal, by running
- /// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
+ /// Returns <see langword="true"/> if this transform and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform other)
+ public bool IsEqualApprox(Transform3D other)
{
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()
{
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()
{
- return String.Format("{0} - {1}", new object[]
- {
- basis.ToString(),
- origin.ToString()
- });
+ 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)
{
- return String.Format("{0} - {1}", new object[]
- {
- basis.ToString(format),
- 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/Core/UnhandledExceptionArgs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs
new file mode 100644
index 0000000000..eae8927ceb
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Godot
+{
+ /// <summary>
+ /// Event arguments for when unhandled exceptions occur.
+ /// </summary>
+ public class UnhandledExceptionArgs
+ {
+ /// <summary>
+ /// Exception object.
+ /// </summary>
+ public Exception Exception { get; private set; }
+
+ internal UnhandledExceptionArgs(Exception exception)
+ {
+ Exception = exception;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 6279ea1ace..fe70d71cce 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -1,16 +1,10 @@
-// file: core/math/math_2d.h
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/math/math_2d.cpp
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/variant_call.cpp
-// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -27,23 +21,36 @@ namespace Godot
/// </summary>
public enum Axis
{
+ /// <summary>
+ /// The vector's X axis.
+ /// </summary>
X = 0,
+ /// <summary>
+ /// The vector's Y axis.
+ /// </summary>
Y
}
/// <summary>
- /// The vector's X component. Also accessible by using the index position `[0]`.
+ /// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
public real_t x;
+
/// <summary>
- /// The vector's Y component. Also accessible by using the index position `[1]`.
+ /// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
public real_t y;
/// <summary>
/// Access vector components using their index.
/// </summary>
- /// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`.</value>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the given the <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"/>.
+ /// </value>
public real_t this[int index]
{
get
@@ -103,7 +110,7 @@ namespace Godot
/// 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 `y` and `x` as parameters: `Mathf.Atan2(v.y, v.x)`.
+ /// 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()
@@ -132,9 +139,9 @@ namespace Godot
}
/// <summary>
- /// Returns the aspect ratio of this vector, the ratio of `x` to `y`.
+ /// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
- /// <returns>The `x` component divided by the `y` component.</returns>
+ /// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
public real_t Aspect()
{
return x / y;
@@ -160,40 +167,39 @@ namespace Godot
}
/// <summary>
- /// Returns the vector with a maximum length by limiting its length to `length`.
+ /// Returns a new vector with all components clamped between the
+ /// components of <paramref name="min"/> and <paramref name="max"/> using
+ /// <see cref="Mathf.Clamp(real_t, real_t, real_t)"/>.
/// </summary>
- /// <param name="length">The length to limit to.</param>
- /// <returns>The vector with its length limited.</returns>
- public Vector2 Clamped(real_t length)
+ /// <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)
{
- var v = this;
- real_t l = Length();
-
- if (l > 0 && length < l)
- {
- v /= l;
- v *= length;
- }
-
- return v;
+ return new Vector2
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y)
+ );
}
/// <summary>
- /// Returns the cross product of this vector and `b`.
+ /// Returns the cross product of this vector and <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector.</param>
/// <returns>The cross product value.</returns>
public real_t Cross(Vector2 b)
{
- return x * b.y - y * b.x;
+ return (x * b.y) - (y * b.x);
}
/// <summary>
- /// Performs a cubic interpolation between vectors `preA`, this vector, `b`, and `postB`, by the given amount `t`.
+ /// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector,
+ /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
/// </summary>
/// <param name="b">The destination vector.</param>
/// <param name="preA">A vector before this vector.</param>
- /// <param name="postB">A vector after `b`.</param>
+ /// <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)
@@ -207,24 +213,26 @@ namespace Godot
real_t t2 = t * t;
real_t t3 = t2 * t;
- return 0.5f * (p1 * 2.0f +
- (-p0 + p2) * t +
- (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 +
- (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
+ return 0.5f * (
+ (p1 * 2.0f) +
+ ((-p0 + p2) * t) +
+ (((2.0f * p0) - (5.0f * p1) + (4 * p2) - p3) * t2) +
+ ((-p0 + (3.0f * p1) - (3.0f * p2) + p3) * t3)
+ );
}
/// <summary>
- /// Returns the normalized vector pointing from this vector to `b`.
+ /// Returns the normalized vector pointing from this vector to <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector to point towards.</param>
- /// <returns>The direction from this vector to `b`.</returns>
+ /// <returns>The direction from this vector to <paramref name="b"/>.</returns>
public Vector2 DirectionTo(Vector2 b)
{
return new Vector2(b.x - x, b.y - y).Normalized();
}
/// <summary>
- /// Returns the squared distance between this vector and `to`.
+ /// 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>
@@ -236,7 +244,7 @@ namespace Godot
}
/// <summary>
- /// Returns the distance between this vector and `to`.
+ /// 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>
@@ -246,13 +254,13 @@ namespace Godot
}
/// <summary>
- /// Returns the dot product of this vector and `with`.
+ /// 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 real_t Dot(Vector2 with)
{
- return x * with.x + y * with.y;
+ return (x * with.x) + (y * with.y);
}
/// <summary>
@@ -265,7 +273,7 @@ namespace Godot
}
/// <summary>
- /// Returns the inverse of this vector. This is the same as `new Vector2(1 / v.x, 1 / v.y)`.
+ /// 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()
@@ -274,9 +282,9 @@ namespace Godot
}
/// <summary>
- /// Returns true if the vector is normalized, and false otherwise.
+ /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
- /// <returns>A bool indicating whether or not the vector is normalized.</returns>
+ /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
public bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
@@ -285,10 +293,11 @@ namespace Godot
/// <summary>
/// Returns the length (magnitude) of this vector.
/// </summary>
+ /// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
public real_t Length()
{
- return Mathf.Sqrt(x * x + y * y);
+ return Mathf.Sqrt((x * x) + (y * y));
}
/// <summary>
@@ -299,12 +308,12 @@ namespace Godot
/// <returns>The squared length of this vector.</returns>
public real_t LengthSquared()
{
- return x * x + y * y;
+ return (x * x) + (y * y);
}
/// <summary>
/// Returns the result of the linear interpolation between
- /// this vector and `to` by amount `weight`.
+ /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
/// </summary>
/// <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>
@@ -320,10 +329,12 @@ namespace Godot
/// <summary>
/// Returns the result of the linear interpolation between
- /// this vector and `to` by the vector amount `weight`.
+ /// 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>
+ /// <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)
{
@@ -335,6 +346,25 @@ namespace Godot
}
/// <summary>
+ /// Returns the vector with a maximum length by limiting its length to <paramref name="length"/>.
+ /// </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)
+ {
+ Vector2 v = this;
+ real_t l = Length();
+
+ if (l > 0 && length < l)
+ {
+ v /= l;
+ v *= length;
+ }
+
+ return v;
+ }
+
+ /// <summary>
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
@@ -355,35 +385,41 @@ namespace Godot
}
/// <summary>
- /// Moves this vector toward `to` by the fixed `delta` amount.
+ /// Moves this vector toward <paramref name="to"/> by the fixed <paramref name="delta"/> amount.
/// </summary>
/// <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)
{
- var v = this;
- var vd = to - v;
- var len = vd.Length();
- return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
+ Vector2 v = this;
+ Vector2 vd = to - v;
+ real_t len = vd.Length();
+ if (len <= delta || len < Mathf.Epsilon)
+ return to;
+
+ return v + (vd / len * delta);
}
/// <summary>
- /// Returns the vector scaled to unit length. Equivalent to `v / v.Length()`.
+ /// 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()
{
- var v = this;
+ Vector2 v = this;
v.Normalize();
return v;
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `mod`.
+ /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> 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(real_t, real_t)"/> by `mod`.</returns>
+ /// <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)
{
Vector2 v;
@@ -393,10 +429,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `modv`'s components.
+ /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> 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(real_t, real_t)"/> by `modv`'s components.</returns>
+ /// <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)
{
Vector2 v;
@@ -406,7 +445,7 @@ namespace Godot
}
/// <summary>
- /// Returns this vector projected onto another vector `b`.
+ /// Returns this vector projected onto another vector <paramref name="onNormal"/>.
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
@@ -416,7 +455,7 @@ namespace Godot
}
/// <summary>
- /// Returns this vector reflected from a plane defined by the given `normal`.
+ /// Returns this vector reflected from a plane defined by the given <paramref name="normal"/>.
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
@@ -425,14 +464,14 @@ namespace Godot
#if DEBUG
if (!normal.IsNormalized())
{
- throw new ArgumentException("Argument is not normalized", nameof(normal));
+ throw new ArgumentException("Argument is not normalized", nameof(normal));
}
#endif
- return 2 * Dot(normal) * normal - this;
+ return (2 * Dot(normal) * normal) - this;
}
/// <summary>
- /// Rotates this vector by `phi` radians.
+ /// Rotates this vector by <paramref name="phi"/> radians.
/// </summary>
/// <param name="phi">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
@@ -460,7 +499,7 @@ namespace Godot
/// on the signs of this vector's components, or zero if the component is zero,
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
- /// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
+ /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
public Vector2 Sign()
{
Vector2 v;
@@ -471,7 +510,7 @@ namespace Godot
/// <summary>
/// Returns the result of the spherical linear interpolation between
- /// this vector and `to` by amount `weight`.
+ /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
///
/// Note: Both vectors must be normalized.
/// </summary>
@@ -487,24 +526,24 @@ namespace Godot
}
if (!to.IsNormalized())
{
- throw new InvalidOperationException("Vector2.Slerp: `to` is not normalized.");
+ throw new InvalidOperationException($"Vector2.Slerp: `{nameof(to)}` is not normalized.");
}
#endif
return Rotated(AngleTo(to) * weight);
}
/// <summary>
- /// Returns this vector slid along a plane defined by the given normal.
+ /// Returns this vector slid along a plane defined by the given <paramref name="normal"/>.
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
public Vector2 Slide(Vector2 normal)
{
- return this - normal * Dot(normal);
+ return this - (normal * Dot(normal));
}
/// <summary>
- /// Returns this vector with each component snapped to the nearest multiple of `step`.
+ /// Returns this vector with each component snapped to the nearest multiple of <paramref name="step"/>.
/// This can also be used to round to an arbitrary number of decimals.
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
@@ -519,7 +558,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Perpendicular()
+ public Vector2 Orthogonal()
{
return new Vector2(y, -x);
}
@@ -535,40 +574,40 @@ namespace Godot
private static readonly Vector2 _left = new Vector2(-1, 0);
/// <summary>
- /// Zero vector, a vector with all components set to `0`.
+ /// Zero vector, a vector with all components set to <c>0</c>.
/// </summary>
- /// <value>Equivalent to `new Vector2(0, 0)`</value>
+ /// <value>Equivalent to <c>new Vector2(0, 0)</c>.</value>
public static Vector2 Zero { get { return _zero; } }
/// <summary>
- /// One vector, a vector with all components set to `1`.
+ /// One vector, a vector with all components set to <c>1</c>.
/// </summary>
- /// <value>Equivalent to `new Vector2(1, 1)`</value>
+ /// <value>Equivalent to <c>new Vector2(1, 1)</c>.</value>
public static Vector2 One { get { return _one; } }
/// <summary>
- /// Infinity vector, a vector with all components set to `Mathf.Inf`.
+ /// Infinity vector, a vector with all components set to <see cref="Mathf.Inf"/>.
/// </summary>
- /// <value>Equivalent to `new Vector2(Mathf.Inf, Mathf.Inf)`</value>
+ /// <value>Equivalent to <c>new Vector2(Mathf.Inf, Mathf.Inf)</c>.</value>
public static Vector2 Inf { get { return _inf; } }
/// <summary>
/// Up unit vector. Y is down in 2D, so this vector points -Y.
/// </summary>
- /// <value>Equivalent to `new Vector2(0, -1)`</value>
+ /// <value>Equivalent to <c>new Vector2(0, -1)</c>.</value>
public static Vector2 Up { get { return _up; } }
/// <summary>
/// Down unit vector. Y is down in 2D, so this vector points +Y.
/// </summary>
- /// <value>Equivalent to `new Vector2(0, 1)`</value>
+ /// <value>Equivalent to <c>new Vector2(0, 1)</c>.</value>
public static Vector2 Down { get { return _down; } }
/// <summary>
/// Right unit vector. Represents the direction of right.
/// </summary>
- /// <value>Equivalent to `new Vector2(1, 0)`</value>
+ /// <value>Equivalent to <c>new Vector2(1, 0)</c>.</value>
public static Vector2 Right { get { return _right; } }
/// <summary>
/// Left unit vector. Represents the direction of left.
/// </summary>
- /// <value>Equivalent to `new Vector2(-1, 0)`</value>
+ /// <value>Equivalent to <c>new Vector2(-1, 0)</c>.</value>
public static Vector2 Left { get { return _left; } }
/// <summary>
@@ -592,6 +631,17 @@ namespace Godot
y = v.y;
}
+ /// <summary>
+ /// Creates a unit Vector2 rotated to the given angle. This is equivalent to doing
+ /// <c>Vector2(Mathf.Cos(angle), Mathf.Sin(angle))</c> or <c>Vector2.Right.Rotated(angle)</c>.
+ /// </summary>
+ /// <param name="angle">Angle of the vector, in radians.</param>
+ /// <returns>The resulting vector.</returns>
+ public static Vector2 FromAngle(real_t angle)
+ {
+ return new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
+ }
+
public static Vector2 operator +(Vector2 left, Vector2 right)
{
left.x += right.x;
@@ -708,6 +758,11 @@ namespace Godot
return left.x >= right.x;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the vector and the other object are equal.</returns>
public override bool Equals(object obj)
{
if (obj is Vector2)
@@ -717,14 +772,19 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other vector to compare.</param>
+ /// <returns>Whether or not the vectors are equal.</returns>
public bool Equals(Vector2 other)
{
return x == other.x && y == other.y;
}
/// <summary>
- /// Returns true if this vector and `other` are approximately equal, by running
- /// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
+ /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
@@ -733,27 +793,31 @@ namespace Godot
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Vector2"/>.
+ /// </summary>
+ /// <returns>A hash code for this vector.</returns>
public override int 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()
{
- return String.Format("({0}, {1})", new object[]
- {
- x.ToString(),
- y.ToString()
- });
+ 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)
{
- return String.Format("({0}, {1})", new object[]
- {
- 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 8dd9ab2f0d..ca4531d885 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -1,11 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
-
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -22,23 +21,36 @@ namespace Godot
/// </summary>
public enum Axis
{
+ /// <summary>
+ /// The vector's X axis.
+ /// </summary>
X = 0,
+ /// <summary>
+ /// The vector's Y axis.
+ /// </summary>
Y
}
/// <summary>
- /// The vector's X component. Also accessible by using the index position `[0]`.
+ /// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
public int x;
+
/// <summary>
- /// The vector's Y component. Also accessible by using the index position `[1]`.
+ /// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
public int y;
/// <summary>
/// Access vector components using their index.
/// </summary>
- /// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`.</value>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the given the <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"/>.
+ /// </value>
public int this[int index]
{
get
@@ -82,7 +94,7 @@ namespace Godot
/// 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 `y` and `x` as parameters: `Mathf.Atan2(v.y, v.x)`.
+ /// 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()
@@ -111,16 +123,33 @@ namespace Godot
}
/// <summary>
- /// Returns the aspect ratio of this vector, the ratio of `x` to `y`.
+ /// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
- /// <returns>The `x` component divided by the `y` component.</returns>
+ /// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
public real_t Aspect()
{
return x / (real_t)y;
}
/// <summary>
- /// Returns the cross product of this vector and `b`.
+ /// Returns a new vector with all components clamped between the
+ /// components of <paramref name="min"/> and <paramref name="max"/> using
+ /// <see cref="Mathf.Clamp(int, int, int)"/>.
+ /// </summary>
+ /// <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)
+ {
+ return new Vector2i
+ (
+ 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="b"/>.
/// </summary>
/// <param name="b">The other vector.</param>
/// <returns>The cross product vector.</returns>
@@ -130,7 +159,7 @@ namespace Godot
}
/// <summary>
- /// Returns the squared distance between this vector and `b`.
+ /// Returns the squared distance between this vector and <paramref name="b"/>.
/// 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>
@@ -142,7 +171,7 @@ namespace Godot
}
/// <summary>
- /// Returns the distance between this vector and `b`.
+ /// Returns the distance between this vector and <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
@@ -152,7 +181,7 @@ namespace Godot
}
/// <summary>
- /// Returns the dot product of this vector and `b`.
+ /// Returns the dot product of this vector and <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
@@ -164,6 +193,7 @@ namespace Godot
/// <summary>
/// Returns the length (magnitude) of this vector.
/// </summary>
+ /// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
public real_t Length()
{
@@ -208,10 +238,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `mod`.
+ /// 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 `mod`.</returns>
+ /// <returns>
+ /// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
+ /// </returns>
public Vector2i PosMod(int mod)
{
Vector2i v = this;
@@ -221,10 +254,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `modv`'s components.
+ /// 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 `modv`'s components.</returns>
+ /// <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;
@@ -238,7 +274,7 @@ namespace Godot
/// on the signs of this vector's components, or zero if the component is zero,
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
- /// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
+ /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
public Vector2i Sign()
{
Vector2i v = this;
@@ -248,13 +284,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector rotated 90 degrees counter-clockwise
+ /// Returns a perpendicular vector rotated 90 degrees counter-clockwise
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Perpendicular()
+ public Vector2i Orthogonal()
{
- return new Vector2(y, -x);
+ return new Vector2i(y, -x);
}
// Constants
@@ -267,35 +303,35 @@ namespace Godot
private static readonly Vector2i _left = new Vector2i(-1, 0);
/// <summary>
- /// Zero vector, a vector with all components set to `0`.
+ /// Zero vector, a vector with all components set to <c>0</c>.
/// </summary>
- /// <value>Equivalent to `new Vector2i(0, 0)`</value>
+ /// <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 `1`.
+ /// One vector, a vector with all components set to <c>1</c>.
/// </summary>
- /// <value>Equivalent to `new Vector2i(1, 1)`</value>
+ /// <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 `new Vector2i(0, -1)`</value>
+ /// <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 `new Vector2i(0, 1)`</value>
+ /// <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 `new Vector2i(1, 0)`</value>
+ /// <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 `new Vector2i(-1, 0)`</value>
+ /// <value>Equivalent to <c>new Vector2i(-1, 0)</c>.</value>
public static Vector2i Left { get { return _left; } }
/// <summary>
@@ -460,16 +496,29 @@ namespace Godot
return left.x >= right.x;
}
+ /// <summary>
+ /// 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)
{
return new Vector2(value.x, value.y);
}
+ /// <summary>
+ /// 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)
{
return new Vector2i(value);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the vector and the other object are equal.</returns>
public override bool Equals(object obj)
{
if (obj is Vector2i)
@@ -480,32 +529,41 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal.
+ /// </summary>
+ /// <param name="other">The other vector to compare.</param>
+ /// <returns>Whether or not the vectors are equal.</returns>
public bool Equals(Vector2i other)
{
return x == other.x && y == other.y;
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Vector2i"/>.
+ /// </summary>
+ /// <returns>A hash code for this vector.</returns>
public override int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
}
+ /// <summary>
+ /// Converts this <see cref="Vector2i"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this vector.</returns>
public override string ToString()
{
- return String.Format("({0}, {1})", new object[]
- {
- this.x.ToString(),
- this.y.ToString()
- });
+ return $"({x}, {y})";
}
+ /// <summary>
+ /// 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)
{
- return String.Format("({0}, {1})", new object[]
- {
- this.x.ToString(format),
- this.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 3b895bbbf6..01e3a71bcb 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -1,16 +1,10 @@
-// file: core/math/vector3.h
-// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
-// file: core/math/vector3.cpp
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/variant_call.cpp
-// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -27,28 +21,46 @@ namespace Godot
/// </summary>
public enum Axis
{
+ /// <summary>
+ /// The vector's X axis.
+ /// </summary>
X = 0,
+ /// <summary>
+ /// The vector's Y axis.
+ /// </summary>
Y,
+ /// <summary>
+ /// The vector's Z axis.
+ /// </summary>
Z
}
/// <summary>
- /// The vector's X component. Also accessible by using the index position `[0]`.
+ /// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
public real_t x;
+
/// <summary>
- /// The vector's Y component. Also accessible by using the index position `[1]`.
+ /// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
public real_t y;
+
/// <summary>
- /// The vector's Z component. Also accessible by using the index position `[2]`.
+ /// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
/// </summary>
public real_t z;
/// <summary>
/// Access vector components using their index.
/// </summary>
- /// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`.</value>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the given the <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"/>.
+ /// </value>
public real_t this[int index]
{
get
@@ -140,7 +152,25 @@ namespace Godot
}
/// <summary>
- /// Returns the cross product of this vector and `b`.
+ /// Returns a new vector with all components clamped between the
+ /// components of <paramref name="min"/> and <paramref name="max"/> using
+ /// <see cref="Mathf.Clamp(real_t, real_t, real_t)"/>.
+ /// </summary>
+ /// <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)
+ {
+ return new Vector3
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y),
+ Mathf.Clamp(z, min.z, max.z)
+ );
+ }
+
+ /// <summary>
+ /// Returns the cross product of this vector and <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector.</param>
/// <returns>The cross product vector.</returns>
@@ -148,19 +178,19 @@ namespace Godot
{
return new Vector3
(
- y * b.z - z * b.y,
- z * b.x - x * b.z,
- x * b.y - y * b.x
+ (y * b.z) - (z * b.y),
+ (z * b.x) - (x * b.z),
+ (x * b.y) - (y * b.x)
);
}
/// <summary>
- /// Performs a cubic interpolation between vectors `preA`, this vector,
- /// `b`, and `postB`, by the given amount `t`.
+ /// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector,
+ /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
/// </summary>
/// <param name="b">The destination vector.</param>
/// <param name="preA">A vector before this vector.</param>
- /// <param name="postB">A vector after `b`.</param>
+ /// <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)
@@ -175,24 +205,24 @@ namespace Godot
real_t t3 = t2 * t;
return 0.5f * (
- p1 * 2.0f + (-p0 + p2) * t +
- (2.0f * p0 - 5.0f * p1 + 4f * p2 - p3) * t2 +
- (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3
- );
+ (p1 * 2.0f) + ((-p0 + p2) * t) +
+ (((2.0f * p0) - (5.0f * p1) + (4f * p2) - p3) * t2) +
+ ((-p0 + (3.0f * p1) - (3.0f * p2) + p3) * t3)
+ );
}
/// <summary>
- /// Returns the normalized vector pointing from this vector to `b`.
+ /// Returns the normalized vector pointing from this vector to <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector to point towards.</param>
- /// <returns>The direction from this vector to `b`.</returns>
+ /// <returns>The direction from this vector to <paramref name="b"/>.</returns>
public Vector3 DirectionTo(Vector3 b)
{
return new Vector3(b.x - x, b.y - y, b.z - z).Normalized();
}
/// <summary>
- /// Returns the squared distance between this vector and `b`.
+ /// Returns the squared distance between this vector and <paramref name="b"/>.
/// 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>
@@ -204,8 +234,9 @@ namespace Godot
}
/// <summary>
- /// Returns the distance between this vector and `b`.
+ /// Returns the distance between this vector and <paramref name="b"/>.
/// </summary>
+ /// <seealso cref="DistanceSquaredTo(Vector3)"/>
/// <param name="b">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
public real_t DistanceTo(Vector3 b)
@@ -214,13 +245,13 @@ namespace Godot
}
/// <summary>
- /// Returns the dot product of this vector and `b`.
+ /// Returns the dot product of this vector and <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
public real_t Dot(Vector3 b)
{
- return x * b.x + y * b.y + z * b.z;
+ return (x * b.x) + (y * b.y) + (z * b.z);
}
/// <summary>
@@ -233,7 +264,7 @@ namespace Godot
}
/// <summary>
- /// Returns the inverse of this vector. This is the same as `new Vector3(1 / v.x, 1 / v.y, 1 / v.z)`.
+ /// 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()
@@ -242,9 +273,9 @@ namespace Godot
}
/// <summary>
- /// Returns true if the vector is normalized, and false otherwise.
+ /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
- /// <returns>A bool indicating whether or not the vector is normalized.</returns>
+ /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
public bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
@@ -253,6 +284,7 @@ namespace Godot
/// <summary>
/// Returns the length (magnitude) of this vector.
/// </summary>
+ /// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
public real_t Length()
{
@@ -280,7 +312,7 @@ namespace Godot
/// <summary>
/// Returns the result of the linear interpolation between
- /// this vector and `to` by amount `weight`.
+ /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
/// </summary>
/// <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>
@@ -297,7 +329,7 @@ namespace Godot
/// <summary>
/// Returns the result of the linear interpolation between
- /// this vector and `to` by the vector amount `weight`.
+ /// 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>
@@ -313,6 +345,25 @@ namespace Godot
}
/// <summary>
+ /// Returns the vector with a maximum length by limiting its length to <paramref name="length"/>.
+ /// </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)
+ {
+ Vector3 v = this;
+ real_t l = Length();
+
+ if (l > 0 && length < l)
+ {
+ v /= l;
+ v *= length;
+ }
+
+ return v;
+ }
+
+ /// <summary>
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
@@ -333,32 +384,35 @@ namespace Godot
}
/// <summary>
- /// Moves this vector toward `to` by the fixed `delta` amount.
+ /// Moves this vector toward <paramref name="to"/> by the fixed <paramref name="delta"/> amount.
/// </summary>
/// <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)
{
- var v = this;
- var vd = to - v;
- var len = vd.Length();
- return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
+ Vector3 v = this;
+ Vector3 vd = to - v;
+ real_t len = vd.Length();
+ if (len <= delta || len < Mathf.Epsilon)
+ return to;
+
+ return v + (vd / len * delta);
}
/// <summary>
- /// Returns the vector scaled to unit length. Equivalent to `v / v.Length()`.
+ /// 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()
{
- var v = this;
+ Vector3 v = this;
v.Normalize();
return v;
}
/// <summary>
- /// Returns the outer product with `b`.
+ /// Returns the outer product with <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector.</param>
/// <returns>A <see cref="Basis"/> representing the outer product matrix.</returns>
@@ -372,10 +426,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `mod`.
+ /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> 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(real_t, real_t)"/> by `mod`.</returns>
+ /// <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)
{
Vector3 v;
@@ -386,10 +443,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `modv`'s components.
+ /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> 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(real_t, real_t)"/> by `modv`'s components.</returns>
+ /// <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)
{
Vector3 v;
@@ -400,7 +460,7 @@ namespace Godot
}
/// <summary>
- /// Returns this vector projected onto another vector `b`.
+ /// Returns this vector projected onto another vector <paramref name="onNormal"/>.
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
@@ -410,7 +470,7 @@ namespace Godot
}
/// <summary>
- /// Returns this vector reflected from a plane defined by the given `normal`.
+ /// Returns this vector reflected from a plane defined by the given <paramref name="normal"/>.
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
@@ -419,15 +479,15 @@ namespace Godot
#if DEBUG
if (!normal.IsNormalized())
{
- throw new ArgumentException("Argument is not normalized", nameof(normal));
+ throw new ArgumentException("Argument is not normalized", nameof(normal));
}
#endif
- return 2.0f * Dot(normal) * normal - this;
+ return (2.0f * Dot(normal) * normal) - this;
}
/// <summary>
- /// Rotates this vector around a given `axis` vector by `phi` radians.
- /// The `axis` vector must be a normalized vector.
+ /// Rotates this vector around a given <paramref name="axis"/> vector by <paramref name="phi"/> radians.
+ /// The <paramref name="axis"/> vector must be a normalized vector.
/// </summary>
/// <param name="axis">The vector to rotate around. Must be normalized.</param>
/// <param name="phi">The angle to rotate by, in radians.</param>
@@ -437,7 +497,7 @@ namespace Godot
#if DEBUG
if (!axis.IsNormalized())
{
- throw new ArgumentException("Argument is not normalized", nameof(axis));
+ throw new ArgumentException("Argument is not normalized", nameof(axis));
}
#endif
return new Basis(axis, phi).Xform(this);
@@ -458,7 +518,7 @@ namespace Godot
/// on the signs of this vector's components, or zero if the component is zero,
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
- /// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
+ /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
public Vector3 Sign()
{
Vector3 v;
@@ -472,7 +532,7 @@ namespace Godot
/// Returns the signed angle to the given vector, in radians.
/// The sign of the angle is positive in a counter-clockwise
/// direction and negative in a clockwise direction when viewed
- /// from the side specified by the `axis`.
+ /// from the side specified by the <paramref name="axis"/>.
/// </summary>
/// <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>
@@ -487,7 +547,7 @@ namespace Godot
/// <summary>
/// Returns the result of the spherical linear interpolation between
- /// this vector and `to` by amount `weight`.
+ /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
///
/// Note: Both vectors must be normalized.
/// </summary>
@@ -503,7 +563,7 @@ namespace Godot
}
if (!to.IsNormalized())
{
- throw new InvalidOperationException("Vector3.Slerp: `to` is not normalized.");
+ throw new InvalidOperationException($"Vector3.Slerp: `{nameof(to)}` is not normalized.");
}
#endif
real_t theta = AngleTo(to);
@@ -511,17 +571,17 @@ namespace Godot
}
/// <summary>
- /// Returns this vector slid along a plane defined by the given normal.
+ /// Returns this vector slid along a plane defined by the given <paramref name="normal"/>.
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
public Vector3 Slide(Vector3 normal)
{
- return this - normal * Dot(normal);
+ return this - (normal * Dot(normal));
}
/// <summary>
- /// Returns this vector with each component snapped to the nearest multiple of `step`.
+ /// Returns this vector with each component snapped to the nearest multiple of <paramref name="step"/>.
/// This can also be used to round to an arbitrary number of decimals.
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
@@ -539,10 +599,10 @@ namespace Godot
/// <summary>
/// Returns a diagonal matrix with the vector as main diagonal.
///
- /// This is equivalent to a Basis with no rotation or shearing and
+ /// This is equivalent to a <see cref="Basis"/> with no rotation or shearing and
/// this vector's components set as the scale.
/// </summary>
- /// <returns>A Basis with the vector as its main diagonal.</returns>
+ /// <returns>A <see cref="Basis"/> with the vector as its main diagonal.</returns>
public Basis ToDiagonalMatrix()
{
return new Basis(
@@ -565,54 +625,54 @@ namespace Godot
private static readonly Vector3 _back = new Vector3(0, 0, 1);
/// <summary>
- /// Zero vector, a vector with all components set to `0`.
+ /// Zero vector, a vector with all components set to <c>0</c>.
/// </summary>
- /// <value>Equivalent to `new Vector3(0, 0, 0)`</value>
+ /// <value>Equivalent to <c>new Vector3(0, 0, 0)</c>.</value>
public static Vector3 Zero { get { return _zero; } }
/// <summary>
- /// One vector, a vector with all components set to `1`.
+ /// One vector, a vector with all components set to <c>1</c>.
/// </summary>
- /// <value>Equivalent to `new Vector3(1, 1, 1)`</value>
+ /// <value>Equivalent to <c>new Vector3(1, 1, 1)</c>.</value>
public static Vector3 One { get { return _one; } }
/// <summary>
- /// Infinity vector, a vector with all components set to `Mathf.Inf`.
+ /// Infinity vector, a vector with all components set to <see cref="Mathf.Inf"/>.
/// </summary>
- /// <value>Equivalent to `new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf)`</value>
+ /// <value>Equivalent to <c>new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf)</c>.</value>
public static Vector3 Inf { get { return _inf; } }
/// <summary>
/// Up unit vector.
/// </summary>
- /// <value>Equivalent to `new Vector3(0, 1, 0)`</value>
+ /// <value>Equivalent to <c>new Vector3(0, 1, 0)</c>.</value>
public static Vector3 Up { get { return _up; } }
/// <summary>
/// Down unit vector.
/// </summary>
- /// <value>Equivalent to `new Vector3(0, -1, 0)`</value>
+ /// <value>Equivalent to <c>new Vector3(0, -1, 0)</c>.</value>
public static Vector3 Down { get { return _down; } }
/// <summary>
/// Right unit vector. Represents the local direction of right,
/// and the global direction of east.
/// </summary>
- /// <value>Equivalent to `new Vector3(1, 0, 0)`</value>
+ /// <value>Equivalent to <c>new Vector3(1, 0, 0)</c>.</value>
public static Vector3 Right { get { return _right; } }
/// <summary>
/// Left unit vector. Represents the local direction of left,
/// and the global direction of west.
/// </summary>
- /// <value>Equivalent to `new Vector3(-1, 0, 0)`</value>
+ /// <value>Equivalent to <c>new Vector3(-1, 0, 0)</c>.</value>
public static Vector3 Left { get { return _left; } }
/// <summary>
/// Forward unit vector. Represents the local direction of forward,
/// and the global direction of north.
/// </summary>
- /// <value>Equivalent to `new Vector3(0, 0, -1)`</value>
+ /// <value>Equivalent to <c>new Vector3(0, 0, -1)</c>.</value>
public static Vector3 Forward { get { return _forward; } }
/// <summary>
/// Back unit vector. Represents the local direction of back,
/// and the global direction of south.
/// </summary>
- /// <value>Equivalent to `new Vector3(0, 0, 1)`</value>
+ /// <value>Equivalent to <c>new Vector3(0, 0, 1)</c>.</value>
public static Vector3 Back { get { return _back; } }
/// <summary>
@@ -781,6 +841,11 @@ namespace Godot
return left.x > right.x;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the vector and the other object are equal.</returns>
public override bool Equals(object obj)
{
if (obj is Vector3)
@@ -791,14 +856,19 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal
+ /// </summary>
+ /// <param name="other">The other vector to compare.</param>
+ /// <returns>Whether or not the vectors are equal.</returns>
public bool Equals(Vector3 other)
{
return x == other.x && y == other.y && z == other.z;
}
/// <summary>
- /// Returns true if this vector and `other` are approximately equal, by running
- /// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
+ /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
@@ -807,29 +877,31 @@ namespace Godot
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Vector3"/>.
+ /// </summary>
+ /// <returns>A hash code for this vector.</returns>
public override int 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()
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- x.ToString(),
- y.ToString(),
- z.ToString()
- });
+ 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)
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- 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 bf25ba9cb3..2a7771cdfc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
@@ -1,11 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
-
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -22,28 +21,46 @@ namespace Godot
/// </summary>
public enum Axis
{
+ /// <summary>
+ /// The vector's X axis.
+ /// </summary>
X = 0,
+ /// <summary>
+ /// The vector's Y axis.
+ /// </summary>
Y,
+ /// <summary>
+ /// The vector's Z axis.
+ /// </summary>
Z
}
/// <summary>
- /// The vector's X component. Also accessible by using the index position `[0]`.
+ /// The vector's X component. Also accessible by using the index position <c>[0]</c>.
/// </summary>
public int x;
+
/// <summary>
- /// The vector's Y component. Also accessible by using the index position `[1]`.
+ /// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
/// </summary>
public int y;
+
/// <summary>
- /// The vector's Z component. Also accessible by using the index position `[2]`.
+ /// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
/// </summary>
public int z;
/// <summary>
- /// Access vector components using their index.
+ /// Access vector components using their <paramref name="index"/>.
/// </summary>
- /// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`.</value>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the given the <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"/>.
+ /// </value>
public int this[int index]
{
get
@@ -89,7 +106,25 @@ namespace Godot
}
/// <summary>
- /// Returns the squared distance between this vector and `b`.
+ /// Returns a new vector with all components clamped between the
+ /// components of <paramref name="min"/> and <paramref name="max"/> using
+ /// <see cref="Mathf.Clamp(int, int, int)"/>.
+ /// </summary>
+ /// <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)
+ {
+ return new Vector3i
+ (
+ 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="b"/>.
/// 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>
@@ -101,8 +136,9 @@ namespace Godot
}
/// <summary>
- /// Returns the distance between this vector and `b`.
+ /// Returns the distance between this vector and <paramref name="b"/>.
/// </summary>
+ /// <seealso cref="DistanceSquaredTo(Vector3i)"/>
/// <param name="b">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
public real_t DistanceTo(Vector3i b)
@@ -111,7 +147,7 @@ namespace Godot
}
/// <summary>
- /// Returns the dot product of this vector and `b`.
+ /// Returns the dot product of this vector and <paramref name="b"/>.
/// </summary>
/// <param name="b">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
@@ -123,6 +159,7 @@ namespace Godot
/// <summary>
/// Returns the length (magnitude) of this vector.
/// </summary>
+ /// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
public real_t Length()
{
@@ -169,10 +206,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `mod`.
+ /// 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 `mod`.</returns>
+ /// <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;
@@ -183,10 +223,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `modv`'s components.
+ /// 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 `modv`'s components.</returns>
+ /// <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;
@@ -201,7 +244,7 @@ namespace Godot
/// on the signs of this vector's components, or zero if the component is zero,
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
- /// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
+ /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
public Vector3i Sign()
{
Vector3i v = this;
@@ -223,49 +266,49 @@ namespace Godot
private static readonly Vector3i _back = new Vector3i(0, 0, 1);
/// <summary>
- /// Zero vector, a vector with all components set to `0`.
+ /// Zero vector, a vector with all components set to <c>0</c>.
/// </summary>
- /// <value>Equivalent to `new Vector3i(0, 0, 0)`</value>
+ /// <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 `1`.
+ /// One vector, a vector with all components set to <c>1</c>.
/// </summary>
- /// <value>Equivalent to `new Vector3i(1, 1, 1)`</value>
+ /// <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 `new Vector3i(0, 1, 0)`</value>
+ /// <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 `new Vector3i(0, -1, 0)`</value>
+ /// <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 `new Vector3i(1, 0, 0)`</value>
+ /// <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 `new Vector3i(-1, 0, 0)`</value>
+ /// <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 `new Vector3i(0, 0, -1)`</value>
+ /// <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 `new Vector3i(0, 0, 1)`</value>
+ /// <value>Equivalent to <c>new Vector3i(0, 0, 1)</c>.</value>
public static Vector3i Back { get { return _back; } }
/// <summary>
@@ -462,16 +505,29 @@ namespace Godot
return left.x > right.x;
}
+ /// <summary>
+ /// 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)
{
return new Vector3(value.x, value.y, value.z);
}
+ /// <summary>
+ /// 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)
{
return new Vector3i(value);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal.
+ /// </summary>
+ /// <param name="obj">The other object to compare.</param>
+ /// <returns>Whether or not the vector and the other object are equal.</returns>
public override bool Equals(object obj)
{
if (obj is Vector3i)
@@ -482,34 +538,41 @@ namespace Godot
return false;
}
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal
+ /// </summary>
+ /// <param name="other">The other vector to compare.</param>
+ /// <returns>Whether or not the vectors are equal.</returns>
public bool Equals(Vector3i other)
{
return x == other.x && y == other.y && z == other.z;
}
+ /// <summary>
+ /// Serves as the hash function for <see cref="Vector3i"/>.
+ /// </summary>
+ /// <returns>A hash code for this vector.</returns>
public override int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
+ /// <summary>
+ /// Converts this <see cref="Vector3i"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this vector.</returns>
public override string ToString()
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- this.x.ToString(),
- this.y.ToString(),
- this.z.ToString()
- });
+ return $"({x}, {y}, {z})";
}
+ /// <summary>
+ /// 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)
{
- return String.Format("({0}, {1}, {2})", new object[]
- {
- this.x.ToString(format),
- this.y.ToString(format),
- this.z.ToString(format)
- });
+ return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})";
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 7c1a23d510..1fcfe74c86 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -14,9 +14,12 @@
<ItemGroup>
<Compile Include="Core\AABB.cs" />
<Compile Include="Core\Array.cs" />
+ <Compile Include="Core\Attributes\AssemblyHasScriptsAttribute.cs" />
+ <Compile Include="Core\Attributes\DisableGodotGeneratorsAttribute.cs" />
<Compile Include="Core\Attributes\ExportAttribute.cs" />
<Compile Include="Core\Attributes\GodotMethodAttribute.cs" />
<Compile Include="Core\Attributes\RPCAttributes.cs" />
+ <Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
<Compile Include="Core\Attributes\SignalAttribute.cs" />
<Compile Include="Core\Attributes\ToolAttribute.cs" />
<Compile Include="Core\Basis.cs" />
@@ -37,6 +40,7 @@
<Compile Include="Core\GodotSynchronizationContext.cs" />
<Compile Include="Core\GodotTaskScheduler.cs" />
<Compile Include="Core\GodotTraceListener.cs" />
+ <Compile Include="Core\GodotUnhandledExceptionEvent.cs" />
<Compile Include="Core\Interfaces\IAwaitable.cs" />
<Compile Include="Core\Interfaces\IAwaiter.cs" />
<Compile Include="Core\Interfaces\ISerializationListener.cs" />
@@ -46,7 +50,7 @@
<Compile Include="Core\NodePath.cs" />
<Compile Include="Core\Object.base.cs" />
<Compile Include="Core\Plane.cs" />
- <Compile Include="Core\Quat.cs" />
+ <Compile Include="Core\Quaternion.cs" />
<Compile Include="Core\Rect2.cs" />
<Compile Include="Core\Rect2i.cs" />
<Compile Include="Core\RID.cs" />
@@ -54,8 +58,9 @@
<Compile Include="Core\SignalAwaiter.cs" />
<Compile Include="Core\StringExtensions.cs" />
<Compile Include="Core\StringName.cs" />
- <Compile Include="Core\Transform.cs" />
<Compile Include="Core\Transform2D.cs" />
+ <Compile Include="Core\Transform3D.cs" />
+ <Compile Include="Core\UnhandledExceptionArgs.cs" />
<Compile Include="Core\Vector2.cs" />
<Compile Include="Core\Vector2i.cs" />
<Compile Include="Core\Vector3.cs" />
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 34a96eba17..6c5503a3bd 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -31,7 +31,7 @@
#ifdef MONO_GLUE_ENABLED
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/string/string_name.h"
#include "../csharp_script.h"
@@ -65,7 +65,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
}
}
- void *data = p_ptr->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+ void *data = CSharpLanguage::get_existing_instance_binding(p_ptr);
if (data) {
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -78,17 +78,17 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
}
}
-void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
+void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
#ifdef DEBUG_ENABLED
CRASH_COND(p_ptr == nullptr);
- // This is only called with Reference derived classes
- CRASH_COND(!Object::cast_to<Reference>(p_ptr));
+ // This is only called with RefCounted derived classes
+ CRASH_COND(!Object::cast_to<RefCounted>(p_ptr));
#endif
- Reference *ref = static_cast<Reference *>(p_ptr);
+ RefCounted *rc = static_cast<RefCounted *>(p_ptr);
- if (ref->get_script_instance()) {
- CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(ref->get_script_instance());
+ if (rc->get_script_instance()) {
+ CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(rc->get_script_instance());
if (cs_instance) {
if (!cs_instance->is_destructing_script_instance()) {
bool delete_owner;
@@ -97,9 +97,9 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea
cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, delete_owner, remove_script_instance);
if (delete_owner) {
- memdelete(ref);
+ memdelete(rc);
} else if (remove_script_instance) {
- ref->set_script_instance(nullptr);
+ rc->set_script_instance(nullptr);
}
}
return;
@@ -108,11 +108,11 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea
// Unsafe refcount decrement. The managed instance also counts as a reference.
// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
- CSharpLanguage::get_singleton()->pre_unsafe_unreference(ref);
- if (ref->unreference()) {
- memdelete(ref);
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(rc);
+ if (rc->unreference()) {
+ memdelete(rc);
} else {
- void *data = ref->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+ void *data = CSharpLanguage::get_existing_instance_binding(rc);
if (data) {
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -145,18 +145,18 @@ MonoObject *godot_icall_Object_weakref(Object *p_ptr) {
}
Ref<WeakRef> wref;
- Reference *ref = Object::cast_to<Reference>(p_ptr);
+ RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
- if (ref) {
- REF r = ref;
+ if (rc) {
+ REF r = rc;
if (!r.is_valid()) {
return nullptr;
}
- wref.instance();
+ wref.instantiate();
wref->set_ref(r);
} else {
- wref.instance();
+ wref.instantiate();
wref->set_obj(p_ptr);
}
@@ -175,8 +175,8 @@ MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
MonoArray *result = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), property_list.size());
int i = 0;
- for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get().name);
+ for (const PropertyInfo &E : property_list) {
+ MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E.name);
mono_array_setref(result, i, boxed);
i++;
}
@@ -242,7 +242,7 @@ MonoString *godot_icall_Object_ToString(Object *p_ptr) {
void godot_register_object_icalls() {
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Ctor", godot_icall_Object_Ctor);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Disposed", godot_icall_Object_Disposed);
- GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Reference_Disposed", godot_icall_Reference_Disposed);
+ GDMonoUtils::add_internal_call("Godot.Object::godot_icall_RefCounted_Disposed", godot_icall_RefCounted_Disposed);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ConnectEventSignals", godot_icall_Object_ConnectEventSignals);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", godot_icall_Object_ClassDB_get_method);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ToString", godot_icall_Object_ToString);
diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp
index 191f863350..86976de244 100644
--- a/modules/mono/glue/collections_glue.cpp
+++ b/modules/mono/glue/collections_glue.cpp
@@ -230,6 +230,19 @@ int32_t godot_icall_Dictionary_Count(Dictionary *ptr) {
return ptr->size();
}
+int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array **keys, Array **values) {
+ *keys = godot_icall_Dictionary_Keys(ptr);
+ *values = godot_icall_Dictionary_Values(ptr);
+ return godot_icall_Dictionary_Count(ptr);
+}
+
+void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, MonoObject **key, MonoObject **value) {
+ Array *keys = godot_icall_Dictionary_Keys(ptr);
+ Array *values = godot_icall_Dictionary_Values(ptr);
+ *key = GDMonoMarshal::variant_to_mono_object(keys->get(index));
+ *value = GDMonoMarshal::variant_to_mono_object(values->get(index));
+}
+
void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
Variant *ret = ptr->getptr(varKey);
@@ -338,6 +351,8 @@ void godot_register_collections_icalls() {
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", godot_icall_Dictionary_Keys);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", godot_icall_Dictionary_Values);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count);
+ GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs);
+ GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains);
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
index 3db52d7c30..eed3bd2167 100644
--- a/modules/mono/glue/glue_header.h
+++ b/modules/mono/glue/glue_header.h
@@ -61,7 +61,7 @@ void godot_register_glue_header_icalls() {
#include "core/config/engine.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "core/string/node_path.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
diff --git a/modules/mono/glue/string_glue.cpp b/modules/mono/glue/string_glue.cpp
index 18a9221f89..bb80a836ad 100644
--- a/modules/mono/glue/string_glue.cpp
+++ b/modules/mono/glue/string_glue.cpp
@@ -67,6 +67,11 @@ MonoString *godot_icall_String_sha256_text(MonoString *p_str) {
return GDMonoMarshal::mono_string_from_godot(ret);
}
+MonoString *godot_icall_String_simplify_path(MonoString *p_str) {
+ String ret = GDMonoMarshal::mono_string_to_godot(p_str).simplify_path();
+ return GDMonoMarshal::mono_string_from_godot(ret);
+}
+
void godot_register_string_icalls() {
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_md5_buffer", godot_icall_String_md5_buffer);
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_md5_text", godot_icall_String_md5_text);
@@ -74,6 +79,7 @@ void godot_register_string_icalls() {
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_rfindn", godot_icall_String_rfindn);
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_sha256_buffer", godot_icall_String_sha256_buffer);
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_sha256_text", godot_icall_String_sha256_text);
+ GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_simplify_path", godot_icall_String_simplify_path);
}
#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index a39a6fe381..375ad413c4 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -31,7 +31,7 @@
#include "godotsharp_dirs.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/os.h"
#ifdef TOOLS_ENABLED
@@ -63,8 +63,8 @@ String _get_expected_build_config() {
String _get_mono_user_dir() {
#ifdef TOOLS_ENABLED
- if (EditorSettings::get_singleton()) {
- return EditorSettings::get_singleton()->get_data_dir().plus_file("mono");
+ if (EditorPaths::get_singleton()) {
+ return EditorPaths::get_singleton()->get_data_dir().plus_file("mono");
} else {
String settings_path;
@@ -179,16 +179,16 @@ private:
#ifdef OSX_ENABLED
if (!DirAccess::exists(data_editor_tools_dir)) {
- data_editor_tools_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Tools");
+ data_editor_tools_dir = exe_dir.plus_file("../Resources/GodotSharp/Tools");
}
if (!DirAccess::exists(data_editor_prebuilt_api_dir)) {
- data_editor_prebuilt_api_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Api");
+ data_editor_prebuilt_api_dir = exe_dir.plus_file("../Resources/GodotSharp/Api");
}
if (!DirAccess::exists(data_mono_root_dir)) {
data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc");
- data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib");
+ data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib");
}
#endif
@@ -218,11 +218,11 @@ private:
#ifdef OSX_ENABLED
if (!DirAccess::exists(data_mono_root_dir)) {
data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc");
- data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib");
+ data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib");
}
if (!DirAccess::exists(data_game_assemblies_dir)) {
- data_game_assemblies_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Assemblies");
+ data_game_assemblies_dir = exe_dir.plus_file("../Resources/GodotSharp/Assemblies");
}
#endif
diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h
index f435aab3dd..d0e51d159f 100644
--- a/modules/mono/mono_gc_handle.h
+++ b/modules/mono/mono_gc_handle.h
@@ -33,7 +33,7 @@
#include <mono/jit/jit.h>
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
namespace gdmono {
@@ -79,8 +79,8 @@ struct MonoGCHandleData {
static MonoGCHandleData new_weak_handle(MonoObject *p_object);
};
-class MonoGCHandleRef : public Reference {
- GDCLASS(MonoGCHandleRef, Reference);
+class MonoGCHandleRef : public RefCounted {
+ GDCLASS(MonoGCHandleRef, RefCounted);
MonoGCHandleData data;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 43a39a4966..1b1349a3a3 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -39,8 +39,8 @@
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#include "core/os/thread.h"
@@ -73,7 +73,7 @@
#endif
// TODO:
-// This has turn into a gigantic mess. There's too much going on here. Too much #ifdef as well.
+// This has turned into a gigantic mess. There's too much going on here. Too much #ifdef as well.
// It's just painful to read... It needs to be re-structured. Please, clean this up, future me.
GDMono *GDMono::singleton = nullptr;
@@ -100,8 +100,8 @@ void gd_mono_setup_runtime_main_args() {
main_args.write[0] = execpath.ptrw();
int i = 1;
- for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) {
- CharString &stored = cmdline_args_utf8.push_back(E->get().utf8())->get();
+ for (const String &E : cmdline_args) {
+ CharString &stored = cmdline_args_utf8.push_back(E.utf8())->get();
main_args.write[i] = stored.ptrw();
i++;
}
@@ -119,11 +119,11 @@ void gd_mono_profiler_init() {
const String env_var_name = "MONO_ENV_OPTIONS";
if (OS::get_singleton()->has_environment(env_var_name)) {
- const auto mono_env_ops = OS::get_singleton()->get_environment(env_var_name);
+ const String mono_env_ops = OS::get_singleton()->get_environment(env_var_name);
// Usually MONO_ENV_OPTIONS looks like: --profile=jb:prof=timeline,ctl=remote,host=127.0.0.1:55467
const String prefix = "--profile=";
if (mono_env_ops.begins_with(prefix)) {
- const auto ops = mono_env_ops.substr(prefix.length(), mono_env_ops.length());
+ const String ops = mono_env_ops.substr(prefix.length(), mono_env_ops.length());
mono_profiler_load(ops.utf8());
}
}
@@ -691,7 +691,7 @@ static bool try_get_cached_api_hash_for(const String &p_api_assemblies_dir, bool
}
Ref<ConfigFile> cfg;
- cfg.instance();
+ cfg.instantiate();
Error cfg_err = cfg->load(cached_api_hash_path);
ERR_FAIL_COND_V(cfg_err != OK, false);
@@ -717,7 +717,7 @@ static void create_cached_api_hash_for(const String &p_api_assemblies_dir) {
String cached_api_hash_path = p_api_assemblies_dir.plus_file("api_hash_cache.cfg");
Ref<ConfigFile> cfg;
- cfg.instance();
+ cfg.instantiate();
cfg->set_value("core", "modified_time", FileAccess::get_modified_time(core_api_assembly_path));
cfg->set_value("editor", "modified_time", FileAccess::get_modified_time(editor_api_assembly_path));
@@ -1006,6 +1006,7 @@ bool GDMono::_load_project_assembly() {
if (success) {
mono_assembly_set_main(project_assembly->get_assembly());
+ CSharpLanguage::get_singleton()->lookup_scripts_in_assembly(project_assembly);
}
return success;
@@ -1334,23 +1335,25 @@ GDMono::~GDMono() {
singleton = nullptr;
}
-_GodotSharp *_GodotSharp::singleton = nullptr;
+namespace mono_bind {
-void _GodotSharp::attach_thread() {
+GodotSharp *GodotSharp::singleton = nullptr;
+
+void GodotSharp::attach_thread() {
GDMonoUtils::attach_current_thread();
}
-void _GodotSharp::detach_thread() {
+void GodotSharp::detach_thread() {
GDMonoUtils::detach_current_thread();
}
-int32_t _GodotSharp::get_domain_id() {
+int32_t GodotSharp::get_domain_id() {
MonoDomain *domain = mono_domain_get();
ERR_FAIL_NULL_V(domain, -1);
return mono_domain_get_id(domain);
}
-int32_t _GodotSharp::get_scripts_domain_id() {
+int32_t GodotSharp::get_scripts_domain_id() {
ERR_FAIL_NULL_V_MSG(GDMono::get_singleton(),
-1, "The Mono runtime is not initialized");
MonoDomain *domain = GDMono::get_singleton()->get_scripts_domain();
@@ -1358,21 +1361,21 @@ int32_t _GodotSharp::get_scripts_domain_id() {
return mono_domain_get_id(domain);
}
-bool _GodotSharp::is_scripts_domain_loaded() {
+bool GodotSharp::is_scripts_domain_loaded() {
return GDMono::get_singleton() != nullptr &&
GDMono::get_singleton()->is_runtime_initialized() &&
GDMono::get_singleton()->get_scripts_domain() != nullptr;
}
-bool _GodotSharp::_is_domain_finalizing_for_unload(int32_t p_domain_id) {
+bool GodotSharp::_is_domain_finalizing_for_unload(int32_t p_domain_id) {
return is_domain_finalizing_for_unload(p_domain_id);
}
-bool _GodotSharp::is_domain_finalizing_for_unload(int32_t p_domain_id) {
+bool GodotSharp::is_domain_finalizing_for_unload(int32_t p_domain_id) {
return is_domain_finalizing_for_unload(mono_domain_get_by_id(p_domain_id));
}
-bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) {
+bool GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) {
GDMono *gd_mono = GDMono::get_singleton();
ERR_FAIL_COND_V_MSG(!gd_mono || !gd_mono->is_runtime_initialized(),
@@ -1387,15 +1390,15 @@ bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) {
return mono_domain_is_unloading(p_domain);
}
-bool _GodotSharp::is_runtime_shutting_down() {
+bool GodotSharp::is_runtime_shutting_down() {
return mono_runtime_is_shutting_down();
}
-bool _GodotSharp::is_runtime_initialized() {
+bool GodotSharp::is_runtime_initialized() {
return GDMono::get_singleton() != nullptr && GDMono::get_singleton()->is_runtime_initialized();
}
-void _GodotSharp::_reload_assemblies(bool p_soft_reload) {
+void GodotSharp::_reload_assemblies(bool p_soft_reload) {
#ifdef GD_MONO_HOT_RELOAD
CRASH_COND(CSharpLanguage::get_singleton() == nullptr);
// This method may be called more than once with `call_deferred`, so we need to check
@@ -1406,24 +1409,26 @@ void _GodotSharp::_reload_assemblies(bool p_soft_reload) {
#endif
}
-void _GodotSharp::_bind_methods() {
- ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread);
- ClassDB::bind_method(D_METHOD("detach_thread"), &_GodotSharp::detach_thread);
+void GodotSharp::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("attach_thread"), &GodotSharp::attach_thread);
+ ClassDB::bind_method(D_METHOD("detach_thread"), &GodotSharp::detach_thread);
- ClassDB::bind_method(D_METHOD("get_domain_id"), &_GodotSharp::get_domain_id);
- ClassDB::bind_method(D_METHOD("get_scripts_domain_id"), &_GodotSharp::get_scripts_domain_id);
- ClassDB::bind_method(D_METHOD("is_scripts_domain_loaded"), &_GodotSharp::is_scripts_domain_loaded);
- ClassDB::bind_method(D_METHOD("is_domain_finalizing_for_unload", "domain_id"), &_GodotSharp::_is_domain_finalizing_for_unload);
+ ClassDB::bind_method(D_METHOD("get_domain_id"), &GodotSharp::get_domain_id);
+ ClassDB::bind_method(D_METHOD("get_scripts_domain_id"), &GodotSharp::get_scripts_domain_id);
+ ClassDB::bind_method(D_METHOD("is_scripts_domain_loaded"), &GodotSharp::is_scripts_domain_loaded);
+ ClassDB::bind_method(D_METHOD("is_domain_finalizing_for_unload", "domain_id"), &GodotSharp::_is_domain_finalizing_for_unload);
- ClassDB::bind_method(D_METHOD("is_runtime_shutting_down"), &_GodotSharp::is_runtime_shutting_down);
- ClassDB::bind_method(D_METHOD("is_runtime_initialized"), &_GodotSharp::is_runtime_initialized);
- ClassDB::bind_method(D_METHOD("_reload_assemblies"), &_GodotSharp::_reload_assemblies);
+ ClassDB::bind_method(D_METHOD("is_runtime_shutting_down"), &GodotSharp::is_runtime_shutting_down);
+ ClassDB::bind_method(D_METHOD("is_runtime_initialized"), &GodotSharp::is_runtime_initialized);
+ ClassDB::bind_method(D_METHOD("_reload_assemblies"), &GodotSharp::_reload_assemblies);
}
-_GodotSharp::_GodotSharp() {
+GodotSharp::GodotSharp() {
singleton = this;
}
-_GodotSharp::~_GodotSharp() {
+GodotSharp::~GodotSharp() {
singleton = nullptr;
}
+
+} // namespace mono_bind
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index 5accc21f8e..4170e5053f 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -293,8 +293,10 @@ public:
gdmono::ScopeExitDomainUnload __gdmono__scope__exit__domain__unload__(m_mono_domain); \
(void)__gdmono__scope__exit__domain__unload__;
-class _GodotSharp : public Object {
- GDCLASS(_GodotSharp, Object);
+namespace mono_bind {
+
+class GodotSharp : public Object {
+ GDCLASS(GodotSharp, Object);
friend class GDMono;
@@ -303,11 +305,11 @@ class _GodotSharp : public Object {
void _reload_assemblies(bool p_soft_reload);
protected:
- static _GodotSharp *singleton;
+ static GodotSharp *singleton;
static void _bind_methods();
public:
- static _GodotSharp *get_singleton() { return singleton; }
+ static GodotSharp *get_singleton() { return singleton; }
void attach_thread();
void detach_thread();
@@ -323,8 +325,10 @@ public:
bool is_runtime_shutting_down();
bool is_runtime_initialized();
- _GodotSharp();
- ~_GodotSharp();
+ GodotSharp();
+ ~GodotSharp();
};
+} // namespace mono_bind
+
#endif // GD_MONO_H
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 1fe06bfbee..67f38bf127 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -34,8 +34,8 @@
#include <mono/metadata/tokentype.h>
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/templates/list.h"
@@ -330,8 +330,8 @@ no_pdb:
void GDMonoAssembly::unload() {
ERR_FAIL_NULL(image); // Should not be called if already unloaded
- for (Map<MonoClass *, GDMonoClass *>::Element *E = cached_raw.front(); E; E = E->next()) {
- memdelete(E->value());
+ for (const KeyValue<MonoClass *, GDMonoClass *> &E : cached_raw) {
+ memdelete(E.value);
}
cached_classes.clear();
@@ -345,6 +345,45 @@ String GDMonoAssembly::get_path() const {
return String::utf8(mono_image_get_filename(image));
}
+bool GDMonoAssembly::has_attribute(GDMonoClass *p_attr_class) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_NULL_V(p_attr_class, false);
+#endif
+
+ if (!attrs_fetched) {
+ fetch_attributes();
+ }
+
+ if (!attributes) {
+ return false;
+ }
+
+ return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr());
+}
+
+MonoObject *GDMonoAssembly::get_attribute(GDMonoClass *p_attr_class) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_NULL_V(p_attr_class, nullptr);
+#endif
+
+ if (!attrs_fetched) {
+ fetch_attributes();
+ }
+
+ if (!attributes) {
+ return nullptr;
+ }
+
+ return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr());
+}
+
+void GDMonoAssembly::fetch_attributes() {
+ ERR_FAIL_COND(attributes != nullptr);
+
+ attributes = mono_custom_attrs_from_assembly(assembly);
+ attrs_fetched = true;
+}
+
GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const StringName &p_name) {
ERR_FAIL_NULL_V(image, nullptr);
@@ -390,70 +429,6 @@ GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) {
return wrapped_class;
}
-GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) {
- GDMonoClass *match = nullptr;
-
- if (gdobject_class_cache_updated) {
- Map<StringName, GDMonoClass *>::Element *result = gdobject_class_cache.find(p_class);
-
- if (result) {
- match = result->get();
- }
- } else {
- List<GDMonoClass *> nested_classes;
-
- int rows = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
-
- for (int i = 1; i < rows; i++) {
- MonoClass *mono_class = mono_class_get(image, (i + 1) | MONO_TOKEN_TYPE_DEF);
-
- if (!mono_class_is_assignable_from(CACHED_CLASS_RAW(GodotObject), mono_class)) {
- continue;
- }
-
- GDMonoClass *current = get_class(mono_class);
-
- if (!current) {
- continue;
- }
-
- nested_classes.push_back(current);
-
- if (!match && current->get_name() == p_class) {
- match = current;
- }
-
- while (!nested_classes.is_empty()) {
- GDMonoClass *current_nested = nested_classes.front()->get();
- nested_classes.pop_front();
-
- void *iter = nullptr;
-
- while (true) {
- MonoClass *raw_nested = mono_class_get_nested_types(current_nested->get_mono_ptr(), &iter);
-
- if (!raw_nested) {
- break;
- }
-
- GDMonoClass *nested_class = get_class(raw_nested);
-
- if (nested_class) {
- gdobject_class_cache.insert(nested_class->get_name(), nested_class);
- nested_classes.push_back(nested_class);
- }
- }
- }
-
- gdobject_class_cache.insert(current->get_name(), current);
- }
-
- gdobject_class_cache_updated = true;
- }
-
- return match;
-}
-
GDMonoAssembly *GDMonoAssembly::load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) {
if (GDMono::get_singleton()->get_corlib_assembly() && (p_name == "mscorlib" || p_name == "mscorlib.dll")) {
return GDMono::get_singleton()->get_corlib_assembly();
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 350fcf3210..6191c491f4 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -71,13 +71,13 @@ class GDMonoAssembly {
MonoImage *image;
MonoAssembly *assembly;
+ bool attrs_fetched = false;
+ MonoCustomAttrInfo *attributes = nullptr;
+
#ifdef GD_MONO_HOT_RELOAD
uint64_t modified_time = 0;
#endif
- bool gdobject_class_cache_updated = false;
- Map<StringName, GDMonoClass *> gdobject_class_cache;
-
HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes;
Map<MonoClass *, GDMonoClass *> cached_raw;
@@ -111,11 +111,14 @@ public:
String get_path() const;
+ bool has_attribute(GDMonoClass *p_attr_class);
+ MonoObject *get_attribute(GDMonoClass *p_attr_class);
+
+ void fetch_attributes();
+
GDMonoClass *get_class(const StringName &p_namespace, const StringName &p_name);
GDMonoClass *get_class(MonoClass *p_mono_class);
- GDMonoClass *get_object_derived_class(const StringName &p_class);
-
static String find_assembly(const String &p_name);
static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String(), const String &p_custom_bcl_dir = String());
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index aea467660f..8b215a66c2 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -109,8 +109,8 @@ void CachedData::clear_godot_api_cache() {
class_Vector3 = nullptr;
class_Vector3i = nullptr;
class_Basis = nullptr;
- class_Quat = nullptr;
- class_Transform = nullptr;
+ class_Quaternion = nullptr;
+ class_Transform3D = nullptr;
class_AABB = nullptr;
class_Color = nullptr;
class_Plane = nullptr;
@@ -141,13 +141,14 @@ void CachedData::clear_godot_api_cache() {
class_SignalAttribute = nullptr;
class_ToolAttribute = nullptr;
class_RemoteAttribute = nullptr;
- class_MasterAttribute = nullptr;
class_PuppetAttribute = nullptr;
- class_RemoteSyncAttribute = nullptr;
- class_MasterSyncAttribute = nullptr;
- class_PuppetSyncAttribute = nullptr;
class_GodotMethodAttribute = nullptr;
field_GodotMethodAttribute_methodName = nullptr;
+ class_ScriptPathAttribute = nullptr;
+ field_ScriptPathAttribute_path = nullptr;
+ class_AssemblyHasScriptsAttribute = nullptr;
+ field_AssemblyHasScriptsAttribute_requiresLookup = nullptr;
+ field_AssemblyHasScriptsAttribute_scriptTypes = nullptr;
field_GodotObject_ptr = nullptr;
field_StringName_ptr = nullptr;
@@ -233,8 +234,8 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3));
CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i));
CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
- CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat));
- CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform));
+ CACHE_CLASS_AND_CHECK(Quaternion, GODOT_API_CLASS(Quaternion));
+ CACHE_CLASS_AND_CHECK(Transform3D, GODOT_API_CLASS(Transform3D));
CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB));
CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
@@ -265,13 +266,14 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute));
CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute));
- CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute));
CACHE_CLASS_AND_CHECK(PuppetAttribute, GODOT_API_CLASS(PuppetAttribute));
- CACHE_CLASS_AND_CHECK(RemoteSyncAttribute, GODOT_API_CLASS(RemoteSyncAttribute));
- CACHE_CLASS_AND_CHECK(MasterSyncAttribute, GODOT_API_CLASS(MasterSyncAttribute));
- CACHE_CLASS_AND_CHECK(PuppetSyncAttribute, GODOT_API_CLASS(PuppetSyncAttribute));
CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
+ CACHE_CLASS_AND_CHECK(ScriptPathAttribute, GODOT_API_CLASS(ScriptPathAttribute));
+ CACHE_FIELD_AND_CHECK(ScriptPathAttribute, path, CACHED_CLASS(ScriptPathAttribute)->get_field("path"));
+ CACHE_CLASS_AND_CHECK(AssemblyHasScriptsAttribute, GODOT_API_CLASS(AssemblyHasScriptsAttribute));
+ CACHE_FIELD_AND_CHECK(AssemblyHasScriptsAttribute, requiresLookup, CACHED_CLASS(AssemblyHasScriptsAttribute)->get_field("requiresLookup"));
+ CACHE_FIELD_AND_CHECK(AssemblyHasScriptsAttribute, scriptTypes, CACHED_CLASS(AssemblyHasScriptsAttribute)->get_field("scriptTypes"));
CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD));
CACHE_FIELD_AND_CHECK(StringName, ptr, CACHED_CLASS(StringName)->get_field(BINDINGS_PTR_FIELD));
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index fb75cb4b1c..fd28bbda14 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -80,8 +80,8 @@ struct CachedData {
GDMonoClass *class_Vector3;
GDMonoClass *class_Vector3i;
GDMonoClass *class_Basis;
- GDMonoClass *class_Quat;
- GDMonoClass *class_Transform;
+ GDMonoClass *class_Quaternion;
+ GDMonoClass *class_Transform3D;
GDMonoClass *class_AABB;
GDMonoClass *class_Color;
GDMonoClass *class_Plane;
@@ -112,13 +112,14 @@ struct CachedData {
GDMonoClass *class_SignalAttribute;
GDMonoClass *class_ToolAttribute;
GDMonoClass *class_RemoteAttribute;
- GDMonoClass *class_MasterAttribute;
GDMonoClass *class_PuppetAttribute;
- GDMonoClass *class_RemoteSyncAttribute;
- GDMonoClass *class_MasterSyncAttribute;
- GDMonoClass *class_PuppetSyncAttribute;
GDMonoClass *class_GodotMethodAttribute;
GDMonoField *field_GodotMethodAttribute_methodName;
+ GDMonoClass *class_ScriptPathAttribute;
+ GDMonoField *field_ScriptPathAttribute_path;
+ GDMonoClass *class_AssemblyHasScriptsAttribute;
+ GDMonoField *field_AssemblyHasScriptsAttribute_requiresLookup;
+ GDMonoField *field_AssemblyHasScriptsAttribute_scriptTypes;
GDMonoField *field_GodotObject_ptr;
GDMonoField *field_StringName_ptr;
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index f9fddd931b..27b4ac7fa7 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -522,12 +522,12 @@ GDMonoClass::~GDMonoClass() {
mono_custom_attrs_free(attributes);
}
- for (Map<StringName, GDMonoField *>::Element *E = fields.front(); E; E = E->next()) {
- memdelete(E->value());
+ for (const KeyValue<StringName, GDMonoField *> &E : fields) {
+ memdelete(E.value);
}
- for (Map<StringName, GDMonoProperty *>::Element *E = properties.front(); E; E = E->next()) {
- memdelete(E->value());
+ for (const KeyValue<StringName, GDMonoProperty *> &E : properties) {
+ memdelete(E.value);
}
{
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 1d4d52dfce..111eaa0bbf 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -146,14 +146,14 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
- if (tclass == CACHED_CLASS(Quat)) {
- GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
+ if (tclass == CACHED_CLASS(Quaternion)) {
+ GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_value.operator ::Quaternion());
mono_field_set_value(p_object, mono_field, &from);
break;
}
- if (tclass == CACHED_CLASS(Transform)) {
- GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
+ if (tclass == CACHED_CLASS(Transform3D)) {
+ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D());
mono_field_set_value(p_object, mono_field, &from);
break;
}
@@ -336,8 +336,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
mono_field_set_value(p_object, mono_field, &from);
} break;
- case Variant::QUAT: {
- GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
+ case Variant::QUATERNION: {
+ GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_value.operator ::Quaternion());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::AABB: {
@@ -348,8 +348,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
mono_field_set_value(p_object, mono_field, &from);
} break;
- case Variant::TRANSFORM: {
- GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
+ case Variant::TRANSFORM3D: {
+ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::COLOR: {
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index 65e2680905..cf76c23926 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -43,7 +43,6 @@
#include <mono/metadata/exception.h>
namespace GDMonoInternals {
-
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// This method should not fail
@@ -52,7 +51,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// All mono objects created from the managed world (e.g.: 'new Player()')
// need to have a CSharpScript in order for their methods to be callable from the unmanaged side
- Reference *ref = Object::cast_to<Reference>(unmanaged);
+ RefCounted *rc = Object::cast_to<RefCounted>(unmanaged);
GDMonoClass *klass = GDMonoUtils::get_object_class(managed);
@@ -74,33 +73,37 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
script_binding.inited = true;
script_binding.type_name = NATIVE_GDMONOCLASS_NAME(klass);
script_binding.wrapper_class = klass;
- script_binding.gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
+ script_binding.gchandle = rc ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
script_binding.owner = unmanaged;
- if (ref) {
+ if (rc) {
// Unsafe refcount increment. The managed instance also counts as a reference.
// This way if the unmanaged world has no references to our owner
// but the managed instance is alive, the refcount will be 1 instead of 0.
- // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
+ // See: godot_icall_RefCounted_Dtor(MonoObject *p_obj, Object *p_ptr)
// May not me referenced yet, so we must use init_ref() instead of reference()
- if (ref->init_ref()) {
- CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ if (rc->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(rc);
}
}
// The object was just created, no script instance binding should have been attached
- CRASH_COND(unmanaged->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()));
+ CRASH_COND(CSharpLanguage::has_instance_binding(unmanaged));
- void *data = (void *)CSharpLanguage::get_singleton()->insert_script_binding(unmanaged, script_binding);
+ void *data;
+ {
+ MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
+ data = (void *)CSharpLanguage::get_singleton()->insert_script_binding(unmanaged, script_binding);
+ }
// Should be thread safe because the object was just created and nothing else should be referencing it
- unmanaged->set_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index(), data);
+ CSharpLanguage::set_instance_binding(unmanaged, data);
return;
}
- MonoGCHandleData gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
+ MonoGCHandleData gchandle = rc ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass, native);
@@ -113,9 +116,11 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
void unhandled_exception(MonoException *p_exc) {
mono_print_unhandled_exception((MonoObject *)p_exc);
+ gd_unhandled_exception_event(p_exc);
if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) {
// Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders
+ mono_unhandled_exception((MonoObject *)p_exc);
GDMono::unhandled_exception_hook((MonoObject *)p_exc, nullptr);
GD_UNREACHABLE();
} else {
@@ -127,4 +132,14 @@ void unhandled_exception(MonoException *p_exc) {
#endif
}
}
+
+void gd_unhandled_exception_event(MonoException *p_exc) {
+ MonoImage *mono_image = GDMono::get_singleton()->get_core_api_assembly()->get_image();
+
+ MonoClass *gd_klass = mono_class_from_name(mono_image, "Godot", "GD");
+ MonoMethod *unhandled_exception_method = mono_class_get_method_from_name(gd_klass, "OnUnhandledException", -1);
+ void *args[1];
+ args[0] = p_exc;
+ mono_runtime_invoke(unhandled_exception_method, nullptr, (void **)args, nullptr);
+}
} // namespace GDMonoInternals
diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h
index 34d2d35b2d..26eb270eee 100644
--- a/modules/mono/mono_gd/gd_mono_internals.h
+++ b/modules/mono/mono_gd/gd_mono_internals.h
@@ -38,7 +38,6 @@
#include "core/object/class_db.h"
namespace GDMonoInternals {
-
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
/**
@@ -46,6 +45,8 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
* Use GDMonoUtils::debug_unhandled_exception(MonoException *) instead.
*/
void unhandled_exception(MonoException *p_exc);
+
+void gd_unhandled_exception_event(MonoException *p_exc);
} // namespace GDMonoInternals
#endif // GD_MONO_INTERNALS_H
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
index dafd36c36b..179bbfb40c 100644
--- a/modules/mono/mono_gd/gd_mono_log.cpp
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -32,7 +32,7 @@
#include <stdlib.h> // abort
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "core/os/os.h"
#include "../godotsharp_dirs.h"
@@ -161,8 +161,8 @@ void GDMonoLog::initialize() {
OS::Time time_now = OS::get_singleton()->get_time();
String log_file_name = str_format("%04d-%02d-%02d_%02d.%02d.%02d",
- date_now.year, date_now.month, date_now.day,
- time_now.hour, time_now.min, time_now.sec);
+ (int)date_now.year, (int)date_now.month, (int)date_now.day,
+ (int)time_now.hour, (int)time_now.minute, (int)time_now.second);
log_file_name += str_format("_%d", OS::get_singleton()->get_process_id());
diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h
index f7a53156ab..9ddbd251ac 100644
--- a/modules/mono/mono_gd/gd_mono_log.h
+++ b/modules/mono/mono_gd/gd_mono_log.h
@@ -41,7 +41,7 @@
#endif
#ifdef GD_MONO_LOG_ENABLED
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#endif
class GDMonoLog {
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 359f6bba4d..c9789bf270 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -104,12 +104,12 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
return Variant::BASIS;
}
- if (vtclass == CACHED_CLASS(Quat)) {
- return Variant::QUAT;
+ if (vtclass == CACHED_CLASS(Quaternion)) {
+ return Variant::QUATERNION;
}
- if (vtclass == CACHED_CLASS(Transform)) {
- return Variant::TRANSFORM;
+ if (vtclass == CACHED_CLASS(Transform3D)) {
+ return Variant::TRANSFORM3D;
}
if (vtclass == CACHED_CLASS(AABB)) {
@@ -508,9 +508,9 @@ MonoObject *variant_to_mono_object(const Variant &p_var) {
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var.operator ::Plane());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from);
}
- case Variant::QUAT: {
- GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_var.operator ::Quat());
- return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Quat), &from);
+ case Variant::QUATERNION: {
+ GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_var.operator ::Quaternion());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Quaternion), &from);
}
case Variant::AABB: {
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_var.operator ::AABB());
@@ -520,9 +520,9 @@ MonoObject *variant_to_mono_object(const Variant &p_var) {
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_var.operator ::Basis());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Basis), &from);
}
- case Variant::TRANSFORM: {
- GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_var.operator ::Transform());
- return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform), &from);
+ case Variant::TRANSFORM3D: {
+ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_var.operator ::Transform3D());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform3D), &from);
}
case Variant::COLOR: {
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var.operator ::Color());
@@ -619,8 +619,8 @@ size_t variant_get_managed_unboxed_size(const ManagedType &p_type) {
RETURN_CHECK_FOR_STRUCT(Vector3);
RETURN_CHECK_FOR_STRUCT(Vector3i);
RETURN_CHECK_FOR_STRUCT(Basis);
- RETURN_CHECK_FOR_STRUCT(Quat);
- RETURN_CHECK_FOR_STRUCT(Transform);
+ RETURN_CHECK_FOR_STRUCT(Quaternion);
+ RETURN_CHECK_FOR_STRUCT(Transform3D);
RETURN_CHECK_FOR_STRUCT(AABB);
RETURN_CHECK_FOR_STRUCT(Color);
RETURN_CHECK_FOR_STRUCT(Plane);
@@ -724,8 +724,8 @@ void *variant_to_managed_unboxed(const Variant &p_var, const ManagedType &p_type
RETURN_CHECK_FOR_STRUCT(Vector3);
RETURN_CHECK_FOR_STRUCT(Vector3i);
RETURN_CHECK_FOR_STRUCT(Basis);
- RETURN_CHECK_FOR_STRUCT(Quat);
- RETURN_CHECK_FOR_STRUCT(Transform);
+ RETURN_CHECK_FOR_STRUCT(Quaternion);
+ RETURN_CHECK_FOR_STRUCT(Transform3D);
RETURN_CHECK_FOR_STRUCT(AABB);
RETURN_CHECK_FOR_STRUCT(Color);
RETURN_CHECK_FOR_STRUCT(Plane);
@@ -880,8 +880,8 @@ MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_ty
RETURN_CHECK_FOR_STRUCT(Vector3);
RETURN_CHECK_FOR_STRUCT(Vector3i);
RETURN_CHECK_FOR_STRUCT(Basis);
- RETURN_CHECK_FOR_STRUCT(Quat);
- RETURN_CHECK_FOR_STRUCT(Transform);
+ RETURN_CHECK_FOR_STRUCT(Quaternion);
+ RETURN_CHECK_FOR_STRUCT(Transform3D);
RETURN_CHECK_FOR_STRUCT(AABB);
RETURN_CHECK_FOR_STRUCT(Color);
RETURN_CHECK_FOR_STRUCT(Plane);
@@ -1036,12 +1036,12 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
return MARSHALLED_IN(Basis, unbox_addr<GDMonoMarshal::M_Basis>(p_obj));
}
- if (vtclass == CACHED_CLASS(Quat)) {
- return MARSHALLED_IN(Quat, unbox_addr<GDMonoMarshal::M_Quat>(p_obj));
+ if (vtclass == CACHED_CLASS(Quaternion)) {
+ return MARSHALLED_IN(Quaternion, unbox_addr<GDMonoMarshal::M_Quaternion>(p_obj));
}
- if (vtclass == CACHED_CLASS(Transform)) {
- return MARSHALLED_IN(Transform, unbox_addr<GDMonoMarshal::M_Transform>(p_obj));
+ if (vtclass == CACHED_CLASS(Transform3D)) {
+ return MARSHALLED_IN(Transform3D, unbox_addr<GDMonoMarshal::M_Transform3D>(p_obj));
}
if (vtclass == CACHED_CLASS(AABB)) {
@@ -1136,8 +1136,8 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
Object *ptr = unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_obj));
if (ptr != nullptr) {
- Reference *ref = Object::cast_to<Reference>(ptr);
- return ref ? Variant(Ref<Reference>(ref)) : Variant(ptr);
+ RefCounted *rc = Object::cast_to<RefCounted>(ptr);
+ return rc ? Variant(Ref<RefCounted>(rc)) : Variant(ptr);
}
return Variant();
}
@@ -1686,7 +1686,9 @@ Callable managed_to_callable(const M_Callable &p_managed_callable) {
Object *target = p_managed_callable.target ?
unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_managed_callable.target)) :
nullptr;
- StringName *method_ptr = unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_callable.method_string_name));
+ StringName *method_ptr = p_managed_callable.method_string_name ?
+ unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_callable.method_string_name)) :
+ nullptr;
StringName method = method_ptr ? *method_ptr : StringName();
return Callable(target, method);
}
@@ -1732,7 +1734,9 @@ Signal managed_to_signal_info(const M_SignalInfo &p_managed_signal) {
Object *owner = p_managed_signal.owner ?
unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_managed_signal.owner)) :
nullptr;
- StringName *name_ptr = unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_signal.name_string_name));
+ StringName *name_ptr = p_managed_signal.name_string_name ?
+ unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_signal.name_string_name)) :
+ nullptr;
StringName name = name_ptr ? *name_ptr : StringName();
return Signal(owner, name);
}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 668809ae5d..88afc7ebc5 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -263,15 +263,15 @@ enum {
MATCHES_Basis = (MATCHES_Vector3 && (sizeof(Basis) == (sizeof(Vector3) * 3))), // No field offset required, it stores an array
- MATCHES_Quat = (MATCHES_real_t && (sizeof(Quat) == (sizeof(real_t) * 4)) &&
- offsetof(Quat, x) == (sizeof(real_t) * 0) &&
- offsetof(Quat, y) == (sizeof(real_t) * 1) &&
- offsetof(Quat, z) == (sizeof(real_t) * 2) &&
- offsetof(Quat, w) == (sizeof(real_t) * 3)),
+ MATCHES_Quaternion = (MATCHES_real_t && (sizeof(Quaternion) == (sizeof(real_t) * 4)) &&
+ offsetof(Quaternion, x) == (sizeof(real_t) * 0) &&
+ offsetof(Quaternion, y) == (sizeof(real_t) * 1) &&
+ offsetof(Quaternion, z) == (sizeof(real_t) * 2) &&
+ offsetof(Quaternion, w) == (sizeof(real_t) * 3)),
- MATCHES_Transform = (MATCHES_Basis && MATCHES_Vector3 && (sizeof(Transform) == (sizeof(Basis) + sizeof(Vector3))) &&
- offsetof(Transform, basis) == 0 &&
- offsetof(Transform, origin) == sizeof(Basis)),
+ MATCHES_Transform3D = (MATCHES_Basis && MATCHES_Vector3 && (sizeof(Transform3D) == (sizeof(Basis) + sizeof(Vector3))) &&
+ offsetof(Transform3D, basis) == 0 &&
+ offsetof(Transform3D, origin) == sizeof(Basis)),
MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) &&
offsetof(AABB, position) == (sizeof(Vector3) * 0) &&
@@ -292,7 +292,7 @@ enum {
#ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY
/* clang-format off */
static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 &&
- MATCHES_Basis && MATCHES_Quat && MATCHES_Transform && MATCHES_AABB && MATCHES_Color &&
+ MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_AABB && MATCHES_Color &&
MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i);
/* clang-format on */
#endif
@@ -420,29 +420,29 @@ struct M_Basis {
}
};
-struct M_Quat {
+struct M_Quaternion {
real_t x, y, z, w;
- static _FORCE_INLINE_ Quat convert_to(const M_Quat &p_from) {
- return Quat(p_from.x, p_from.y, p_from.z, p_from.w);
+ static _FORCE_INLINE_ Quaternion convert_to(const M_Quaternion &p_from) {
+ return Quaternion(p_from.x, p_from.y, p_from.z, p_from.w);
}
- static _FORCE_INLINE_ M_Quat convert_from(const Quat &p_from) {
- M_Quat ret = { p_from.x, p_from.y, p_from.z, p_from.w };
+ static _FORCE_INLINE_ M_Quaternion convert_from(const Quaternion &p_from) {
+ M_Quaternion ret = { p_from.x, p_from.y, p_from.z, p_from.w };
return ret;
}
};
-struct M_Transform {
+struct M_Transform3D {
M_Basis basis;
M_Vector3 origin;
- static _FORCE_INLINE_ Transform convert_to(const M_Transform &p_from) {
- return Transform(M_Basis::convert_to(p_from.basis), M_Vector3::convert_to(p_from.origin));
+ static _FORCE_INLINE_ Transform3D convert_to(const M_Transform3D &p_from) {
+ return Transform3D(M_Basis::convert_to(p_from.basis), M_Vector3::convert_to(p_from.origin));
}
- static _FORCE_INLINE_ M_Transform convert_from(const Transform &p_from) {
- M_Transform ret = { M_Basis::convert_from(p_from.basis), M_Vector3::convert_from(p_from.origin) };
+ static _FORCE_INLINE_ M_Transform3D convert_from(const Transform3D &p_from) {
+ M_Transform3D ret = { M_Basis::convert_from(p_from.basis), M_Vector3::convert_from(p_from.origin) };
return ret;
}
};
@@ -533,8 +533,8 @@ DECL_TYPE_MARSHAL_TEMPLATES(Transform2D)
DECL_TYPE_MARSHAL_TEMPLATES(Vector3)
DECL_TYPE_MARSHAL_TEMPLATES(Vector3i)
DECL_TYPE_MARSHAL_TEMPLATES(Basis)
-DECL_TYPE_MARSHAL_TEMPLATES(Quat)
-DECL_TYPE_MARSHAL_TEMPLATES(Transform)
+DECL_TYPE_MARSHAL_TEMPLATES(Quaternion)
+DECL_TYPE_MARSHAL_TEMPLATES(Transform3D)
DECL_TYPE_MARSHAL_TEMPLATES(AABB)
DECL_TYPE_MARSHAL_TEMPLATES(Color)
DECL_TYPE_MARSHAL_TEMPLATES(Plane)
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 6e0a263c7f..13939bd014 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -35,8 +35,8 @@
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
-#include "core/object/reference.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
+#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/os/os.h"
@@ -68,22 +68,10 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
// If the owner does not have a CSharpInstance...
- void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
-
+ void *data = CSharpLanguage::get_instance_binding(unmanaged);
ERR_FAIL_NULL_V(data, nullptr);
-
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value();
-
- if (!script_binding.inited) {
- MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
-
- if (!script_binding.inited) { // Other thread may have set it up
- // Already had a binding that needs to be setup
- CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged);
-
- ERR_FAIL_COND_V(!script_binding.inited, nullptr);
- }
- }
+ ERR_FAIL_COND_V(!script_binding.inited, nullptr);
MonoGCHandleData &gchandle = script_binding.gchandle;
@@ -108,15 +96,15 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
gchandle = MonoGCHandleData::new_strong_handle(mono_object);
// Tie managed to unmanaged
- Reference *ref = Object::cast_to<Reference>(unmanaged);
+ RefCounted *rc = Object::cast_to<RefCounted>(unmanaged);
- if (ref) {
+ if (rc) {
// Unsafe refcount increment. The managed instance also counts as a reference.
// This way if the unmanaged world has no references to our owner
// but the managed instance is alive, the refcount will be 1 instead of 0.
- // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
- ref->reference();
- CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ // See: godot_icall_RefCounted_Dtor(MonoObject *p_obj, Object *p_ptr)
+ rc->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(rc);
}
return mono_object;
@@ -238,7 +226,7 @@ GDMonoClass *get_class_native_base(GDMonoClass *p_class) {
MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) {
bool parent_is_object_class = ClassDB::is_parent_class(p_object->get_class_name(), p_native);
ERR_FAIL_COND_V_MSG(!parent_is_object_class, nullptr,
- "Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'.");
+ "Type inherits from native type '" + p_native + "', so it can't be instantiated in object of type: '" + p_object->get_class() + "'.");
MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
ERR_FAIL_NULL_V(mono_object, nullptr);
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 9e024418e1..773501e93d 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -41,7 +41,7 @@
#endif
#include "core/object/class_db.h"
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#define UNHANDLED_EXCEPTION(m_exc) \
if (unlikely(m_exc != nullptr)) { \
diff --git a/modules/mono/mono_gd/gd_mono_wasm_m2n.h b/modules/mono/mono_gd/gd_mono_wasm_m2n.h
index 159a2ed7b6..366662ff81 100644
--- a/modules/mono/mono_gd/gd_mono_wasm_m2n.h
+++ b/modules/mono/mono_gd/gd_mono_wasm_m2n.h
@@ -176,7 +176,7 @@ T m2n_arg_cast(Mono_InterpMethodArguments *p_margs, size_t p_idx) {
} else if constexpr (cookie == 'F') {
return *reinterpret_cast<float *>(&p_margs->fargs[fidx(p_idx)]);
} else if constexpr (cookie == 'D') {
- return (T)(size_t)p_margs->fargs[p_idx];
+ return (T)p_margs->fargs[p_idx];
}
}
diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp
index cba29d63cd..c65353dfd1 100644
--- a/modules/mono/mono_gd/support/android_support.cpp
+++ b/modules/mono/mono_gd/support/android_support.cpp
@@ -415,8 +415,7 @@ GD_PINVOKE_EXPORT int32_t monodroid_get_system_property(const char *p_name, char
if (r_value) {
if (len >= 0) {
*r_value = (char *)malloc(len + 1);
- if (!*r_value)
- return -1;
+ ERR_FAIL_NULL_V_MSG(*r_value, -1, "Out of memory.");
memcpy(*r_value, prop_value_str, len);
(*r_value)[len] = '\0';
} else {
@@ -637,6 +636,7 @@ GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array)
if (dns_servers_count > 0) {
size_t ret_size = sizeof(char *) * (size_t)dns_servers_count;
*r_dns_servers_array = malloc(ret_size); // freed by the BCL
+ ERR_FAIL_NULL_V_MSG(*r_dns_servers_array, -1, "Out of memory.");
memcpy(*r_dns_servers_array, dns_servers, ret_size);
}
diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm
index cdee04edcf..23424fbaf9 100644
--- a/modules/mono/mono_gd/support/ios_support.mm
+++ b/modules/mono/mono_gd/support/ios_support.mm
@@ -57,9 +57,9 @@ void ios_mono_log_callback(const char *log_domain, const char *log_level, const
}
void initialize() {
- mono_dllmap_insert(NULL, "System.Native", NULL, "__Internal", NULL);
- mono_dllmap_insert(NULL, "System.IO.Compression.Native", NULL, "__Internal", NULL);
- mono_dllmap_insert(NULL, "System.Security.Cryptography.Native.Apple", NULL, "__Internal", NULL);
+ mono_dllmap_insert(nullptr, "System.Native", nullptr, "__Internal", nullptr);
+ mono_dllmap_insert(nullptr, "System.IO.Compression.Native", nullptr, "__Internal", nullptr);
+ mono_dllmap_insert(nullptr, "System.Security.Cryptography.Native.Apple", nullptr, "__Internal", nullptr);
#ifdef IOS_DEVICE
// This function is defined in an auto-generated source file
@@ -85,7 +85,7 @@ void cleanup() {
GD_PINVOKE_EXPORT const char *xamarin_get_locale_country_code() {
NSLocale *locale = [NSLocale currentLocale];
NSString *countryCode = [locale objectForKey:NSLocaleCountryCode];
- if (countryCode == NULL) {
+ if (countryCode == nullptr) {
return strdup("US");
}
return strdup([countryCode UTF8String]);
diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp
index 80eb47bfd4..98e83335e9 100644
--- a/modules/mono/register_types.cpp
+++ b/modules/mono/register_types.cpp
@@ -38,24 +38,24 @@ CSharpLanguage *script_language_cs = nullptr;
Ref<ResourceFormatLoaderCSharpScript> resource_loader_cs;
Ref<ResourceFormatSaverCSharpScript> resource_saver_cs;
-_GodotSharp *_godotsharp = nullptr;
+mono_bind::GodotSharp *_godotsharp = nullptr;
void register_mono_types() {
- ClassDB::register_class<CSharpScript>();
+ GDREGISTER_CLASS(CSharpScript);
- _godotsharp = memnew(_GodotSharp);
+ _godotsharp = memnew(mono_bind::GodotSharp);
- ClassDB::register_class<_GodotSharp>();
- Engine::get_singleton()->add_singleton(Engine::Singleton("GodotSharp", _GodotSharp::get_singleton()));
+ GDREGISTER_CLASS(mono_bind::GodotSharp);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("GodotSharp", mono_bind::GodotSharp::get_singleton()));
script_language_cs = memnew(CSharpLanguage);
script_language_cs->set_language_index(ScriptServer::get_language_count());
ScriptServer::register_language(script_language_cs);
- resource_loader_cs.instance();
+ resource_loader_cs.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_cs);
- resource_saver_cs.instance();
+ resource_saver_cs.instantiate();
ResourceSaver::add_resource_format_saver(resource_saver_cs);
}
diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h
index 4c77f8cfed..e12ea45b3f 100644
--- a/modules/mono/signal_awaiter_utils.h
+++ b/modules/mono/signal_awaiter_utils.h
@@ -31,7 +31,7 @@
#ifndef SIGNAL_AWAITER_UTILS_H
#define SIGNAL_AWAITER_UTILS_H
-#include "core/object/reference.h"
+#include "core/object/ref_counted.h"
#include "csharp_script.h"
#include "mono_gc_handle.h"
diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp
index bb1265e959..6b616dd52d 100644
--- a/modules/mono/utils/mono_reg_utils.cpp
+++ b/modules/mono/utils/mono_reg_utils.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "mono_reg_utils.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#ifdef WINDOWS_ENABLED
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
index 93d44628ac..ec04d50704 100644
--- a/modules/mono/utils/path_utils.cpp
+++ b/modules/mono/utils/path_utils.cpp
@@ -31,8 +31,8 @@
#include "path_utils.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/os/os.h"
#ifdef WINDOWS_ENABLED
@@ -80,7 +80,7 @@ String cwd() {
}
String abspath(const String &p_path) {
- if (p_path.is_abs_path()) {
+ if (p_path.is_absolute_path()) {
return p_path.simplify_path();
} else {
return path::join(path::cwd(), p_path).simplify_path();
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index 43de77005e..2fb5e446da 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -30,7 +30,7 @@
#include "string_utils.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include <stdio.h>
#include <stdlib.h>
@@ -170,10 +170,10 @@ Error read_all_file_utf8(const String &p_path, String &r_content) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
- int len = f->get_len();
+ uint64_t len = f->get_length();
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
- int r = f->get_buffer(w, len);
+ uint64_t r = f->get_buffer(w, len);
f->close();
memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
@@ -200,7 +200,7 @@ String str_format(const char *p_format, ...) {
return res;
}
-#if defined(MINGW_ENABLED) || defined(_MSC_VER) && _MSC_VER < 1900
+#if defined(MINGW_ENABLED)
#define gd_vsnprintf(m_buffer, m_count, m_format, m_args_copy) vsnprintf_s(m_buffer, m_count, _TRUNCATE, m_format, m_args_copy)
#define gd_vscprintf(m_format, m_args_copy) _vscprintf(m_format, m_args_copy)
#else