Skip to content

Commit 2a5e46f

Browse files
author
Roberto De Ioris
committed
improved array usage for structs, still buggy
1 parent 799cbd5 commit 2a5e46f

File tree

2 files changed

+152
-17
lines changed

2 files changed

+152
-17
lines changed

Source/UnrealEnginePython/Private/UEPyModule.cpp

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,16 @@ static PyObject *ue_PyUObject_call(ue_PyUObject *self, PyObject *args, PyObject
715715
Py_DECREF(py_args);
716716
return (PyObject *)ret;
717717
}
718+
// if it is a uscriptstruct, instantiate a new struct
719+
if (self->ue_object->IsA<UScriptStruct>()) {
720+
UScriptStruct *u_script_struct = (UScriptStruct *)self->ue_object;
721+
uint8 *data = (uint8*)FMemory_Alloca(u_script_struct->GetStructureSize());
722+
u_script_struct->InitializeStruct(data);
723+
#if WITH_EDITOR
724+
u_script_struct->InitializeDefaultValue(data);
725+
#endif
726+
return py_ue_new_uscriptstruct(u_script_struct, data);
727+
}
718728
return PyErr_Format(PyExc_Exception, "the specified uobject has no __call__ support");
719729
}
720730

@@ -1404,13 +1414,13 @@ PyObject *ue_py_convert_property(UProperty *prop, uint8 *buffer) {
14041414
FScriptArrayHelper_InContainer array_helper(casted_prop, buffer);
14051415
PyObject *py_list = PyList_New(0);
14061416
UProperty *array_prop = casted_prop->Inner;
1407-
if (array_prop->IsA<UStructProperty>()) {
1408-
uint8 *array_buffer = (uint8 *)FMemory_Alloca(array_prop->GetSize());
1417+
/*if (array_prop->IsA<UStructProperty>()) {
1418+
uint8 *array_buffer = (uint8 *)FMemory::Malloc(array_prop->GetSize());
1419+
array_prop->InitializeValue(array_buffer);
14091420
for (int i = 0; i < array_helper.Num(); i++) {
1410-
array_prop->InitializeValue(array_buffer);
14111421
array_prop->CopyCompleteValueFromScriptVM(array_buffer, array_helper.GetRawPtr(i));
14121422
PyObject *item = ue_py_convert_property(array_prop, array_buffer);
1413-
array_prop->DestroyValue(array_buffer);
1423+
//array_prop->DestroyValue(array_buffer);
14141424
if (!item) {
14151425
Py_DECREF(py_list);
14161426
return NULL;
@@ -1419,17 +1429,17 @@ PyObject *ue_py_convert_property(UProperty *prop, uint8 *buffer) {
14191429
Py_DECREF(item);
14201430
}
14211431
}
1422-
else {
1423-
for (int i = 0; i < array_helper.Num(); i++) {
1424-
PyObject *item = ue_py_convert_property(array_prop, array_helper.GetRawPtr(i));
1425-
if (!item) {
1426-
Py_DECREF(py_list);
1427-
return NULL;
1428-
}
1429-
PyList_Append(py_list, item);
1430-
Py_DECREF(item);
1432+
else {*/
1433+
for (int i = 0; i < array_helper.Num(); i++) {
1434+
PyObject *item = ue_py_convert_property(array_prop, array_helper.GetRawPtr(i));
1435+
if (!item) {
1436+
Py_DECREF(py_list);
1437+
return NULL;
14311438
}
1439+
PyList_Append(py_list, item);
1440+
Py_DECREF(item);
14321441
}
1442+
//}
14331443
return py_list;
14341444
}
14351445

@@ -1511,6 +1521,19 @@ bool ue_py_convert_pyobject(PyObject *py_obj, UProperty *prop, uint8 *buffer) {
15111521
helper.RemoveValues(pylist_len, helper.Num() - pylist_len);
15121522
}
15131523

1524+
/*if (array_prop->IsA<UStructProperty>()) {
1525+
for (int i = 0; i < (int)pylist_len; i++) {
1526+
PyObject *py_item = PyList_GetItem(py_obj, i);
1527+
// ensure py_item is a UScriptStruct
1528+
if (ue_PyUScriptStruct *u_struct = py_ue_is_uscriptstruct(py_item)) {
1529+
array_prop->CopySingleValue(helper.GetRawPtr(i), u_struct->data);
1530+
}
1531+
Py_DECREF(py_item);
1532+
}
1533+
return true;
1534+
}
1535+
else {*/
1536+
15141537
for (int i = 0; i < (int)pylist_len; i++) {
15151538
uint8 *item_buf = helper.GetRawPtr(i);
15161539
PyObject *py_item = PyList_GetItem(py_obj, i);
@@ -1520,8 +1543,10 @@ bool ue_py_convert_pyobject(PyObject *py_obj, UProperty *prop, uint8 *buffer) {
15201543
}
15211544
Py_DECREF(py_item);
15221545
}
1546+
//}
15231547
return true;
15241548
}
1549+
15251550
return false;
15261551
}
15271552

@@ -1592,7 +1617,8 @@ bool ue_py_convert_pyobject(PyObject *py_obj, UProperty *prop, uint8 *buffer) {
15921617
ue_PyUScriptStruct *py_u_struct = (ue_PyUScriptStruct *)py_obj;
15931618
if (auto casted_prop = Cast<UStructProperty>(prop)) {
15941619
if (casted_prop->Struct == py_u_struct->u_struct) {
1595-
*casted_prop->ContainerPtrToValuePtr<uint8 *>(buffer) = py_u_struct->data;
1620+
uint8 *dest = *casted_prop->ContainerPtrToValuePtr<uint8 *>(buffer);
1621+
FMemory::Memcpy(dest, py_u_struct->data, py_u_struct->u_struct->GetStructureSize());
15961622
return true;
15971623
}
15981624
}

Source/UnrealEnginePython/Private/UEPyUScriptStruct.cpp

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,54 @@ static PyObject *py_ue_uscriptstruct_get_field(ue_PyUScriptStruct *self, PyObjec
1616
return ue_py_convert_property(u_property, self->data);
1717
}
1818

19+
static PyObject *py_ue_uscriptstruct_set_field(ue_PyUScriptStruct *self, PyObject * args) {
20+
char *name;
21+
PyObject *value;
22+
if (!PyArg_ParseTuple(args, "sO:set_field", &name, &value)) {
23+
return NULL;
24+
}
25+
26+
UProperty *u_property = self->u_struct->FindPropertyByName(FName(UTF8_TO_TCHAR(name)));
27+
if (!u_property)
28+
return PyErr_Format(PyExc_Exception, "unable to find property %s", name);
29+
30+
31+
if (!ue_py_convert_pyobject(value, u_property, self->data)) {
32+
return PyErr_Format(PyExc_Exception, "unable to set property %s", name);
33+
}
34+
35+
Py_INCREF(Py_None);
36+
return Py_None;
37+
38+
}
39+
40+
static PyObject *py_ue_uscriptstruct_fields(ue_PyUScriptStruct *self, PyObject * args) {
41+
PyObject *ret = PyList_New(0);
42+
43+
for (TFieldIterator<UProperty> PropIt(self->u_struct); PropIt; ++PropIt)
44+
{
45+
UProperty* property = *PropIt;
46+
PyObject *property_name = PyUnicode_FromString(TCHAR_TO_UTF8(*property->GetName()));
47+
PyList_Append(ret, property_name);
48+
Py_DECREF(property_name);
49+
}
50+
51+
return ret;
52+
}
53+
54+
static PyObject *py_ue_uscriptstruct_get_struct(ue_PyUScriptStruct *self, PyObject * args) {
55+
ue_PyUObject *ret = ue_get_python_wrapper(self->u_struct);
56+
if (!ret)
57+
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state");
58+
Py_INCREF(ret);
59+
return (PyObject *)ret;
60+
}
61+
1962
static PyMethodDef ue_PyUScriptStruct_methods[] = {
2063
{ "get_field", (PyCFunction)py_ue_uscriptstruct_get_field, METH_VARARGS, "" },
64+
{ "set_field", (PyCFunction)py_ue_uscriptstruct_set_field, METH_VARARGS, "" },
65+
{ "fields", (PyCFunction)py_ue_uscriptstruct_fields, METH_VARARGS, "" },
66+
{ "get_struct", (PyCFunction)py_ue_uscriptstruct_get_struct, METH_VARARGS, "" },
2167
{ NULL } /* Sentinel */
2268
};
2369

@@ -28,6 +74,40 @@ static PyObject *ue_PyUScriptStruct_str(ue_PyUScriptStruct *self)
2874
TCHAR_TO_UTF8(*self->u_struct->GetName()), self->u_struct->GetStructureSize());
2975
}
3076

77+
static PyObject *ue_PyUScriptStruct_getattro(ue_PyUScriptStruct *self, PyObject *attr_name) {
78+
PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, attr_name);
79+
if (!ret) {
80+
if (PyUnicodeOrString_Check(attr_name)) {
81+
char *attr = PyUnicode_AsUTF8(attr_name);
82+
// first check for property
83+
UProperty *u_property = self->u_struct->FindPropertyByName(FName(UTF8_TO_TCHAR(attr)));
84+
if (u_property) {
85+
// swallow previous exception
86+
PyErr_Clear();
87+
return ue_py_convert_property(u_property, self->data);
88+
}
89+
}
90+
}
91+
return ret;
92+
}
93+
94+
static int ue_PyUScriptStruct_setattro(ue_PyUScriptStruct *self, PyObject *attr_name, PyObject *value) {
95+
// first of all check for UProperty
96+
if (PyUnicodeOrString_Check(attr_name)) {
97+
char *attr = PyUnicode_AsUTF8(attr_name);
98+
// first check for property
99+
UProperty *u_property = self->u_struct->FindPropertyByName(FName(UTF8_TO_TCHAR(attr)));
100+
if (u_property) {
101+
if (ue_py_convert_pyobject(value, u_property, self->data)) {
102+
return 0;
103+
}
104+
PyErr_SetString(PyExc_ValueError, "invalid value for UProperty");
105+
return -1;
106+
}
107+
}
108+
return PyObject_GenericSetAttr((PyObject *)self, attr_name, value);
109+
}
110+
31111
static PyTypeObject ue_PyUScriptStructType = {
32112
PyVarObject_HEAD_INIT(NULL, 0)
33113
"unreal_engine.UScriptStruct", /* tp_name */
@@ -45,8 +125,8 @@ static PyTypeObject ue_PyUScriptStructType = {
45125
0, /* tp_hash */
46126
0, /* tp_call */
47127
(reprfunc)ue_PyUScriptStruct_str, /* tp_str */
48-
0, /* tp_getattro */
49-
0, /* tp_setattro */
128+
(getattrofunc)ue_PyUScriptStruct_getattro, /* tp_getattro */
129+
(setattrofunc)ue_PyUScriptStruct_setattro, /* tp_setattro */
50130
0, /* tp_as_buffer */
51131
Py_TPFLAGS_DEFAULT, /* tp_flags */
52132
"Unreal Engine Editor UScriptStruct", /* tp_doc */
@@ -61,10 +141,37 @@ static PyTypeObject ue_PyUScriptStructType = {
61141
0,
62142
};
63143

144+
static int ue_py_uscriptstruct_init(ue_PyUScriptStruct *self, PyObject *args, PyObject *kwargs) {
145+
PyObject *py_struct;
146+
if (!PyArg_ParseTuple(args, "O", &py_struct))
147+
return -1;
148+
149+
if (!ue_is_pyuobject(py_struct)) {
150+
PyErr_SetString(PyExc_Exception, "argument is not a UScriptStruct");
151+
return -1;
152+
}
153+
154+
ue_PyUObject *py_u_obj = (ue_PyUObject *)py_struct;
155+
if (!py_u_obj->ue_object->IsA<UScriptStruct>()) {
156+
PyErr_SetString(PyExc_Exception, "argument is not a UScriptStruct");
157+
return -1;
158+
}
159+
160+
self->u_struct = (UScriptStruct *)py_u_obj->ue_object;
161+
self->data = (uint8*)FMemory::Malloc(self->u_struct->GetStructureSize());
162+
self->u_struct->InitializeStruct(self->data);
163+
#if WITH_EDITOR
164+
self->u_struct->InitializeDefaultValue(self->data);
165+
#endif
166+
return 0;
167+
}
168+
64169

65170
void ue_python_init_uscriptstruct(PyObject *ue_module) {
66171
ue_PyUScriptStructType.tp_new = PyType_GenericNew;
67172

173+
ue_PyUScriptStructType.tp_init = (initproc)ue_py_uscriptstruct_init;
174+
68175
if (PyType_Ready(&ue_PyUScriptStructType) < 0)
69176
return;
70177

@@ -75,7 +182,9 @@ void ue_python_init_uscriptstruct(PyObject *ue_module) {
75182
PyObject *py_ue_new_uscriptstruct(UScriptStruct *u_struct, uint8 *data) {
76183
ue_PyUScriptStruct *ret = (ue_PyUScriptStruct *)PyObject_New(ue_PyUScriptStruct, &ue_PyUScriptStructType);
77184
ret->u_struct = u_struct;
78-
ret->data = data;
185+
uint8 *struct_data = (uint8*)FMemory::Malloc(u_struct->GetStructureSize());
186+
FMemory::Memcpy(struct_data, data, u_struct->GetStructureSize());
187+
ret->data = struct_data;
79188
return (PyObject *)ret;
80189
}
81190

0 commit comments

Comments
 (0)