Merge pull request #12178 from neikeq/k
Export attribute fixes and improvements
This commit is contained in:
commit
fb7428e797
|
@ -1268,8 +1268,10 @@ bool CSharpScript::_update_exports() {
|
|||
for (int i = 0; i < fields.size(); i++) {
|
||||
GDMonoField *field = fields[i];
|
||||
|
||||
if (field->is_static() || field->get_visibility() != GDMono::PUBLIC)
|
||||
if (field->is_static()) {
|
||||
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;
|
||||
|
@ -1277,17 +1279,39 @@ bool CSharpScript::_update_exports() {
|
|||
if (member_info.has(cname))
|
||||
continue;
|
||||
|
||||
Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type());
|
||||
ManagedType field_type = field->get_type();
|
||||
Variant::Type type = GDMonoMarshal::managed_to_variant_type(field_type);
|
||||
|
||||
if (field->has_attribute(CACHED_CLASS(ExportAttribute))) {
|
||||
// Field has Export attribute
|
||||
MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute));
|
||||
|
||||
// Field has Export attribute
|
||||
int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr);
|
||||
String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr);
|
||||
int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr);
|
||||
PropertyHint hint;
|
||||
String hint_string;
|
||||
|
||||
PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage));
|
||||
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;
|
||||
|
||||
Vector<MonoClassField *> fields = field_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 (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);
|
||||
}
|
||||
|
||||
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_back(prop_info);
|
||||
|
@ -1711,16 +1735,6 @@ void CSharpScript::update_exports() {
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
_update_exports();
|
||||
|
||||
if (placeholders.size()) {
|
||||
Map<StringName, Variant> values;
|
||||
List<PropertyInfo> propnames;
|
||||
_update_exports_values(values, propnames);
|
||||
|
||||
for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
|
||||
E->get()->update(propnames, values);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,11 @@ namespace Godot
|
|||
{
|
||||
private int hint;
|
||||
private string hint_string;
|
||||
private int usage;
|
||||
|
||||
public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "", int usage = GD.PROPERTY_USAGE_DEFAULT)
|
||||
public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "")
|
||||
{
|
||||
this.hint = hint;
|
||||
this.hint_string = hint_string;
|
||||
this.usage = usage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,14 @@ bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
|
|||
return mono_class_is_assignable_from(mono_class, p_from->mono_class);
|
||||
}
|
||||
|
||||
String GDMonoClass::get_full_name() const {
|
||||
|
||||
String res = namespace_name;
|
||||
if (res.length())
|
||||
res += ".";
|
||||
return res + class_name;
|
||||
}
|
||||
|
||||
GDMonoClass *GDMonoClass::get_parent_class() {
|
||||
|
||||
if (assembly) {
|
||||
|
@ -56,6 +64,30 @@ GDMonoClass *GDMonoClass::get_parent_class() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Vector<MonoClassField *> GDMonoClass::get_enum_fields() {
|
||||
|
||||
bool class_is_enum = mono_class_is_enum(mono_class);
|
||||
ERR_FAIL_COND_V(!class_is_enum, Vector<MonoClassField *>());
|
||||
|
||||
Vector<MonoClassField *> enum_fields;
|
||||
|
||||
void *iter = NULL;
|
||||
MonoClassField *raw_field = NULL;
|
||||
while ((raw_field = mono_class_get_fields(get_raw(), &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.
|
||||
// Enum constants are static, so we will use this to ignore the value__ field.
|
||||
if (field_flags & MONO_FIELD_ATTR_PUBLIC && field_flags & MONO_FIELD_ATTR_STATIC) {
|
||||
enum_fields.push_back(raw_field);
|
||||
}
|
||||
}
|
||||
|
||||
return enum_fields;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool GDMonoClass::has_method(const StringName &p_name) {
|
||||
|
||||
return get_method(p_name) != NULL;
|
||||
|
|
|
@ -98,8 +98,14 @@ public:
|
|||
_FORCE_INLINE_ MonoClass *get_raw() const { return mono_class; }
|
||||
_FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; }
|
||||
|
||||
String get_full_name() const;
|
||||
|
||||
GDMonoClass *get_parent_class();
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Vector<MonoClassField *> get_enum_fields();
|
||||
#endif
|
||||
|
||||
bool has_method(const StringName &p_name);
|
||||
|
||||
bool has_attribute(GDMonoClass *p_attr_class);
|
||||
|
|
|
@ -51,6 +51,7 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
|
|||
{ \
|
||||
m_type val = p_value.operator m_type(); \
|
||||
mono_field_set_value(p_object, mono_field, &val); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define SET_FROM_ARRAY_AND_BREAK(m_type) \
|
||||
|
@ -137,6 +138,9 @@ 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()))
|
||||
SET_FROM_PRIMITIVE(signed int);
|
||||
|
||||
ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + tclass->get_name());
|
||||
ERR_FAIL();
|
||||
} break;
|
||||
|
|
|
@ -112,6 +112,9 @@ 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()))
|
||||
return Variant::INT;
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_ARRAY:
|
||||
|
@ -165,9 +168,12 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
|
|||
return Variant::DICTIONARY;
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
} break;
|
||||
}
|
||||
|
||||
// No error, the caller will decide what to do in this case
|
||||
// Unknown
|
||||
return Variant::NIL;
|
||||
}
|
||||
|
||||
|
@ -299,6 +305,11 @@ 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())) {
|
||||
int val = p_var->operator signed int();
|
||||
return BOX_ENUM(tclass->get_raw(), val);
|
||||
}
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_ARRAY:
|
||||
|
@ -515,6 +526,9 @@ 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()))
|
||||
return unbox<int32_t>(p_obj);
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_ARRAY:
|
||||
|
|
|
@ -53,6 +53,7 @@ T unbox(MonoObject *p_obj) {
|
|||
#define BOX_UINT8(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), &x)
|
||||
#define BOX_BOOLEAN(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(bool), &x)
|
||||
#define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x)
|
||||
#define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x)
|
||||
|
||||
Variant::Type managed_to_variant_type(const ManagedType &p_type);
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ void MonoCache::clear_members() {
|
|||
class_NodePath = NULL;
|
||||
class_RID = NULL;
|
||||
class_GodotObject = NULL;
|
||||
class_GodotReference = NULL;
|
||||
class_Node = NULL;
|
||||
class_Control = NULL;
|
||||
class_Spatial = NULL;
|
||||
|
@ -95,7 +96,6 @@ void MonoCache::clear_members() {
|
|||
class_ExportAttribute = NULL;
|
||||
field_ExportAttribute_hint = NULL;
|
||||
field_ExportAttribute_hint_string = NULL;
|
||||
field_ExportAttribute_usage = NULL;
|
||||
class_ToolAttribute = NULL;
|
||||
class_RemoteAttribute = NULL;
|
||||
class_SyncAttribute = NULL;
|
||||
|
@ -153,6 +153,7 @@ void update_godot_api_cache() {
|
|||
CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath));
|
||||
CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(NodePath));
|
||||
CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object));
|
||||
CACHE_CLASS_AND_CHECK(GodotReference, GODOT_API_CLASS(Reference));
|
||||
CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
|
||||
CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
|
||||
CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
|
||||
|
@ -163,7 +164,6 @@ void update_godot_api_cache() {
|
|||
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, usage, CACHED_CLASS(ExportAttribute)->get_field("usage"));
|
||||
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));
|
||||
|
|
|
@ -88,6 +88,7 @@ struct MonoCache {
|
|||
GDMonoClass *class_NodePath;
|
||||
GDMonoClass *class_RID;
|
||||
GDMonoClass *class_GodotObject;
|
||||
GDMonoClass *class_GodotReference;
|
||||
GDMonoClass *class_Node;
|
||||
GDMonoClass *class_Control;
|
||||
GDMonoClass *class_Spatial;
|
||||
|
@ -97,7 +98,6 @@ struct MonoCache {
|
|||
GDMonoClass *class_ExportAttribute;
|
||||
GDMonoField *field_ExportAttribute_hint;
|
||||
GDMonoField *field_ExportAttribute_hint_string;
|
||||
GDMonoField *field_ExportAttribute_usage;
|
||||
GDMonoClass *class_ToolAttribute;
|
||||
GDMonoClass *class_RemoteAttribute;
|
||||
GDMonoClass *class_SyncAttribute;
|
||||
|
@ -164,7 +164,7 @@ String get_exception_name_and_message(MonoObject *p_ex);
|
|||
|
||||
} // GDMonoUtils
|
||||
|
||||
#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field("nativeName")->get_value(NULL)))
|
||||
#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())
|
||||
|
|
Loading…
Reference in New Issue