فهرست منبع

Merge pull request #71356 from raulsntos/dotnet/get

C#: Lookup signals and methods in Get method
Rémi Verschelde 2 سال پیش
والد
کامیت
0d1b5f8832

+ 33 - 0
modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs

@@ -272,6 +272,25 @@ namespace Godot.SourceGenerators
                 source.Append("    }\n");
             }
 
+            // Generate HasGodotClassSignal
+
+            if (godotSignalDelegates.Count > 0)
+            {
+                source.Append(
+                    "    protected override bool HasGodotClassSignal(in godot_string_name signal)\n    {\n");
+
+                bool isFirstEntry = true;
+                foreach (var signal in godotSignalDelegates)
+                {
+                    GenerateHasSignalEntry(signal.Name, source, isFirstEntry);
+                    isFirstEntry = false;
+                }
+
+                source.Append("        return base.HasGodotClassSignal(signal);\n");
+
+                source.Append("    }\n");
+            }
+
             source.Append("}\n"); // partial class
 
             if (isInnerClass)
@@ -397,6 +416,20 @@ namespace Godot.SourceGenerators
                 PropertyHint.None, string.Empty, propUsage, exported: false);
         }
 
+        private static void GenerateHasSignalEntry(
+            string signalName,
+            StringBuilder source,
+            bool isFirstEntry
+        )
+        {
+            source.Append("        ");
+            if (!isFirstEntry)
+                source.Append("else ");
+            source.Append("if (signal == SignalName.");
+            source.Append(signalName);
+            source.Append(") {\n           return true;\n        }\n");
+        }
+
         private static void GenerateSignalEventInvoker(
             GodotSignalDelegateData signal,
             StringBuilder source

+ 40 - 0
modules/mono/editor/bindings_generator.cpp

@@ -84,10 +84,12 @@ StringBuilder &operator<<(StringBuilder &r_sb, const char *p_cstring) {
 #define CS_PROPERTY_SINGLETON "Singleton"
 #define CS_METHOD_INVOKE_GODOT_CLASS_METHOD "InvokeGodotClassMethod"
 #define CS_METHOD_HAS_GODOT_CLASS_METHOD "HasGodotClassMethod"
+#define CS_METHOD_HAS_GODOT_CLASS_SIGNAL "HasGodotClassSignal"
 
 #define CS_STATIC_FIELD_NATIVE_CTOR "NativeCtor"
 #define CS_STATIC_FIELD_METHOD_BIND_PREFIX "MethodBind"
 #define CS_STATIC_FIELD_METHOD_PROXY_NAME_PREFIX "MethodProxyName_"
+#define CS_STATIC_FIELD_SIGNAL_PROXY_NAME_PREFIX "SignalProxyName_"
 
 #define ICALL_PREFIX "godot_icall_"
 #define ICALL_CLASSDB_GET_METHOD "ClassDB_get_method"
@@ -1640,6 +1642,16 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 				   << " = \"" << imethod.proxy_name << "\";\n";
 		}
 
+		// Generate signal names cache fields
+
+		for (const SignalInterface &isignal : itype.signals_) {
+			output << MEMBER_BEGIN "// ReSharper disable once InconsistentNaming\n"
+				   << INDENT1 "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
+				   << INDENT1 "private static readonly StringName "
+				   << CS_STATIC_FIELD_SIGNAL_PROXY_NAME_PREFIX << isignal.name
+				   << " = \"" << isignal.proxy_name << "\";\n";
+		}
+
 		// TODO: Only generate HasGodotClassMethod and InvokeGodotClassMethod if there's any method
 
 		// Generate InvokeGodotClassMethod
@@ -1753,6 +1765,34 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 		}
 
 		output << INDENT1 "}\n";
+
+		// Generate HasGodotClassSignal
+
+		output << MEMBER_BEGIN "protected internal " << (is_derived_type ? "override" : "virtual")
+			   << " bool " CS_METHOD_HAS_GODOT_CLASS_SIGNAL "(in godot_string_name signal)\n"
+			   << INDENT1 "{\n";
+
+		for (const SignalInterface &isignal : itype.signals_) {
+			// We check for native names (snake_case). If we detect one, we call HasGodotClassSignal
+			// again, but this time with the respective proxy name (PascalCase). It's the job of
+			// user derived classes to override the method and check for those. Our C# source
+			// generators take care of generating those override methods.
+			output << INDENT2 "if (signal == SignalName." << isignal.proxy_name
+				   << ")\n" INDENT2 "{\n"
+				   << INDENT3 "if (" CS_METHOD_HAS_GODOT_CLASS_SIGNAL "("
+				   << CS_STATIC_FIELD_SIGNAL_PROXY_NAME_PREFIX << isignal.name
+				   << ".NativeValue.DangerousSelfRef))\n" INDENT3 "{\n"
+				   << INDENT4 "return true;\n"
+				   << INDENT3 "}\n" INDENT2 "}\n";
+		}
+
+		if (is_derived_type) {
+			output << INDENT2 "return base." CS_METHOD_HAS_GODOT_CLASS_SIGNAL "(signal);\n";
+		} else {
+			output << INDENT2 "return false;\n";
+		}
+
+		output << INDENT1 "}\n";
 	}
 
 	//Generate StringName for all class members

+ 17 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs

@@ -84,12 +84,29 @@ namespace Godot.Bridge
                 if (godotObject == null)
                     throw new InvalidOperationException();
 
+                // Properties
                 if (godotObject.GetGodotClassPropertyValue(CustomUnsafe.AsRef(name), out godot_variant outRetValue))
                 {
                     *outRet = outRetValue;
                     return godot_bool.True;
                 }
 
+                // Signals
+                if (godotObject.HasGodotClassSignal(CustomUnsafe.AsRef(name)))
+                {
+                    godot_signal signal = new godot_signal(*name, godotObject.GetInstanceId());
+                    *outRet = VariantUtils.CreateFromSignalTakingOwnershipOfDisposableValue(signal);
+                    return godot_bool.True;
+                }
+
+                // Methods
+                if (godotObject.HasGodotClassMethod(CustomUnsafe.AsRef(name)))
+                {
+                    godot_callable method = new godot_callable(*name, godotObject.GetInstanceId());
+                    *outRet = VariantUtils.CreateFromCallableTakingOwnershipOfDisposableValue(method);
+                    return godot_bool.True;
+                }
+
                 var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
                     NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(name)));