summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
authorRaul Santos <raulsntos@gmail.com>2023-01-13 20:59:02 +0100
committerRaul Santos <raulsntos@gmail.com>2023-01-13 22:19:25 +0100
commita6ba914f1505a5db165a7b3fe44aa7d3c06cdf8b (patch)
treebd5342a509df403bf114b25f6be121d5a7a5f38b /modules/mono
parent3c9bf4bc210a8e6a208f30ca59de4d4d7e18c04d (diff)
C#: Lookup signals and methods in Get method
Allows to retrieve `Callable`s and `Signal`s using `Get` like it works in GDScript.
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs33
-rw-r--r--modules/mono/editor/bindings_generator.cpp40
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs17
3 files changed, 90 insertions, 0 deletions
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
index ba6c10aa31..d67cb5349d 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
+++ b/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
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index c0d88553ad..3bdd67603b 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/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"
@@ -1608,6 +1610,16 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
<< " = \"" << imethod.proxy_name << "\";\n";
}
+ // Generate signal names cache fields
+
+ for (const SignalInterface &isignal : itype.signals_) {
+ output << MEMBER_BEGIN "// ReSharper disable once InconsistentNaming\n"
+ << INDENT1 "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
+ << INDENT1 "private static readonly StringName "
+ << CS_STATIC_FIELD_SIGNAL_PROXY_NAME_PREFIX << isignal.name
+ << " = \"" << isignal.proxy_name << "\";\n";
+ }
+
// TODO: Only generate HasGodotClassMethod and InvokeGodotClassMethod if there's any method
// Generate InvokeGodotClassMethod
@@ -1721,6 +1733,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
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs
index 354212da1b..ccb21502c0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs
+++ b/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)));