diff options
Diffstat (limited to 'modules/mono')
59 files changed, 1753 insertions, 643 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index af5a0334c3..949c636050 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "csharp_script.h" #include <mono/metadata/threads.h> @@ -122,6 +123,16 @@ void CSharpLanguage::init() { void CSharpLanguage::finish() { + finalizing = true; + +#ifdef TOOLS_ENABLED + // Must be here, to avoid StringName leaks + if (BindingsGenerator::singleton) { + memdelete(BindingsGenerator::singleton); + BindingsGenerator::singleton = NULL; + } +#endif + // Release gchandle bindings before finalizing mono runtime gchandle_bindings.clear(); @@ -129,6 +140,8 @@ void CSharpLanguage::finish() { memdelete(gdmono); gdmono = NULL; } + + finalizing = false; } void CSharpLanguage::get_reserved_words(List<String> *p_words) const { @@ -742,6 +755,8 @@ CSharpLanguage::CSharpLanguage() { ERR_FAIL_COND(singleton); singleton = this; + finalizing = false; + gdmono = NULL; #ifdef NO_THREADS @@ -798,12 +813,9 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { ERR_FAIL_NULL_V(mono_object, NULL); // Tie managed to unmanaged - bool strong_handle = true; Reference *ref = Object::cast_to<Reference>(p_object); if (ref) { - strong_handle = false; - // Unsafe refcount increment. The managed instance also counts as a reference. // This way if the unmanaged world has no references to our owner // but the managed instance is alive, the refcount will be 1 instead of 0. @@ -812,8 +824,7 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { ref->reference(); } - Ref<MonoGCHandle> gchandle = strong_handle ? MonoGCHandle::create_strong(mono_object) : - MonoGCHandle::create_weak(mono_object); + Ref<MonoGCHandle> gchandle = MonoGCHandle::create_strong(mono_object); #ifndef NO_THREADS script_bind_lock->lock(); @@ -838,27 +849,38 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { return; } + if (finalizing) + return; // inside CSharpLanguage::finish(), all the gchandle bindings are released there + #ifndef NO_THREADS script_bind_lock->lock(); #endif - gchandle_bindings.erase((Map<Object *, Ref<MonoGCHandle> >::Element *)p_data); + Map<Object *, Ref<MonoGCHandle> >::Element *data = (Map<Object *, Ref<MonoGCHandle> >::Element *)p_data; + + // Set the native instance field to IntPtr.Zero, if not yet garbage collected + MonoObject *mono_object = data->value()->get_target(); + if (mono_object) { + CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, NULL); + } + + gchandle_bindings.erase(data); #ifndef NO_THREADS script_bind_lock->unlock(); #endif } -void CSharpInstance::_ml_call_reversed(GDMonoClass *klass, const StringName &p_method, const Variant **p_args, int p_argcount) { +void CSharpInstance::_ml_call_reversed(MonoObject *p_mono_object, GDMonoClass *p_klass, const StringName &p_method, const Variant **p_args, int p_argcount) { - GDMonoClass *base = klass->get_parent_class(); + GDMonoClass *base = p_klass->get_parent_class(); if (base && base != script->native) - _ml_call_reversed(base, p_method, p_args, p_argcount); + _ml_call_reversed(p_mono_object, base, p_method, p_args, p_argcount); - GDMonoMethod *method = klass->get_method(p_method, p_argcount); + GDMonoMethod *method = p_klass->get_method(p_method, p_argcount); if (method) { - method->invoke(get_mono_object(), p_args); + method->invoke(p_mono_object, p_args); } } @@ -892,19 +914,23 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_COND_V(!script.is_valid(), false); + MonoObject *mono_object = get_mono_object(); + ERR_FAIL_NULL_V(mono_object, false); + GDMonoClass *top = script->script_class; while (top && top != script->native) { GDMonoField *field = script->script_class->get_field(p_name); if (field) { - MonoObject *mono_object = get_mono_object(); - - ERR_EXPLAIN("Reference has been garbage collected?"); - ERR_FAIL_NULL_V(mono_object, false); + field->set_value_from_variant(mono_object, p_value); + return true; + } - field->set_value(mono_object, p_value); + GDMonoProperty *property = script->script_class->get_property(p_name); + if (property) { + property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object(p_value)); return true; } @@ -913,16 +939,15 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { // Call _set - Variant name = p_name; - const Variant *args[2] = { &name, &p_value }; - - MonoObject *mono_object = get_mono_object(); top = script->script_class; while (top && top != script->native) { GDMonoMethod *method = top->get_method(CACHED_STRING_NAME(_set), 2); if (method) { + Variant name = p_name; + const Variant *args[2] = { &name, &p_value }; + MonoObject *ret = method->invoke(mono_object, args); if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret) == true) @@ -939,31 +964,49 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const { ERR_FAIL_COND_V(!script.is_valid(), false); + MonoObject *mono_object = get_mono_object(); + ERR_FAIL_NULL_V(mono_object, false); + GDMonoClass *top = script->script_class; while (top && top != script->native) { GDMonoField *field = top->get_field(p_name); if (field) { - MonoObject *mono_object = get_mono_object(); - - ERR_EXPLAIN("Reference has been garbage collected?"); - ERR_FAIL_NULL_V(mono_object, false); - MonoObject *value = field->get_value(mono_object); r_ret = GDMonoMarshal::mono_object_to_variant(value, field->get_type()); return true; } - // Call _get + GDMonoProperty *property = top->get_property(p_name); + + if (property) { + MonoObject *exc = NULL; + MonoObject *value = property->get_value(mono_object, &exc); + if (exc) { + r_ret = Variant(); + GDMonoUtils::print_unhandled_exception(exc); + } else { + r_ret = GDMonoMarshal::mono_object_to_variant(value, property->get_type()); + } + return true; + } + + top = top->get_parent_class(); + } + + // Call _get + top = script->script_class; + + while (top && top != script->native) { GDMonoMethod *method = top->get_method(CACHED_STRING_NAME(_get), 1); if (method) { Variant name = p_name; const Variant *args[1] = { &name }; - MonoObject *ret = method->invoke(get_mono_object(), args); + MonoObject *ret = method->invoke(mono_object, args); if (ret) { r_ret = GDMonoMarshal::mono_object_to_variant(ret); @@ -1020,7 +1063,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, MonoObject *mono_object = get_mono_object(); - ERR_EXPLAIN("Reference has been garbage collected?"); ERR_FAIL_NULL_V(mono_object, Variant()); if (!script.is_valid()) @@ -1054,23 +1096,34 @@ void CSharpInstance::call_multilevel(const StringName &p_method, const Variant * if (script.is_valid()) { MonoObject *mono_object = get_mono_object(); - GDMonoClass *top = script->script_class; + ERR_FAIL_NULL(mono_object); - while (top && top != script->native) { - GDMonoMethod *method = top->get_method(p_method, p_argcount); + _call_multilevel(mono_object, p_method, p_args, p_argcount); + } +} - if (method) - method->invoke(mono_object, p_args); +void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount) { - top = top->get_parent_class(); - } + GDMonoClass *top = script->script_class; + + while (top && top != script->native) { + GDMonoMethod *method = top->get_method(p_method, p_argcount); + + if (method) + method->invoke(p_mono_object, p_args); + + top = top->get_parent_class(); } } void CSharpInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { if (script.is_valid()) { - _ml_call_reversed(script->script_class, p_method, p_args, p_argcount); + MonoObject *mono_object = get_mono_object(); + + ERR_FAIL_NULL(mono_object); + + _ml_call_reversed(mono_object, script->script_class, p_method, p_args, p_argcount); } } @@ -1118,7 +1171,7 @@ void CSharpInstance::refcount_incremented() { Reference *ref_owner = Object::cast_to<Reference>(owner); - if (ref_owner->reference_get_count() > 1) { // Remember the managed side holds a reference, hence 1 instead of 0 here + if (ref_owner->reference_get_count() > 1) { // The managed side also holds a reference, hence 1 instead of 0 // The reference count was increased after the managed side was the only one referencing our owner. // This means the owner is being referenced again by the unmanaged side, // so the owner must hold the managed side alive again to avoid it from being GCed. @@ -1138,7 +1191,7 @@ bool CSharpInstance::refcount_decremented() { int refcount = ref_owner->reference_get_count(); - if (refcount == 1) { // Remember the managed side holds a reference, hence 1 instead of 0 here + if (refcount == 1) { // The managed side also holds a reference, hence 1 instead of 0 // If owner owner is no longer referenced by the unmanaged side, // the managed instance takes responsibility of deleting the owner when GCed. @@ -1155,6 +1208,20 @@ bool CSharpInstance::refcount_decremented() { return ref_dying; } +ScriptInstance::RPCMode CSharpInstance::_member_get_rpc_mode(GDMonoClassMember *p_member) const { + + if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) + return RPC_MODE_REMOTE; + if (p_member->has_attribute(CACHED_CLASS(SyncAttribute))) + return RPC_MODE_SYNC; + if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) + return RPC_MODE_MASTER; + if (p_member->has_attribute(CACHED_CLASS(SlaveAttribute))) + return RPC_MODE_SLAVE; + + return RPC_MODE_DISABLED; +} + ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const { GDMonoClass *top = script->script_class; @@ -1162,17 +1229,8 @@ ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) while (top && top != script->native) { GDMonoMethod *method = top->get_method(p_method); - if (method) { // TODO should we reject static methods? - // TODO cache result - if (method->has_attribute(CACHED_CLASS(RemoteAttribute))) - return RPC_MODE_REMOTE; - if (method->has_attribute(CACHED_CLASS(SyncAttribute))) - return RPC_MODE_SYNC; - if (method->has_attribute(CACHED_CLASS(MasterAttribute))) - return RPC_MODE_MASTER; - if (method->has_attribute(CACHED_CLASS(SlaveAttribute))) - return RPC_MODE_SLAVE; - } + if (method && !method->is_static()) + return _member_get_rpc_mode(method); top = top->get_parent_class(); } @@ -1187,17 +1245,13 @@ ScriptInstance::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab while (top && top != script->native) { GDMonoField *field = top->get_field(p_variable); - if (field) { // TODO should we reject static fields? - // TODO cache result - if (field->has_attribute(CACHED_CLASS(RemoteAttribute))) - return RPC_MODE_REMOTE; - if (field->has_attribute(CACHED_CLASS(SyncAttribute))) - return RPC_MODE_SYNC; - if (field->has_attribute(CACHED_CLASS(MasterAttribute))) - return RPC_MODE_MASTER; - if (field->has_attribute(CACHED_CLASS(SlaveAttribute))) - return RPC_MODE_SLAVE; - } + if (field && !field->is_static()) + return _member_get_rpc_mode(field); + + GDMonoProperty *property = top->get_property(p_variable); + + if (property && !property->is_static()) + return _member_get_rpc_mode(property); top = top->get_parent_class(); } @@ -1207,10 +1261,25 @@ ScriptInstance::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab void CSharpInstance::notification(int p_notification) { + MonoObject *mono_object = get_mono_object(); + + if (p_notification == Object::NOTIFICATION_PREDELETE) { + if (mono_object != NULL) { // otherwise it was collected, and the finalizer already called NOTIFICATION_PREDELETE + call_notification_no_check(mono_object, p_notification); + // Set the native instance field to IntPtr.Zero + CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, NULL); + } + return; + } + + call_notification_no_check(mono_object, p_notification); +} + +void CSharpInstance::call_notification_no_check(MonoObject *p_mono_object, int p_notification) { Variant value = p_notification; const Variant *args[1] = { &value }; - call_multilevel(CACHED_STRING_NAME(_notification), args, 1); + _call_multilevel(p_mono_object, CACHED_STRING_NAME(_notification), args, 1); } Ref<Script> CSharpInstance::get_script() const { @@ -1307,7 +1376,7 @@ bool CSharpScript::_update_exports() { // We are creating a temporary new instance of the class here to get the default value // TODO Workaround. Should be replaced with IL opcodes analysis - MonoObject *tmp_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_raw()); + MonoObject *tmp_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_mono_ptr()); if (tmp_object) { CACHED_FIELD(GodotObject, ptr)->set_value_raw(tmp_object, tmp_object); // FIXME WTF is this workaround @@ -1330,65 +1399,55 @@ bool CSharpScript::_update_exports() { GDMonoClass *top = script_class; while (top && top != native) { + PropertyInfo prop_info; + bool exported; + const Vector<GDMonoField *> &fields = top->get_all_fields(); for (int i = fields.size() - 1; i >= 0; i--) { GDMonoField *field = fields[i]; - if (field->is_static()) { - if (field->has_attribute(CACHED_CLASS(ExportAttribute))) - ERR_PRINTS("Cannot export field because it is static: " + top->get_full_name() + "." + field->get_name()); - continue; - } - - String name = field->get_name(); - StringName cname = name; + if (_get_member_export(top, field, prop_info, exported)) { + StringName name = field->get_name(); - if (member_info.has(cname)) - continue; + if (exported) { + member_info[name] = prop_info; + exported_members_cache.push_front(prop_info); - ManagedType field_type = field->get_type(); - Variant::Type type = GDMonoMarshal::managed_to_variant_type(field_type); + if (tmp_object) { + exported_members_defval_cache[name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); + } + } else { + member_info[name] = prop_info; + } + } + } - if (field->has_attribute(CACHED_CLASS(ExportAttribute))) { - // Field has Export attribute - MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute)); + const Vector<GDMonoProperty *> &properties = top->get_all_properties(); - PropertyHint hint; - String hint_string; + for (int i = properties.size() - 1; i >= 0; i--) { + GDMonoProperty *property = properties[i]; - if (type == Variant::NIL) { - ERR_PRINTS("Unknown type of exported field: " + top->get_full_name() + "." + field->get_name()); - continue; - } else if (type == Variant::INT && field_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(field_type.type_class->get_raw())) { - type = Variant::INT; - hint = PROPERTY_HINT_ENUM; + if (_get_member_export(top, property, prop_info, exported)) { + StringName name = property->get_name(); - Vector<MonoClassField *> fields = field_type.type_class->get_enum_fields(); + if (exported) { + member_info[name] = prop_info; + exported_members_cache.push_front(prop_info); - for (int i = 0; i < fields.size(); i++) { - if (i > 0) - hint_string += ","; - hint_string += mono_field_get_name(fields[i]); + if (tmp_object) { + MonoObject *exc = NULL; + MonoObject *ret = property->get_value(tmp_object, &exc); + if (exc) { + exported_members_defval_cache[name] = Variant(); + GDMonoUtils::print_unhandled_exception(exc); + } else { + exported_members_defval_cache[name] = GDMonoMarshal::mono_object_to_variant(ret); + } } - } else if (type == Variant::OBJECT && CACHED_CLASS(GodotReference)->is_assignable_from(field_type.type_class)) { - hint = PROPERTY_HINT_RESOURCE_TYPE; - hint_string = NATIVE_GDMONOCLASS_NAME(field_type.type_class); } else { - hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); - hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr); + member_info[name] = prop_info; } - - PropertyInfo prop_info = PropertyInfo(type, name, hint, hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE); - - member_info[cname] = prop_info; - exported_members_cache.push_front(prop_info); - - if (tmp_object) { - exported_members_defval_cache[cname] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); - } - } else { - member_info[cname] = PropertyInfo(type, name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE); } } @@ -1412,6 +1471,77 @@ bool CSharpScript::_update_exports() { return false; } +bool CSharpScript::_get_member_export(GDMonoClass *p_class, GDMonoClassMember *p_member, PropertyInfo &r_prop_info, bool &r_exported) { + + StringName name = p_member->get_name(); + + if (p_member->is_static()) { + if (p_member->has_attribute(CACHED_CLASS(ExportAttribute))) + ERR_PRINTS("Cannot export member because it is static: " + p_class->get_full_name() + "." + name.operator String()); + return false; + } + + if (member_info.has(name)) + return false; + + ManagedType type; + + if (p_member->get_member_type() == GDMonoClassMember::MEMBER_TYPE_FIELD) { + type = static_cast<GDMonoField *>(p_member)->get_type(); + } else if (p_member->get_member_type() == GDMonoClassMember::MEMBER_TYPE_PROPERTY) { + type = static_cast<GDMonoProperty *>(p_member)->get_type(); + } else { + CRASH_NOW(); + } + + Variant::Type variant_type = GDMonoMarshal::managed_to_variant_type(type); + + if (p_member->has_attribute(CACHED_CLASS(ExportAttribute))) { + if (p_member->get_member_type() == GDMonoClassMember::MEMBER_TYPE_PROPERTY) { + GDMonoProperty *property = static_cast<GDMonoProperty *>(p_member); + if (!property->has_getter() || !property->has_setter()) { + ERR_PRINTS("Cannot export property because it does not provide a getter or a setter: " + p_class->get_full_name() + "." + name.operator String()); + return false; + } + } + + MonoObject *attr = p_member->get_attribute(CACHED_CLASS(ExportAttribute)); + + PropertyHint hint; + String hint_string; + + if (variant_type == Variant::NIL) { + ERR_PRINTS("Unknown type of exported member: " + p_class->get_full_name() + "." + name.operator String()); + return false; + } else if (variant_type == Variant::INT && type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(type.type_class->get_mono_ptr())) { + variant_type = Variant::INT; + hint = PROPERTY_HINT_ENUM; + + Vector<MonoClassField *> fields = type.type_class->get_enum_fields(); + + for (int i = 0; i < fields.size(); i++) { + if (i > 0) + hint_string += ","; + hint_string += mono_field_get_name(fields[i]); + } + } else if (variant_type == Variant::OBJECT && CACHED_CLASS(GodotReference)->is_assignable_from(type.type_class)) { + hint = PROPERTY_HINT_RESOURCE_TYPE; + hint_string = NATIVE_GDMONOCLASS_NAME(type.type_class); + } else { + hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); + hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr); + } + + r_prop_info = PropertyInfo(variant_type, name.operator String(), hint, hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE); + r_exported = true; + } else { + r_prop_info = PropertyInfo(variant_type, name.operator String(), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE); + r_exported = false; + } + + return true; +} + void CSharpScript::_clear() { tool = false; @@ -1580,7 +1710,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg /* STEP 2, INITIALIZE AND CONSTRUCT */ - MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_raw()); + MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_mono_ptr()); if (!mono_object) { instance->script = Ref<CSharpScript>(); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 255665b495..171601f3d8 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef CSHARP_SCRIPT_H #define CSHARP_SCRIPT_H @@ -104,6 +105,8 @@ class CSharpScript : public Script { void _clear(); bool _update_exports(); + bool _get_member_export(GDMonoClass *p_class, GDMonoClassMember *p_member, PropertyInfo &r_prop_info, bool &r_exported); + CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error); Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error); @@ -167,7 +170,7 @@ class CSharpInstance : public ScriptInstance { bool base_ref; bool ref_dying; - void _ml_call_reversed(GDMonoClass *klass, const StringName &p_method, const Variant **p_args, int p_argcount); + void _ml_call_reversed(MonoObject *p_mono_object, GDMonoClass *klass, const StringName &p_method, const Variant **p_args, int p_argcount); void _reference_owner_unsafe(); void _unreference_owner_unsafe(); @@ -176,6 +179,10 @@ class CSharpInstance : public ScriptInstance { friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *); static CSharpInstance *create_for_managed_type(Object *p_owner, CSharpScript *p_script, const Ref<MonoGCHandle> &p_gchandle); + void _call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount); + + RPCMode _member_get_rpc_mode(GDMonoClassMember *p_member) const; + public: MonoObject *get_mono_object() const; @@ -192,13 +199,14 @@ public: void mono_object_disposed(); - void refcount_incremented(); - bool refcount_decremented(); + virtual void refcount_incremented(); + virtual bool refcount_decremented(); - RPCMode get_rpc_mode(const StringName &p_method) const; - RPCMode get_rset_mode(const StringName &p_variable) const; + virtual RPCMode get_rpc_mode(const StringName &p_method) const; + virtual RPCMode get_rset_mode(const StringName &p_variable) const; virtual void notification(int p_notification); + void call_notification_no_check(MonoObject *p_mono_object, int p_notification); virtual Ref<Script> get_script() const; @@ -215,6 +223,8 @@ class CSharpLanguage : public ScriptLanguage { static CSharpLanguage *singleton; + bool finalizing; + GDMono *gdmono; SelfList<CSharpScript>::List script_list; diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index fbb9b2ed14..2205ac4e98 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "bindings_generator.h" #ifdef DEBUG_METHODS_ENABLED @@ -108,7 +109,9 @@ const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in bool BindingsGenerator::verbose_output = false; -static String snake_to_pascal_case(const String &p_identifier) { +BindingsGenerator *BindingsGenerator::singleton = NULL; + +static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper = false) { String ret; Vector<String> parts = p_identifier.split("_", true); @@ -118,6 +121,10 @@ static String snake_to_pascal_case(const String &p_identifier) { if (part.length()) { part[0] = _find_upper(part[0]); + if (p_input_is_upper) { + for (int j = 1; j < part.length(); j++) + part[j] = _find_lower(part[j]); + } ret += part; } else { if (i == 0 || i == (parts.size() - 1)) { @@ -137,7 +144,7 @@ static String snake_to_pascal_case(const String &p_identifier) { return ret; } -static String snake_to_camel_case(const String &p_identifier) { +static String snake_to_camel_case(const String &p_identifier, bool p_input_is_upper = false) { String ret; Vector<String> parts = p_identifier.split("_", true); @@ -146,8 +153,13 @@ static String snake_to_camel_case(const String &p_identifier) { String part = parts[i]; if (part.length()) { - if (i != 0) + if (i != 0) { part[0] = _find_upper(part[0]); + } + if (p_input_is_upper) { + for (int j = i != 0 ? 1 : 0; j < part.length(); j++) + part[j] = _find_lower(part[j]); + } ret += part; } else { if (i == 0 || i == (parts.size() - 1)) { @@ -167,12 +179,31 @@ static String snake_to_camel_case(const String &p_identifier) { return ret; } +String BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) { + + CRASH_COND(p_ienum.constants.empty()); + + const List<ConstantInterface>::Element *front = p_ienum.constants.front(); + int candidate_len = front->get().name.length(); + + for (const List<ConstantInterface>::Element *E = front->next(); E; E = E->next()) { + int j = 0; + for (j = 0; j < candidate_len && j < E->get().name.length(); j++) { + if (front->get().name[j] != E->get().name[j]) + break; + } + candidate_len = j; + } + + return front->get().name.substr(0, candidate_len); +} + void BindingsGenerator::_generate_header_icalls() { core_custom_icalls.clear(); core_custom_icalls.push_back(InternalCall(ICALL_GET_METHODBIND, "IntPtr", "string type, string method")); - core_custom_icalls.push_back(InternalCall(ICALL_OBJECT_DTOR, "void", "IntPtr ptr")); + core_custom_icalls.push_back(InternalCall(ICALL_OBJECT_DTOR, "void", "object obj, IntPtr ptr")); core_custom_icalls.push_back(InternalCall(ICALL_CONNECT_SIGNAL_AWAITER, "Error", "IntPtr source, string signal, IntPtr target, " CS_CLASS_SIGNALAWAITER " awaiter")); @@ -220,7 +251,7 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type); String im_sig = "IntPtr " CS_PARAM_METHODBIND ", IntPtr " CS_PARAM_INSTANCE; - String im_unique_sig = imethod.return_type + ",IntPtr,IntPtr"; + String im_unique_sig = imethod.return_type.operator String() + ",IntPtr,IntPtr"; // Get arguments information int i = 0; @@ -256,6 +287,129 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { } } +void BindingsGenerator::_generate_global_constants(List<String> &p_output) { + + // Constants (in partial GD class) + + p_output.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); + p_output.push_back(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{"); + + for (const List<ConstantInterface>::Element *E = global_constants.front(); E; E = E->next()) { + const ConstantInterface &iconstant = E->get(); + + if (iconstant.const_doc && iconstant.const_doc->description.size()) { + p_output.push_back(MEMBER_BEGIN "/// <summary>\n"); + + Vector<String> description_lines = iconstant.const_doc->description.split("\n"); + + for (int i = 0; i < description_lines.size(); i++) { + String description_line = description_lines[i].strip_edges(); + if (description_line.size()) { + p_output.push_back(INDENT2 "/// "); + p_output.push_back(description_line.xml_escape()); + p_output.push_back("\n"); + } + } + + p_output.push_back(INDENT2 "/// </summary>"); + } + + p_output.push_back(MEMBER_BEGIN "public const int "); + p_output.push_back(iconstant.name); + p_output.push_back(" = "); + p_output.push_back(itos(iconstant.value)); + p_output.push_back(";"); + } + + if (!global_constants.empty()) + p_output.push_back("\n"); + + p_output.push_back(INDENT1 CLOSE_BLOCK); // end of GD class + + // Enums + + for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) { + const EnumInterface &ienum = E->get(); + + CRASH_COND(ienum.constants.empty()); + + String enum_proxy_name = ienum.cname.operator String(); + + bool enum_in_static_class = false; + + if (enum_proxy_name.find(".") > 0) { + enum_in_static_class = true; + String enum_class_name = enum_proxy_name.get_slicec('.', 0); + enum_proxy_name = enum_proxy_name.get_slicec('.', 1); + + CRASH_COND(enum_class_name != "Variant"); // Hard-coded... + + if (verbose_output) { + WARN_PRINTS("Declaring global enum `" + enum_proxy_name + "` inside static class `" + enum_class_name + "`"); + } + + p_output.push_back("\n" INDENT1 "public static partial class "); + p_output.push_back(enum_class_name); + p_output.push_back("\n" INDENT1 OPEN_BLOCK); + } + + p_output.push_back("\n" INDENT1 "public enum "); + p_output.push_back(enum_proxy_name); + p_output.push_back("\n" INDENT1 OPEN_BLOCK); + + for (const List<ConstantInterface>::Element *E = ienum.constants.front(); E; E = E->next()) { + const ConstantInterface &iconstant = E->get(); + + if (iconstant.const_doc && iconstant.const_doc->description.size()) { + p_output.push_back(INDENT2 "/// <summary>\n"); + + Vector<String> description_lines = iconstant.const_doc->description.split("\n"); + + for (int i = 0; i < description_lines.size(); i++) { + String description_line = description_lines[i].strip_edges(); + if (description_line.size()) { + p_output.push_back(INDENT2 "/// "); + p_output.push_back(description_line.xml_escape()); + p_output.push_back("\n"); + } + } + + p_output.push_back(INDENT2 "/// </summary>\n"); + } + + String constant_name = iconstant.name; + + if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) { + constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length()); + } + + if (constant_name[0] >= '0' && constant_name[0] <= '9') { + // The name of enum constants may begin with a numeric digit when strip from the enum prefix, + // so we make the prefix one word shorter in those cases. + int i = 0; + for (i = ienum.prefix.length() - 1; i >= 0; i--) { + if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z') + break; + } + constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name; + } + + p_output.push_back(INDENT2); + p_output.push_back(constant_name); + p_output.push_back(" = "); + p_output.push_back(itos(iconstant.value)); + p_output.push_back(E != ienum.constants.back() ? ",\n" : "\n"); + } + + p_output.push_back(INDENT1 CLOSE_BLOCK); + + if (enum_in_static_class) + p_output.push_back(INDENT1 CLOSE_BLOCK); + } + + p_output.push_back(CLOSE_BLOCK); // end of namespace +} + Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bool p_verbose_output) { verbose_output = p_verbose_output; @@ -282,7 +436,19 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo if (!solution.set_path(p_output_dir)) return ERR_FILE_NOT_FOUND; - for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { + // Generate source file for global scope constants and enums + { + List<String> constants_source; + _generate_global_constants(constants_source); + String output_file = path_join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs"); + Error save_err = _save_file(output_file, constants_source); + if (save_err != OK) + return save_err; + + compile_items.push_back(output_file); + } + + for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { const TypeInterface &itype = E->get(); if (itype.api_type == ClassDB::API_EDITOR) @@ -314,49 +480,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo #undef GENERATE_BUILTIN_TYPE - // Generate source for GlobalConstants - - String constants_source; - int global_constants_count = GlobalConstants::get_global_constant_count(); - - if (global_constants_count > 0) { - Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope"); - - ERR_EXPLAIN("Could not find `@GlobalScope` in DocData"); - ERR_FAIL_COND_V(!match, ERR_BUG); - - const DocData::ClassDoc &global_scope_doc = match->value(); - - for (int i = 0; i < global_constants_count; i++) { - const DocData::ConstantDoc &const_doc = global_scope_doc.constants[i]; - - if (i > 0) - constants_source += MEMBER_BEGIN; - - if (const_doc.description.size()) { - constants_source += "/// <summary>\n"; - - Vector<String> description_lines = const_doc.description.split("\n"); - - for (int i = 0; i < description_lines.size(); i++) { - if (description_lines[i].size()) { - constants_source += INDENT2 "/// "; - constants_source += description_lines[i].strip_edges().xml_escape(); - constants_source += "\n"; - } - } - - constants_source += INDENT2 "/// </summary>" MEMBER_BEGIN; - } - - constants_source += "public const int "; - constants_source += GlobalConstants::get_global_constant_name(i); - constants_source += " = "; - constants_source += itos(GlobalConstants::get_global_constant_value(i)); - constants_source += ";"; - } - } - // Generate sources from compressed files Map<String, CompressedFile> compressed_files; @@ -372,19 +495,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo data.resize(file_data.uncompressed_size); Compression::decompress(data.ptrw(), file_data.uncompressed_size, file_data.data, file_data.compressed_size, Compression::MODE_DEFLATE); - if (file_name.get_basename() == BINDINGS_GLOBAL_SCOPE_CLASS) { - // GD.cs must be formatted to include the generated global constants - String data_str = String::utf8(reinterpret_cast<const char *>(data.ptr()), data.size()); - - Dictionary format_keys; - format_keys["GodotGlobalConstants"] = constants_source; - data_str = data_str.format(format_keys, "/*{_}*/"); - - CharString data_utf8 = data_str.utf8(); - data.resize(data_utf8.length()); - copymem(data.ptrw(), reinterpret_cast<const uint8_t *>(data_utf8.get_data()), data_utf8.length()); - } - FileAccessRef file = FileAccess::open(output_file, FileAccess::WRITE); ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE); file->store_buffer(data.ptr(), data.size()); @@ -470,7 +580,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, if (!solution.set_path(p_output_dir)) return ERR_FILE_NOT_FOUND; - for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { + for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { const TypeInterface &itype = E->get(); if (itype.api_type != ClassDB::API_EDITOR) @@ -543,7 +653,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, // e.g.: warning CS0108: 'SpriteBase3D.FLAG_MAX' hides inherited member 'GeometryInstance.FLAG_MAX'. Use the new keyword if hiding was intended. Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) { - bool is_derived_type = itype.base_name.length(); + bool is_derived_type = itype.base_name != StringName(); List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; @@ -569,9 +679,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str Vector<String> description_lines = class_doc->description.split("\n"); for (int i = 0; i < description_lines.size(); i++) { - if (description_lines[i].size()) { + String description_line = description_lines[i].strip_edges(); + if (description_line.size()) { output.push_back(INDENT1 "/// "); - output.push_back(description_lines[i].strip_edges().xml_escape()); + output.push_back(description_line.xml_escape()); output.push_back("\n"); } } @@ -592,7 +703,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back(obj_types[itype.base_name].proxy_name); output.push_back("\n"); } else { - ERR_PRINTS("Base type '" + itype.base_name + "' does not exist, for class " + itype.name); + ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name); return ERR_INVALID_DATA; } @@ -602,18 +713,19 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // Add constants - for (int i = 0; i < class_doc->constants.size(); i++) { - const DocData::ConstantDoc &const_doc = class_doc->constants[i]; + for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) { + const ConstantInterface &iconstant = E->get(); - if (const_doc.description.size()) { + if (iconstant.const_doc && iconstant.const_doc->description.size()) { output.push_back(MEMBER_BEGIN "/// <summary>\n"); - Vector<String> description_lines = const_doc.description.split("\n"); + Vector<String> description_lines = iconstant.const_doc->description.split("\n"); for (int i = 0; i < description_lines.size(); i++) { - if (description_lines[i].size()) { + String description_line = description_lines[i].strip_edges(); + if (description_line.size()) { output.push_back(INDENT2 "/// "); - output.push_back(description_lines[i].strip_edges().xml_escape()); + output.push_back(description_line.xml_escape()); output.push_back("\n"); } } @@ -622,24 +734,84 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.push_back(MEMBER_BEGIN "public const int "); - output.push_back(const_doc.name); + output.push_back(iconstant.name); output.push_back(" = "); - output.push_back(const_doc.value); + output.push_back(itos(iconstant.value)); output.push_back(";"); } - if (class_doc->constants.size()) + if (itype.constants.size()) output.push_back("\n"); - // Add properties + // Add enums + + for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) { + const EnumInterface &ienum = E->get(); + + ERR_FAIL_COND_V(ienum.constants.empty(), ERR_BUG); + + output.push_back(MEMBER_BEGIN "public enum "); + output.push_back(ienum.cname.operator String()); + output.push_back(MEMBER_BEGIN OPEN_BLOCK); + + for (const List<ConstantInterface>::Element *E = ienum.constants.front(); E; E = E->next()) { + const ConstantInterface &iconstant = E->get(); + + if (iconstant.const_doc && iconstant.const_doc->description.size()) { + output.push_back(INDENT3 "/// <summary>\n"); + + Vector<String> description_lines = iconstant.const_doc->description.split("\n"); + + for (int i = 0; i < description_lines.size(); i++) { + String description_line = description_lines[i].strip_edges(); + if (description_line.size()) { + output.push_back(INDENT3 "/// "); + output.push_back(description_line.xml_escape()); + output.push_back("\n"); + } + } + + output.push_back(INDENT3 "/// </summary>\n"); + } + + String constant_name = iconstant.name; + + if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) { + constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length()); + } + + if (constant_name[0] >= '0' && constant_name[0] <= '9') { + // The name of enum constants may begin with a numeric digit when strip from the enum prefix, + // so we make the prefix one word shorter in those cases. + int i = 0; + for (i = ienum.prefix.length() - 1; i >= 0; i--) { + if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z') + break; + } + constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name; + } + + output.push_back(INDENT3); + output.push_back(constant_name); + output.push_back(" = "); + output.push_back(itos(iconstant.value)); + output.push_back(E != ienum.constants.back() ? ",\n" : "\n"); + } + + output.push_back(INDENT2 CLOSE_BLOCK); + } + + if (itype.enums.size()) + output.push_back("\n"); - const Vector<DocData::PropertyDoc> &properties = class_doc->properties; + // Add properties - for (int i = 0; i < properties.size(); i++) { - const DocData::PropertyDoc &prop_doc = properties[i]; - Error prop_err = _generate_cs_property(itype, prop_doc, output); + for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) { + const PropertyInterface &iprop = E->get(); + Error prop_err = _generate_cs_property(itype, iprop, output); if (prop_err != OK) { - ERR_EXPLAIN("Failed to generate property '" + prop_doc.name + "' for class '" + itype.name + "'"); + ERR_EXPLAIN("Failed to generate property '" + iprop.cname.operator String() + + "' for class '" + itype.name + "'"); ERR_FAIL_V(prop_err); } } @@ -762,18 +934,18 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN " = false;\n" INDENT5 CS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR - "(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD - " = IntPtr.Zero;\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3 + "(this, " BINDINGS_PTR_FIELD ");\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3 + "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" INDENT3 "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2); - Map<String, TypeInterface>::Element *array_itype = builtin_types.find("Array"); + Map<StringName, TypeInterface>::Element *array_itype = builtin_types.find(name_cache.type_Array); if (!array_itype) { ERR_PRINT("BUG: Array type interface not found!"); return ERR_BUG; } - Map<String, TypeInterface>::Element *object_itype = obj_types.find("Object"); + Map<StringName, TypeInterface>::Element *object_itype = obj_types.find("Object"); if (!object_itype) { ERR_PRINT("BUG: Object type interface not found!"); @@ -787,7 +959,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } } - Map<String, String>::Element *extra_member = extra_members.find(itype.name); + Map<StringName, String>::Element *extra_member = extra_members.find(itype.cname); if (extra_member) output.push_back(extra_member->get()); @@ -820,43 +992,39 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str return _save_file(p_output_file, output); } -Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const DocData::PropertyDoc &p_prop_doc, List<String> &p_output) { +Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const PropertyInterface &p_iprop, List<String> &p_output) { - const MethodInterface *setter = p_itype.find_method_by_name(p_prop_doc.setter); + const MethodInterface *setter = p_itype.find_method_by_name(p_iprop.setter); // Search it in base types too const TypeInterface *current_type = &p_itype; - while (!setter && current_type->base_name.length()) { - Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); + while (!setter && current_type->base_name != StringName()) { + Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); ERR_FAIL_NULL_V(base_match, ERR_BUG); current_type = &base_match->get(); - setter = current_type->find_method_by_name(p_prop_doc.setter); + setter = current_type->find_method_by_name(p_iprop.setter); } - const MethodInterface *getter = p_itype.find_method_by_name(p_prop_doc.getter); + const MethodInterface *getter = p_itype.find_method_by_name(p_iprop.getter); // Search it in base types too current_type = &p_itype; - while (!getter && current_type->base_name.length()) { - Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); + while (!getter && current_type->base_name != StringName()) { + Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); ERR_FAIL_NULL_V(base_match, ERR_BUG); current_type = &base_match->get(); - getter = current_type->find_method_by_name(p_prop_doc.getter); + getter = current_type->find_method_by_name(p_iprop.getter); } ERR_FAIL_COND_V(!setter && !getter, ERR_BUG); - bool is_valid = false; - int prop_index = ClassDB::get_property_index(p_itype.name, p_prop_doc.name, &is_valid); - ERR_FAIL_COND_V(!is_valid, ERR_BUG); - if (setter) { - int setter_argc = prop_index != -1 ? 2 : 1; + int setter_argc = p_iprop.index != -1 ? 2 : 1; ERR_FAIL_COND_V(setter->arguments.size() != setter_argc, ERR_BUG); } if (getter) { - int getter_argc = prop_index != -1 ? 1 : 0; + int getter_argc = p_iprop.index != -1 ? 1 : 0; ERR_FAIL_COND_V(getter->arguments.size() != getter_argc, ERR_BUG); } @@ -864,18 +1032,12 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte ERR_FAIL_COND_V(getter->return_type != setter->arguments.back()->get().type, ERR_BUG); } - // Let's not trust PropertyDoc::type - String proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type; + StringName proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type; const TypeInterface *prop_itype = _get_type_by_name_or_null(proptype_name); - if (!prop_itype) { - // Try with underscore prefix - prop_itype = _get_type_by_name_or_null("_" + proptype_name); - } + ERR_FAIL_NULL_V(prop_itype, ERR_BUG); // Property type not found - ERR_FAIL_NULL_V(prop_itype, ERR_BUG); - - String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(p_prop_doc.name)); + String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(p_iprop.cname)); // Prevent property and enclosing type from sharing the same name if (prop_proxy_name == p_itype.proxy_name) { @@ -887,15 +1049,16 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte prop_proxy_name += "_"; } - if (p_prop_doc.description.size()) { + if (p_iprop.prop_doc && p_iprop.prop_doc->description.size()) { p_output.push_back(MEMBER_BEGIN "/// <summary>\n"); - Vector<String> description_lines = p_prop_doc.description.split("\n"); + Vector<String> description_lines = p_iprop.prop_doc->description.split("\n"); for (int i = 0; i < description_lines.size(); i++) { - if (description_lines[i].size()) { + String description_line = description_lines[i].strip_edges(); + if (description_line.size()) { p_output.push_back(INDENT2 "/// "); - p_output.push_back(description_lines[i].strip_edges().xml_escape()); + p_output.push_back(description_line.xml_escape()); p_output.push_back("\n"); } } @@ -917,16 +1080,34 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte p_output.push_back(INDENT3 "get\n" OPEN_BLOCK_L3); p_output.push_back("return "); p_output.push_back(getter->proxy_name + "("); - if (prop_index != -1) - p_output.push_back(itos(prop_index)); + if (p_iprop.index != -1) { + const ArgumentInterface &idx_arg = getter->arguments.front()->get(); + if (idx_arg.type != name_cache.type_int) { + // Assume the index parameter is an enum + const TypeInterface *idx_arg_type = _get_type_by_name_or_null(idx_arg.type); + CRASH_COND(idx_arg_type == NULL); + p_output.push_back("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index)); + } else { + p_output.push_back(itos(p_iprop.index)); + } + } p_output.push_back(");\n" CLOSE_BLOCK_L3); } if (setter) { p_output.push_back(INDENT3 "set\n" OPEN_BLOCK_L3); p_output.push_back(setter->proxy_name + "("); - if (prop_index != -1) - p_output.push_back(itos(prop_index) + ", "); + if (p_iprop.index != -1) { + const ArgumentInterface &idx_arg = setter->arguments.front()->get(); + if (idx_arg.type != name_cache.type_int) { + // Assume the index parameter is an enum + const TypeInterface *idx_arg_type = _get_type_by_name_or_null(idx_arg.type); + CRASH_COND(idx_arg_type == NULL); + p_output.push_back("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index) + ", "); + } else { + p_output.push_back(itos(p_iprop.index) + ", "); + } + } p_output.push_back("value);\n" CLOSE_BLOCK_L3); } @@ -1033,9 +1214,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf Vector<String> description_lines = p_imethod.method_doc->description.split("\n"); for (int i = 0; i < description_lines.size(); i++) { - if (description_lines[i].size()) { + String description_line = description_lines[i].strip_edges(); + if (description_line.size()) { p_output.push_back(INDENT2 "/// "); - p_output.push_back(description_lines[i].strip_edges().xml_escape()); + p_output.push_back(description_line.xml_escape()); p_output.push_back("\n"); } } @@ -1069,7 +1251,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf if (p_imethod.is_virtual) { // Godot virtual method must be overridden, therefore we return a default value by default. - if (return_type->name == "void") { + if (return_type->cname == name_cache.type_void) { p_output.push_back("return;\n" CLOSE_BLOCK_L2); } else { p_output.push_back("return default("); @@ -1108,7 +1290,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf if (p_imethod.arguments.size()) p_output.push_back(cs_in_statements); - if (return_type->name == "void") { + if (return_type->cname == name_cache.type_void) { p_output.push_back(im_call); } else if (return_type->cs_out.empty()) { p_output.push_back("return " + im_call); @@ -1142,7 +1324,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { generated_icall_funcs.clear(); - for (Map<String, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) { + for (Map<StringName, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) { const TypeInterface &itype = type_elem->get(); List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; @@ -1295,7 +1477,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte if (p_imethod.is_virtual) return OK; // Ignore - bool ret_void = p_imethod.return_type == "void"; + bool ret_void = p_imethod.return_type == name_cache.type_void; const TypeInterface *return_type = _get_type_by_name_or_placeholder(p_imethod.return_type); @@ -1447,14 +1629,19 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte return OK; } -const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const String &p_name) { +const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const StringName &p_cname) { + + const Map<StringName, TypeInterface>::Element *match = builtin_types.find(p_cname); - const Map<String, TypeInterface>::Element *match = builtin_types.find(p_name); + if (match) + return &match->get(); + + match = obj_types.find(p_cname); if (match) return &match->get(); - match = obj_types.find(p_name); + match = enum_types.find(p_cname); if (match) return &match->get(); @@ -1462,24 +1649,27 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_ return NULL; } -const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_placeholder(const String &p_name) { +const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_placeholder(const StringName &p_cname) { - const TypeInterface *found = _get_type_by_name_or_null(p_name); + const TypeInterface *found = _get_type_by_name_or_null(p_cname); if (found) return found; - ERR_PRINTS(String() + "Type not found. Creating placeholder: " + p_name); + ERR_PRINTS(String() + "Type not found. Creating placeholder: " + p_cname.operator String()); - const Map<String, TypeInterface>::Element *match = placeholder_types.find(p_name); + const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_cname); if (match) return &match->get(); TypeInterface placeholder; - TypeInterface::create_placeholder_type(placeholder, p_name); + TypeInterface::create_placeholder_type(placeholder, p_cname); + + return &placeholder_types.insert(placeholder.cname, placeholder)->get(); +} - return &placeholder_types.insert(placeholder.name, placeholder)->get(); +static void _create_constant_interface_from(const StringName &p_constant, const DocData::ClassDoc &p_classdoc) { } void BindingsGenerator::_populate_object_type_interfaces() { @@ -1490,8 +1680,6 @@ void BindingsGenerator::_populate_object_type_interfaces() { ClassDB::get_class_list(&class_list); class_list.sort_custom<StringName::AlphCompare>(); - StringName refclass_name = String("Reference"); - while (class_list.size()) { StringName type_cname = class_list.front()->get(); @@ -1502,21 +1690,23 @@ void BindingsGenerator::_populate_object_type_interfaces() { continue; } + if (!ClassDB::is_class_exposed(type_cname)) { + if (verbose_output) + WARN_PRINTS("Ignoring type " + type_cname.operator String() + " because it's not exposed"); + class_list.pop_front(); + continue; + } + + ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(type_cname); + TypeInterface itype = TypeInterface::create_object_type(type_cname, api_type); itype.base_name = ClassDB::get_parent_class(type_cname); itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name); itype.is_instantiable = ClassDB::can_instance(type_cname) && !itype.is_singleton; - itype.is_reference = ClassDB::is_parent_class(type_cname, refclass_name); + itype.is_reference = ClassDB::is_parent_class(type_cname, name_cache.type_Reference); itype.memory_own = itype.is_reference; - if (!ClassDB::is_class_exposed(type_cname)) { - if (verbose_output) - WARN_PRINTS("Ignoring type " + String(type_cname) + " because it's not exposed"); - class_list.pop_front(); - continue; - } - itype.c_out = "\treturn "; itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED; itype.c_out += itype.is_reference ? "(%1.ptr());\n" : "(%1);\n"; @@ -1530,6 +1720,53 @@ void BindingsGenerator::_populate_object_type_interfaces() { itype.im_type_in = "IntPtr"; itype.im_type_out = itype.proxy_name; + List<PropertyInfo> property_list; + ClassDB::get_property_list(type_cname, &property_list, true); + + // Populate properties + + for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) { + const PropertyInfo &property = E->get(); + + if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_CATEGORY) + continue; + + PropertyInterface iprop; + iprop.cname = property.name; + iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname)); + iprop.setter = ClassDB::get_property_setter(type_cname, iprop.cname); + iprop.getter = ClassDB::get_property_getter(type_cname, iprop.cname); + + bool valid = false; + iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid); + ERR_FAIL_COND(!valid); + + // Prevent property and enclosing type from sharing the same name + if (iprop.proxy_name == itype.proxy_name) { + if (verbose_output) { + WARN_PRINTS("Name of property `" + iprop.proxy_name + "` is ambiguous with the name of its class `" + + itype.proxy_name + "`. Renaming property to `" + iprop.proxy_name + "_`"); + } + + iprop.proxy_name += "_"; + } + + iprop.prop_doc = NULL; + + for (int i = 0; i < itype.class_doc->properties.size(); i++) { + const DocData::PropertyDoc &prop_doc = itype.class_doc->properties[i]; + + if (prop_doc.name == iprop.cname) { + iprop.prop_doc = &prop_doc; + break; + } + } + + itype.properties.push_back(iprop); + } + + // Populate methods + List<MethodInfo> virtual_method_list; ClassDB::get_virtual_methods(type_cname, &virtual_method_list, true); @@ -1547,6 +1784,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { MethodInterface imethod; imethod.name = method_info.name; + imethod.cname = imethod.name; if (method_info.flags & METHOD_FLAG_VIRTUAL) imethod.is_virtual = true; @@ -1570,12 +1808,12 @@ void BindingsGenerator::_populate_object_type_interfaces() { // The method Object.free is registered as a virtual method, but without the virtual flag. // This is because this method is not supposed to be overridden, but called. // We assume the return type is void. - imethod.return_type = "void"; + imethod.return_type = name_cache.type_void; // Actually, more methods like this may be added in the future, // which could actually will return something differnet. // Let's put this to notify us if that ever happens. - if (itype.name != "Object" || imethod.name != "free") { + if (itype.cname != name_cache.type_Object || imethod.name != "free") { if (verbose_output) { WARN_PRINTS("Notification: New unexpected virtual non-overridable method found.\n" "We only expected Object.free, but found " + @@ -1585,22 +1823,21 @@ void BindingsGenerator::_populate_object_type_interfaces() { } else { ERR_PRINTS("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name); } - } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { - //imethod.return_type = return_info.class_name; - imethod.return_type = "int"; + } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { // TODO redundant? + imethod.return_type = return_info.class_name; } else if (return_info.class_name != StringName()) { imethod.return_type = return_info.class_name; } else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { imethod.return_type = return_info.hint_string; } else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { - imethod.return_type = "Variant"; + imethod.return_type = name_cache.type_Variant; } else if (return_info.type == Variant::NIL) { - imethod.return_type = "void"; + imethod.return_type = name_cache.type_void; } else { imethod.return_type = Variant::get_type_name(return_info.type); } - if (!itype.requires_collections && imethod.return_type == "Dictionary") + if (!itype.requires_collections && imethod.return_type == name_cache.type_Dictionary) itype.requires_collections = true; for (int i = 0; i < argc; i++) { @@ -1609,22 +1846,21 @@ void BindingsGenerator::_populate_object_type_interfaces() { ArgumentInterface iarg; iarg.name = arginfo.name; - if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { - //iarg.type = arginfo.class_name; - iarg.type = "int"; + if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { // TODO redundant? + iarg.type = arginfo.class_name; } else if (arginfo.class_name != StringName()) { iarg.type = arginfo.class_name; } else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { iarg.type = arginfo.hint_string; } else if (arginfo.type == Variant::NIL) { - iarg.type = "Variant"; + iarg.type = name_cache.type_Variant; } else { iarg.type = Variant::get_type_name(arginfo.type); } iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name)); - if (!itype.requires_collections && iarg.type == "Dictionary") + if (!itype.requires_collections && iarg.type == name_cache.type_Dictionary) itype.requires_collections = true; if (m && m->has_default_argument(i)) { @@ -1636,7 +1872,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { if (imethod.is_vararg) { ArgumentInterface ivararg; - ivararg.type = "VarArg"; + ivararg.type = name_cache.type_VarArg; ivararg.name = "@args"; imethod.add_argument(ivararg); } @@ -1663,12 +1899,10 @@ void BindingsGenerator::_populate_object_type_interfaces() { } if (!imethod.is_virtual && imethod.name[0] == '_') { - const Vector<DocData::PropertyDoc> &properties = itype.class_doc->properties; + for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) { + const PropertyInterface &iprop = E->get(); - for (int i = 0; i < properties.size(); i++) { - const DocData::PropertyDoc &prop_doc = properties[i]; - - if (prop_doc.getter == imethod.name || prop_doc.setter == imethod.name) { + if (iprop.setter == imethod.name || iprop.getter == imethod.name) { imethod.is_internal = true; itype.methods.push_back(imethod); break; @@ -1679,7 +1913,84 @@ void BindingsGenerator::_populate_object_type_interfaces() { } } - obj_types.insert(itype.name, itype); + // Populate enums and constants + + List<String> constant_list; + ClassDB::get_integer_constant_list(type_cname, &constant_list, true); + + const HashMap<StringName, List<StringName> > &enum_map = class_info->enum_map; + const StringName *k = NULL; + + while ((k = enum_map.next(k))) { + StringName enum_proxy_cname = *k; + String enum_proxy_name = enum_proxy_cname.operator String(); + if (itype.find_property_by_proxy_name(enum_proxy_cname)) { + // We have several conflicts between enums and PascalCase properties, + // so we append 'Enum' to the enum name in those cases. + enum_proxy_name += "Enum"; + enum_proxy_cname = StringName(enum_proxy_name); + } + EnumInterface ienum(enum_proxy_cname); + const List<StringName> &constants = enum_map.get(*k); + for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) { + int *value = class_info->constant_map.getptr(E->get()); + ERR_FAIL_NULL(value); + constant_list.erase(E->get().operator String()); + + ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value); + + iconstant.const_doc = NULL; + for (int i = 0; i < itype.class_doc->constants.size(); i++) { + const DocData::ConstantDoc &const_doc = itype.class_doc->constants[i]; + + if (const_doc.name == iconstant.name) { + iconstant.const_doc = &const_doc; + break; + } + } + + ienum.constants.push_back(iconstant); + } + + ienum.prefix = _determine_enum_prefix(ienum); + + itype.enums.push_back(ienum); + + TypeInterface enum_itype; + enum_itype.name = itype.name + "." + String(*k); + enum_itype.cname = StringName(enum_itype.name); + enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name; + enum_itype.c_arg_in = "&%s"; + enum_itype.c_type = "int"; + enum_itype.c_type_in = "int"; + enum_itype.c_type_out = "int"; + enum_itype.cs_type = enum_itype.proxy_name; + enum_itype.im_type_in = enum_itype.proxy_name; + enum_itype.im_type_out = enum_itype.proxy_name; + enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[enum_itype.proxy_name]; + enum_types.insert(enum_itype.cname, enum_itype); + } + + for (const List<String>::Element *E = constant_list.front(); E; E = E->next()) { + int *value = class_info->constant_map.getptr(E->get()); + ERR_FAIL_NULL(value); + + ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value); + + iconstant.const_doc = NULL; + for (int i = 0; i < itype.class_doc->constants.size(); i++) { + const DocData::ConstantDoc &const_doc = itype.class_doc->constants[i]; + + if (const_doc.name == iconstant.name) { + iconstant.const_doc = &const_doc; + break; + } + } + + itype.constants.push_back(iconstant); + } + + obj_types.insert(itype.cname, itype); class_list.pop_front(); } @@ -1704,7 +2015,10 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg r_iarg.default_argument = bool(p_val) ? "true" : "false"; break; case Variant::INT: - break; // Keep it + if (r_iarg.type != name_cache.type_int) { + r_iarg.default_argument = "(%s)" + r_iarg.default_argument; + } + break; case Variant::REAL: #ifndef REAL_T_IS_DOUBLE r_iarg.default_argument += "f"; @@ -1762,7 +2076,7 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg default: {} } - if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type == "Variant" && r_iarg.default_argument != "null") + if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type == name_cache.type_Variant && r_iarg.default_argument != "null") r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; } @@ -1774,7 +2088,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { #define INSERT_STRUCT_TYPE(m_type, m_type_in) \ { \ - itype = TypeInterface::create_value_type(#m_type); \ + itype = TypeInterface::create_value_type(String(#m_type)); \ itype.c_in = "\tMARSHALLED_IN(" #m_type ", %1, %1_in);\n"; \ itype.c_out = "\tMARSHALLED_OUT(" #m_type ", %1, ret_out)\n" \ "\treturn mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(%2), ret_out);\n"; \ @@ -1783,7 +2097,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_in = "ref %s"; \ itype.cs_out = "return (" #m_type ")%0;"; \ itype.im_type_out = "object"; \ - builtin_types.insert(#m_type, itype); \ + builtin_types.insert(itype.cname, itype); \ } INSERT_STRUCT_TYPE(Vector2, "real_t*") @@ -1799,22 +2113,22 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { #undef INSERT_STRUCT_TYPE -#define INSERT_PRIMITIVE_TYPE(m_type) \ - { \ - itype = TypeInterface::create_value_type(#m_type); \ - itype.c_arg_in = "&%s"; \ - itype.c_type_in = #m_type; \ - itype.c_type_out = #m_type; \ - itype.im_type_in = #m_type; \ - itype.im_type_out = #m_type; \ - builtin_types.insert(#m_type, itype); \ +#define INSERT_PRIMITIVE_TYPE(m_type) \ + { \ + itype = TypeInterface::create_value_type(String(#m_type)); \ + itype.c_arg_in = "&%s"; \ + itype.c_type_in = #m_type; \ + itype.c_type_out = #m_type; \ + itype.im_type_in = #m_type; \ + itype.im_type_out = #m_type; \ + builtin_types.insert(itype.cname, itype); \ } INSERT_PRIMITIVE_TYPE(bool) //INSERT_PRIMITIVE_TYPE(int) // int - itype = TypeInterface::create_value_type("int"); + itype = TypeInterface::create_value_type(String("int")); itype.c_arg_in = "&%s_in"; //* ptrcall only supports int64_t and uint64_t itype.c_in = "\t%0 %1_in = (%0)%1;\n"; @@ -1825,7 +2139,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.c_type_out = itype.name; itype.im_type_in = itype.name; itype.im_type_out = itype.name; - builtin_types.insert(itype.name, itype); + builtin_types.insert(itype.cname, itype); #undef INSERT_PRIMITIVE_TYPE @@ -1836,6 +2150,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { #else itype.name = "float"; #endif + itype.cname = itype.name; itype.proxy_name = itype.name; itype.c_arg_in = "&%s_in"; //* ptrcall only supports double @@ -1848,11 +2163,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_type = itype.proxy_name; itype.im_type_in = itype.proxy_name; itype.im_type_out = itype.proxy_name; - builtin_types.insert(itype.name, itype); + builtin_types.insert(itype.cname, itype); // String itype = TypeInterface(); itype.name = "String"; + itype.cname = itype.name; itype.proxy_name = "string"; itype.c_in = "\t%0 %1_in = " C_METHOD_MONOSTR_TO_GODOT "(%1);\n"; itype.c_out = "\treturn " C_METHOD_MONOSTR_FROM_GODOT "(%1);\n"; @@ -1863,11 +2179,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_type = itype.proxy_name; itype.im_type_in = itype.proxy_name; itype.im_type_out = itype.proxy_name; - builtin_types.insert(itype.name, itype); + builtin_types.insert(itype.cname, itype); // NodePath itype = TypeInterface(); itype.name = "NodePath"; + itype.cname = itype.name; itype.proxy_name = "NodePath"; itype.c_out = "\treturn memnew(NodePath(%1));\n"; itype.c_type = itype.name; @@ -1879,16 +2196,17 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; _populate_builtin_type(itype, Variant::NODE_PATH); - extra_members.insert(itype.name, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2 - "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2 - MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2 - MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2 - "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2); - builtin_types.insert(itype.name, itype); + extra_members.insert(itype.cname, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2 + "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2 + MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2 + MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2 + "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2); + builtin_types.insert(itype.cname, itype); // RID itype = TypeInterface(); itype.name = "RID"; + itype.cname = itype.name; itype.proxy_name = "RID"; itype.c_out = "\treturn memnew(RID(%1));\n"; itype.c_type = itype.name; @@ -1900,13 +2218,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; _populate_builtin_type(itype, Variant::_RID); - extra_members.insert(itype.name, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2 - "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2); - builtin_types.insert(itype.name, itype); + extra_members.insert(itype.cname, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2 + "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2); + builtin_types.insert(itype.cname, itype); // Variant itype = TypeInterface(); itype.name = "Variant"; + itype.cname = itype.name; itype.proxy_name = "object"; itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_VARIANT "(%1);\n"; itype.c_out = "\treturn " C_METHOD_MANAGED_FROM_VARIANT "(%1);\n"; @@ -1917,11 +2236,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_type = itype.proxy_name; itype.im_type_in = "object"; itype.im_type_out = itype.proxy_name; - builtin_types.insert(itype.name, itype); + builtin_types.insert(itype.cname, itype); // VarArg (fictitious type to represent variable arguments) itype = TypeInterface(); itype.name = "VarArg"; + itype.cname = itype.name; itype.proxy_name = "object[]"; itype.c_in = "\t%0 %1_in = " C_METHOD_MONOARRAY_TO(Array) "(%1);\n"; itype.c_arg_in = "&%s_in"; @@ -1929,12 +2249,13 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.c_type_in = "MonoArray*"; itype.cs_type = "params object[]"; itype.im_type_in = "object[]"; - builtin_types.insert(itype.name, itype); + builtin_types.insert(itype.cname, itype); #define INSERT_ARRAY_FULL(m_name, m_type, m_proxy_t) \ { \ itype = TypeInterface(); \ itype.name = #m_name; \ + itype.cname = itype.name; \ itype.proxy_name = #m_proxy_t "[]"; \ itype.c_in = "\t%0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \ itype.c_out = "\treturn " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \ @@ -1971,6 +2292,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { // Dictionary itype = TypeInterface(); itype.name = "Dictionary"; + itype.cname = itype.name; itype.proxy_name = "Dictionary<object, object>"; itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_DICT "(%1);\n"; itype.c_out = "\treturn " C_METHOD_MANAGED_FROM_DICT "(%1);\n"; @@ -1981,11 +2303,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_type = itype.proxy_name; itype.im_type_in = itype.proxy_name; itype.im_type_out = itype.proxy_name; - builtin_types.insert(itype.name, itype); + builtin_types.insert(itype.cname, itype); // void (fictitious type to represent the return type of methods that do not return anything) itype = TypeInterface(); itype.name = "void"; + itype.cname = itype.name; itype.proxy_name = itype.name; itype.c_type = itype.name; itype.c_type_in = itype.c_type; @@ -1993,21 +2316,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_type = itype.proxy_name; itype.im_type_in = itype.proxy_name; itype.im_type_out = itype.proxy_name; - builtin_types.insert(itype.name, itype); - - // Error - itype = TypeInterface(); - itype.name = "Error"; - itype.proxy_name = "Error"; - itype.c_type = itype.name; - itype.c_type_in = itype.c_type; - itype.c_type_out = itype.c_type; - itype.cs_type = itype.proxy_name; - itype.cs_in = "(int)%0"; - itype.cs_out = "return (Error)%s;"; - itype.im_type_in = "int"; - itype.im_type_out = "int"; - builtin_types.insert(itype.name, itype); + builtin_types.insert(itype.cname, itype); } void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype) { @@ -2024,6 +2333,7 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: MethodInterface imethod; imethod.name = mi.name; + imethod.cname = imethod.name; imethod.proxy_name = mi.name; for (int i = 0; i < mi.arguments.size(); i++) { @@ -2033,11 +2343,11 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: iarg.name = pi.name; if (pi.type == Variant::NIL) - iarg.type = "Variant"; + iarg.type = name_cache.type_Variant; else iarg.type = Variant::get_type_name(pi.type); - if (!r_itype.requires_collections && iarg.type == "Dictionary") + if (!r_itype.requires_collections && iarg.type == name_cache.type_Dictionary) r_itype.requires_collections = true; if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0) @@ -2048,12 +2358,12 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: if (mi.return_val.type == Variant::NIL) { if (mi.return_val.name != "") - imethod.return_type = "Variant"; + imethod.return_type = name_cache.type_Variant; } else { imethod.return_type = Variant::get_type_name(mi.return_val.type); } - if (!r_itype.requires_collections && imethod.return_type == "Dictionary") + if (!r_itype.requires_collections && imethod.return_type == name_cache.type_Dictionary) r_itype.requires_collections = true; if (r_itype.class_doc) { @@ -2069,15 +2379,112 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: } } -BindingsGenerator::BindingsGenerator() { +void BindingsGenerator::_populate_global_constants() { + + int global_constants_count = GlobalConstants::get_global_constant_count(); + + if (global_constants_count > 0) { + Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope"); + + ERR_EXPLAIN("Could not find `@GlobalScope` in DocData"); + CRASH_COND(!match); + + const DocData::ClassDoc &global_scope_doc = match->value(); + + for (int i = 0; i < global_constants_count; i++) { + + String constant_name = GlobalConstants::get_global_constant_name(i); + + const DocData::ConstantDoc *const_doc = NULL; + for (int i = 0; i < global_scope_doc.constants.size(); i++) { + const DocData::ConstantDoc &curr_const_doc = global_scope_doc.constants[i]; + + if (curr_const_doc.name == constant_name) { + const_doc = &curr_const_doc; + break; + } + } + + int constant_value = GlobalConstants::get_global_constant_value(i); + StringName enum_name = GlobalConstants::get_global_constant_enum(i); + + ConstantInterface iconstant(snake_to_pascal_case(constant_name, true), constant_value); + iconstant.const_doc = const_doc; + + if (enum_name != StringName()) { + EnumInterface ienum(enum_name); + List<EnumInterface>::Element *match = global_enums.find(ienum); + if (match) { + match->get().constants.push_back(iconstant); + } else { + ienum.constants.push_back(iconstant); + global_enums.push_back(ienum); + } + } else { + global_constants.push_back(iconstant); + } + } + + for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) { + EnumInterface &ienum = E->get(); + + TypeInterface enum_itype; + enum_itype = TypeInterface::create_value_type(ienum.cname); + enum_itype.c_arg_in = "&%s"; + enum_itype.c_type = "int"; + enum_itype.c_type_in = "int"; + enum_itype.c_type_out = "int"; + enum_itype.im_type_in = enum_itype.name; + enum_itype.im_type_out = enum_itype.name; + enum_types.insert(enum_itype.cname, enum_itype); + + ienum.prefix = _determine_enum_prefix(ienum); + + // HARDCODED + if (ienum.cname == name_cache.enum_Error) { + if (!ienum.prefix.empty()) { // Just in case it ever changes + ERR_PRINTS("Prefix for enum 'Error' is not empty"); + } + + ienum.prefix = "Err"; + } + } + } + + // HARDCODED + List<StringName> hardcoded_enums; + hardcoded_enums.push_back("Vector3.Axis"); + for (List<StringName>::Element *E = hardcoded_enums.front(); E; E = E->next()) { + // These enums are not generated and must be written manually (e.g.: Vector3.Axis) + // Here, we are assuming core types do not begin with underscore + TypeInterface enum_itype; + enum_itype = TypeInterface::create_value_type(E->get()); + enum_itype.c_arg_in = "&%s"; + enum_itype.c_type = "int"; + enum_itype.c_type_in = "int"; + enum_itype.c_type_out = "int"; + enum_itype.im_type_in = enum_itype.name; + enum_itype.im_type_out = enum_itype.name; + enum_types.insert(enum_itype.cname, enum_itype); + } +} + +void BindingsGenerator::initialize() { EditorHelp::generate_doc(); + enum_types.clear(); + _populate_object_type_interfaces(); _populate_builtin_type_interfaces(); + + _populate_global_constants(); + + // Populate internal calls (after populating type interfaces and global constants) + _generate_header_icalls(); - for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) + for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) _generate_method_icalls(E->get()); _generate_method_icalls(builtin_types["NodePath"]); @@ -2104,7 +2511,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) const List<String>::Element *path_elem = elem->next(); if (path_elem) { - if (get_singleton().generate_glue(path_elem->get()) != OK) + if (get_singleton()->generate_glue(path_elem->get()) != OK) ERR_PRINT("Mono glue generation failed"); elem = elem->next(); } else { @@ -2118,7 +2525,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) const List<String>::Element *path_elem = elem->next(); if (path_elem) { - if (get_singleton().generate_cs_core_project(path_elem->get()) != OK) + if (get_singleton()->generate_cs_core_project(path_elem->get()) != OK) ERR_PRINT("Generation of solution and C# project for the Core API failed"); elem = elem->next(); } else { @@ -2133,7 +2540,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) if (path_elem) { if (path_elem->next()) { - if (get_singleton().generate_cs_editor_project(path_elem->get(), path_elem->next()->get()) != OK) + if (get_singleton()->generate_cs_editor_project(path_elem->get(), path_elem->next()->get()) != OK) ERR_PRINT("Generation of solution and C# project for the Editor API failed"); elem = path_elem->next(); } else { diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index dfa3aa9911..717a6b7a6b 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef BINDINGS_GENERATOR_H #define BINDINGS_GENERATOR_H @@ -39,6 +40,47 @@ #include "ustring.h" class BindingsGenerator { + + struct ConstantInterface { + String name; + int value; + const DocData::ConstantDoc *const_doc; + + ConstantInterface() {} + + ConstantInterface(const String &p_name, int p_value) { + name = p_name; + value = p_value; + } + }; + + struct EnumInterface { + StringName cname; + String prefix; + List<ConstantInterface> constants; + + _FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const { + return p_ienum.cname == cname; + } + + EnumInterface() {} + + EnumInterface(const StringName &p_cname) { + cname = p_cname; + } + }; + + struct PropertyInterface { + StringName cname; + String proxy_name; + int index; + + StringName setter; + StringName getter; + + const DocData::PropertyDoc *prop_doc; + }; + struct ArgumentInterface { enum DefaultParamMode { CONSTANT, @@ -46,7 +88,7 @@ class BindingsGenerator { NULLABLE_REF }; - String type; + StringName type; String name; String default_argument; DefaultParamMode def_param_mode; @@ -58,6 +100,7 @@ class BindingsGenerator { struct MethodInterface { String name; + StringName cname; /** * Name of the C# method @@ -67,7 +110,7 @@ class BindingsGenerator { /** * [TypeInterface::name] of the return type */ - String return_type; + StringName return_type; /** * Determines if the method has a variable number of arguments (VarArg) @@ -103,7 +146,7 @@ class BindingsGenerator { } MethodInterface() { - return_type = "void"; + return_type = BindingsGenerator::get_singleton()->name_cache.type_void; is_vararg = false; is_virtual = false; requires_object_call = false; @@ -118,11 +161,12 @@ class BindingsGenerator { * Also used to format [c_out]. */ String name; + StringName cname; /** * Identifier name of the base class. */ - String base_name; + StringName base_name; /** * Name of the C# class @@ -256,23 +300,32 @@ class BindingsGenerator { const DocData::ClassDoc *class_doc; + List<ConstantInterface> constants; + List<EnumInterface> enums; + List<PropertyInterface> properties; List<MethodInterface> methods; - const MethodInterface *find_method_by_name(const String &p_name) const { - + const MethodInterface *find_method_by_name(const StringName &p_cname) const { for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) { - if (E->get().name == p_name) + if (E->get().cname == p_cname) return &E->get(); } return NULL; } - static TypeInterface create_value_type(const String &p_name) { - TypeInterface itype; + const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const { + for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) { + if (E->get().proxy_name == p_proxy_name) + return &E->get(); + } - itype.name = p_name; - itype.proxy_name = p_name; + return NULL; + } + + private: + static void _init_value_type(TypeInterface &itype) { + itype.proxy_name = itype.name; itype.c_type = itype.name; itype.c_type_in = "void*"; @@ -281,15 +334,31 @@ class BindingsGenerator { itype.im_type_in = "ref " + itype.proxy_name; itype.im_type_out = itype.proxy_name; itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name]; + } + public: + static TypeInterface create_value_type(const String &p_name) { + TypeInterface itype; + itype.name = p_name; + itype.cname = StringName(p_name); + _init_value_type(itype); + return itype; + } + + static TypeInterface create_value_type(const StringName &p_name) { + TypeInterface itype; + itype.name = p_name.operator String(); + itype.cname = p_name; + _init_value_type(itype); return itype; } - static TypeInterface create_object_type(const String &p_name, ClassDB::APIType p_api_type) { + static TypeInterface create_object_type(const StringName &p_cname, ClassDB::APIType p_api_type) { TypeInterface itype; - itype.name = p_name; - itype.proxy_name = p_name.begins_with("_") ? p_name.substr(1, p_name.length()) : p_name; + itype.name = p_cname; + itype.cname = p_cname; + itype.proxy_name = itype.name.begins_with("_") ? itype.name.substr(1, itype.name.length()) : itype.name; itype.api_type = p_api_type; itype.is_object_type = true; itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name]; @@ -297,9 +366,10 @@ class BindingsGenerator { return itype; } - static void create_placeholder_type(TypeInterface &r_itype, const String &p_name) { - r_itype.name = p_name; - r_itype.proxy_name = p_name; + static void create_placeholder_type(TypeInterface &r_itype, const StringName &p_cname) { + r_itype.name = p_cname; + r_itype.cname = p_cname; + r_itype.proxy_name = r_itype.name; r_itype.c_type = r_itype.name; r_itype.c_type_in = "MonoObject*"; @@ -359,11 +429,15 @@ class BindingsGenerator { static bool verbose_output; - Map<String, TypeInterface> placeholder_types; - Map<String, TypeInterface> builtin_types; - Map<String, TypeInterface> obj_types; + Map<StringName, TypeInterface> placeholder_types; + Map<StringName, TypeInterface> builtin_types; + Map<StringName, TypeInterface> enum_types; + Map<StringName, TypeInterface> obj_types; - Map<String, String> extra_members; + List<EnumInterface> global_enums; + List<ConstantInterface> global_constants; + + Map<StringName, String> extra_members; List<InternalCall> method_icalls; Map<const MethodInterface *, const InternalCall *> method_icalls_map; @@ -373,8 +447,36 @@ class BindingsGenerator { List<InternalCall> core_custom_icalls; List<InternalCall> editor_custom_icalls; - const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) { + struct NameCache { + StringName type_void; + StringName type_int; + StringName type_Array; + StringName type_Dictionary; + StringName type_Variant; + StringName type_VarArg; + StringName type_Object; + StringName type_Reference; + StringName enum_Error; + + NameCache() { + type_void = StaticCString::create("void"); + type_int = StaticCString::create("int"); + type_Array = StaticCString::create("Array"); + type_Dictionary = StaticCString::create("Dictionary"); + type_Variant = StaticCString::create("Variant"); + type_VarArg = StaticCString::create("VarArg"); + type_Object = StaticCString::create("Object"); + type_Reference = StaticCString::create("Reference"); + enum_Error = StaticCString::create("Error"); + } + NameCache(const NameCache &); + NameCache &operator=(const NameCache &); + }; + + NameCache name_cache; + + const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) { const List<InternalCall>::Element *it = p_list.front(); while (it) { if (it->get().name == p_name) return it; @@ -392,11 +494,13 @@ class BindingsGenerator { return p_type.name; } + String _determine_enum_prefix(const EnumInterface &p_ienum); + void _generate_header_icalls(); void _generate_method_icalls(const TypeInterface &p_itype); - const TypeInterface *_get_type_by_name_or_null(const String &p_name); - const TypeInterface *_get_type_by_name_or_placeholder(const String &p_name); + const TypeInterface *_get_type_by_name_or_null(const StringName &p_cname); + const TypeInterface *_get_type_by_name_or_placeholder(const StringName &p_cname); void _default_argument_from_variant(const Variant &p_var, ArgumentInterface &r_iarg); void _populate_builtin_type(TypeInterface &r_type, Variant::Type vtype); @@ -404,27 +508,39 @@ class BindingsGenerator { void _populate_object_type_interfaces(); void _populate_builtin_type_interfaces(); + void _populate_global_constants(); + Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file); - Error _generate_cs_property(const TypeInterface &p_itype, const DocData::PropertyDoc &p_prop_doc, List<String> &p_output); + Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_prop_doc, List<String> &p_output); Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output); + void _generate_global_constants(List<String> &p_output); + Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, List<String> &p_output); Error _save_file(const String &path, const List<String> &content); - BindingsGenerator(); + BindingsGenerator() {} BindingsGenerator(const BindingsGenerator &); BindingsGenerator &operator=(const BindingsGenerator &); + friend class CSharpLanguage; + static BindingsGenerator *singleton; + public: Error generate_cs_core_project(const String &p_output_dir, bool p_verbose_output = true); Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true); Error generate_glue(const String &p_output_dir); - static BindingsGenerator &get_singleton() { - static BindingsGenerator singleton; + void initialize(); + + _FORCE_INLINE_ static BindingsGenerator *get_singleton() { + if (!singleton) { + singleton = memnew(BindingsGenerator); + singleton->initialize(); + } return singleton; } diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp index 9a1efb4423..e4269b0aec 100644 --- a/modules/mono/editor/csharp_project.cpp +++ b/modules/mono/editor/csharp_project.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "csharp_project.h" #include "os/os.h" @@ -54,7 +55,7 @@ String generate_core_api_project(const String &p_dir, const Vector<String> &p_fi ERR_FAIL_V(String()); } - return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : ""; + return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String(); } String generate_editor_api_project(const String &p_dir, const String &p_core_dll_path, const Vector<String> &p_files) { @@ -75,7 +76,7 @@ String generate_editor_api_project(const String &p_dir, const String &p_core_dll ERR_FAIL_V(String()); } - return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : ""; + return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String(); } String generate_game_project(const String &p_dir, const String &p_name, const Vector<String> &p_files) { @@ -96,7 +97,7 @@ String generate_game_project(const String &p_dir, const String &p_name, const Ve ERR_FAIL_V(String()); } - return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : ""; + return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String(); } void add_item(const String &p_project_path, const String &p_item_type, const String &p_include) { diff --git a/modules/mono/editor/csharp_project.h b/modules/mono/editor/csharp_project.h index 44e8325a59..381dd17e02 100644 --- a/modules/mono/editor/csharp_project.h +++ b/modules/mono/editor/csharp_project.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef CSHARP_PROJECT_H #define CSHARP_PROJECT_H diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index b88d34fc33..6b41b10981 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "godotsharp_builds.h" #include "main/main.h" @@ -238,12 +239,12 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { #error "How am I supposed to generate the bindings?" #endif - BindingsGenerator &gen = BindingsGenerator::get_singleton(); + BindingsGenerator *gen = BindingsGenerator::get_singleton(); bool gen_verbose = OS::get_singleton()->is_stdout_verbose(); Error err = p_api_type == API_CORE ? - gen.generate_cs_core_project(api_sln_dir, gen_verbose) : - gen.generate_cs_editor_project(api_sln_dir, core_api_assembly, gen_verbose); + gen->generate_cs_core_project(api_sln_dir, gen_verbose) : + gen->generate_cs_editor_project(api_sln_dir, core_api_assembly, gen_verbose); if (err != OK) { show_build_error_dialog("Failed to generate " + api_name + " solution. Error: " + itos(err)); @@ -313,7 +314,7 @@ GodotSharpBuilds *GodotSharpBuilds::singleton = NULL; void GodotSharpBuilds::build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code) { BuildProcess *match = builds.getptr(p_build_info); - ERR_FAIL_COND(!match); + ERR_FAIL_NULL(match); BuildProcess &bp = *match; bp.on_exit(p_exit_code); @@ -446,7 +447,7 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Build", "BuildInstance"); - MonoObject *mono_object = mono_object_new(mono_domain_get(), klass->get_raw()); + MonoObject *mono_object = mono_object_new(mono_domain_get(), klass->get_mono_ptr()); // Construct diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h index 7d2f38a774..5d2390ecd9 100644 --- a/modules/mono/editor/godotsharp_builds.h +++ b/modules/mono/editor/godotsharp_builds.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GODOTSHARP_BUILDS_H #define GODOTSHARP_BUILDS_H diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index 1bc1e8a515..da0a7b4fbd 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "godotsharp_editor.h" #include "core/os/os.h" @@ -50,9 +51,9 @@ GodotSharpEditor *GodotSharpEditor::singleton = NULL; bool GodotSharpEditor::_create_project_solution() { - EditorProgress pr("create_csharp_solution", "Generating solution...", 2); + EditorProgress pr("create_csharp_solution", TTR("Generating solution..."), 2); - pr.step("Generating C# project..."); + pr.step(TTR("Generating C# project...")); String path = OS::get_singleton()->get_resource_dir(); String name = ProjectSettings::get_singleton()->get("application/config/name"); @@ -67,7 +68,7 @@ bool GodotSharpEditor::_create_project_solution() { NETSolution solution(name); if (!solution.set_path(path)) { - show_error_dialog("Failed to create solution."); + show_error_dialog(TTR("Failed to create solution.")); return false; } @@ -79,7 +80,7 @@ bool GodotSharpEditor::_create_project_solution() { Error sln_error = solution.save(); if (sln_error != OK) { - show_error_dialog("Failed to save solution."); + show_error_dialog(TTR("Failed to save solution.")); return false; } @@ -89,13 +90,13 @@ bool GodotSharpEditor::_create_project_solution() { if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR)) return false; - pr.step("Done"); + pr.step(TTR("Done")); // Here, after all calls to progress_task_step call_deferred("_remove_create_sln_menu_option"); } else { - show_error_dialog("Failed to create C# project."); + show_error_dialog(TTR("Failed to create C# project.")); } return true; @@ -194,14 +195,14 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { error_dialog = memnew(AcceptDialog); editor->get_gui_base()->add_child(error_dialog); - bottom_panel_btn = editor->add_bottom_panel_item("Mono", memnew(MonoBottomPanel(editor))); + bottom_panel_btn = editor->add_bottom_panel_item(TTR("Mono"), memnew(MonoBottomPanel(editor))); godotsharp_builds = memnew(GodotSharpBuilds); editor->add_child(memnew(MonoReloadNode)); menu_button = memnew(MenuButton); - menu_button->set_text("Mono"); + menu_button->set_text(TTR("Mono")); menu_popup = menu_button->get_popup(); String sln_path = GodotSharpDirs::get_project_sln_path(); @@ -209,7 +210,7 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) { bottom_panel_btn->hide(); - menu_popup->add_item("Create C# solution", MENU_CREATE_SLN); + menu_popup->add_item(TTR("Create C# solution"), MENU_CREATE_SLN); } menu_popup->connect("id_pressed", this, "_menu_option_pressed"); diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h index 0f2c163582..1b83bae1cd 100644 --- a/modules/mono/editor/godotsharp_editor.h +++ b/modules/mono/editor/godotsharp_editor.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GODOTSHARP_EDITOR_H #define GODOTSHARP_EDITOR_H diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 31dc09856a..43689548b5 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "mono_bottom_panel.h" #include "../csharp_script.h" @@ -197,7 +198,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { panel_builds_tab->add_child(toolbar_hbc); ToolButton *build_project_btn = memnew(ToolButton); - build_project_btn->set_text("Build Project"); + build_project_btn->set_text(TTR("Build Project")); build_project_btn->set_focus_mode(FOCUS_NONE); build_project_btn->connect("pressed", this, "_build_project_pressed"); toolbar_hbc->add_child(build_project_btn); @@ -205,7 +206,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { toolbar_hbc->add_spacer(); warnings_btn = memnew(ToolButton); - warnings_btn->set_text("Warnings"); + warnings_btn->set_text(TTR("Warnings")); warnings_btn->set_toggle_mode(true); warnings_btn->set_pressed(true); warnings_btn->set_visible(false); @@ -214,7 +215,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { toolbar_hbc->add_child(warnings_btn); errors_btn = memnew(ToolButton); - errors_btn->set_text("Errors"); + errors_btn->set_text(TTR("Errors")); errors_btn->set_toggle_mode(true); errors_btn->set_pressed(true); errors_btn->set_visible(false); diff --git a/modules/mono/editor/mono_bottom_panel.h b/modules/mono/editor/mono_bottom_panel.h index 5cc4aa3240..a44d3a9af8 100644 --- a/modules/mono/editor/mono_bottom_panel.h +++ b/modules/mono/editor/mono_bottom_panel.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef MONO_BOTTOM_PANEL_H #define MONO_BOTTOM_PANEL_H diff --git a/modules/mono/editor/mono_build_info.h b/modules/mono/editor/mono_build_info.h index f3b3e43b6d..4806764a61 100644 --- a/modules/mono/editor/mono_build_info.h +++ b/modules/mono/editor/mono_build_info.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef MONO_BUILD_INFO_H #define MONO_BUILD_INFO_H diff --git a/modules/mono/editor/monodevelop_instance.cpp b/modules/mono/editor/monodevelop_instance.cpp index a34d82ffcb..0b0b36e1e3 100644 --- a/modules/mono/editor/monodevelop_instance.cpp +++ b/modules/mono/editor/monodevelop_instance.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "monodevelop_instance.h" #include "../mono_gd/gd_mono.h" @@ -62,7 +63,7 @@ MonoDevelopInstance::MonoDevelopInstance(const String &p_solution) { GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Editor", "MonoDevelopInstance"); - MonoObject *obj = mono_object_new(TOOLS_DOMAIN, klass->get_raw()); + MonoObject *obj = mono_object_new(TOOLS_DOMAIN, klass->get_mono_ptr()); GDMonoMethod *ctor = klass->get_method(".ctor", 1); MonoObject *ex = NULL; diff --git a/modules/mono/editor/monodevelop_instance.h b/modules/mono/editor/monodevelop_instance.h index 9eb154eba1..7e8a76b595 100644 --- a/modules/mono/editor/monodevelop_instance.h +++ b/modules/mono/editor/monodevelop_instance.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef MONODEVELOP_INSTANCE_H #define MONODEVELOP_INSTANCE_H diff --git a/modules/mono/editor/net_solution.cpp b/modules/mono/editor/net_solution.cpp index fa60c310db..dab96e44e9 100644 --- a/modules/mono/editor/net_solution.cpp +++ b/modules/mono/editor/net_solution.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "net_solution.h" #include "os/dir_access.h" diff --git a/modules/mono/editor/net_solution.h b/modules/mono/editor/net_solution.h index d7ccebb7df..293e86917a 100644 --- a/modules/mono/editor/net_solution.h +++ b/modules/mono/editor/net_solution.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef NET_SOLUTION_H #define NET_SOLUTION_H diff --git a/modules/mono/glue/cs_files/Error.cs b/modules/mono/glue/cs_files/Error.cs deleted file mode 100644 index dee4b88f74..0000000000 --- a/modules/mono/glue/cs_files/Error.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Godot -{ - public enum Error : int - { - OK = 0, - FAILED = 1, - ERR_UNAVAILABLE = 2, - ERR_UNCONFIGURED = 3, - ERR_UNAUTHORIZED = 4, - ERR_PARAMETER_RANGE_ERROR = 5, - ERR_OUT_OF_MEMORY = 6, - ERR_FILE_NOT_FOUND = 7, - ERR_FILE_BAD_DRIVE = 8, - ERR_FILE_BAD_PATH = 9, - ERR_FILE_NO_PERMISSION = 10, - ERR_FILE_ALREADY_IN_USE = 11, - ERR_FILE_CANT_OPEN = 12, - ERR_FILE_CANT_WRITE = 13, - ERR_FILE_CANT_READ = 14, - ERR_FILE_UNRECOGNIZED = 15, - ERR_FILE_CORRUPT = 16, - ERR_FILE_MISSING_DEPENDENCIES = 17, - ERR_FILE_EOF = 18, - ERR_CANT_OPEN = 19, - ERR_CANT_CREATE = 20, - ERR_PARSE_ERROR = 43, - ERROR_QUERY_FAILED = 21, - ERR_ALREADY_IN_USE = 22, - ERR_LOCKED = 23, - ERR_TIMEOUT = 24, - ERR_CANT_AQUIRE_RESOURCE = 28, - ERR_INVALID_DATA = 30, - ERR_INVALID_PARAMETER = 31, - ERR_ALREADY_EXISTS = 32, - ERR_DOES_NOT_EXIST = 33, - ERR_DATABASE_CANT_READ = 34, - ERR_DATABASE_CANT_WRITE = 35, - ERR_COMPILATION_FAILED = 36, - ERR_METHOD_NOT_FOUND = 37, - ERR_LINK_FAILED = 38, - ERR_SCRIPT_FAILED = 39, - ERR_CYCLIC_LINK = 40, - ERR_BUSY = 44, - ERR_HELP = 46, - ERR_BUG = 47 - } -} diff --git a/modules/mono/glue/cs_files/ExportAttribute.cs b/modules/mono/glue/cs_files/ExportAttribute.cs index dce9cc59a0..e6f569e1bb 100644 --- a/modules/mono/glue/cs_files/ExportAttribute.cs +++ b/modules/mono/glue/cs_files/ExportAttribute.cs @@ -5,13 +5,13 @@ namespace Godot [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class ExportAttribute : Attribute { - private int hint; - private string hint_string; + private PropertyHint hint; + private string hintString; - public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "") + public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "") { this.hint = hint; - this.hint_string = hint_string; + this.hintString = hintString; } } } diff --git a/modules/mono/glue/cs_files/GD.cs b/modules/mono/glue/cs_files/GD.cs index 99fc289161..b335ef55e4 100644 --- a/modules/mono/glue/cs_files/GD.cs +++ b/modules/mono/glue/cs_files/GD.cs @@ -2,10 +2,8 @@ using System; namespace Godot { - public static class GD + public static partial class GD { - /*{GodotGlobalConstants}*/ - public static object Bytes2Var(byte[] bytes) { return NativeCalls.godot_icall_Godot_bytes2var(bytes); diff --git a/modules/mono/glue/cs_files/Rect2.cs b/modules/mono/glue/cs_files/Rect2.cs index f2718d7b7a..e1fbb65da5 100644 --- a/modules/mono/glue/cs_files/Rect2.cs +++ b/modules/mono/glue/cs_files/Rect2.cs @@ -109,14 +109,14 @@ namespace Godot return g; } - public Rect2 GrowMargin(int margin, float by) + public Rect2 GrowMargin(Margin margin, float by) { Rect2 g = this; - g.GrowIndividual((GD.MARGIN_LEFT == margin) ? by : 0, - (GD.MARGIN_TOP == margin) ? by : 0, - (GD.MARGIN_RIGHT == margin) ? by : 0, - (GD.MARGIN_BOTTOM == margin) ? by : 0); + g.GrowIndividual((Margin.Left == margin) ? by : 0, + (Margin.Top == margin) ? by : 0, + (Margin.Right == margin) ? by : 0, + (Margin.Bottom == margin) ? by : 0); return g; } @@ -230,4 +230,4 @@ namespace Godot }); } } -}
\ No newline at end of file +} diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index 75a4eb2b40..32988c5afa 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "../csharp_script.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_internals.h" @@ -53,9 +54,11 @@ } \ Object *m_instance = ci->creation_func(); -void godot_icall_Object_Dtor(Object *ptr) { - ERR_FAIL_NULL(ptr); - _GodotSharp::get_singleton()->queue_dispose(ptr); +void godot_icall_Object_Dtor(MonoObject *obj, Object *ptr) { +#ifdef DEBUG_ENABLED + CRASH_COND(ptr == NULL); +#endif + _GodotSharp::get_singleton()->queue_dispose(obj, ptr); } // -- ClassDB -- diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h index f941a4d6c5..4c26c3e6bd 100644 --- a/modules/mono/godotsharp_defs.h +++ b/modules/mono/godotsharp_defs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GODOTSHARP_DEFS_H #define GODOTSHARP_DEFS_H diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index 0f6245a37c..92c5cdc5c1 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "godotsharp_dirs.h" #include "os/os.h" diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h index 914df40629..e87b5a4150 100644 --- a/modules/mono/godotsharp_dirs.h +++ b/modules/mono/godotsharp_dirs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GODOTSHARP_DIRS_H #define GODOTSHARP_DIRS_H diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp index 121392b3f8..4e82bcd03e 100644 --- a/modules/mono/mono_gc_handle.cpp +++ b/modules/mono/mono_gc_handle.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "mono_gc_handle.h" #include "mono_gd/gd_mono.h" @@ -41,10 +42,7 @@ uint32_t MonoGCHandle::make_strong_handle(MonoObject *p_object) { uint32_t MonoGCHandle::make_weak_handle(MonoObject *p_object) { - return mono_gchandle_new_weakref( - p_object, - true /* track_resurrection: allows us to invoke _notification(NOTIFICATION_PREDELETE) while disposing */ - ); + return mono_gchandle_new_weakref(p_object, false); } Ref<MonoGCHandle> MonoGCHandle::create_strong(MonoObject *p_object) { diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h index cf5b6cec21..9cb3ef0fbb 100644 --- a/modules/mono/mono_gc_handle.h +++ b/modules/mono/mono_gc_handle.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef CSHARP_GC_HANDLE_H #define CSHARP_GC_HANDLE_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index c997b0f000..d4df7e0cb2 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono.h" #include <mono/metadata/exception.h> @@ -52,8 +53,7 @@ void gdmono_unhandled_exception_hook(MonoObject *exc, void *user_data) { (void)user_data; // UNUSED - ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8()); - mono_print_unhandled_exception(exc); + GDMonoUtils::print_unhandled_exception(exc); abort(); } @@ -703,7 +703,7 @@ bool _GodotSharp::is_domain_loaded() { call_deferred("_dispose_callback"); \ } -void _GodotSharp::queue_dispose(Object *p_object) { +void _GodotSharp::queue_dispose(MonoObject *p_mono_object, Object *p_object) { if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) { _dispose_object(p_object); @@ -712,6 +712,13 @@ void _GodotSharp::queue_dispose(Object *p_object) { queue_mutex->lock(); #endif + // This is our last chance to invoke notification predelete (this is being called from the finalizer) + // We must use the MonoObject* passed by the finalizer, because the weak GC handle target returns NULL at this point + CSharpInstance *si = CAST_CSHARP_INSTANCE(p_object->get_script_instance()); + if (si) { + si->call_notification_no_check(p_mono_object, Object::NOTIFICATION_PREDELETE); + } + ENQUEUE_FOR_DISPOSAL(obj_delete_queue, p_object); #ifndef NO_THREADS diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index b188c0730a..67251778c6 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONO_H #define GD_MONO_H @@ -112,14 +113,6 @@ public: #endif #endif - enum MemberVisibility { - PRIVATE, - PROTECTED_AND_INTERNAL, // FAM_AND_ASSEM - INTERNAL, // ASSEMBLY - PROTECTED, // FAMILY - PUBLIC - }; - static GDMono *get_singleton() { return singleton; } // Do not use these, unless you know what you're doing @@ -215,7 +208,7 @@ public: bool is_finalizing_domain(); bool is_domain_loaded(); - void queue_dispose(Object *p_object); + void queue_dispose(MonoObject *p_mono_object, Object *p_object); void queue_dispose(NodePath *p_node_path); void queue_dispose(RID *p_rid); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 7dc7043eec..ba56ed6ed5 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_assembly.h" #include <mono/metadata/mono-debug.h> @@ -318,7 +319,7 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) void *iter = NULL; while (true) { - MonoClass *raw_nested = mono_class_get_nested_types(current_nested->get_raw(), &iter); + MonoClass *raw_nested = mono_class_get_nested_types(current_nested->get_mono_ptr(), &iter); if (!raw_nested) break; diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 710b674622..8e7aa701bf 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONO_ASSEMBLY_H #define GD_MONO_ASSEMBLY_H diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 77ba0ee90e..d3315568cb 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_class.h" #include <mono/metadata/attrdefs.h> @@ -35,7 +36,7 @@ MonoType *GDMonoClass::get_raw_type(GDMonoClass *p_class) { - return mono_class_get_type(p_class->get_raw()); + return mono_class_get_type(p_class->get_mono_ptr()); } bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const { @@ -74,7 +75,7 @@ Vector<MonoClassField *> GDMonoClass::get_enum_fields() { void *iter = NULL; MonoClassField *raw_field = NULL; - while ((raw_field = mono_class_get_fields(get_raw(), &iter)) != NULL) { + while ((raw_field = mono_class_get_fields(get_mono_ptr(), &iter)) != NULL) { uint32_t field_flags = mono_field_get_flags(raw_field); // Enums have an instance field named value__ which holds the value of the enum. @@ -105,7 +106,7 @@ bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) { if (!attributes) return false; - return mono_custom_attrs_has_attr(attributes, p_attr_class->get_raw()); + return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); } MonoObject *GDMonoClass::get_attribute(GDMonoClass *p_attr_class) { @@ -120,14 +121,14 @@ MonoObject *GDMonoClass::get_attribute(GDMonoClass *p_attr_class) { if (!attributes) return NULL; - return mono_custom_attrs_get_attr(attributes, p_attr_class->get_raw()); + return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoClass::fetch_attributes() { ERR_FAIL_COND(attributes != NULL); - attributes = mono_custom_attrs_from_class(get_raw()); + attributes = mono_custom_attrs_from_class(get_mono_ptr()); attrs_fetched = true; } @@ -140,7 +141,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base void *iter = NULL; MonoMethod *raw_method = NULL; - while ((raw_method = mono_class_get_methods(get_raw(), &iter)) != NULL) { + while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) { StringName name = mono_method_get_name(raw_method); GDMonoMethod *method = get_method(raw_method, name); @@ -334,7 +335,7 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { void *iter = NULL; MonoClassField *raw_field = NULL; - while ((raw_field = mono_class_get_fields(get_raw(), &iter)) != NULL) { + while ((raw_field = mono_class_get_fields(mono_class, &iter)) != NULL) { StringName name = mono_field_get_name(raw_field); Map<StringName, GDMonoField *>::Element *match = fields.find(name); @@ -353,6 +354,54 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { return fields_list; } +GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) { + + Map<StringName, GDMonoProperty *>::Element *result = properties.find(p_name); + + if (result) + return result->value(); + + if (properties_fetched) + return NULL; + + MonoProperty *raw_property = mono_class_get_property_from_name(mono_class, String(p_name).utf8().get_data()); + + if (raw_property) { + GDMonoProperty *property = memnew(GDMonoProperty(raw_property, this)); + properties.insert(p_name, property); + + return property; + } + + return NULL; +} + +const Vector<GDMonoProperty *> &GDMonoClass::get_all_properties() { + + if (properties_fetched) + return properties_list; + + void *iter = NULL; + MonoProperty *raw_property = NULL; + while ((raw_property = mono_class_get_properties(mono_class, &iter)) != NULL) { + StringName name = mono_property_get_name(raw_property); + + Map<StringName, GDMonoProperty *>::Element *match = properties.find(name); + + if (match) { + properties_list.push_back(match->get()); + } else { + GDMonoProperty *property = memnew(GDMonoProperty(raw_property, this)); + properties.insert(name, property); + properties_list.push_back(property); + } + } + + properties_fetched = true; + + return properties_list; +} + GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) { namespace_name = p_namespace; @@ -365,6 +414,7 @@ GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name methods_fetched = false; fields_fetched = false; + properties_fetched = false; } GDMonoClass::~GDMonoClass() { @@ -377,6 +427,10 @@ GDMonoClass::~GDMonoClass() { memdelete(E->value()); } + for (Map<StringName, GDMonoProperty *>::Element *E = properties.front(); E; E = E->next()) { + memdelete(E->value()); + } + { // Ugly workaround... // We may have duplicated values, because we redirect snake_case methods to PascalCasel (only Godot API methods). diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index ef1ca425a7..b6052ac0ed 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONO_CLASS_H #define GD_MONO_CLASS_H @@ -38,6 +39,7 @@ #include "gd_mono_field.h" #include "gd_mono_header.h" #include "gd_mono_method.h" +#include "gd_mono_property.h" #include "gd_mono_utils.h" class GDMonoClass { @@ -84,6 +86,10 @@ class GDMonoClass { Map<StringName, GDMonoField *> fields; Vector<GDMonoField *> fields_list; + bool properties_fetched; + Map<StringName, GDMonoProperty *> properties; + Vector<GDMonoProperty *> properties_list; + friend class GDMonoAssembly; GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly); @@ -95,7 +101,7 @@ public: _FORCE_INLINE_ StringName get_namespace() const { return namespace_name; } _FORCE_INLINE_ StringName get_name() const { return class_name; } - _FORCE_INLINE_ MonoClass *get_raw() const { return mono_class; } + _FORCE_INLINE_ MonoClass *get_mono_ptr() const { return mono_class; } _FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; } String get_full_name() const; @@ -124,6 +130,9 @@ public: GDMonoField *get_field(const StringName &p_name); const Vector<GDMonoField *> &get_all_fields(); + GDMonoProperty *get_property(const StringName &p_name); + const Vector<GDMonoProperty *> &get_all_properties(); + ~GDMonoClass(); }; diff --git a/modules/mono/mono_gd/gd_mono_class_member.h b/modules/mono/mono_gd/gd_mono_class_member.h new file mode 100644 index 0000000000..008ea0e416 --- /dev/null +++ b/modules/mono/mono_gd/gd_mono_class_member.h @@ -0,0 +1,67 @@ +/*************************************************************************/ +/* gd_mono_class_member.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef GD_MONO_CLASS_MEMBER_H +#define GD_MONO_CLASS_MEMBER_H + +#include "gd_mono_header.h" + +#include <mono/metadata/object.h> + +class GDMonoClassMember { +public: + enum Visibility { + PRIVATE, + PROTECTED_AND_INTERNAL, // FAM_AND_ASSEM + INTERNAL, // ASSEMBLY + PROTECTED, // FAMILY + PUBLIC + }; + + enum MemberType { + MEMBER_TYPE_FIELD, + MEMBER_TYPE_PROPERTY, + MEMBER_TYPE_METHOD + }; + + virtual ~GDMonoClassMember() {} + + virtual MemberType get_member_type() = 0; + + virtual StringName get_name() = 0; + + virtual bool is_static() = 0; + + virtual Visibility get_visibility() = 0; + + virtual bool has_attribute(GDMonoClass *p_attr_class) = 0; + virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) = 0; +}; + +#endif // GD_MONO_CLASS_MEMBER_H diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index eb34f9dd3f..3b91777ed4 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_field.h" #include <mono/metadata/attrdefs.h> @@ -38,7 +39,7 @@ void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) { mono_field_set_value(p_object, mono_field, &p_ptr); } -void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) { +void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_value) { #define SET_FROM_STRUCT_AND_BREAK(m_type) \ { \ const m_type &val = p_value.operator ::m_type(); \ @@ -138,7 +139,7 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) { if (tclass == CACHED_CLASS(Plane)) SET_FROM_STRUCT_AND_BREAK(Plane); - if (mono_class_is_enum(tclass->get_raw())) + if (mono_class_is_enum(tclass->get_mono_ptr())) SET_FROM_PRIMITIVE(signed int); ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + tclass->get_name()); @@ -264,7 +265,7 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) { } break; case MONO_TYPE_GENERICINST: { - if (CACHED_RAW_MONO_CLASS(Dictionary) == type.type_class->get_raw()) { + if (CACHED_RAW_MONO_CLASS(Dictionary) == type.type_class->get_mono_ptr()) { MonoObject *managed = GDMonoMarshal::Dictionary_to_mono_object(p_value.operator Dictionary()); mono_field_set_value(p_object, mono_field, managed); break; @@ -280,6 +281,10 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) { #undef SET_FROM_PRIMITIVE } +MonoObject *GDMonoField::get_value(MonoObject *p_object) { + return mono_field_get_value_object(mono_domain_get(), mono_field, p_object); +} + bool GDMonoField::get_bool_value(MonoObject *p_object) { return (bool)GDMonoMarshal::unbox<MonoBoolean>(get_value(p_object)); } @@ -290,7 +295,7 @@ int GDMonoField::get_int_value(MonoObject *p_object) { String GDMonoField::get_string_value(MonoObject *p_object) { MonoObject *val = get_value(p_object); - return val ? GDMonoMarshal::mono_string_to_godot((MonoString *)val) : String(); + return GDMonoMarshal::mono_string_to_godot((MonoString *)val); } bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) { @@ -302,7 +307,7 @@ bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) { if (!attributes) return false; - return mono_custom_attrs_has_attr(attributes, p_attr_class->get_raw()); + return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); } MonoObject *GDMonoField::get_attribute(GDMonoClass *p_attr_class) { @@ -314,12 +319,12 @@ MonoObject *GDMonoField::get_attribute(GDMonoClass *p_attr_class) { if (!attributes) return NULL; - return mono_custom_attrs_get_attr(attributes, p_attr_class->get_raw()); + return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoField::fetch_attributes() { ERR_FAIL_COND(attributes != NULL); - attributes = mono_custom_attrs_from_field(owner->get_raw(), get_raw()); + attributes = mono_custom_attrs_from_field(owner->get_mono_ptr(), mono_field); attrs_fetched = true; } @@ -327,26 +332,26 @@ bool GDMonoField::is_static() { return mono_field_get_flags(mono_field) & MONO_FIELD_ATTR_STATIC; } -GDMono::MemberVisibility GDMonoField::get_visibility() { +GDMonoClassMember::Visibility GDMonoField::get_visibility() { switch (mono_field_get_flags(mono_field) & MONO_FIELD_ATTR_FIELD_ACCESS_MASK) { case MONO_FIELD_ATTR_PRIVATE: - return GDMono::PRIVATE; + return GDMonoClassMember::PRIVATE; case MONO_FIELD_ATTR_FAM_AND_ASSEM: - return GDMono::PROTECTED_AND_INTERNAL; + return GDMonoClassMember::PROTECTED_AND_INTERNAL; case MONO_FIELD_ATTR_ASSEMBLY: - return GDMono::INTERNAL; + return GDMonoClassMember::INTERNAL; case MONO_FIELD_ATTR_FAMILY: - return GDMono::PROTECTED; + return GDMonoClassMember::PROTECTED; case MONO_FIELD_ATTR_PUBLIC: - return GDMono::PUBLIC; + return GDMonoClassMember::PUBLIC; default: - ERR_FAIL_V(GDMono::PRIVATE); + ERR_FAIL_V(GDMonoClassMember::PRIVATE); } } -GDMonoField::GDMonoField(MonoClassField *p_raw_field, GDMonoClass *p_owner) { +GDMonoField::GDMonoField(MonoClassField *p_mono_field, GDMonoClass *p_owner) { owner = p_owner; - mono_field = p_raw_field; + mono_field = p_mono_field; name = mono_field_get_name(mono_field); MonoType *field_type = mono_field_get_type(mono_field); type.type_encoding = mono_type_get_type(field_type); diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index b7e1942d71..a6b368c4d6 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,47 +27,49 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GDMONOFIELD_H #define GDMONOFIELD_H #include "gd_mono.h" +#include "gd_mono_class_member.h" #include "gd_mono_header.h" -class GDMonoField { +class GDMonoField : public GDMonoClassMember { + GDMonoClass *owner; MonoClassField *mono_field; - String name; + StringName name; ManagedType type; bool attrs_fetched; MonoCustomAttrInfo *attributes; public: - _FORCE_INLINE_ String get_name() const { return name; } - _FORCE_INLINE_ ManagedType get_type() const { return type; } + virtual MemberType get_member_type() { return MEMBER_TYPE_FIELD; } - _FORCE_INLINE_ MonoClassField *get_raw() const { return mono_field; } + virtual StringName get_name() { return name; } + + virtual bool is_static(); + virtual Visibility get_visibility(); + + virtual bool has_attribute(GDMonoClass *p_attr_class); + virtual MonoObject *get_attribute(GDMonoClass *p_attr_class); + void fetch_attributes(); + + _FORCE_INLINE_ ManagedType get_type() const { return type; } void set_value_raw(MonoObject *p_object, void *p_ptr); - void set_value(MonoObject *p_object, const Variant &p_value); + void set_value_from_variant(MonoObject *p_object, const Variant &p_value); - _FORCE_INLINE_ MonoObject *get_value(MonoObject *p_object) { - return mono_field_get_value_object(mono_domain_get(), mono_field, p_object); - } + MonoObject *get_value(MonoObject *p_object); bool get_bool_value(MonoObject *p_object); int get_int_value(MonoObject *p_object); String get_string_value(MonoObject *p_object); - bool has_attribute(GDMonoClass *p_attr_class); - MonoObject *get_attribute(GDMonoClass *p_attr_class); - void fetch_attributes(); - - bool is_static(); - GDMono::MemberVisibility get_visibility(); - - GDMonoField(MonoClassField *p_raw_field, GDMonoClass *p_owner); + GDMonoField(MonoClassField *p_mono_field, GDMonoClass *p_owner); ~GDMonoField(); }; diff --git a/modules/mono/mono_gd/gd_mono_header.h b/modules/mono/mono_gd/gd_mono_header.h index 803d394f96..2b5110f0b9 100644 --- a/modules/mono/mono_gd/gd_mono_header.h +++ b/modules/mono/mono_gd/gd_mono_header.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONO_HEADER_H #define GD_MONO_HEADER_H @@ -34,8 +35,10 @@ class GDMonoAssembly; class GDMonoClass; -class GDMonoMethod; +class GDMonoClassMember; class GDMonoField; +class GDMonoProperty; +class GDMonoMethod; struct ManagedType { int type_encoding; diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index 56e8a01567..a1a79f957f 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* godotsharp_internals.cpp */ +/* gd_mono_internals.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_internals.h" #include "../csharp_script.h" diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h index 6bdf4a6c46..abec65e7d4 100644 --- a/modules/mono/mono_gd/gd_mono_internals.h +++ b/modules/mono/mono_gd/gd_mono_internals.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* godotsharp_internals.h */ +/* gd_mono_internals.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONO_INTERNALS_H #define GD_MONO_INTERNALS_H diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index e8aea8624d..eabea8dc3c 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_log.h" #include <mono/utils/mono-logger.h> diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h index 497f1e5317..a7e374858c 100644 --- a/modules/mono/mono_gd/gd_mono_log.h +++ b/modules/mono/mono_gd/gd_mono_log.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONO_LOG_H #define GD_MONO_LOG_H diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 8bc2bb5096..1ec8f41c91 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_marshal.h" #include "gd_mono.h" @@ -113,7 +114,7 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { if (tclass == CACHED_CLASS(Plane)) return Variant::PLANE; - if (mono_class_is_enum(tclass->get_raw())) + if (mono_class_is_enum(tclass->get_mono_ptr())) return Variant::INT; } break; @@ -164,7 +165,7 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { } break; case MONO_TYPE_GENERICINST: { - if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_raw()) { + if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_mono_ptr()) { return Variant::DICTIONARY; } } break; @@ -306,9 +307,9 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty if (tclass == CACHED_CLASS(Plane)) RETURN_BOXED_STRUCT(Plane, p_var); - if (mono_class_is_enum(tclass->get_raw())) { + if (mono_class_is_enum(tclass->get_mono_ptr())) { int val = p_var->operator signed int(); - return BOX_ENUM(tclass->get_raw(), val); + return BOX_ENUM(tclass->get_mono_ptr(), val); } } break; @@ -432,7 +433,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty } break; case MONO_TYPE_GENERICINST: { - if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_raw()) { + if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_mono_ptr()) { return Dictionary_to_mono_object(p_var->operator Dictionary()); } } break; @@ -490,8 +491,9 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) { return unbox<double>(p_obj); case MONO_TYPE_STRING: { - String str = mono_string_to_godot((MonoString *)p_obj); - return str; + if (p_obj == NULL) + return Variant(); // NIL + return mono_string_to_godot_not_null((MonoString *)p_obj); } break; case MONO_TYPE_VALUETYPE: { @@ -527,7 +529,7 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) { if (tclass == CACHED_CLASS(Plane)) RETURN_UNBOXED_STRUCT(Plane, p_obj); - if (mono_class_is_enum(tclass->get_raw())) + if (mono_class_is_enum(tclass->get_mono_ptr())) return unbox<int32_t>(p_obj); } break; @@ -584,7 +586,7 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) { } break; case MONO_TYPE_GENERICINST: { - if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_raw()) { + if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_mono_ptr()) { return mono_object_to_Dictionary(p_obj); } } break; diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 443e947fb5..727b9fa230 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GDMONOMARSHAL_H #define GDMONOMARSHAL_H @@ -62,13 +63,20 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type); String mono_to_utf8_string(MonoString *p_mono_string); String mono_to_utf16_string(MonoString *p_mono_string); -_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { +_FORCE_INLINE_ String mono_string_to_godot_not_null(MonoString *p_mono_string) { if (sizeof(CharType) == 2) return mono_to_utf16_string(p_mono_string); return mono_to_utf8_string(p_mono_string); } +_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { + if (p_mono_string == NULL) + return String(); + + return mono_string_to_godot_not_null(p_mono_string); +} + _FORCE_INLINE_ MonoString *mono_from_utf8_string(const String &p_string) { return mono_string_new(mono_domain_get(), p_string.utf8().get_data()); } diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp index eb97d62900..1f8e9a1926 100644 --- a/modules/mono/mono_gd/gd_mono_method.cpp +++ b/modules/mono/mono_gd/gd_mono_method.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,11 +27,14 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_method.h" #include "gd_mono_class.h" #include "gd_mono_marshal.h" +#include <mono/metadata/attrdefs.h> + void GDMonoMethod::_update_signature() { // Apparently MonoMethodSignature needs not to be freed. // mono_method_signature caches the result, we don't need to cache it ourselves. @@ -41,7 +44,6 @@ void GDMonoMethod::_update_signature() { } void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) { - is_instance = mono_signature_is_instance(p_method_sig); params_count = mono_signature_get_param_count(p_method_sig); MonoType *ret_type = mono_signature_get_return_type(p_method_sig); @@ -61,15 +63,34 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) { param_type.type_encoding = mono_type_get_type(param_raw_type); - if (param_type.type_encoding != MONO_TYPE_VOID) { - MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type); - param_type.type_class = GDMono::get_singleton()->get_class(param_type_class); - } + MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type); + param_type.type_class = GDMono::get_singleton()->get_class(param_type_class); param_types.push_back(param_type); } } +bool GDMonoMethod::is_static() { + return mono_method_get_flags(mono_method, NULL) & MONO_METHOD_ATTR_STATIC; +} + +GDMonoClassMember::Visibility GDMonoMethod::get_visibility() { + switch (mono_method_get_flags(mono_method, NULL) & MONO_METHOD_ATTR_ACCESS_MASK) { + case MONO_METHOD_ATTR_PRIVATE: + return GDMonoClassMember::PRIVATE; + case MONO_METHOD_ATTR_FAM_AND_ASSEM: + return GDMonoClassMember::PROTECTED_AND_INTERNAL; + case MONO_METHOD_ATTR_ASSEM: + return GDMonoClassMember::INTERNAL; + case MONO_METHOD_ATTR_FAMILY: + return GDMonoClassMember::PROTECTED; + case MONO_METHOD_ATTR_PUBLIC: + return GDMonoClassMember::PUBLIC; + default: + ERR_FAIL_V(GDMonoClassMember::PRIVATE); + } +} + void *GDMonoMethod::get_thunk() { return mono_method_get_unmanaged_thunk(mono_method); } @@ -87,11 +108,11 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, MonoObject *ret = mono_runtime_invoke_array(mono_method, p_object, params, &exc); if (exc) { + ret = NULL; if (r_exc) { *r_exc = exc; } else { - ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8()); - mono_print_unhandled_exception(exc); + GDMonoUtils::print_unhandled_exception(exc); } } @@ -104,8 +125,7 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, if (r_exc) { *r_exc = exc; } else { - ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8()); - mono_print_unhandled_exception(exc); + GDMonoUtils::print_unhandled_exception(exc); } } @@ -123,11 +143,11 @@ MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, Mono MonoObject *ret = mono_runtime_invoke(mono_method, p_object, p_params, &exc); if (exc) { + ret = NULL; if (r_exc) { *r_exc = exc; } else { - ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8()); - mono_print_unhandled_exception(exc); + GDMonoUtils::print_unhandled_exception(exc); } } @@ -143,7 +163,7 @@ bool GDMonoMethod::has_attribute(GDMonoClass *p_attr_class) { if (!attributes) return false; - return mono_custom_attrs_has_attr(attributes, p_attr_class->get_raw()); + return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); } MonoObject *GDMonoMethod::get_attribute(GDMonoClass *p_attr_class) { @@ -155,7 +175,7 @@ MonoObject *GDMonoMethod::get_attribute(GDMonoClass *p_attr_class) { if (!attributes) return NULL; - return mono_custom_attrs_get_attr(attributes, p_attr_class->get_raw()); + return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoMethod::fetch_attributes() { diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h index ea4bc8e707..14df8dcfb4 100644 --- a/modules/mono/mono_gd/gd_mono_method.h +++ b/modules/mono/mono_gd/gd_mono_method.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,17 +27,18 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONO_METHOD_H #define GD_MONO_METHOD_H #include "gd_mono.h" +#include "gd_mono_class_member.h" #include "gd_mono_header.h" -class GDMonoMethod { +class GDMonoMethod : public GDMonoClassMember { StringName name; - bool is_instance; int params_count; ManagedType return_type; Vector<ManagedType> param_types; @@ -53,9 +54,18 @@ class GDMonoMethod { MonoMethod *mono_method; public: - _FORCE_INLINE_ StringName get_name() { return name; } + virtual MemberType get_member_type() { return MEMBER_TYPE_METHOD; } + + virtual StringName get_name() { return name; } + + virtual bool is_static(); + + virtual Visibility get_visibility(); + + virtual bool has_attribute(GDMonoClass *p_attr_class); + virtual MonoObject *get_attribute(GDMonoClass *p_attr_class); + virtual void fetch_attributes(); - _FORCE_INLINE_ bool is_static() { return !is_instance; } _FORCE_INLINE_ int get_parameters_count() { return params_count; } _FORCE_INLINE_ ManagedType get_return_type() { return return_type; } @@ -65,10 +75,6 @@ public: MonoObject *invoke(MonoObject *p_object, MonoObject **r_exc = NULL); MonoObject *invoke_raw(MonoObject *p_object, void **p_params, MonoObject **r_exc = NULL); - bool has_attribute(GDMonoClass *p_attr_class); - MonoObject *get_attribute(GDMonoClass *p_attr_class); - void fetch_attributes(); - String get_full_name(bool p_signature = false) const; String get_full_name_no_class() const; String get_ret_type_full_name() const; diff --git a/modules/mono/mono_gd/gd_mono_property.cpp b/modules/mono/mono_gd/gd_mono_property.cpp new file mode 100644 index 0000000000..bc5a1d3a39 --- /dev/null +++ b/modules/mono/mono_gd/gd_mono_property.cpp @@ -0,0 +1,199 @@ +/*************************************************************************/ +/* gd_mono_property.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "gd_mono_property.h" + +#include "gd_mono_class.h" +#include "gd_mono_marshal.h" + +#include <mono/metadata/attrdefs.h> + +GDMonoProperty::GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_owner) { + owner = p_owner; + mono_property = p_mono_property; + name = mono_property_get_name(mono_property); + + MonoMethod *prop_method = mono_property_get_get_method(mono_property); + + if (prop_method) { + MonoMethodSignature *getter_sig = mono_method_signature(prop_method); + + MonoType *ret_type = mono_signature_get_return_type(getter_sig); + + type.type_encoding = mono_type_get_type(ret_type); + MonoClass *ret_type_class = mono_class_from_mono_type(ret_type); + type.type_class = GDMono::get_singleton()->get_class(ret_type_class); + } else { + prop_method = mono_property_get_set_method(mono_property); + + MonoMethodSignature *setter_sig = mono_method_signature(prop_method); + + void *iter = NULL; + MonoType *param_raw_type = mono_signature_get_params(setter_sig, &iter); + + type.type_encoding = mono_type_get_type(param_raw_type); + MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type); + type.type_class = GDMono::get_singleton()->get_class(param_type_class); + } + + attrs_fetched = false; + attributes = NULL; +} + +GDMonoProperty::~GDMonoProperty() { + if (attributes) { + mono_custom_attrs_free(attributes); + } +} + +bool GDMonoProperty::is_static() { + MonoMethod *prop_method = mono_property_get_get_method(mono_property); + if (prop_method == NULL) + prop_method = mono_property_get_set_method(mono_property); + return mono_method_get_flags(prop_method, NULL) & MONO_METHOD_ATTR_STATIC; +} + +GDMonoClassMember::Visibility GDMonoProperty::get_visibility() { + MonoMethod *prop_method = mono_property_get_get_method(mono_property); + if (prop_method == NULL) + prop_method = mono_property_get_set_method(mono_property); + + switch (mono_method_get_flags(prop_method, NULL) & MONO_METHOD_ATTR_ACCESS_MASK) { + case MONO_METHOD_ATTR_PRIVATE: + return GDMonoClassMember::PRIVATE; + case MONO_METHOD_ATTR_FAM_AND_ASSEM: + return GDMonoClassMember::PROTECTED_AND_INTERNAL; + case MONO_METHOD_ATTR_ASSEM: + return GDMonoClassMember::INTERNAL; + case MONO_METHOD_ATTR_FAMILY: + return GDMonoClassMember::PROTECTED; + case MONO_METHOD_ATTR_PUBLIC: + return GDMonoClassMember::PUBLIC; + default: + ERR_FAIL_V(GDMonoClassMember::PRIVATE); + } +} + +bool GDMonoProperty::has_attribute(GDMonoClass *p_attr_class) { + ERR_FAIL_NULL_V(p_attr_class, false); + + if (!attrs_fetched) + fetch_attributes(); + + if (!attributes) + return false; + + return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); +} + +MonoObject *GDMonoProperty::get_attribute(GDMonoClass *p_attr_class) { + ERR_FAIL_NULL_V(p_attr_class, NULL); + + if (!attrs_fetched) + fetch_attributes(); + + if (!attributes) + return NULL; + + return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); +} + +void GDMonoProperty::fetch_attributes() { + ERR_FAIL_COND(attributes != NULL); + attributes = mono_custom_attrs_from_property(owner->get_mono_ptr(), mono_property); + attrs_fetched = true; +} + +bool GDMonoProperty::has_getter() { + return mono_property_get_get_method(mono_property) != NULL; +} + +bool GDMonoProperty::has_setter() { + return mono_property_get_set_method(mono_property) != NULL; +} + +void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoObject **r_exc) { + MonoMethod *prop_method = mono_property_get_get_method(mono_property); + + MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1); + mono_array_set(params, MonoObject *, 0, p_value); + + MonoObject *exc = NULL; + mono_runtime_invoke_array(prop_method, p_object, params, &exc); + + if (exc) { + if (r_exc) { + *r_exc = exc; + } else { + GDMonoUtils::print_unhandled_exception(exc); + } + } +} + +void GDMonoProperty::set_value(MonoObject *p_object, void **p_params, MonoObject **r_exc) { + MonoObject *exc = NULL; + mono_property_set_value(mono_property, p_object, p_params, &exc); + + if (exc) { + if (r_exc) { + *r_exc = exc; + } else { + GDMonoUtils::print_unhandled_exception(exc); + } + } +} + +MonoObject *GDMonoProperty::get_value(MonoObject *p_object, MonoObject **r_exc) { + MonoObject *exc = NULL; + MonoObject *ret = mono_property_get_value(mono_property, p_object, NULL, &exc); + + if (exc) { + ret = NULL; + if (r_exc) { + *r_exc = exc; + } else { + GDMonoUtils::print_unhandled_exception(exc); + } + } + + return ret; +} + +bool GDMonoProperty::get_bool_value(MonoObject *p_object) { + return (bool)GDMonoMarshal::unbox<MonoBoolean>(get_value(p_object)); +} + +int GDMonoProperty::get_int_value(MonoObject *p_object) { + return GDMonoMarshal::unbox<int32_t>(get_value(p_object)); +} + +String GDMonoProperty::get_string_value(MonoObject *p_object) { + MonoObject *val = get_value(p_object); + return GDMonoMarshal::mono_string_to_godot((MonoString *)val); +} diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h new file mode 100644 index 0000000000..2a0065e850 --- /dev/null +++ b/modules/mono/mono_gd/gd_mono_property.h @@ -0,0 +1,77 @@ +/*************************************************************************/ +/* gd_mono_property.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef GD_MONO_PROPERTY_H +#define GD_MONO_PROPERTY_H + +#include "gd_mono.h" +#include "gd_mono_class_member.h" +#include "gd_mono_header.h" + +class GDMonoProperty : public GDMonoClassMember { + + GDMonoClass *owner; + MonoProperty *mono_property; + + StringName name; + ManagedType type; + + bool attrs_fetched; + MonoCustomAttrInfo *attributes; + +public: + virtual MemberType get_member_type() { return MEMBER_TYPE_PROPERTY; } + + virtual StringName get_name() { return name; } + + virtual bool is_static(); + virtual Visibility get_visibility(); + + virtual bool has_attribute(GDMonoClass *p_attr_class); + virtual MonoObject *get_attribute(GDMonoClass *p_attr_class); + void fetch_attributes(); + + bool has_getter(); + bool has_setter(); + + _FORCE_INLINE_ ManagedType get_type() const { return type; } + + void set_value(MonoObject *p_object, MonoObject *p_value, MonoObject **r_exc = NULL); + void set_value(MonoObject *p_object, void **p_params, MonoObject **r_exc = NULL); + MonoObject *get_value(MonoObject *p_object, MonoObject **r_exc = NULL); + + bool get_bool_value(MonoObject *p_object); + int get_int_value(MonoObject *p_object); + String get_string_value(MonoObject *p_object); + + GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_owner); + ~GDMonoProperty(); +}; + +#endif // GD_MONO_PROPERTY_H diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 1cccd0ad9d..ff999b36f2 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "gd_mono_utils.h" #include "os/dir_access.h" @@ -95,7 +96,7 @@ void MonoCache::clear_members() { class_ExportAttribute = NULL; field_ExportAttribute_hint = NULL; - field_ExportAttribute_hint_string = NULL; + field_ExportAttribute_hintString = NULL; class_ToolAttribute = NULL; class_RemoteAttribute = NULL; class_SyncAttribute = NULL; @@ -163,7 +164,7 @@ void update_godot_api_cache() { // Attributes CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute)); CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint")); - CACHE_FIELD_AND_CHECK(ExportAttribute, hint_string, CACHED_CLASS(ExportAttribute)->get_field("hint_string")); + CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString")); CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute)); CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute)); CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute)); @@ -198,7 +199,7 @@ void update_godot_api_cache() { CACHE_RAW_MONO_CLASS_AND_CHECK(Dictionary, mono_class_from_mono_type(dict_type)); } - MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_raw()); + MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr()); mono_runtime_object_init(task_scheduler); mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); } @@ -298,7 +299,7 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa ERR_FAIL_V(NULL); } - MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_raw()); + MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr()); ERR_FAIL_NULL_V(mono_object, NULL); CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object); @@ -364,4 +365,10 @@ String get_exception_name_and_message(MonoObject *p_ex) { return res; } + +void print_unhandled_exception(MonoObject *p_ex) { + ERR_PRINT(GDMonoUtils::get_exception_name_and_message(p_ex).utf8()); + mono_print_unhandled_exception(p_ex); +} + } // namespace GDMonoUtils diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index c38f8c5af5..284585856e 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef GD_MONOUTILS_H #define GD_MONOUTILS_H @@ -97,7 +98,7 @@ struct MonoCache { GDMonoClass *class_ExportAttribute; GDMonoField *field_ExportAttribute_hint; - GDMonoField *field_ExportAttribute_hint_string; + GDMonoField *field_ExportAttribute_hintString; GDMonoClass *class_ToolAttribute; GDMonoClass *class_RemoteAttribute; GDMonoClass *class_SyncAttribute; @@ -166,12 +167,14 @@ MonoDomain *create_domain(const String &p_friendly_name); String get_exception_name_and_message(MonoObject *p_ex); +void print_unhandled_exception(MonoObject *p_ex); + } // namespace GDMonoUtils #define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL))) #define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class) -#define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_raw()) +#define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_mono_ptr()) #define CACHED_NS_CLASS(m_ns, m_class) (GDMonoUtils::mono_cache.class_##m_ns##_##m_class) #define CACHED_RAW_MONO_CLASS(m_class) (GDMonoUtils::mono_cache.rawclass_##m_class) #define CACHED_FIELD(m_class, m_field) (GDMonoUtils::mono_cache.field_##m_class##_##m_field) diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp index 217460a439..4410996546 100644 --- a/modules/mono/register_types.cpp +++ b/modules/mono/register_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "register_types.h" #include "engine.h" diff --git a/modules/mono/register_types.h b/modules/mono/register_types.h index 6cf706b944..ab8a7d6463 100644 --- a/modules/mono/register_types.h +++ b/modules/mono/register_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,5 +27,6 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + void register_mono_types(); void unregister_mono_types(); diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 47cc11cc0a..2671e9a970 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "signal_awaiter_utils.h" #include "csharp_script.h" diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h index 0d615b5826..a6a205ff8d 100644 --- a/modules/mono/signal_awaiter_utils.h +++ b/modules/mono/signal_awaiter_utils.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef SIGNAL_AWAITER_UTILS_H #define SIGNAL_AWAITER_UTILS_H diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp index 2e90b3b716..9bb8da8ac0 100644 --- a/modules/mono/utils/mono_reg_utils.cpp +++ b/modules/mono/utils/mono_reg_utils.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "mono_reg_utils.h" #ifdef WINDOWS_ENABLED diff --git a/modules/mono/utils/mono_reg_utils.h b/modules/mono/utils/mono_reg_utils.h index 599828aa80..edf31f5a07 100644 --- a/modules/mono/utils/mono_reg_utils.h +++ b/modules/mono/utils/mono_reg_utils.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef MONO_REG_UTILS_H #define MONO_REG_UTILS_H diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index 105c2c981e..4b77aeb54e 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "path_utils.h" #include "os/dir_access.h" diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h index 445604300d..184cacfac7 100644 --- a/modules/mono/utils/path_utils.h +++ b/modules/mono/utils/path_utils.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef PATH_UTILS_H #define PATH_UTILS_H diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index 8f817771ac..8691932f9a 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #include "string_utils.h" namespace { diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h index a0d66ebdc3..5dddaee6e8 100644 --- a/modules/mono/utils/string_utils.h +++ b/modules/mono/utils/string_utils.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -27,6 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + #ifndef STRING_FORMAT_H #define STRING_FORMAT_H |