@@ -2642,9 +2642,18 @@ bool ue_py_convert_pyobject(PyObject *py_obj, UProperty *prop, uint8 *buffer, in
26422642 {
26432643 if (auto casted_prop = Cast<UObjectPropertyBase>(prop))
26442644 {
2645- // ensure the object type is correct, otherwise crash could happen (soon or later)
2646- if (!ue_obj->ue_object ->IsA (casted_prop->PropertyClass ))
2647- return false ;
2645+ // if the property specifies an interface, the object must be of a class that implements it
2646+ if (casted_prop->PropertyClass ->HasAnyClassFlags (CLASS_Interface))
2647+ {
2648+ if (!ue_obj->ue_object ->GetClass ()->ImplementsInterface (casted_prop->PropertyClass ))
2649+ return false ;
2650+ }
2651+ else
2652+ {
2653+ // ensure the object type is correct, otherwise crash could happen (soon or later)
2654+ if (!ue_obj->ue_object ->IsA (casted_prop->PropertyClass ))
2655+ return false ;
2656+ }
26482657
26492658 casted_prop->SetObjectPropertyValue_InContainer (buffer, ue_obj->ue_object , index);
26502659
@@ -3151,35 +3160,103 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
31513160 {
31523161 prop = NewObject<UIntProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
31533162 }
3163+ else if ((PyTypeObject *)value == &ue_PyFVectorType)
3164+ {
3165+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3166+ prop_struct->Struct = TBaseStructure<FVector>::Get ();
3167+ prop = prop_struct;
3168+ }
3169+ else if ((PyTypeObject *)value == &ue_PyFRotatorType)
3170+ {
3171+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3172+ prop_struct->Struct = TBaseStructure<FRotator>::Get ();
3173+ prop = prop_struct;
3174+ }
3175+ else if ((PyTypeObject *)value == &ue_PyFLinearColorType)
3176+ {
3177+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3178+ prop_struct->Struct = TBaseStructure<FLinearColor>::Get ();
3179+ prop = prop_struct;
3180+ }
3181+ else if ((PyTypeObject *)value == &ue_PyFColorType)
3182+ {
3183+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3184+ prop_struct->Struct = TBaseStructure<FColor>::Get ();
3185+ prop = prop_struct;
3186+ }
3187+ else if ((PyTypeObject *)value == &ue_PyFTransformType)
3188+ {
3189+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3190+ prop_struct->Struct = TBaseStructure<FTransform>::Get ();
3191+ prop = prop_struct;
3192+ }
3193+ else if ((PyTypeObject *)value == &ue_PyFQuatType)
3194+ {
3195+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3196+ prop_struct->Struct = TBaseStructure<FQuat>::Get ();
3197+ prop = prop_struct;
3198+ }
3199+ else if (PyObject_IsInstance (value, (PyObject *)&PyType_Type))
3200+ {
3201+ // Method annotation like foo:typing.Type[Pawn] produces annotations like typing.Type[Pawn], with .__args__ = (Pawn,)
3202+ PyObject *type_args = PyObject_GetAttrString (value, " __args__" );
3203+ if (!type_args)
3204+ {
3205+ UE_LOG (LogPython, Error, TEXT (" missing type info on %s" ), UTF8_TO_TCHAR (name));
3206+ return nullptr ;
3207+ }
3208+ if (PyTuple_Size (type_args) != 1 )
3209+ {
3210+ Py_DECREF (type_args);
3211+ UE_LOG (LogPython, Error, TEXT (" exactly one class is allowed in type info for %s" ), UTF8_TO_TCHAR (name));
3212+ return nullptr ;
3213+ }
3214+ PyObject *py_class = PyTuple_GetItem (type_args, 0 );
3215+ ue_PyUObject *py_obj = ue_is_pyuobject (py_class);
3216+ if (!py_obj)
3217+ {
3218+ Py_DECREF (type_args);
3219+ UE_LOG (LogPython, Error, TEXT (" type for %s must be a ue_PyUObject" ), UTF8_TO_TCHAR (name));
3220+ return nullptr ;
3221+ }
3222+ if (!py_obj->ue_object ->IsA <UClass>())
3223+ {
3224+ Py_DECREF (type_args);
3225+ UE_LOG (LogPython, Error, TEXT (" type for %s must be a UClass" ), UTF8_TO_TCHAR (name));
3226+ return nullptr ;
3227+ }
3228+ UClassProperty *prop_class = NewObject<UClassProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3229+ prop_class->SetMetaClass ((UClass*)py_obj->ue_object );
3230+ prop_class->PropertyClass = UClass::StaticClass ();
3231+ prop = prop_class;
3232+ Py_DECREF (type_args);
3233+ }
31543234 }
31553235 else if (ue_PyUObject *py_obj = ue_is_pyuobject (value))
31563236 {
31573237 if (py_obj->ue_object ->IsA <UClass>())
31583238 {
31593239 UClass *p_u_class = (UClass *)py_obj->ue_object ;
3160- if (p_u_class->IsChildOf <UClass>())
3161- {
3162- UClassProperty *prop_base = NewObject<UClassProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3163- if (p_u_class == UClass::StaticClass ())
3164- {
3165- prop_base->SetMetaClass (UObject::StaticClass ());
3166- }
3167- else
3168- {
3169- prop_base->SetMetaClass (p_u_class->GetClass ());
3170- }
3171- prop_base->PropertyClass = UClass::StaticClass ();
3172- prop = prop_base;
3173- }
3174- else
3175- {
3176- UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3177- prop_base->SetPropertyClass (p_u_class);
3178- prop = prop_base;
3179- }
3180- }
3240+ UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3241+ prop_base->SetPropertyClass (p_u_class);
3242+ prop = prop_base;
3243+ }
3244+ else if (py_obj->ue_object ->IsA <UEnum>())
3245+ {
3246+ UEnumProperty *prop_enum = NewObject<UEnumProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3247+ UNumericProperty *prop_underlying = NewObject<UByteProperty>(prop_enum, TEXT (" UnderlyingType" ), RF_Public);
3248+ prop_enum->SetEnum ((UEnum*)py_obj->ue_object );
3249+ prop_enum->AddCppProperty (prop_underlying);
3250+ prop = prop_enum;
3251+ }
3252+ else if (py_obj->ue_object ->IsA <UStruct>())
3253+ {
3254+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3255+ prop_struct->Struct = (UScriptStruct*)py_obj->ue_object ;
3256+ prop = prop_struct;
3257+ }
31813258 }
3182- // TODO add native types (like vectors, rotators...)
3259+
31833260 if (prop)
31843261 {
31853262 prop->SetPropertyFlags (CPF_Parm);
@@ -3222,35 +3299,103 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
32223299 {
32233300 prop = NewObject<UIntProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
32243301 }
3302+ else if ((PyTypeObject *)py_return_value == &ue_PyFVectorType)
3303+ {
3304+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3305+ prop_struct->Struct = TBaseStructure<FVector>::Get ();
3306+ prop = prop_struct;
3307+ }
3308+ else if ((PyTypeObject *)py_return_value == &ue_PyFRotatorType)
3309+ {
3310+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3311+ prop_struct->Struct = TBaseStructure<FRotator>::Get ();
3312+ prop = prop_struct;
3313+ }
3314+ else if ((PyTypeObject *)py_return_value == &ue_PyFLinearColorType)
3315+ {
3316+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3317+ prop_struct->Struct = TBaseStructure<FLinearColor>::Get ();
3318+ prop = prop_struct;
3319+ }
3320+ else if ((PyTypeObject *)py_return_value == &ue_PyFColorType)
3321+ {
3322+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3323+ prop_struct->Struct = TBaseStructure<FColor>::Get ();
3324+ prop = prop_struct;
3325+ }
3326+ else if ((PyTypeObject *)py_return_value == &ue_PyFTransformType)
3327+ {
3328+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3329+ prop_struct->Struct = TBaseStructure<FTransform>::Get ();
3330+ prop = prop_struct;
3331+ }
3332+ else if ((PyTypeObject *)py_return_value == &ue_PyFQuatType)
3333+ {
3334+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3335+ prop_struct->Struct = TBaseStructure<FQuat>::Get ();
3336+ prop = prop_struct;
3337+ }
3338+ else if (PyObject_IsInstance (py_return_value, (PyObject *)&PyType_Type))
3339+ {
3340+ // Method annotation like foo:typing.Type[Pawn] produces annotations like typing.Type[Pawn], with .__args__ = (Pawn,)
3341+ PyObject *type_args = PyObject_GetAttrString (py_return_value, " __args__" );
3342+ if (!type_args)
3343+ {
3344+ UE_LOG (LogPython, Error, TEXT (" missing type info on %s" ), UTF8_TO_TCHAR (name));
3345+ return nullptr ;
3346+ }
3347+ if (PyTuple_Size (type_args) != 1 )
3348+ {
3349+ Py_DECREF (type_args);
3350+ UE_LOG (LogPython, Error, TEXT (" exactly one class is allowed in type info for %s" ), UTF8_TO_TCHAR (name));
3351+ return nullptr ;
3352+ }
3353+ PyObject *py_class = PyTuple_GetItem (type_args, 0 );
3354+ ue_PyUObject *py_obj = ue_is_pyuobject (py_class);
3355+ if (!py_obj)
3356+ {
3357+ Py_DECREF (type_args);
3358+ UE_LOG (LogPython, Error, TEXT (" type for %s must be a ue_PyUObject" ), UTF8_TO_TCHAR (name));
3359+ return nullptr ;
3360+ }
3361+ if (!py_obj->ue_object ->IsA <UClass>())
3362+ {
3363+ Py_DECREF (type_args);
3364+ UE_LOG (LogPython, Error, TEXT (" type for %s must be a UClass" ), UTF8_TO_TCHAR (name));
3365+ return nullptr ;
3366+ }
3367+ UClassProperty *prop_class = NewObject<UClassProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3368+ prop_class->SetMetaClass ((UClass*)py_obj->ue_object );
3369+ prop_class->PropertyClass = UClass::StaticClass ();
3370+ prop = prop_class;
3371+ Py_DECREF (type_args);
3372+ }
32253373 }
32263374 else if (ue_PyUObject *py_obj = ue_is_pyuobject (py_return_value))
32273375 {
3228- if (py_obj->ue_object ->IsA <UClass>())
3229- {
3230- UClass *p_u_class = (UClass *)py_obj->ue_object ;
3231- if (p_u_class->IsChildOf <UClass>())
3232- {
3233- UClassProperty *prop_base = NewObject<UClassProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3234- if (p_u_class == UClass::StaticClass ())
3235- {
3236- prop_base->SetMetaClass (UObject::StaticClass ());
3237- }
3238- else
3239- {
3240- prop_base->SetMetaClass (p_u_class->GetClass ());
3241- }
3242- prop_base->PropertyClass = UClass::StaticClass ();
3243- prop = prop_base;
3244- }
3245- else
3246- {
3247- UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3248- prop_base->SetPropertyClass (p_u_class);
3249- prop = prop_base;
3250- }
3251- }
3376+ if (py_obj->ue_object ->IsA <UClass>())
3377+ {
3378+ UClass *p_u_class = (UClass *)py_obj->ue_object ;
3379+ UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3380+ prop_base->SetPropertyClass (p_u_class);
3381+ prop = prop_base;
3382+ }
3383+ else if (py_obj->ue_object ->IsA <UEnum>())
3384+ {
3385+ UEnumProperty *prop_enum = NewObject<UEnumProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3386+ UNumericProperty *prop_underlying = NewObject<UByteProperty>(prop_enum, TEXT (" UnderlyingType" ), RF_Public);
3387+ prop_enum->SetEnum ((UEnum*)py_obj->ue_object );
3388+ prop_enum->AddCppProperty (prop_underlying);
3389+ prop = prop_enum;
3390+ }
3391+ else if (py_obj->ue_object ->IsA <UStruct>())
3392+ {
3393+ UStructProperty *prop_struct = NewObject<UStructProperty>(function, UTF8_TO_TCHAR (p_name), RF_Public);
3394+ prop_struct->Struct = (UScriptStruct*)py_obj->ue_object ;
3395+ prop = prop_struct;
3396+ }
32523397 }
3253- // TODO add native types (like vectors, rotators...)
3398+
32543399 if (prop)
32553400 {
32563401 prop->SetPropertyFlags (CPF_Parm | CPF_OutParm | CPF_ReturnParm);
0 commit comments