summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/csharp_script.cpp21
-rw-r--r--modules/mono/csharp_script.h5
-rw-r--r--modules/mono/editor/bindings_generator.cpp2
-rw-r--r--modules/mono/glue/Managed/Files/Transform2D.cs62
-rw-r--r--modules/mono/glue/base_object_glue.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_field.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp43
-rw-r--r--modules/mono/mono_gd/gd_mono_method.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_property.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp15
-rw-r--r--modules/mono/mono_gd/i_mono_class_member.h (renamed from modules/mono/mono_gd/gd_mono_class_member.h)8
11 files changed, 128 insertions, 36 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 5da1344595..9c127b837d 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1113,19 +1113,23 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) {
+ SCOPED_MUTEX_LOCK(language_bind_mutex);
+
+ Map<Object *, CSharpScriptBinding>::Element *match = script_bindings.find(p_object);
+ if (match)
+ return (void *)match;
+
CSharpScriptBinding script_binding;
if (!setup_csharp_script_binding(script_binding, p_object))
return NULL;
- void *data;
+ return (void *)insert_script_binding(p_object, script_binding);
+}
- {
- SCOPED_MUTEX_LOCK(language_bind_mutex);
- data = (void *)script_bindings.insert(p_object, script_binding);
- }
+Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
- return data;
+ return script_bindings.insert(p_object, p_script_binding);
}
void CSharpLanguage::free_instance_binding_data(void *p_data) {
@@ -2279,17 +2283,18 @@ void CSharpScript::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &CSharpScript::_new, MethodInfo(Variant::OBJECT, "new"));
}
-Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class) {
+Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) {
// This method should not fail
CRASH_COND(!p_class);
+ // TODO: Cache the 'CSharpScript' associated with this 'p_class' instead of allocating a new one every time
Ref<CSharpScript> script = memnew(CSharpScript);
script->name = p_class->get_name();
script->script_class = p_class;
- script->native = GDMonoUtils::get_class_native_base(script->script_class);
+ script->native = p_native;
CRASH_COND(script->native == NULL);
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index db9d6a73a2..8b1a4b5f7e 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -135,7 +135,7 @@ class CSharpScript : public Script {
// Do not use unless you know what you are doing
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
- static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class);
+ static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native);
protected:
static void _bind_methods();
@@ -312,6 +312,8 @@ class CSharpLanguage : public ScriptLanguage {
public:
StringNameCache string_names;
+ Mutex *get_language_bind_mutex() { return language_bind_mutex; }
+
_FORCE_INLINE_ int get_language_index() { return lang_idx; }
void set_language_index(int p_idx);
@@ -406,6 +408,7 @@ public:
virtual void refcount_incremented_instance_binding(Object *p_object);
virtual bool refcount_decremented_instance_binding(Object *p_object);
+ Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object);
#ifdef DEBUG_ENABLED
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 0b6a6a327c..77e9b1f1f4 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -849,6 +849,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
}
+ // TODO: BINDINGS_NATIVE_NAME_FIELD should be StringName, once we support it in C#
+
if (itype.is_singleton) {
// Add the type name and the singleton pointer as static fields
diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs
index f89c99cff2..df7ba3402d 100644
--- a/modules/mono/glue/Managed/Files/Transform2D.cs
+++ b/modules/mono/glue/Managed/Files/Transform2D.cs
@@ -17,12 +17,40 @@ namespace Godot
public real_t Rotation
{
- get { return Mathf.Atan2(y.x, origin.y); }
+ get
+ {
+ real_t det = BasisDeterminant();
+ Transform2D t = Orthonormalized();
+ if (det < 0)
+ {
+ t.ScaleBasis(new Vector2(1, -1));
+ }
+ return Mathf.Atan2(t.x.y, t.x.x);
+ }
+ set
+ {
+ Vector2 scale = Scale;
+ x.x = y.y = Mathf.Cos(value);
+ x.y = y.x = Mathf.Sin(value);
+ y.x *= -1;
+ Scale = scale;
+ }
}
public Vector2 Scale
{
- get { return new Vector2(x.Length(), y.Length()); }
+ get
+ {
+ real_t detSign = Mathf.Sign(BasisDeterminant());
+ return new Vector2(x.Length(), detSign * y.Length());
+ }
+ set
+ {
+ x = x.Normalized();
+ y = y.Normalized();
+ x *= value.x;
+ y *= value.y;
+ }
}
public Vector2 this[int index]
@@ -95,7 +123,7 @@ namespace Godot
{
var inv = this;
- real_t det = this[0, 0] * this[1, 1] - this[1, 0] * this[0, 1];
+ real_t det = BasisDeterminant();
if (det == 0)
{
@@ -107,20 +135,25 @@ namespace Godot
);
}
- real_t idet = 1.0f / det;
+ real_t detInv = 1.0f / det;
real_t temp = this[0, 0];
this[0, 0] = this[1, 1];
this[1, 1] = temp;
- this[0] *= new Vector2(idet, -idet);
- this[1] *= new Vector2(-idet, idet);
+ this[0] *= new Vector2(detInv, -detInv);
+ this[1] *= new Vector2(-detInv, detInv);
this[2] = BasisXform(-this[2]);
return inv;
}
+ private real_t BasisDeterminant()
+ {
+ return x.x * y.y - x.y * y.x;
+ }
+
public Vector2 BasisXform(Vector2 v)
{
return new Vector2(Tdotx(v), Tdoty(v));
@@ -220,6 +253,14 @@ namespace Godot
return copy;
}
+ private void ScaleBasis(Vector2 scale)
+ {
+ x.x *= scale.x;
+ x.y *= scale.y;
+ y.x *= scale.x;
+ y.y *= scale.y;
+ }
+
private real_t Tdotx(Vector2 with)
{
return this[0, 0] * with[0] + this[1, 0] * with[1];
@@ -274,12 +315,9 @@ namespace Godot
public Transform2D(real_t rot, Vector2 pos)
{
- real_t cr = Mathf.Cos(rot);
- real_t sr = Mathf.Sin(rot);
- x.x = cr;
- x.y = -sr;
- y.x = sr;
- y.y = cr;
+ x.x = y.y = Mathf.Cos(rot);
+ x.y = y.x = Mathf.Sin(rot);
+ y.x *= -1;
origin = pos;
}
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 2963619b79..fad02b01d3 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -33,7 +33,7 @@
#ifdef MONO_GLUE_ENABLED
#include "core/reference.h"
-#include "core/string_db.h"
+#include "core/string_name.h"
#include "../csharp_script.h"
#include "../mono_gd/gd_mono_internals.h"
diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h
index a3244101d8..e348583370 100644
--- a/modules/mono/mono_gd/gd_mono_field.h
+++ b/modules/mono/mono_gd/gd_mono_field.h
@@ -32,8 +32,8 @@
#define GDMONOFIELD_H
#include "gd_mono.h"
-#include "gd_mono_class_member.h"
#include "gd_mono_header.h"
+#include "i_mono_class_member.h"
class GDMonoField : public IMonoClassMember {
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index 0daa394e63..14ec24466b 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -34,6 +34,8 @@
#include "../mono_gc_handle.h"
#include "../utils/macros.h"
#include "../utils/thread_local.h"
+#include "gd_mono_class.h"
+#include "gd_mono_marshal.h"
#include "gd_mono_utils.h"
#include <mono/metadata/exception.h>
@@ -55,10 +57,49 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
CRASH_COND(!klass);
+ GDMonoClass *native = GDMonoUtils::get_class_native_base(klass);
+
+ CRASH_COND(native == NULL);
+
+ if (native == klass) {
+ // If it's just a wrapper Godot class and not a custom inheriting class, then attach a
+ // script binding instead. One of the advantages of this is that if a script is attached
+ // later and it's not a C# script, then the managed object won't have to be disposed.
+ // Another reason for doing this is that this instance could outlive CSharpLanguage, which would
+ // be problematic when using a script. See: https://github.com/godotengine/godot/issues/25621
+
+ CSharpScriptBinding script_binding;
+
+ script_binding.inited = true;
+ script_binding.type_name = NATIVE_GDMONOCLASS_NAME(klass);
+ script_binding.wrapper_class = klass;
+ script_binding.gchandle = MonoGCHandle::create_strong(managed);
+
+ Reference *ref = Object::cast_to<Reference>(unmanaged);
+ if (ref) {
+ // 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.
+ // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
+
+ ref->reference();
+ }
+
+ // The object was just created, no script instance binding should have been attached
+ CRASH_COND(unmanaged->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()));
+
+ void *data = (void *)CSharpLanguage::get_singleton()->insert_script_binding(unmanaged, script_binding);
+
+ // Should be thread safe because the object was just created and nothing else should be referencing it
+ unmanaged->set_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index(), data);
+
+ return;
+ }
+
Ref<MonoGCHandle> gchandle = ref ? MonoGCHandle::create_weak(managed) :
MonoGCHandle::create_strong(managed);
- Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass);
+ Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass, native);
CRASH_COND(script.is_null());
diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h
index fc035d387c..f74cef438d 100644
--- a/modules/mono/mono_gd/gd_mono_method.h
+++ b/modules/mono/mono_gd/gd_mono_method.h
@@ -32,8 +32,8 @@
#define GD_MONO_METHOD_H
#include "gd_mono.h"
-#include "gd_mono_class_member.h"
#include "gd_mono_header.h"
+#include "i_mono_class_member.h"
class GDMonoMethod : public IMonoClassMember {
diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h
index d8a9f69ffb..2700c460b0 100644
--- a/modules/mono/mono_gd/gd_mono_property.h
+++ b/modules/mono/mono_gd/gd_mono_property.h
@@ -32,8 +32,8 @@
#define GD_MONO_PROPERTY_H
#include "gd_mono.h"
-#include "gd_mono_class_member.h"
#include "gd_mono_header.h"
+#include "i_mono_class_member.h"
class GDMonoProperty : public IMonoClassMember {
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index ac6ccac3a7..3b97339fea 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -39,6 +39,7 @@
#include "../csharp_script.h"
#include "../utils/macros.h"
+#include "../utils/mutex_utils.h"
#include "gd_mono.h"
#include "gd_mono_class.h"
#include "gd_mono_marshal.h"
@@ -281,17 +282,19 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
- if (!data)
- return NULL;
+ ERR_FAIL_NULL_V(data, NULL);
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value();
if (!script_binding.inited) {
- // Already had a binding that needs to be setup
- CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged);
+ SCOPED_MUTEX_LOCK(CSharpLanguage::get_singleton()->get_language_bind_mutex());
+
+ if (!script_binding.inited) { // Other thread may have set it up
+ // Already had a binding that needs to be setup
+ CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged);
- if (!script_binding.inited)
- return NULL;
+ ERR_FAIL_COND_V(!script_binding.inited, NULL);
+ }
}
Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
diff --git a/modules/mono/mono_gd/gd_mono_class_member.h b/modules/mono/mono_gd/i_mono_class_member.h
index 3058b18c05..553d9edc72 100644
--- a/modules/mono/mono_gd/gd_mono_class_member.h
+++ b/modules/mono/mono_gd/i_mono_class_member.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_mono_class_member.h */
+/* i_mono_class_member.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_MONO_CLASS_MEMBER_H
-#define GD_MONO_CLASS_MEMBER_H
+#ifndef I_MONO_CLASS_MEMBER_H
+#define I_MONO_CLASS_MEMBER_H
#include "gd_mono_header.h"
@@ -65,4 +65,4 @@ public:
virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) = 0;
};
-#endif // GD_MONO_CLASS_MEMBER_H
+#endif // I_MONO_CLASS_MEMBER_H