diff options
Diffstat (limited to 'modules/mono')
31 files changed, 299 insertions, 90 deletions
diff --git a/modules/mono/build_scripts/make_android_mono_config.py b/modules/mono/build_scripts/make_android_mono_config.py index 1920ef1c1a..3459244bc2 100644 --- a/modules/mono/build_scripts/make_android_mono_config.py +++ b/modules/mono/build_scripts/make_android_mono_config.py @@ -43,7 +43,7 @@ String get_godot_android_mono_config() { Compression::decompress(w, config_uncompressed_size, config_compressed_data, config_compressed_size, Compression::MODE_DEFLATE); String s; - if (s.parse_utf8((const char *)w, data.size())) { + if (s.parse_utf8((const char *)w, data.size()) != OK) { ERR_FAIL_V(String()); } return s; diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index 3afde1e8d3..c4547b4323 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -124,7 +124,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - for (const KeyValue<StringName, int> &F : t->constant_map) { + for (const KeyValue<StringName, int64_t> &F : t->constant_map) { snames.push_back(F.key); } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 622838b308..3dc26cfbe4 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2866,6 +2866,12 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage r_hint = PROPERTY_HINT_RESOURCE_TYPE; r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class)); + } else if (p_variant_type == Variant::OBJECT && CACHED_CLASS(Node)->is_assignable_from(p_type.type_class)) { + GDMonoClass *field_native_class = GDMonoUtils::get_class_native_base(p_type.type_class); + CRASH_COND(field_native_class == nullptr); + + r_hint = PROPERTY_HINT_NODE_TYPE; + r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class)); } else if (p_allow_generics && p_variant_type == Variant::ARRAY) { // Nested arrays are not supported in the inspector @@ -3063,16 +3069,11 @@ 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()) { - 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.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); + Multiplayer::RPCConfig rpc_config = p_script->_member_get_rpc_config(methods[i]); + if (rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) { + // RPC annotations can only be used once per method + if (p_script->rpc_functions.find(rpc_config) == -1) { + p_script->rpc_functions.push_back(rpc_config); } } } @@ -3507,15 +3508,19 @@ int CSharpScript::get_member_line(const StringName &p_member) const { return -1; } -Multiplayer::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const { - if (p_member->has_attribute(CACHED_CLASS(AnyPeerAttribute))) { - return Multiplayer::RPC_MODE_ANY_PEER; - } - if (p_member->has_attribute(CACHED_CLASS(AuthorityAttribute))) { - return Multiplayer::RPC_MODE_AUTHORITY; +Multiplayer::RPCConfig CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const { + Multiplayer::RPCConfig rpc_config; + + MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute)); + if (rpc_attribute != nullptr) { + rpc_config.name = p_member->get_name(); + rpc_config.rpc_mode = (Multiplayer::RPCMode)CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute); + rpc_config.call_local = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute); + rpc_config.transfer_mode = (Multiplayer::TransferMode)CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute); + rpc_config.channel = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute); } - return Multiplayer::RPC_MODE_DISABLED; + return rpc_config; } const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 69bd8703aa..b17473470f 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -179,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); - Multiplayer::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const; + Multiplayer::RPCConfig _member_get_rpc_config(IMonoClassMember *p_member) const; protected: static void _bind_methods(); @@ -502,6 +502,7 @@ public: /* TODO? */ void get_public_functions(List<MethodInfo> *p_functions) const override {} /* TODO? */ void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {} + /* TODO? */ void get_public_annotations(List<MethodInfo> *p_annotations) const override {} void reload_all_scripts() override; void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) override; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj index ae78da27bc..303ca3a293 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj @@ -12,6 +12,6 @@ <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> </ItemGroup> <ItemGroup> - <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> </ItemGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj index dad6b9ae7a..02f1764f32 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj @@ -19,6 +19,6 @@ A client using this library is only compatible with servers of the same major ve </Description> </PropertyGroup> <ItemGroup> - <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> </ItemGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs index 9e8f7ef1b1..3c020a2589 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs @@ -126,7 +126,7 @@ namespace GodotTools.Build { base._Ready(); - MinimumSize = new Vector2(0, 228) * EditorScale; + CustomMinimumSize = new Vector2(0, 228) * EditorScale; SizeFlagsVertical = (int)SizeFlags.ExpandFill; var toolBarHBox = new HBoxContainer { SizeFlagsHorizontal = (int)SizeFlags.ExpandFill }; diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs index 16dd1c8c6b..63b97e981e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs @@ -99,7 +99,7 @@ namespace GodotTools.Build if (Utils.OS.IsWindows) { // %APPDATA% for both - return new[] {Path.Combine(applicationData, "NuGet", "NuGet.Config")}; + return new[] { Path.Combine(applicationData, "NuGet", "NuGet.Config") }; } var paths = new string[2]; @@ -156,6 +156,7 @@ namespace GodotTools.Build </packageSources> </configuration> "; + System.IO.Directory.CreateDirectory(Path.GetDirectoryName(nuGetConfigPath)); System.IO.File.WriteAllText(nuGetConfigPath, defaultConfig, Encoding.UTF8); // UTF-8 with BOM } diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index b9aa760f4d..f1d45463c5 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -19,7 +19,7 @@ <ItemGroup> <PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" /> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <Reference Include="GodotSharp"> <HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath> <Private>False</Private> diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 960d2fe27c..7cc195201b 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -954,7 +954,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { } } - p_output.append(MEMBER_BEGIN "public const int "); + p_output.append(MEMBER_BEGIN "public const long "); p_output.append(iconstant.proxy_name); p_output.append(" = "); p_output.append(itos(iconstant.value)); @@ -990,8 +990,13 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { p_output.append("\n" INDENT1 OPEN_BLOCK); } + if (ienum.is_flags) { + p_output.append("\n" INDENT1 "[System.Flags]"); + } + p_output.append("\n" INDENT1 "public enum "); p_output.append(enum_proxy_name); + p_output.append(" : long"); p_output.append("\n" INDENT1 OPEN_BLOCK); const ConstantInterface &last = ienum.constants.back()->get(); @@ -1417,7 +1422,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } } - output.append(MEMBER_BEGIN "public const int "); + output.append(MEMBER_BEGIN "public const long "); output.append(iconstant.proxy_name); output.append(" = "); output.append(itos(iconstant.value)); @@ -1433,8 +1438,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str for (const EnumInterface &ienum : itype.enums) { ERR_FAIL_COND_V(ienum.constants.is_empty(), ERR_BUG); + if (ienum.is_flags) { + output.append(MEMBER_BEGIN "[System.Flags]"); + } + output.append(MEMBER_BEGIN "public enum "); output.append(ienum.cname.operator String()); + output.append(" : long"); output.append(MEMBER_BEGIN OPEN_BLOCK); const ConstantInterface &last = ienum.constants.back()->get(); @@ -2863,7 +2873,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { " We only expected Object.free, but found '" + itype.name + "." + imethod.name + "'."); } - } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + } else if (return_info.type == Variant::INT && return_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { imethod.return_type.cname = return_info.class_name; imethod.return_type.is_enum = true; } else if (return_info.class_name != StringName()) { @@ -2901,7 +2911,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ArgumentInterface iarg; iarg.name = orig_arg_name; - if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { iarg.type.cname = arginfo.class_name; iarg.type.is_enum = true; } else if (arginfo.class_name != StringName()) { @@ -3009,7 +3019,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ArgumentInterface iarg; iarg.name = orig_arg_name; - if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { iarg.type.cname = arginfo.class_name; iarg.type.is_enum = true; } else if (arginfo.class_name != StringName()) { @@ -3073,9 +3083,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() { List<String> constants; ClassDB::get_integer_constant_list(type_cname, &constants, true); - const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map; + const HashMap<StringName, ClassDB::ClassInfo::EnumInfo> &enum_map = class_info->enum_map; - for (const KeyValue<StringName, List<StringName>> &E : enum_map) { + for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &E : enum_map) { StringName enum_proxy_cname = E.key; String enum_proxy_name = enum_proxy_cname.operator String(); if (itype.find_property_by_proxy_name(enum_proxy_cname)) { @@ -3085,10 +3095,11 @@ bool BindingsGenerator::_populate_object_type_interfaces() { enum_proxy_cname = StringName(enum_proxy_name); } EnumInterface ienum(enum_proxy_cname); - const List<StringName> &enum_constants = E.value; + ienum.is_flags = E.value.is_bitfield; + const List<StringName> &enum_constants = E.value.constants; for (const StringName &constant_cname : enum_constants) { String constant_name = constant_cname.operator String(); - int *value = class_info->constant_map.getptr(constant_cname); + int64_t *value = class_info->constant_map.getptr(constant_cname); ERR_FAIL_NULL_V(value, false); constants.erase(constant_name); @@ -3123,7 +3134,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { } for (const String &constant_name : constants) { - int *value = class_info->constant_map.getptr(StringName(constant_name)); + int64_t *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); @@ -3666,7 +3677,7 @@ void BindingsGenerator::_populate_global_constants() { } } - int constant_value = CoreConstants::get_global_constant_value(i); + int64_t constant_value = CoreConstants::get_global_constant_value(i); StringName enum_name = CoreConstants::get_global_constant_enum(i); ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), constant_value); @@ -3674,6 +3685,7 @@ void BindingsGenerator::_populate_global_constants() { if (enum_name != StringName()) { EnumInterface ienum(enum_name); + // TODO: ienum.is_flags is always false for core constants since they don't seem to support bitfield enums List<EnumInterface>::Element *enum_match = global_enums.find(ienum); if (enum_match) { enum_match->get().constants.push_back(iconstant); diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index f0ba2b18e4..1547d0ed2f 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -45,12 +45,12 @@ class BindingsGenerator { struct ConstantInterface { String name; String proxy_name; - int value = 0; + int64_t value = 0; const DocData::ConstantDoc *const_doc; ConstantInterface() {} - ConstantInterface(const String &p_name, const String &p_proxy_name, int p_value) { + ConstantInterface(const String &p_name, const String &p_proxy_name, int64_t p_value) { name = p_name; proxy_name = p_proxy_name; value = p_value; @@ -60,6 +60,7 @@ class BindingsGenerator { struct EnumInterface { StringName cname; List<ConstantInterface> constants; + bool is_flags = false; _FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const { return p_ienum.cname == cname; diff --git a/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs b/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs index 0690205d01..9e1b7ef580 100644 --- a/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs +++ b/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs @@ -7,12 +7,10 @@ using System; [Tool] public partial class _CLASS_ : _BASE_ { - public override Object _PostImport(Node scene) + public override Godot.Object _PostImport(Node scene) { - // Modify the contents of the scene upon import. For example, setting up LODs: -// scene.GetNode<MeshInstance3D>("HighPolyMesh").DrawDistanceEnd = 5.0 -// scene.GetNode<MeshInstance3D>("LowPolyMesh").DrawDistanceBegin = 5.0 - return scene // Return the modified root node when you're done. + // Modify the contents of the scene upon import. + return scene; // Return the modified root node when you're done. } } #endif diff --git a/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs b/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs index 4e2d9b7088..bf2c9434e4 100644 --- a/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs +++ b/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs @@ -7,9 +7,9 @@ using System; [Tool] public partial class _CLASS_ : _BASE_ { - public override Object _PostImport(Node scene) + public override Godot.Object _PostImport(Node scene) { - return scene + return scene; } } #endif diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs new file mode 100644 index 0000000000..0a1c8322d7 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs @@ -0,0 +1,43 @@ +using System; + +namespace Godot +{ + /// <summary> + /// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>, + /// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers). + /// See <see cref="RPCMode"/> and <see cref="TransferMode"/>. By default, methods are not exposed to networking + /// (and RPCs). + /// </summary> + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class RPCAttribute : Attribute + { + /// <summary> + /// RPC mode for the annotated method. + /// </summary> + public RPCMode Mode { get; } = RPCMode.Disabled; + + /// <summary> + /// If the method will also be called locally; otherwise, it is only called remotely. + /// </summary> + public bool CallLocal { get; set; } = false; + + /// <summary> + /// Transfer mode for the annotated method. + /// </summary> + public TransferMode TransferMode { get; set; } = TransferMode.Reliable; + + /// <summary> + /// Transfer channel for the annotated mode. + /// </summary> + public int TransferChannel { get; set; } = 0; + + /// <summary> + /// Constructs a <see cref="RPCAttribute"/> instance. + /// </summary> + /// <param name="mode">The RPC mode to use.</param> + public RPCAttribute(RPCMode mode = RPCMode.Authority) + { + Mode = mode; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs deleted file mode 100644 index f0d37c344d..0000000000 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace Godot -{ - /// <summary> - /// Constructs a new AnyPeerAttribute instance. Members with the AnyPeerAttribute are given authority over their own player. - /// </summary> - [AttributeUsage(AttributeTargets.Method)] - public class AnyPeerAttribute : Attribute { } - - /// <summary> - /// Constructs a new AuthorityAttribute instance. Members with the AuthorityAttribute are given authority over the game. - /// </summary> - [AttributeUsage(AttributeTargets.Method)] - public class AuthorityAttribute : Attribute { } -} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index 74aa38386f..bb076a9633 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -239,6 +239,27 @@ namespace Godot } /// <summary> + /// Converts one or more arguments of any type to string in the best way possible and prints them to the console. The following BBCode tags are supported: b, i, u, s, indent, code, url, center, right, color, bgcolor, fgcolor. Color tags only support named colors such as [code]red[/code], [i]not[/i] hexadecimal color codes. Unsupported tags will be left as-is in standard output. + /// When printing to standard output, the supported subset of BBCode is converted to ANSI escape codes for the terminal emulator to display. Displaying ANSI escape codes is currently only supported on Linux and macOS. Support for ANSI escape codes may vary across terminal emulators, especially for italic and strikethrough. + /// + /// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/> + /// to print error and warning messages instead of <see cref="Print(object[])"/> or <see cref="PrintRich(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> + /// GD.PrintRich("[b]Hello world![/b]"); // Prints out "Hello world!" in bold. + /// </code> + /// </example> + /// <param name="what">Arguments that will be printed.</param> + /// </summary> + public static void PrintRich(params object[] what) + { + godot_icall_GD_print_rich(GetPrintParams(what)); + } + + /// <summary> /// Prints the current stack trace information to the console. /// </summary> public static void PrintStack() @@ -562,6 +583,9 @@ namespace Godot internal static extern void godot_icall_GD_print(object[] what); [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void godot_icall_GD_print_rich(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void godot_icall_GD_printerr(object[] what); [MethodImpl(MethodImplOptions.InternalCall)] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index ce213da6a7..36b7d0f80f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -198,6 +198,28 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by + /// the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="start">The start value for the interpolation.</param> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination value for the interpolation.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The resulting value of the interpolation.</returns> + public static real_t BezierInterpolate(real_t start, real_t control1, real_t control2, real_t end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return start * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Converts an angle expressed in degrees to radians. /// </summary> /// <param name="deg">An angle expressed in degrees.</param> @@ -276,10 +298,14 @@ namespace Godot /// Returns a normalized value considering the given range. /// This is the opposite of <see cref="Lerp(real_t, real_t, real_t)"/>. /// </summary> - /// <param name="from">The interpolated value.</param> + /// <param name="from">The start value for interpolation.</param> /// <param name="to">The destination value for interpolation.</param> - /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> - /// <returns>The resulting value of the inverse interpolation.</returns> + /// <param name="weight">The interpolated value.</param> + /// <returns> + /// The resulting value of the inverse interpolation. + /// The returned value will be between 0.0 and 1.0 if <paramref name="weight"/> is + /// between <paramref name="from"/> and <paramref name="to"/> (inclusive). + /// </returns> public static real_t InverseLerp(real_t from, real_t to, real_t weight) { return (weight - from) / (to - from); @@ -516,6 +542,21 @@ namespace Godot } /// <summary> + /// Maps a <paramref name="value"/> from [<paramref name="inFrom"/>, <paramref name="inTo"/>] + /// to [<paramref name="outFrom"/>, <paramref name="outTo"/>]. + /// </summary> + /// <param name="value">The value to map.</param> + /// <param name="inFrom">The start value for the input interpolation.</param> + /// <param name="inTo">The destination value for the input interpolation.</param> + /// <param name="outFrom">The start value for the output interpolation.</param> + /// <param name="outTo">The destination value for the output interpolation.</param> + /// <returns>The resulting mapped value mapped.</returns> + public static real_t RangeLerp(real_t value, real_t inFrom, real_t inTo, real_t outFrom, real_t outTo) + { + return Lerp(outFrom, outTo, InverseLerp(inFrom, inTo, value)); + } + + /// <summary> /// Rounds <paramref name="s"/> to the nearest whole number, /// with halfway cases rounded towards the nearest multiple of two. /// </summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs index 40fb5f8788..9ae01016cb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs @@ -170,6 +170,21 @@ namespace Godot } /// <summary> + /// Returns all names concatenated with a slash character (<c>/</c>). + /// </summary> + /// <example> + /// <code> + /// var nodepath = new NodePath("Path2D/PathFollow2D/Sprite2D:texture:load_path"); + /// GD.Print(nodepath.GetConcatenatedNames()); // Path2D/PathFollow2D/Sprite2D + /// </code> + /// </example> + /// <returns>The names concatenated with <c>/</c>.</returns> + public string GetConcatenatedNames() + { + return godot_icall_NodePath_get_concatenated_names(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> @@ -269,6 +284,9 @@ namespace Godot private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] + private static extern string godot_icall_NodePath_get_concatenated_names(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 9e990ce83e..7bdbe1c28b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -221,6 +221,27 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector + /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination vector.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The interpolated vector.</returns> + public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> /// <param name="to">The other vector to point towards.</param> @@ -522,9 +543,10 @@ namespace Godot { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); - if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { - // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. - return Lerp(to, weight); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) + { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } real_t startLength = Mathf.Sqrt(startLengthSquared); real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index 412a885daa..b61954a84c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -461,7 +461,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector2i"/> + /// Divides each component of the <see cref="Vector2i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 56859da7f2..480165d44a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -214,6 +214,27 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector + /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination vector.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The interpolated vector.</returns> + public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> /// <param name="to">The other vector to point towards.</param> @@ -562,9 +583,10 @@ namespace Godot { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); - if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { - // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. - return Lerp(to, weight); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) + { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } real_t startLength = Mathf.Sqrt(startLengthSquared); real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index abfd2ae720..0d4894f206 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -449,7 +449,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector3i"/> + /// Divides each component of the <see cref="Vector3i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 1fcfe74c86..e59f45bbf6 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -18,7 +18,7 @@ <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\RPCAttribute.cs" /> <Compile Include="Core\Attributes\ScriptPathAttribute.cs" /> <Compile Include="Core\Attributes\SignalAttribute.cs" /> <Compile Include="Core\Attributes\ToolAttribute.cs" /> diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp index 8aead217cf..8b1c2b729e 100644 --- a/modules/mono/glue/gd_glue.cpp +++ b/modules/mono/glue/gd_glue.cpp @@ -90,6 +90,27 @@ void godot_icall_GD_print(MonoArray *p_what) { print_line(str); } +void godot_icall_GD_print_rich(MonoArray *p_what) { + String str; + int length = mono_array_length(p_what); + + for (int i = 0; i < length; i++) { + MonoObject *elem = mono_array_get(p_what, MonoObject *, i); + + MonoException *exc = nullptr; + String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc); + + if (exc) { + GDMonoUtils::set_pending_exception(exc); + return; + } + + str += elem_str; + } + + print_line_rich(str); +} + void godot_icall_GD_printerr(MonoArray *p_what) { String str; int length = mono_array_length(p_what); @@ -300,6 +321,7 @@ void godot_register_gd_icalls() { GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pusherror", godot_icall_GD_pusherror); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pushwarning", godot_icall_GD_pushwarning); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print", godot_icall_GD_print); + GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print_rich", godot_icall_GD_print_rich); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printerr", godot_icall_GD_printerr); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printraw", godot_icall_GD_printraw); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_prints", godot_icall_GD_prints); diff --git a/modules/mono/glue/nodepath_glue.cpp b/modules/mono/glue/nodepath_glue.cpp index 0ea9814b1a..16e1509eb0 100644 --- a/modules/mono/glue/nodepath_glue.cpp +++ b/modules/mono/glue/nodepath_glue.cpp @@ -68,6 +68,10 @@ MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) { return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx)); } +MonoString *godot_icall_NodePath_get_concatenated_names(NodePath *p_ptr) { + return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_names()); +} + MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) { return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames()); } @@ -85,6 +89,7 @@ void godot_register_nodepath_icalls() { GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", godot_icall_NodePath_Dtor); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", godot_icall_NodePath_operator_String); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path); + GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_names", godot_icall_NodePath_get_concatenated_names); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", godot_icall_NodePath_get_name); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", godot_icall_NodePath_get_name_count); diff --git a/modules/mono/managed_callable.cpp b/modules/mono/managed_callable.cpp index 4f7783b765..c159bb9eea 100644 --- a/modules/mono/managed_callable.cpp +++ b/modules/mono/managed_callable.cpp @@ -66,9 +66,8 @@ bool ManagedCallable::compare_less(const CallableCustom *p_a, const CallableCust } uint32_t ManagedCallable::hash() const { - // hmm uint32_t hash = delegate_invoke->get_name().hash(); - return hash_djb2_one_64(delegate_handle.handle, hash); + return hash_murmur3_one_64(delegate_handle.handle, hash); } String ManagedCallable::get_as_text() const { diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index 44a8e26b8f..fd78fae4ad 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -140,8 +140,11 @@ void CachedData::clear_godot_api_cache() { field_ExportAttribute_hintString = nullptr; class_SignalAttribute = nullptr; class_ToolAttribute = nullptr; - class_AnyPeerAttribute = nullptr; - class_AuthorityAttribute = nullptr; + class_RPCAttribute = nullptr; + property_RPCAttribute_Mode = nullptr; + property_RPCAttribute_CallLocal = nullptr; + property_RPCAttribute_TransferMode = nullptr; + property_RPCAttribute_TransferChannel = nullptr; class_GodotMethodAttribute = nullptr; field_GodotMethodAttribute_methodName = nullptr; class_ScriptPathAttribute = nullptr; @@ -268,8 +271,11 @@ void update_godot_api_cache() { CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString")); CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute)); CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute)); - CACHE_CLASS_AND_CHECK(AnyPeerAttribute, GODOT_API_CLASS(AnyPeerAttribute)); - CACHE_CLASS_AND_CHECK(AuthorityAttribute, GODOT_API_CLASS(AuthorityAttribute)); + CACHE_CLASS_AND_CHECK(RPCAttribute, GODOT_API_CLASS(RPCAttribute)); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, Mode, CACHED_CLASS(RPCAttribute)->get_property("Mode")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, CallLocal, CACHED_CLASS(RPCAttribute)->get_property("CallLocal")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferMode, CACHED_CLASS(RPCAttribute)->get_property("TransferMode")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferChannel, CACHED_CLASS(RPCAttribute)->get_property("TransferChannel")); 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)); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 92136e1f41..b3b0865608 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -111,8 +111,11 @@ struct CachedData { GDMonoField *field_ExportAttribute_hintString = nullptr; GDMonoClass *class_SignalAttribute = nullptr; GDMonoClass *class_ToolAttribute = nullptr; - GDMonoClass *class_AnyPeerAttribute = nullptr; - GDMonoClass *class_AuthorityAttribute = nullptr; + GDMonoClass *class_RPCAttribute = nullptr; + GDMonoProperty *property_RPCAttribute_Mode = nullptr; + GDMonoProperty *property_RPCAttribute_CallLocal = nullptr; + GDMonoProperty *property_RPCAttribute_TransferMode = nullptr; + GDMonoProperty *property_RPCAttribute_TransferChannel = nullptr; GDMonoClass *class_GodotMethodAttribute = nullptr; GDMonoField *field_GodotMethodAttribute_methodName = nullptr; GDMonoClass *class_ScriptPathAttribute = nullptr; diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 315a9c29f6..618e1b58e0 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -63,7 +63,7 @@ bool SignalAwaiterCallable::compare_less(const CallableCustom *p_a, const Callab uint32_t SignalAwaiterCallable::hash() const { uint32_t hash = signal.hash(); - return hash_djb2_one_64(target_id, hash); + return hash_murmur3_one_64(target_id, hash); } String SignalAwaiterCallable::get_as_text() const { @@ -164,7 +164,7 @@ bool EventSignalCallable::compare_less(const CallableCustom *p_a, const Callable uint32_t EventSignalCallable::hash() const { uint32_t hash = event_signal->field->get_name().hash(); - return hash_djb2_one_64(owner->get_instance_id(), hash); + return hash_murmur3_one_64(owner->get_instance_id(), hash); } String EventSignalCallable::get_as_text() const { diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index 15a0b28181..a1905dfcfe 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -62,7 +62,8 @@ String cwd() { } String result; - if (result.parse_utf16(buffer.ptr())) { + result.parse_utf16(buffer.ptr()); + if (result.is_empty()) { return "."; } return result.simplify_path(); @@ -73,7 +74,7 @@ String cwd() { } String result; - if (result.parse_utf8(buffer)) { + if (result.parse_utf8(buffer) != OK) { return "."; } @@ -114,7 +115,8 @@ String realpath(const String &p_path) { ::CloseHandle(hFile); String result; - if (result.parse_utf16(buffer.ptr())) { + result.parse_utf16(buffer.ptr()); + if (result.is_empty()) { return p_path; } @@ -127,10 +129,10 @@ String realpath(const String &p_path) { } String result; - bool parse_ok = result.parse_utf8(resolved_path); + Error parse_ok = result.parse_utf8(resolved_path); ::free(resolved_path); - if (parse_ok) { + if (parse_ok != OK) { return p_path; } diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index e6975611d2..975f2d8332 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -145,7 +145,7 @@ bool is_csharp_keyword(const String &p_name) { p_name == "do" || p_name == "double" || p_name == "else" || p_name == "enum" || p_name == "event" || p_name == "explicit" || p_name == "extern" || p_name == "false" || p_name == "finally" || p_name == "fixed" || p_name == "float" || p_name == "for" || - p_name == "forech" || p_name == "goto" || p_name == "if" || p_name == "implicit" || + p_name == "foreach" || p_name == "goto" || p_name == "if" || p_name == "implicit" || p_name == "in" || p_name == "int" || p_name == "interface" || p_name == "internal" || p_name == "is" || p_name == "lock" || p_name == "long" || p_name == "namespace" || p_name == "new" || p_name == "null" || p_name == "object" || p_name == "operator" || @@ -178,7 +178,7 @@ Error read_all_file_utf8(const String &p_path, String &r_content) { w[len] = 0; String source; - if (source.parse_utf8((const char *)w)) { + if (source.parse_utf8((const char *)w) != OK) { ERR_FAIL_V(ERR_INVALID_DATA); } |