1 /*************************************************************************/
2 /* gd_mono_field.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #include "gd_mono_field.h"
32
33 #include <mono/metadata/attrdefs.h>
34
35 #include "gd_mono_cache.h"
36 #include "gd_mono_class.h"
37 #include "gd_mono_marshal.h"
38 #include "gd_mono_utils.h"
39
set_value_raw(MonoObject * p_object,void * p_ptr)40 void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) {
41 mono_field_set_value(p_object, mono_field, &p_ptr);
42 }
43
set_value_from_variant(MonoObject * p_object,const Variant & p_value)44 void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_value) {
45 #define SET_FROM_STRUCT(m_type) \
46 { \
47 GDMonoMarshal::M_##m_type from = MARSHALLED_OUT(m_type, p_value.operator ::m_type()); \
48 mono_field_set_value(p_object, mono_field, &from); \
49 }
50
51 #define SET_FROM_ARRAY(m_type) \
52 { \
53 MonoArray *managed = GDMonoMarshal::m_type##_to_mono_array(p_value.operator ::m_type()); \
54 mono_field_set_value(p_object, mono_field, managed); \
55 }
56
57 switch (type.type_encoding) {
58 case MONO_TYPE_BOOLEAN: {
59 MonoBoolean val = p_value.operator bool();
60 mono_field_set_value(p_object, mono_field, &val);
61 } break;
62
63 case MONO_TYPE_CHAR: {
64 int16_t val = p_value.operator unsigned short();
65 mono_field_set_value(p_object, mono_field, &val);
66 } break;
67
68 case MONO_TYPE_I1: {
69 int8_t val = p_value.operator signed char();
70 mono_field_set_value(p_object, mono_field, &val);
71 } break;
72 case MONO_TYPE_I2: {
73 int16_t val = p_value.operator signed short();
74 mono_field_set_value(p_object, mono_field, &val);
75 } break;
76 case MONO_TYPE_I4: {
77 int32_t val = p_value.operator signed int();
78 mono_field_set_value(p_object, mono_field, &val);
79 } break;
80 case MONO_TYPE_I8: {
81 int64_t val = p_value.operator int64_t();
82 mono_field_set_value(p_object, mono_field, &val);
83 } break;
84
85 case MONO_TYPE_U1: {
86 uint8_t val = p_value.operator unsigned char();
87 mono_field_set_value(p_object, mono_field, &val);
88 } break;
89 case MONO_TYPE_U2: {
90 uint16_t val = p_value.operator unsigned short();
91 mono_field_set_value(p_object, mono_field, &val);
92 } break;
93 case MONO_TYPE_U4: {
94 uint32_t val = p_value.operator unsigned int();
95 mono_field_set_value(p_object, mono_field, &val);
96 } break;
97 case MONO_TYPE_U8: {
98 uint64_t val = p_value.operator uint64_t();
99 mono_field_set_value(p_object, mono_field, &val);
100 } break;
101
102 case MONO_TYPE_R4: {
103 float val = p_value.operator float();
104 mono_field_set_value(p_object, mono_field, &val);
105 } break;
106
107 case MONO_TYPE_R8: {
108 double val = p_value.operator double();
109 mono_field_set_value(p_object, mono_field, &val);
110 } break;
111
112 case MONO_TYPE_STRING: {
113 if (p_value.get_type() == Variant::NIL) {
114 // Otherwise, Variant -> String would return the string "Null"
115 MonoString *mono_string = NULL;
116 mono_field_set_value(p_object, mono_field, mono_string);
117 } else {
118 MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
119 mono_field_set_value(p_object, mono_field, mono_string);
120 }
121 } break;
122
123 case MONO_TYPE_VALUETYPE: {
124 GDMonoClass *tclass = type.type_class;
125
126 if (tclass == CACHED_CLASS(Vector2)) {
127 SET_FROM_STRUCT(Vector2);
128 break;
129 }
130
131 if (tclass == CACHED_CLASS(Rect2)) {
132 SET_FROM_STRUCT(Rect2);
133 break;
134 }
135
136 if (tclass == CACHED_CLASS(Transform2D)) {
137 SET_FROM_STRUCT(Transform2D);
138 break;
139 }
140
141 if (tclass == CACHED_CLASS(Vector3)) {
142 SET_FROM_STRUCT(Vector3);
143 break;
144 }
145
146 if (tclass == CACHED_CLASS(Basis)) {
147 SET_FROM_STRUCT(Basis);
148 break;
149 }
150
151 if (tclass == CACHED_CLASS(Quat)) {
152 SET_FROM_STRUCT(Quat);
153 break;
154 }
155
156 if (tclass == CACHED_CLASS(Transform)) {
157 SET_FROM_STRUCT(Transform);
158 break;
159 }
160
161 if (tclass == CACHED_CLASS(AABB)) {
162 SET_FROM_STRUCT(AABB);
163 break;
164 }
165
166 if (tclass == CACHED_CLASS(Color)) {
167 SET_FROM_STRUCT(Color);
168 break;
169 }
170
171 if (tclass == CACHED_CLASS(Plane)) {
172 SET_FROM_STRUCT(Plane);
173 break;
174 }
175
176 if (mono_class_is_enum(tclass->get_mono_ptr())) {
177 MonoType *enum_basetype = mono_class_enum_basetype(tclass->get_mono_ptr());
178 switch (mono_type_get_type(enum_basetype)) {
179 case MONO_TYPE_BOOLEAN: {
180 MonoBoolean val = p_value.operator bool();
181 mono_field_set_value(p_object, mono_field, &val);
182 break;
183 }
184 case MONO_TYPE_CHAR: {
185 uint16_t val = p_value.operator unsigned short();
186 mono_field_set_value(p_object, mono_field, &val);
187 break;
188 }
189 case MONO_TYPE_I1: {
190 int8_t val = p_value.operator signed char();
191 mono_field_set_value(p_object, mono_field, &val);
192 break;
193 }
194 case MONO_TYPE_I2: {
195 int16_t val = p_value.operator signed short();
196 mono_field_set_value(p_object, mono_field, &val);
197 break;
198 }
199 case MONO_TYPE_I4: {
200 int32_t val = p_value.operator signed int();
201 mono_field_set_value(p_object, mono_field, &val);
202 break;
203 }
204 case MONO_TYPE_I8: {
205 int64_t val = p_value.operator int64_t();
206 mono_field_set_value(p_object, mono_field, &val);
207 break;
208 }
209 case MONO_TYPE_U1: {
210 uint8_t val = p_value.operator unsigned char();
211 mono_field_set_value(p_object, mono_field, &val);
212 break;
213 }
214 case MONO_TYPE_U2: {
215 uint16_t val = p_value.operator unsigned short();
216 mono_field_set_value(p_object, mono_field, &val);
217 break;
218 }
219 case MONO_TYPE_U4: {
220 uint32_t val = p_value.operator unsigned int();
221 mono_field_set_value(p_object, mono_field, &val);
222 break;
223 }
224 case MONO_TYPE_U8: {
225 uint64_t val = p_value.operator uint64_t();
226 mono_field_set_value(p_object, mono_field, &val);
227 break;
228 }
229 default: {
230 ERR_FAIL_MSG("Attempted to convert Variant to a managed enum value of unmarshallable base type.");
231 }
232 }
233
234 break;
235 }
236
237 ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + tclass->get_name() + "'.");
238 } break;
239
240 case MONO_TYPE_ARRAY:
241 case MONO_TYPE_SZARRAY: {
242 MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
243
244 if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) {
245 SET_FROM_ARRAY(Array);
246 break;
247 }
248
249 if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) {
250 SET_FROM_ARRAY(PoolByteArray);
251 break;
252 }
253
254 if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) {
255 SET_FROM_ARRAY(PoolIntArray);
256 break;
257 }
258
259 if (array_type->eklass == REAL_T_MONOCLASS) {
260 SET_FROM_ARRAY(PoolRealArray);
261 break;
262 }
263
264 if (array_type->eklass == CACHED_CLASS_RAW(String)) {
265 SET_FROM_ARRAY(PoolStringArray);
266 break;
267 }
268
269 if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) {
270 SET_FROM_ARRAY(PoolVector2Array);
271 break;
272 }
273
274 if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) {
275 SET_FROM_ARRAY(PoolVector3Array);
276 break;
277 }
278
279 if (array_type->eklass == CACHED_CLASS_RAW(Color)) {
280 SET_FROM_ARRAY(PoolColorArray);
281 break;
282 }
283
284 GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
285 if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) {
286 MonoArray *managed = GDMonoMarshal::Array_to_mono_array(p_value.operator ::Array(), array_type_class);
287 mono_field_set_value(p_object, mono_field, managed);
288 break;
289 }
290
291 ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type.");
292 } break;
293
294 case MONO_TYPE_CLASS: {
295 GDMonoClass *type_class = type.type_class;
296
297 // GodotObject
298 if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
299 MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
300 mono_field_set_value(p_object, mono_field, managed);
301 break;
302 }
303
304 if (CACHED_CLASS(NodePath) == type_class) {
305 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
306 mono_field_set_value(p_object, mono_field, managed);
307 break;
308 }
309
310 if (CACHED_CLASS(RID) == type_class) {
311 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator RID());
312 mono_field_set_value(p_object, mono_field, managed);
313 break;
314 }
315
316 // Godot.Collections.Dictionary or IDictionary
317 if (CACHED_CLASS(Dictionary) == type_class || type_class == CACHED_CLASS(System_Collections_IDictionary)) {
318 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
319 mono_field_set_value(p_object, mono_field, managed);
320 break;
321 }
322
323 // Godot.Collections.Array or ICollection or IEnumerable
324 if (CACHED_CLASS(Array) == type_class ||
325 type_class == CACHED_CLASS(System_Collections_ICollection) ||
326 type_class == CACHED_CLASS(System_Collections_IEnumerable)) {
327 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
328 mono_field_set_value(p_object, mono_field, managed);
329 break;
330 }
331
332 ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + type_class->get_name() + "'.");
333 } break;
334
335 case MONO_TYPE_OBJECT: {
336 // Variant
337 switch (p_value.get_type()) {
338 case Variant::BOOL: {
339 MonoBoolean val = p_value.operator bool();
340 mono_field_set_value(p_object, mono_field, &val);
341 } break;
342 case Variant::INT: {
343 int32_t val = p_value.operator signed int();
344 mono_field_set_value(p_object, mono_field, &val);
345 } break;
346 case Variant::REAL: {
347 #ifdef REAL_T_IS_DOUBLE
348 double val = p_value.operator double();
349 mono_field_set_value(p_object, mono_field, &val);
350 #else
351 float val = p_value.operator float();
352 mono_field_set_value(p_object, mono_field, &val);
353 #endif
354 } break;
355 case Variant::STRING: {
356 MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
357 mono_field_set_value(p_object, mono_field, mono_string);
358 } break;
359 case Variant::VECTOR2: {
360 SET_FROM_STRUCT(Vector2);
361 } break;
362 case Variant::RECT2: {
363 SET_FROM_STRUCT(Rect2);
364 } break;
365 case Variant::VECTOR3: {
366 SET_FROM_STRUCT(Vector3);
367 } break;
368 case Variant::TRANSFORM2D: {
369 SET_FROM_STRUCT(Transform2D);
370 } break;
371 case Variant::PLANE: {
372 SET_FROM_STRUCT(Plane);
373 } break;
374 case Variant::QUAT: {
375 SET_FROM_STRUCT(Quat);
376 } break;
377 case Variant::AABB: {
378 SET_FROM_STRUCT(AABB);
379 } break;
380 case Variant::BASIS: {
381 SET_FROM_STRUCT(Basis);
382 } break;
383 case Variant::TRANSFORM: {
384 SET_FROM_STRUCT(Transform);
385 } break;
386 case Variant::COLOR: {
387 SET_FROM_STRUCT(Color);
388 } break;
389 case Variant::NODE_PATH: {
390 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
391 mono_field_set_value(p_object, mono_field, managed);
392 } break;
393 case Variant::_RID: {
394 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator RID());
395 mono_field_set_value(p_object, mono_field, managed);
396 } break;
397 case Variant::OBJECT: {
398 MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
399 mono_field_set_value(p_object, mono_field, managed);
400 break;
401 }
402 case Variant::DICTIONARY: {
403 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
404 mono_field_set_value(p_object, mono_field, managed);
405 } break;
406 case Variant::ARRAY: {
407 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
408 mono_field_set_value(p_object, mono_field, managed);
409 } break;
410 case Variant::POOL_BYTE_ARRAY: {
411 SET_FROM_ARRAY(PoolByteArray);
412 } break;
413 case Variant::POOL_INT_ARRAY: {
414 SET_FROM_ARRAY(PoolIntArray);
415 } break;
416 case Variant::POOL_REAL_ARRAY: {
417 SET_FROM_ARRAY(PoolRealArray);
418 } break;
419 case Variant::POOL_STRING_ARRAY: {
420 SET_FROM_ARRAY(PoolStringArray);
421 } break;
422 case Variant::POOL_VECTOR2_ARRAY: {
423 SET_FROM_ARRAY(PoolVector2Array);
424 } break;
425 case Variant::POOL_VECTOR3_ARRAY: {
426 SET_FROM_ARRAY(PoolVector3Array);
427 } break;
428 case Variant::POOL_COLOR_ARRAY: {
429 SET_FROM_ARRAY(PoolColorArray);
430 } break;
431 default: break;
432 }
433 } break;
434
435 case MONO_TYPE_GENERICINST: {
436 MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type.type_class->get_mono_type());
437
438 // Godot.Collections.Dictionary<TKey, TValue>
439 if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
440 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), type.type_class);
441 mono_field_set_value(p_object, mono_field, managed);
442 break;
443 }
444
445 // Godot.Collections.Array<T>
446 if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
447 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), type.type_class);
448 mono_field_set_value(p_object, mono_field, managed);
449 break;
450 }
451
452 // System.Collections.Generic.Dictionary<TKey, TValue>
453 if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) {
454 MonoReflectionType *key_reftype = nullptr;
455 MonoReflectionType *value_reftype = nullptr;
456 GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
457 MonoObject *managed = GDMonoMarshal::Dictionary_to_system_generic_dict(p_value.operator Dictionary(),
458 type.type_class, key_reftype, value_reftype);
459 mono_field_set_value(p_object, mono_field, managed);
460 break;
461 }
462
463 // System.Collections.Generic.List<T>
464 if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) {
465 MonoReflectionType *elem_reftype = nullptr;
466 GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
467 MonoObject *managed = GDMonoMarshal::Array_to_system_generic_list(p_value.operator Array(),
468 type.type_class, elem_reftype);
469 mono_field_set_value(p_object, mono_field, managed);
470 break;
471 }
472
473 // IDictionary<TKey, TValue>
474 if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) {
475 MonoReflectionType *key_reftype;
476 MonoReflectionType *value_reftype;
477 GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
478 GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype);
479
480 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), godot_dict_class);
481 mono_field_set_value(p_object, mono_field, managed);
482 break;
483 }
484
485 // ICollection<T> or IEnumerable<T>
486 if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) {
487 MonoReflectionType *elem_reftype;
488 GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
489 GDMonoClass *godot_array_class = GDMonoUtils::Marshal::make_generic_array_type(elem_reftype);
490
491 MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), godot_array_class);
492 mono_field_set_value(p_object, mono_field, managed);
493 break;
494 }
495 } break;
496
497 default: {
498 ERR_PRINTS("Attempted to set the value of a field of unexpected type encoding: " + itos(type.type_encoding) + ".");
499 } break;
500 }
501
502 #undef SET_FROM_ARRAY_AND_BREAK
503 #undef SET_FROM_STRUCT_AND_BREAK
504 }
505
get_value(MonoObject * p_object)506 MonoObject *GDMonoField::get_value(MonoObject *p_object) {
507 return mono_field_get_value_object(mono_domain_get(), mono_field, p_object);
508 }
509
get_bool_value(MonoObject * p_object)510 bool GDMonoField::get_bool_value(MonoObject *p_object) {
511 return (bool)GDMonoMarshal::unbox<MonoBoolean>(get_value(p_object));
512 }
513
get_int_value(MonoObject * p_object)514 int GDMonoField::get_int_value(MonoObject *p_object) {
515 return GDMonoMarshal::unbox<int32_t>(get_value(p_object));
516 }
517
get_string_value(MonoObject * p_object)518 String GDMonoField::get_string_value(MonoObject *p_object) {
519 MonoObject *val = get_value(p_object);
520 return GDMonoMarshal::mono_string_to_godot((MonoString *)val);
521 }
522
has_attribute(GDMonoClass * p_attr_class)523 bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) {
524 ERR_FAIL_NULL_V(p_attr_class, false);
525
526 if (!attrs_fetched)
527 fetch_attributes();
528
529 if (!attributes)
530 return false;
531
532 return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr());
533 }
534
get_attribute(GDMonoClass * p_attr_class)535 MonoObject *GDMonoField::get_attribute(GDMonoClass *p_attr_class) {
536 ERR_FAIL_NULL_V(p_attr_class, NULL);
537
538 if (!attrs_fetched)
539 fetch_attributes();
540
541 if (!attributes)
542 return NULL;
543
544 return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr());
545 }
546
fetch_attributes()547 void GDMonoField::fetch_attributes() {
548 ERR_FAIL_COND(attributes != NULL);
549 attributes = mono_custom_attrs_from_field(owner->get_mono_ptr(), mono_field);
550 attrs_fetched = true;
551 }
552
is_static()553 bool GDMonoField::is_static() {
554 return mono_field_get_flags(mono_field) & MONO_FIELD_ATTR_STATIC;
555 }
556
get_visibility()557 IMonoClassMember::Visibility GDMonoField::get_visibility() {
558 switch (mono_field_get_flags(mono_field) & MONO_FIELD_ATTR_FIELD_ACCESS_MASK) {
559 case MONO_FIELD_ATTR_PRIVATE:
560 return IMonoClassMember::PRIVATE;
561 case MONO_FIELD_ATTR_FAM_AND_ASSEM:
562 return IMonoClassMember::PROTECTED_AND_INTERNAL;
563 case MONO_FIELD_ATTR_ASSEMBLY:
564 return IMonoClassMember::INTERNAL;
565 case MONO_FIELD_ATTR_FAMILY:
566 return IMonoClassMember::PROTECTED;
567 case MONO_FIELD_ATTR_PUBLIC:
568 return IMonoClassMember::PUBLIC;
569 default:
570 ERR_FAIL_V(IMonoClassMember::PRIVATE);
571 }
572 }
573
GDMonoField(MonoClassField * p_mono_field,GDMonoClass * p_owner)574 GDMonoField::GDMonoField(MonoClassField *p_mono_field, GDMonoClass *p_owner) {
575 owner = p_owner;
576 mono_field = p_mono_field;
577 name = mono_field_get_name(mono_field);
578 MonoType *field_type = mono_field_get_type(mono_field);
579 type.type_encoding = mono_type_get_type(field_type);
580 MonoClass *field_type_class = mono_class_from_mono_type(field_type);
581 type.type_class = GDMono::get_singleton()->get_class(field_type_class);
582
583 attrs_fetched = false;
584 attributes = NULL;
585 }
586
~GDMonoField()587 GDMonoField::~GDMonoField() {
588 if (attributes) {
589 mono_custom_attrs_free(attributes);
590 }
591 }
592