summaryrefslogtreecommitdiff
path: root/modules/mono/glue/base_object_glue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/glue/base_object_glue.cpp')
-rw-r--r--modules/mono/glue/base_object_glue.cpp113
1 files changed, 97 insertions, 16 deletions
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 58916c5283..7385014a53 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 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 */
@@ -33,12 +33,14 @@
#ifdef MONO_GLUE_ENABLED
#include "core/reference.h"
-#include "core/string_db.h"
+#include "core/string_name.h"
#include "../csharp_script.h"
+#include "../mono_gd/gd_mono_class.h"
#include "../mono_gd/gd_mono_internals.h"
#include "../mono_gd/gd_mono_utils.h"
#include "../signal_awaiter_utils.h"
+#include "arguments_vector.h"
Object *godot_icall_Object_Ctor(MonoObject *p_obj) {
Object *instance = memnew(Object);
@@ -65,14 +67,17 @@ 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());
if (data) {
- Ref<MonoGCHandle> &gchandle = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get().gchandle;
- if (gchandle.is_valid()) {
- CSharpLanguage::release_script_gchandle(p_obj, gchandle);
+ CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ if (script_binding.inited) {
+ Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
+ if (gchandle.is_valid()) {
+ CSharpLanguage::release_script_gchandle(p_obj, gchandle);
+ }
}
}
}
-void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_finalizer) {
+void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
#ifdef DEBUG_ENABLED
CRASH_COND(p_ptr == NULL);
// This is only called with Reference derived classes
@@ -85,11 +90,14 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_
CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(ref->get_script_instance());
if (cs_instance) {
if (!cs_instance->is_destructing_script_instance()) {
- bool r_owner_deleted;
- cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, r_owner_deleted);
- if (!r_owner_deleted && !p_is_finalizer) {
- // If the native instance is still alive and Dispose() was called
- // (instead of the finalizer), then we remove the script instance.
+ bool delete_owner;
+ bool remove_script_instance;
+
+ cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, delete_owner, remove_script_instance);
+
+ if (delete_owner) {
+ memdelete(ref);
+ } else if (remove_script_instance) {
ref->set_script_instance(NULL);
}
}
@@ -105,9 +113,12 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_
void *data = ref->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
if (data) {
- Ref<MonoGCHandle> &gchandle = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get().gchandle;
- if (gchandle.is_valid()) {
- CSharpLanguage::release_script_gchandle(p_obj, gchandle);
+ CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ if (script_binding.inited) {
+ Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
+ if (gchandle.is_valid()) {
+ CSharpLanguage::release_script_gchandle(p_obj, gchandle);
+ }
}
}
}
@@ -138,7 +149,7 @@ MonoObject *godot_icall_Object_weakref(Object *p_obj) {
wref->set_obj(p_obj);
}
- return GDMonoUtils::create_managed_for_godot_object(CACHED_CLASS(WeakRef), Reference::get_class_static(), Object::cast_to<Object>(wref.ptr()));
+ return GDMonoUtils::unmanaged_get_managed(wref.ptr());
}
Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal, Object *p_target, MonoObject *p_awaiter) {
@@ -146,13 +157,83 @@ Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal,
return SignalAwaiterUtils::connect_signal_awaiter(p_source, signal, p_target, p_awaiter);
}
+MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
+ List<PropertyInfo> property_list;
+ p_ptr->get_property_list(&property_list);
+
+ 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);
+ mono_array_set(result, MonoString *, i, boxed);
+ i++;
+ }
+
+ return result;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoString *p_name, MonoArray *p_args, MonoObject **r_result) {
+ String name = GDMonoMarshal::mono_string_to_godot(p_name);
+
+ int argc = mono_array_length(p_args);
+
+ ArgumentsVector<Variant> arg_store(argc);
+ ArgumentsVector<const Variant *> args(argc);
+
+ for (int i = 0; i < argc; i++) {
+ MonoObject *elem = mono_array_get(p_args, MonoObject *, i);
+ arg_store.set(i, GDMonoMarshal::mono_object_to_variant(elem));
+ args.set(i, &arg_store.get(i));
+ }
+
+ Variant::CallError error;
+ Variant result = p_ptr->call(StringName(name), args.ptr(), argc, error);
+
+ *r_result = GDMonoMarshal::variant_to_mono_object(result);
+
+ return error.error == Variant::CallError::CALL_OK;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result) {
+ String name = GDMonoMarshal::mono_string_to_godot(p_name);
+
+ bool valid;
+ Variant value = p_ptr->get(StringName(name), &valid);
+
+ if (valid) {
+ *r_result = GDMonoMarshal::variant_to_mono_object(value);
+ }
+
+ return valid;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value) {
+ String name = GDMonoMarshal::mono_string_to_godot(p_name);
+ Variant value = GDMonoMarshal::mono_object_to_variant(p_value);
+
+ bool valid;
+ p_ptr->set(StringName(name), value, &valid);
+
+ return valid;
+}
+
+MonoString *godot_icall_Object_ToString(Object *p_ptr) {
+ return GDMonoMarshal::mono_string_from_godot(Variant(p_ptr).operator String());
+}
+
void godot_register_object_icalls() {
mono_add_internal_call("Godot.Object::godot_icall_Object_Ctor", (void *)godot_icall_Object_Ctor);
mono_add_internal_call("Godot.Object::godot_icall_Object_Disposed", (void *)godot_icall_Object_Disposed);
mono_add_internal_call("Godot.Object::godot_icall_Reference_Disposed", (void *)godot_icall_Reference_Disposed);
mono_add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", (void *)godot_icall_Object_ClassDB_get_method);
+ mono_add_internal_call("Godot.Object::godot_icall_Object_ToString", (void *)godot_icall_Object_ToString);
mono_add_internal_call("Godot.Object::godot_icall_Object_weakref", (void *)godot_icall_Object_weakref);
mono_add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", (void *)godot_icall_SignalAwaiter_connect);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMemberList", (void *)godot_icall_DynamicGodotObject_SetMemberList);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_InvokeMember", (void *)godot_icall_DynamicGodotObject_InvokeMember);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_GetMember", (void *)godot_icall_DynamicGodotObject_GetMember);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMember", (void *)godot_icall_DynamicGodotObject_SetMember);
}
#endif // MONO_GLUE_ENABLED