diff options
-rw-r--r-- | modules/mono/csharp_script.cpp | 31 | ||||
-rw-r--r-- | modules/mono/csharp_script.h | 4 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_class.cpp | 21 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_class.h | 7 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_method.cpp | 27 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_method.h | 5 |
6 files changed, 93 insertions, 2 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 3c818898e6..943d95bfc9 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2474,6 +2474,18 @@ void CSharpScript::set_source_code(const String &p_code) { #endif } +void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const { + + if (!script_class) + return; + + // 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()); + } +} + bool CSharpScript::has_method(const StringName &p_method) const { if (!script_class) @@ -2482,6 +2494,25 @@ bool CSharpScript::has_method(const StringName &p_method) const { return script_class->has_fetched_method_unknown_params(p_method); } +MethodInfo CSharpScript::get_method_info(const StringName &p_method) const { + + if (!script_class) + return MethodInfo(); + + GDMonoClass *top = script_class; + + while (top && top != native) { + GDMonoMethod *params = top->get_fetched_method_unknown_params(p_method); + if (params) { + return params->get_method_info(); + } + + top = top->get_parent_class(); + } + + return MethodInfo(); +} + Error CSharpScript::reload(bool p_keep_state) { bool has_instances; diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 501e0d9d6d..08466bae58 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -174,9 +174,9 @@ public: virtual Ref<Script> get_base_script() const; virtual ScriptLanguage *get_language() const; - /* TODO */ virtual void get_script_method_list(List<MethodInfo> *p_list) const {} + virtual void get_script_method_list(List<MethodInfo> *p_list) const; bool has_method(const StringName &p_method) const; - /* TODO */ MethodInfo get_method_info(const StringName &p_method) const { return MethodInfo(); } + MethodInfo get_method_info(const StringName &p_method) const; virtual int get_member_line(const StringName &p_member) const; diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 4e515cde28..c55f9160bd 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -151,6 +151,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) { StringName name = mono_method_get_name(raw_method); + // get_method implicitly fetches methods and adds them to this->methods GDMonoMethod *method = get_method(raw_method, name); ERR_CONTINUE(!method); @@ -449,6 +450,21 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() { return delegates_list; } +const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() { + + if (!method_list_fetched) { + void *iter = NULL; + MonoMethod *raw_method = NULL; + while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) { + method_list.push_back(memnew(GDMonoMethod(mono_method_get_name(raw_method), raw_method))); + } + + method_list_fetched = true; + } + + return method_list; +} + GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) { namespace_name = p_namespace; @@ -460,6 +476,7 @@ GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name attributes = NULL; methods_fetched = false; + method_list_fetched = false; fields_fetched = false; properties_fetched = false; delegates_fetched = false; @@ -512,4 +529,8 @@ GDMonoClass::~GDMonoClass() { methods.clear(); } + + for (int i = 0; i < method_list.size(); ++i) { + memdelete(method_list[i]); + } } diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index 477305d503..689001f494 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -79,9 +79,14 @@ class GDMonoClass { bool attrs_fetched; MonoCustomAttrInfo *attributes; + // This contains both the original method names and remapped method names from the native Godot identifiers to the C# functions. + // Most method-related functions refer to this and it's possible this is unintuitive for outside users; this may be a prime location for refactoring or renaming. bool methods_fetched; HashMap<MethodKey, GDMonoMethod *, MethodKey::Hasher> methods; + bool method_list_fetched; + Vector<GDMonoMethod *> method_list; + bool fields_fetched; Map<StringName, GDMonoField *> fields; Vector<GDMonoField *> fields_list; @@ -143,6 +148,8 @@ public: const Vector<GDMonoClass *> &get_all_delegates(); + const Vector<GDMonoMethod *> &get_all_methods(); + ~GDMonoClass(); }; diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp index 630bda8b4e..6ef6e97f5a 100644 --- a/modules/mono/mono_gd/gd_mono_method.cpp +++ b/modules/mono/mono_gd/gd_mono_method.cpp @@ -68,6 +68,10 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) { param_types.push_back(param_type); } + + // clear the cache + method_info_fetched = false; + method_info = MethodInfo(); } bool GDMonoMethod::is_static() { @@ -246,11 +250,34 @@ void GDMonoMethod::get_parameter_types(Vector<ManagedType> &types) const { } } +const MethodInfo &GDMonoMethod::get_method_info() { + + if (!method_info_fetched) { + method_info.name = name; + method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type), ""); + + Vector<StringName> names; + get_parameter_names(names); + + for (int i = 0; i < params_count; ++i) { + method_info.arguments.push_back(PropertyInfo(GDMonoMarshal::managed_to_variant_type(param_types[i]), names[i])); + } + + // TODO: default arguments + + method_info_fetched = true; + } + + return method_info; +} + GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) { name = p_name; mono_method = p_method; + method_info_fetched = false; + attrs_fetched = false; attributes = NULL; diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h index 444ec2a67d..6c3ae5fce0 100644 --- a/modules/mono/mono_gd/gd_mono_method.h +++ b/modules/mono/mono_gd/gd_mono_method.h @@ -43,6 +43,9 @@ class GDMonoMethod : public GDMonoClassMember { ManagedType return_type; Vector<ManagedType> param_types; + bool method_info_fetched; + MethodInfo method_info; + bool attrs_fetched; MonoCustomAttrInfo *attributes; @@ -83,6 +86,8 @@ public: void get_parameter_names(Vector<StringName> &names) const; void get_parameter_types(Vector<ManagedType> &types) const; + const MethodInfo &get_method_info(); + GDMonoMethod(StringName p_name, MonoMethod *p_method); ~GDMonoMethod(); }; |