Skip to content

Commit ed4ccec

Browse files
author
Roberto De Ioris
committed
added support for pure-python factories
1 parent e88731d commit ed4ccec

File tree

2 files changed

+115
-14
lines changed

2 files changed

+115
-14
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include "UnrealEd.h"
4+
#include "PyFactory.generated.h"
5+
6+
UCLASS()
7+
class UPyFactory : public UFactory
8+
{
9+
GENERATED_BODY()
10+
11+
public:
12+
13+
virtual UObject* FactoryCreateFile(UClass * Class, UObject *InParent, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, FFeedbackContext *Warn, bool& bOutOperationCanceled) override {
14+
return PyFactoryCreateFile(Class, InParent, InName.ToString(), Filename);
15+
}
16+
17+
virtual UClass* ResolveSupportedClass() override {
18+
if (SupportedClass)
19+
return SupportedClass;
20+
return PyResolveSupportedClass();
21+
}
22+
23+
UFUNCTION(BlueprintImplementableEvent)
24+
UObject* PyFactoryCreateFile(class UClass * Class, UObject *InParent, const FString & InName, const FString & Filename);
25+
26+
UFUNCTION(BlueprintImplementableEvent)
27+
UClass* PyResolveSupportedClass();
28+
29+
};
30+
31+

Source/UnrealEnginePython/Private/UEPyModule.cpp

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,14 @@ static int unreal_engine_py_init(ue_PyUObject *self, PyObject *args, PyObject *k
12821282
PyObject *py_init = PyDict_GetItemString(class_attributes, (char *)"__init__");
12831283
if (py_init && PyCallable_Check(py_init)) {
12841284
new_u_py_class->SetPyConstructor(py_init);
1285+
ue_PyUObject *new_default_self = ue_get_python_wrapper(new_u_py_class->ClassDefaultObject);
1286+
if (!new_default_self) {
1287+
unreal_engine_py_log_error();
1288+
UE_LOG(LogPython, Error, TEXT("unable to call __init__ on new ClassDefaultObject"));
1289+
}
1290+
else {
1291+
new_u_py_class->CallPyConstructor(new_default_self);
1292+
}
12851293
}
12861294
}
12871295

@@ -1968,7 +1976,7 @@ bool ue_py_convert_pyobject(PyObject *py_obj, UProperty *prop, uint8 *buffer) {
19681976
}
19691977
return false;
19701978
}
1971-
1979+
19721980
if (ue_PyFTransform *py_transform = py_ue_is_ftransform(py_obj)) {
19731981
if (auto casted_prop = Cast<UStructProperty>(prop)) {
19741982
if (casted_prop->Struct == TBaseStructure<FTransform>::Get()) {
@@ -2432,9 +2440,23 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
24322440
}
24332441
else if (ue_PyUObject *py_obj = ue_is_pyuobject(value)) {
24342442
if (py_obj->ue_object->IsA<UClass>()) {
2435-
UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR(p_name), RF_Public);
2436-
prop_base->SetPropertyClass((UClass *)py_obj->ue_object);
2437-
prop = prop_base;
2443+
UClass *p_u_class = (UClass *)py_obj->ue_object;
2444+
if (p_u_class->IsChildOf<UClass>()) {
2445+
UClassProperty *prop_base = NewObject<UClassProperty>(function, UTF8_TO_TCHAR(p_name), RF_Public);
2446+
if (p_u_class == UClass::StaticClass()) {
2447+
prop_base->SetMetaClass(UObject::StaticClass());
2448+
}
2449+
else {
2450+
prop_base->SetMetaClass(p_u_class->GetClass());
2451+
}
2452+
prop_base->PropertyClass = UClass::StaticClass();
2453+
prop = prop_base;
2454+
}
2455+
else {
2456+
UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR(p_name), RF_Public);
2457+
prop_base->SetPropertyClass(p_u_class);
2458+
prop = prop_base;
2459+
}
24382460
}
24392461
}
24402462
// TODO add native types (like vectors, rotators...)
@@ -2444,6 +2466,7 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
24442466
next_property = &prop->Next;
24452467
*next_property_link = prop;
24462468
next_property_link = &prop->PropertyLinkNext;
2469+
UE_LOG(LogPython, Warning, TEXT("added prop %s"), UTF8_TO_TCHAR(p_name));
24472470
}
24482471
else {
24492472
UE_LOG(LogPython, Warning, TEXT("Unable to map argument %s to function %s"), UTF8_TO_TCHAR(p_name), UTF8_TO_TCHAR(name));
@@ -2454,6 +2477,7 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
24542477
if (annotations) {
24552478
PyObject *py_return_value = PyDict_GetItemString(annotations, "return");
24562479
if (py_return_value) {
2480+
UE_LOG(LogPython, Warning, TEXT("Return Value found"));
24572481
UProperty *prop = nullptr;
24582482
char *p_name = (char *) "ReturnValue";
24592483
if (PyType_Check(py_return_value)) {
@@ -2472,14 +2496,28 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
24722496
}
24732497
else if (ue_PyUObject *py_obj = ue_is_pyuobject(py_return_value)) {
24742498
if (py_obj->ue_object->IsA<UClass>()) {
2475-
UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR(p_name), RF_Public);
2476-
prop_base->SetPropertyClass((UClass *)py_obj->ue_object);
2477-
prop = prop_base;
2499+
UClass *p_u_class = (UClass *)py_obj->ue_object;
2500+
if (p_u_class->IsChildOf<UClass>()) {
2501+
UClassProperty *prop_base = NewObject<UClassProperty>(function, UTF8_TO_TCHAR(p_name), RF_Public);
2502+
if (p_u_class == UClass::StaticClass()) {
2503+
prop_base->SetMetaClass(UObject::StaticClass());
2504+
}
2505+
else {
2506+
prop_base->SetMetaClass(p_u_class->GetClass());
2507+
}
2508+
prop_base->PropertyClass = UClass::StaticClass();
2509+
prop = prop_base;
2510+
}
2511+
else {
2512+
UObjectProperty *prop_base = NewObject<UObjectProperty>(function, UTF8_TO_TCHAR(p_name), RF_Public);
2513+
prop_base->SetPropertyClass(p_u_class);
2514+
prop = prop_base;
2515+
}
24782516
}
24792517
}
24802518
// TODO add native types (like vectors, rotators...)
24812519
if (prop) {
2482-
prop->SetPropertyFlags(CPF_Parm | CPF_ReturnParm);
2520+
prop->SetPropertyFlags(CPF_Parm | CPF_OutParm | CPF_ReturnParm);
24832521
*next_property = prop;
24842522
next_property = &prop->Next;
24852523
*next_property_link = prop;
@@ -2491,16 +2529,43 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
24912529
}
24922530
}
24932531

2532+
// link to fix props Offset_Internal
2533+
function->Bind();
2534+
function->StaticLink(true);
2535+
24942536
if (parent_function) {
2495-
if (!parent_function->IsSignatureCompatibleWith(function)) {
2496-
UE_LOG(LogPython, Error, TEXT("function %s signature's is not compatible with the parent"), UTF8_TO_TCHAR(name));
2537+
2538+
if (!function->IsSignatureCompatibleWith(parent_function)) {
2539+
TFieldIterator<UProperty> It(parent_function);
2540+
while (It) {
2541+
UProperty *p = *It;
2542+
if (p->PropertyFlags & CPF_Parm) {
2543+
UE_LOG(LogPython, Warning, TEXT("Parent PROP: %s %d/%d %d %d %d %s %p"), *p->GetName(), (int)p->PropertyFlags, (int)UFunction::GetDefaultIgnoredSignatureCompatibilityFlags(), (int)(p->PropertyFlags & ~UFunction::GetDefaultIgnoredSignatureCompatibilityFlags()), p->GetSize(), p->GetOffset_ForGC(), *p->GetClass()->GetName(), p->GetClass());
2544+
UClassProperty *ucp = Cast<UClassProperty>(p);
2545+
if (ucp) {
2546+
UE_LOG(LogPython, Warning, TEXT("Parent UClassProperty = %p %s %p %s"), ucp->PropertyClass, *ucp->PropertyClass->GetName(), ucp->MetaClass, *ucp->MetaClass->GetName());
2547+
}
2548+
}
2549+
++It;
2550+
}
2551+
2552+
TFieldIterator<UProperty> It2(function);
2553+
while (It2) {
2554+
UProperty *p = *It2;
2555+
if (p->PropertyFlags & CPF_Parm) {
2556+
UE_LOG(LogPython, Warning, TEXT("Function PROP: %s %d/%d %d %d %d %s %p"), *p->GetName(), (int)p->PropertyFlags, (int)UFunction::GetDefaultIgnoredSignatureCompatibilityFlags(), (int)(p->PropertyFlags & ~UFunction::GetDefaultIgnoredSignatureCompatibilityFlags()), p->GetSize(), p->GetOffset_ForGC(), *p->GetClass()->GetName(), p->GetClass());
2557+
UClassProperty *ucp = Cast<UClassProperty>(p);
2558+
if (ucp) {
2559+
UE_LOG(LogPython, Warning, TEXT("Function UClassProperty = %p %s %p %s"), ucp->PropertyClass, *ucp->PropertyClass->GetName(), ucp->MetaClass, *ucp->MetaClass->GetName());
2560+
}
2561+
}
2562+
++It2;
2563+
}
2564+
PyErr_Format(PyExc_Exception, "function %s signature's is not compatible with the parent", name);
24972565
return nullptr;
24982566
}
24992567
}
25002568

2501-
function->Bind();
2502-
function->StaticLink(true);
2503-
25042569
function->ParmsSize = 0;
25052570
function->NumParms = 0;
25062571

@@ -2517,7 +2582,12 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
25172582
}
25182583
}
25192584

2520-
UE_LOG(LogPython, Warning, TEXT("REGISTERED FUNCTION %s WITH %d PARAMS (size %d) %d"), *function->GetFName().ToString(), function->NumParms, function->ParmsSize, function->PropertiesSize);
2585+
if (parent_function) {
2586+
UE_LOG(LogPython, Warning, TEXT("OVERRIDDEN FUNCTION %s WITH %d PARAMS (size %d) %d"), *function->GetFName().ToString(), function->NumParms, function->ParmsSize, function->PropertiesSize);
2587+
}
2588+
else {
2589+
UE_LOG(LogPython, Warning, TEXT("REGISTERED FUNCTION %s WITH %d PARAMS (size %d) %d"), *function->GetFName().ToString(), function->NumParms, function->ParmsSize, function->PropertiesSize);
2590+
}
25212591

25222592
function->FunctionFlags = function_flags;
25232593

0 commit comments

Comments
 (0)