Skip to content

Commit 0c60e9a

Browse files
author
Roberto De Ioris
committed
improved struct management, added api for user defined struct
1 parent 7825acf commit 0c60e9a

File tree

8 files changed

+334
-24
lines changed

8 files changed

+334
-24
lines changed

Source/UnrealEnginePython/Private/UEPyEngine.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ PyObject *py_unreal_engine_string_to_guid(PyObject * self, PyObject * args)
425425
char *str;
426426
if (!PyArg_ParseTuple(args, "s:string_to_guid", &str))
427427
{
428-
return NULL;
428+
return nullptr;
429429
}
430430

431431
FGuid guid;
@@ -444,7 +444,21 @@ PyObject *py_unreal_engine_new_guid(PyObject * self, PyObject * args)
444444
FGuid guid = FGuid::NewGuid();
445445

446446
return py_ue_new_uscriptstruct(FindObject<UScriptStruct>(ANY_PACKAGE, UTF8_TO_TCHAR((char *)"Guid")), (uint8 *)&guid);
447+
}
448+
449+
PyObject *py_unreal_engine_guid_to_string(PyObject * self, PyObject * args)
450+
{
451+
PyObject *py_guid;
452+
if (!PyArg_ParseTuple(args, "O:guid_to_string", &py_guid))
453+
{
454+
return nullptr;
455+
}
456+
457+
FGuid *guid = ue_py_check_fguid(py_guid);
458+
if (!guid)
459+
return PyErr_Format(PyExc_Exception, "object is not a FGuid");
447460

461+
return PyUnicode_FromString(TCHAR_TO_UTF8(*guid->ToString()));
448462
}
449463

450464
PyObject *py_unreal_engine_slate_tick(PyObject * self, PyObject * args)

Source/UnrealEnginePython/Private/UEPyEngine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ PyObject *py_unreal_engine_load_package(PyObject *, PyObject *);
3333

3434
PyObject *py_unreal_engine_string_to_guid(PyObject *, PyObject *);
3535
PyObject *py_unreal_engine_new_guid(PyObject *, PyObject *);
36+
PyObject *py_unreal_engine_guid_to_string(PyObject *, PyObject *);
3637

3738
PyObject *py_unreal_engine_engine_tick(PyObject *, PyObject *);
3839
PyObject *py_unreal_engine_slate_tick(PyObject *, PyObject *);

Source/UnrealEnginePython/Private/UEPyModule.cpp

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "UObject/UEPyAnimSequence.h"
3636
#include "UObject/UEPyCapture.h"
3737
#include "UObject/UEPyLandscape.h"
38+
#include "UObject/UEPyUserDefinedStruct.h"
3839

3940

4041
#include "UEPyAssetUserData.h"
@@ -258,6 +259,7 @@ static PyMethodDef unreal_engine_methods[] = {
258259

259260
{ "string_to_guid", py_unreal_engine_string_to_guid, METH_VARARGS, "" },
260261
{ "new_guid", py_unreal_engine_new_guid, METH_VARARGS, "" },
262+
{ "guid_to_string", py_unreal_engine_guid_to_string, METH_VARARGS, "" },
261263

262264
{ "heightmap_expand", py_unreal_engine_heightmap_expand, METH_VARARGS, "" },
263265
{ "heightmap_import", py_unreal_engine_heightmap_import, METH_VARARGS, "" },
@@ -521,6 +523,12 @@ static PyMethodDef ue_PyUObject_methods[] = {
521523
{ "node_reconstruct", (PyCFunction)py_ue_node_reconstruct, METH_VARARGS, "" },
522524

523525
{ "get_material_graph", (PyCFunction)py_ue_get_material_graph, METH_VARARGS, "" },
526+
527+
{ "struct_add_variable", (PyCFunction)py_ue_struct_add_variable, METH_VARARGS, "" },
528+
{ "struct_get_variables", (PyCFunction)py_ue_struct_get_variables, METH_VARARGS, "" },
529+
{ "struct_remove_variable", (PyCFunction)py_ue_struct_remove_variable, METH_VARARGS, "" },
530+
{ "struct_move_variable_up", (PyCFunction)py_ue_struct_move_variable_up, METH_VARARGS, "" },
531+
{ "struct_move_variable_down", (PyCFunction)py_ue_struct_move_variable_down, METH_VARARGS, "" },
524532
#endif
525533

526534
{ "is_rooted", (PyCFunction)py_ue_is_rooted, METH_VARARGS, "" },
@@ -935,7 +943,7 @@ void ue_pydelegates_cleanup(ue_PyUObject *self)
935943
UE_LOG(LogPython, Warning, TEXT("Removing UPythonDelegate %p from ue_PyUObject %p mapped to UObject %p"), py_delegate, self, self->ue_object);
936944
#endif
937945
py_delegate->RemoveFromRoot();
938-
}
946+
}
939947
}
940948
self->python_delegates_gc->clear();
941949
delete self->python_delegates_gc;
@@ -1032,9 +1040,9 @@ static PyObject *ue_PyUObject_getattro(ue_PyUObject *self, PyObject *attr_name)
10321040
#else
10331041
return PyLong_FromLong(u_enum->FindEnumIndex(item.Key));
10341042
#endif
1043+
}
10351044
}
10361045
}
1037-
}
10381046
#endif
10391047
if (self->ue_object->IsA<UEnum>())
10401048
{
@@ -1046,16 +1054,16 @@ static PyObject *ue_PyUObject_getattro(ue_PyUObject *self, PyObject *attr_name)
10461054
return PyLong_FromLong(u_enum->FindEnumIndex(FName(UTF8_TO_TCHAR(attr))));
10471055
#endif
10481056
}
1049-
}
1057+
}
10501058

10511059
if (function)
10521060
{
10531061
// swallow previous exception
10541062
PyErr_Clear();
10551063
return py_ue_new_callable(function, self->ue_object);
10561064
}
1065+
}
10571066
}
1058-
}
10591067
return ret;
10601068
}
10611069

@@ -2048,7 +2056,7 @@ void unreal_engine_py_log_error()
20482056
if (zero)
20492057
{
20502058
msg = PyBytes_AsString(zero);
2051-
}
2059+
}
20522060
#else
20532061
msg = PyString_AsString(PyObject_Str(value));
20542062
#endif
@@ -2234,8 +2242,7 @@ PyObject *ue_py_convert_property(UProperty *prop, uint8 *buffer)
22342242
Py_INCREF(ret);
22352243
return (PyObject *)ret;
22362244
}
2237-
Py_INCREF(Py_None);
2238-
return Py_None;
2245+
Py_RETURN_NONE;
22392246
}
22402247

22412248
if (auto casted_prop = Cast<UClassProperty>(prop))
@@ -2753,24 +2760,47 @@ bool ue_py_convert_pyobject(PyObject *py_obj, UProperty *prop, uint8 *buffer)
27532760
ue_PyUObject *ue_obj = (ue_PyUObject *)py_obj;
27542761
if (ue_obj->ue_object->IsA<UClass>())
27552762
{
2756-
auto casted_prop = Cast<UClassProperty>(prop);
2757-
if (!casted_prop)
2758-
return false;
2759-
casted_prop->SetPropertyValue_InContainer(buffer, (UClass *)ue_obj->ue_object);
2760-
return true;
2763+
if (auto casted_prop = Cast<UClassProperty>(prop))
2764+
{
2765+
casted_prop->SetPropertyValue_InContainer(buffer, ue_obj->ue_object);
2766+
return true;
2767+
}
2768+
else if (auto casted_prop = Cast<USoftClassProperty>(prop))
2769+
{
2770+
casted_prop->SetPropertyValue_InContainer(buffer, FSoftObjectPtr(ue_obj->ue_object));
2771+
return true;
2772+
}
2773+
else if (auto casted_prop = Cast<USoftObjectProperty>(prop))
2774+
{
2775+
casted_prop->SetPropertyValue_InContainer(buffer, FSoftObjectPtr(ue_obj->ue_object));
2776+
return true;
2777+
}
2778+
2779+
return false;
27612780
}
27622781

2782+
27632783
if (ue_obj->ue_object->IsA<UObject>())
27642784
{
2765-
auto casted_prop = Cast<UObjectPropertyBase>(prop);
2766-
if (!casted_prop)
2767-
return false;
2768-
// ensure the object type is correct, otherwise crash could happen (soon or later)
2769-
if (!ue_obj->ue_object->IsA(casted_prop->PropertyClass))
2770-
return false;
2771-
casted_prop->SetObjectPropertyValue_InContainer(buffer, ue_obj->ue_object);
2772-
return true;
2785+
if (auto casted_prop = Cast<UObjectPropertyBase>(prop))
2786+
{
2787+
// ensure the object type is correct, otherwise crash could happen (soon or later)
2788+
if (!ue_obj->ue_object->IsA(casted_prop->PropertyClass))
2789+
return false;
2790+
casted_prop->SetObjectPropertyValue_InContainer(buffer, ue_obj->ue_object);
2791+
return true;
2792+
}
2793+
else if (auto casted_prop = Cast<USoftObjectProperty>(prop))
2794+
2795+
{
2796+
if (!ue_obj->ue_object->IsA(casted_prop->PropertyClass))
2797+
return false;
2798+
casted_prop->SetPropertyValue_InContainer(buffer, FSoftObjectPtr(ue_obj->ue_object));
2799+
return true;
2800+
}
2801+
27732802
}
2803+
return false;
27742804
}
27752805

27762806
if (py_obj == Py_None)
@@ -2978,9 +3008,9 @@ PyObject *py_ue_ufunction_call(UFunction *u_function, UObject *u_obj, PyObject *
29783008
#else
29793009
prop->ImportText(*default_key_value, prop->ContainerPtrToValuePtr<uint8>(buffer), PPF_Localized, NULL);
29803010
#endif
2981-
}
3011+
}
29823012
#endif
2983-
}
3013+
}
29843014

29853015
Py_ssize_t tuple_len = PyTuple_Size(args);
29863016

@@ -3463,3 +3493,19 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
34633493

34643494
return function;
34653495
}
3496+
3497+
FGuid *ue_py_check_fguid(PyObject *py_obj)
3498+
{
3499+
ue_PyUScriptStruct *ue_py_struct = py_ue_is_uscriptstruct(py_obj);
3500+
if (!ue_py_struct)
3501+
{
3502+
return nullptr;
3503+
}
3504+
3505+
if (ue_py_struct->u_struct == FindObject<UScriptStruct>(ANY_PACKAGE, UTF8_TO_TCHAR((char *)"Guid")))
3506+
{
3507+
return (FGuid*)ue_py_struct->data;
3508+
}
3509+
3510+
return nullptr;
3511+
}

Source/UnrealEnginePython/Private/UEPyModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,5 @@ template <typename T> T *ue_py_check_struct(PyObject *py_obj) {
6969

7070
return nullptr;
7171
}
72+
73+
FGuid *ue_py_check_fguid(PyObject *);

Source/UnrealEnginePython/Private/UEPyUScriptStruct.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ PyObject *py_ue_new_uscriptstruct(UScriptStruct *u_struct, uint8 *data) {
263263
ue_PyUScriptStruct *ret = (ue_PyUScriptStruct *)PyObject_New(ue_PyUScriptStruct, &ue_PyUScriptStructType);
264264
ret->u_struct = u_struct;
265265
uint8 *struct_data = (uint8*)FMemory::Malloc(u_struct->GetStructureSize());
266-
FMemory::Memcpy(struct_data, data, u_struct->GetStructureSize());
266+
ret->u_struct->InitializeStruct(struct_data);
267+
ret->u_struct->CopyScriptStruct(struct_data, data);
267268
ret->data = struct_data;
268269
return (PyObject *)ret;
269270
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#include "UnrealEnginePythonPrivatePCH.h"
2+
3+
4+
#if WITH_EDITOR
5+
#include "Classes/UserDefinedStructure/UserDefinedStructEditorData.h"
6+
#include "Public/Kismet2/StructureEditorUtils.h"
7+
8+
9+
10+
PyObject *py_ue_struct_add_variable(ue_PyUObject * self, PyObject * args)
11+
{
12+
13+
ue_py_check(self);
14+
15+
PyObject *py_var;
16+
17+
if (!PyArg_ParseTuple(args, "O:struct_add_variable", &py_var))
18+
{
19+
return nullptr;
20+
}
21+
22+
UUserDefinedStruct *u_struct = ue_py_check_type<UUserDefinedStruct>(self);
23+
if (!u_struct)
24+
return PyErr_Format(PyExc_Exception, "uobject is not a UUserDefinedStruct");
25+
26+
FStructVariableDescription *var = ue_py_check_struct<FStructVariableDescription>(py_var);
27+
if (!var)
28+
return PyErr_Format(PyExc_Exception, "argument is not a FStructVariableDescription");
29+
30+
var->VarGuid = FGuid::NewGuid();
31+
32+
FStructureEditorUtils::GetVarDesc(u_struct).Add(*var);
33+
34+
FStructureEditorUtils::OnStructureChanged(u_struct, FStructureEditorUtils::EStructureEditorChangeInfo::AddedVariable);
35+
36+
return py_ue_new_uscriptstruct(FindObject<UScriptStruct>(ANY_PACKAGE, UTF8_TO_TCHAR((char *)"Guid")), (uint8 *)&var->VarGuid);
37+
}
38+
39+
PyObject *py_ue_struct_get_variables(ue_PyUObject * self, PyObject * args)
40+
{
41+
42+
ue_py_check(self);
43+
44+
UUserDefinedStruct *u_struct = ue_py_check_type<UUserDefinedStruct>(self);
45+
if (!u_struct)
46+
return PyErr_Format(PyExc_Exception, "uobject is not a UUserDefinedStruct");
47+
48+
TArray<FStructVariableDescription> variables = FStructureEditorUtils::GetVarDesc(u_struct);
49+
50+
PyObject *py_list = PyList_New(0);
51+
for (FStructVariableDescription description : variables)
52+
{
53+
PyList_Append(py_list, py_ue_new_uscriptstruct(FStructVariableDescription::StaticStruct(), (uint8*)&description));
54+
}
55+
return py_list;
56+
}
57+
58+
PyObject *py_ue_struct_remove_variable(ue_PyUObject * self, PyObject * args)
59+
{
60+
61+
ue_py_check(self);
62+
63+
PyObject *py_guid;
64+
65+
if (!PyArg_ParseTuple(args, "O:struct_remove_variable", &py_guid))
66+
{
67+
return nullptr;
68+
}
69+
70+
UUserDefinedStruct *u_struct = ue_py_check_type<UUserDefinedStruct>(self);
71+
if (!u_struct)
72+
return PyErr_Format(PyExc_Exception, "uobject is not a UUserDefinedStruct");
73+
74+
FGuid *guid = ue_py_check_fguid(py_guid);
75+
if (!guid)
76+
return PyErr_Format(PyExc_Exception, "object is not a FGuid");
77+
78+
if (FStructureEditorUtils::RemoveVariable(u_struct, *guid))
79+
{
80+
Py_RETURN_TRUE;
81+
}
82+
83+
Py_RETURN_FALSE;
84+
}
85+
86+
PyObject *py_ue_struct_move_variable_up(ue_PyUObject * self, PyObject * args)
87+
{
88+
89+
ue_py_check(self);
90+
91+
PyObject *py_guid;
92+
93+
if (!PyArg_ParseTuple(args, "O:struct_move_variable_up", &py_guid))
94+
{
95+
return nullptr;
96+
}
97+
98+
UUserDefinedStruct *u_struct = ue_py_check_type<UUserDefinedStruct>(self);
99+
if (!u_struct)
100+
return PyErr_Format(PyExc_Exception, "uobject is not a UUserDefinedStruct");
101+
102+
FGuid *guid = ue_py_check_fguid(py_guid);
103+
if (!guid)
104+
return PyErr_Format(PyExc_Exception, "object is not a FGuid");
105+
106+
if (FStructureEditorUtils::MoveVariable(u_struct, *guid, FStructureEditorUtils::EMoveDirection::MD_Up))
107+
{
108+
Py_RETURN_TRUE;
109+
}
110+
111+
Py_RETURN_FALSE;
112+
}
113+
114+
PyObject *py_ue_struct_move_variable_down(ue_PyUObject * self, PyObject * args)
115+
{
116+
117+
ue_py_check(self);
118+
119+
PyObject *py_guid;
120+
121+
if (!PyArg_ParseTuple(args, "O:struct_move_variable_down", &py_guid))
122+
{
123+
return nullptr;
124+
}
125+
126+
UUserDefinedStruct *u_struct = ue_py_check_type<UUserDefinedStruct>(self);
127+
if (!u_struct)
128+
return PyErr_Format(PyExc_Exception, "uobject is not a UUserDefinedStruct");
129+
130+
FGuid *guid = ue_py_check_fguid(py_guid);
131+
if (!guid)
132+
return PyErr_Format(PyExc_Exception, "object is not a FGuid");
133+
134+
if (FStructureEditorUtils::MoveVariable(u_struct, *guid, FStructureEditorUtils::EMoveDirection::MD_Down))
135+
{
136+
Py_RETURN_TRUE;
137+
}
138+
139+
Py_RETURN_FALSE;
140+
}
141+
142+
#endif
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
4+
#include "UnrealEnginePython.h"
5+
6+
7+
PyObject *py_ue_struct_add_variable(ue_PyUObject *, PyObject *);
8+
PyObject *py_ue_struct_get_variables(ue_PyUObject *, PyObject *);
9+
PyObject *py_ue_struct_remove_variable(ue_PyUObject *, PyObject *);
10+
PyObject *py_ue_struct_move_variable_up(ue_PyUObject *, PyObject *);
11+
PyObject *py_ue_struct_move_variable_down(ue_PyUObject *, PyObject *);

0 commit comments

Comments
 (0)