Skip to content

Commit 24f94b0

Browse files
author
Roberto De Ioris
committed
2 parents eb55f82 + 2e9d250 commit 24f94b0

File tree

7 files changed

+393
-2
lines changed

7 files changed

+393
-2
lines changed

CONTRIBUTORS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1+
Tony Barbieri

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ Creating a new blueprint class managed by python
126126
We are going to create a new Actor based on python (instead of C++ or blueprints)
127127

128128
This is the "gentle" approach, using a 'proxy' python class to speak with the UE4 api. Once you get familiar with the system, you can
129-
go further and start working withe native subclassing api (https://github.com/20tab/UnrealEnginePython/blob/master/docs/SubclassingAPI.md)
129+
go further and start working withe native subclassing api (https://github.com/20tab/UnrealEnginePython/blob/master/docs/Subclassing_API.md)
130130

131131
In the content browser click on 'add new' and choose 'blueprint class'
132132

Source/UnrealEnginePython/Private/UEPyEditor.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,40 @@ PyObject *py_unreal_engine_get_assets(PyObject * self, PyObject * args) {
264264
return assets_list;
265265
}
266266

267+
PyObject *py_unreal_engine_get_assets_by_filter(PyObject * self, PyObject * args) {
268+
269+
PyObject *pyfilter;
270+
271+
if (!PyArg_ParseTuple(args, "O:get_assets_by_filter", &pyfilter)) {
272+
return NULL;
273+
}
274+
275+
ue_PyFARFilter *filter = py_ue_is_farfilter(pyfilter);
276+
if (!filter)
277+
return PyErr_Format(PyExc_Exception, "Arg is not a FARFilter");
278+
279+
if (!GEditor)
280+
return PyErr_Format(PyExc_Exception, "no GEditor found");
281+
282+
py_ue_sync_farfilter((PyObject *)filter);
283+
TArray<FAssetData> assets;
284+
FAssetRegistryModule& AssetRegistryModule = FModuleManager::GetModuleChecked<FAssetRegistryModule>("AssetRegistry");
285+
AssetRegistryModule.Get().SearchAllAssets(true);
286+
AssetRegistryModule.Get().GetAssets(filter->filter, assets);
287+
288+
PyObject *assets_list = PyList_New(0);
289+
for (FAssetData asset : assets) {
290+
if (!asset.IsValid())
291+
continue;
292+
ue_PyUObject *ret = ue_get_python_wrapper(asset.GetAsset());
293+
if (ret) {
294+
PyList_Append(assets_list, (PyObject *)ret);
295+
}
296+
}
297+
298+
return assets_list;
299+
}
300+
267301
PyObject *py_unreal_engine_get_assets_by_class(PyObject * self, PyObject * args) {
268302
char *path;
269303
PyObject *py_recursive = nullptr;
Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
#include "UnrealEnginePythonPrivatePCH.h"
2+
3+
static PyObject *py_ue_farfilter_append(ue_PyFARFilter *self, PyObject * args) {
4+
PyObject *pyfilter = nullptr;
5+
py_ue_sync_farfilter((PyObject *)self);
6+
if (!PyArg_ParseTuple(args, "|O:append", &pyfilter))
7+
return NULL;
8+
ue_PyFARFilter *filter = py_ue_is_farfilter(pyfilter);
9+
self->filter.Append(filter->filter);
10+
Py_RETURN_NONE;
11+
}
12+
13+
static PyObject *py_ue_farfilter_clear(ue_PyFARFilter *self) {
14+
py_ue_clear_farfilter(self);
15+
self->filter.Clear();
16+
Py_RETURN_NONE;
17+
}
18+
19+
static PyObject *py_ue_farfilter_is_empty(ue_PyFARFilter *self, PyObject * args) {
20+
py_ue_sync_farfilter((PyObject *)self);
21+
if (self->filter.IsEmpty())
22+
Py_RETURN_TRUE;
23+
Py_RETURN_FALSE;
24+
}
25+
26+
static PyMethodDef ue_PyFARFilter_methods[] = {
27+
{ "append", (PyCFunction)py_ue_farfilter_append, METH_VARARGS, "" },
28+
{ "clear", (PyCFunction)py_ue_farfilter_clear, METH_VARARGS, "" },
29+
{ "is_empty", (PyCFunction)py_ue_farfilter_is_empty, METH_VARARGS, "" },
30+
{ NULL } /* Sentinel */
31+
};
32+
33+
static PyObject *py_ue_farfilter_get_include_only_on_disk_assets(ue_PyFARFilter *self, void *closure) {
34+
if (self->filter.bIncludeOnlyOnDiskAssets)
35+
Py_RETURN_TRUE;
36+
Py_RETURN_FALSE;
37+
}
38+
39+
static int py_ue_farfilter_set_include_only_on_disk_assets(ue_PyFARFilter *self, PyObject *value, void *closure) {
40+
if (value && PyBool_Check(value)) {
41+
if (PyObject_IsTrue(value))
42+
self->filter.bIncludeOnlyOnDiskAssets = true;
43+
else
44+
self->filter.bIncludeOnlyOnDiskAssets = false;
45+
return 0;
46+
}
47+
PyErr_SetString(PyExc_TypeError, "value is not a bool");
48+
return -1;
49+
}
50+
51+
static PyObject *py_ue_farfilter_get_recursive_classes(ue_PyFARFilter *self, void *closure) {
52+
if (self->filter.bRecursiveClasses)
53+
Py_RETURN_TRUE;
54+
Py_RETURN_FALSE;
55+
}
56+
57+
static int py_ue_farfilter_set_recursive_classes(ue_PyFARFilter *self, PyObject *value, void *closure) {
58+
if (value && PyBool_Check(value)) {
59+
if (PyObject_IsTrue(value))
60+
self->filter.bRecursiveClasses = true;
61+
else
62+
self->filter.bRecursiveClasses = false;
63+
return 0;
64+
}
65+
PyErr_SetString(PyExc_TypeError, "value is not a bool");
66+
return -1;
67+
}
68+
69+
static PyObject *py_ue_farfilter_get_recursive_paths(ue_PyFARFilter *self, void *closure) {
70+
if (self->filter.bRecursivePaths)
71+
Py_RETURN_TRUE;
72+
Py_RETURN_FALSE;
73+
}
74+
75+
static int py_ue_farfilter_set_recursive_paths(ue_PyFARFilter *self, PyObject *value, void *closure) {
76+
if (value && PyBool_Check(value)) {
77+
if (PyObject_IsTrue(value))
78+
self->filter.bRecursivePaths = true;
79+
else
80+
self->filter.bRecursivePaths = false;
81+
return 0;
82+
}
83+
PyErr_SetString(PyExc_TypeError, "value is not a bool");
84+
return -1;
85+
}
86+
87+
static PyGetSetDef ue_PyFARFilter_getseters[] = {
88+
{ "include_only_on_disk_assets", (getter)py_ue_farfilter_get_include_only_on_disk_assets,
89+
(setter)py_ue_farfilter_set_include_only_on_disk_assets, (bool)false, NULL },
90+
{ "recursive_classes", (getter)py_ue_farfilter_get_recursive_classes,
91+
(setter)py_ue_farfilter_set_recursive_classes, (bool)false, NULL },
92+
{ "recursive_paths", (getter)py_ue_farfilter_get_recursive_paths,
93+
(setter)py_ue_farfilter_set_recursive_paths, (bool)false, NULL },
94+
{ NULL } /* Sentinel */
95+
};
96+
97+
static PyMemberDef ue_PyFARFilter_members[] = {
98+
{ "class_names", T_OBJECT_EX, offsetof(ue_PyFARFilter, class_names), 0, "class_names" },
99+
{ "object_paths", T_OBJECT_EX, offsetof(ue_PyFARFilter, object_paths), 0, "object_paths" },
100+
{ "package_names", T_OBJECT_EX, offsetof(ue_PyFARFilter, package_names), 0, "package_names" },
101+
{ "package_paths", T_OBJECT_EX, offsetof(ue_PyFARFilter, package_paths), 0, "package_paths" },
102+
{ "recursive_classes_exclusion_set", T_OBJECT_EX, offsetof(ue_PyFARFilter, recursive_classes_exclusion_set), 0, "recursive_classes_exclusion_set" },
103+
{ "tags_and_values", T_OBJECT_EX, offsetof(ue_PyFARFilter, tags_and_values), 0, "tags_and_values" },
104+
{ NULL } /* Sentinel */
105+
};
106+
107+
static int ue_py_farfilter_init(ue_PyFARFilter *self, PyObject *args, PyObject *kwargs) {
108+
return 0;
109+
}
110+
111+
static void ue_py_farfilter_dealloc(ue_PyFARFilter *self) {
112+
Py_XDECREF(self->class_names);
113+
Py_XDECREF(self->object_paths);
114+
Py_XDECREF(self->package_names);
115+
Py_XDECREF(self->package_paths);
116+
Py_XDECREF(self->recursive_classes_exclusion_set);
117+
Py_XDECREF(self->tags_and_values);
118+
self->ob_type->tp_free((PyObject*)self);
119+
}
120+
121+
static PyObject * ue_py_farfilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
122+
{
123+
ue_PyFARFilter *self;
124+
125+
self = (ue_PyFARFilter *)type->tp_alloc(type, 0);
126+
if (self != NULL) {
127+
self->class_names = PyList_New(0);
128+
if (self->class_names == NULL)
129+
{
130+
Py_DECREF(self);
131+
return NULL;
132+
}
133+
134+
self->object_paths = PyList_New(0);
135+
if (self->object_paths == NULL)
136+
{
137+
Py_DECREF(self);
138+
return NULL;
139+
}
140+
141+
self->package_names = PyList_New(0);
142+
if (self->package_names == NULL)
143+
{
144+
Py_DECREF(self);
145+
return NULL;
146+
}
147+
148+
self->package_paths = PyList_New(0);
149+
if (self->package_paths == NULL)
150+
{
151+
Py_DECREF(self);
152+
return NULL;
153+
}
154+
155+
self->recursive_classes_exclusion_set = PySet_New(0);
156+
if (self->recursive_classes_exclusion_set == NULL)
157+
{
158+
Py_DECREF(self);
159+
return NULL;
160+
}
161+
162+
PyObject *collections = PyImport_ImportModule("collections");
163+
PyObject *collections_module_dict = PyModule_GetDict(collections);
164+
PyObject *defaultdict_cls = PyDict_GetItemString(collections_module_dict, "defaultdict");
165+
166+
PyObject *main_module = PyImport_ImportModule("__main__");
167+
PyObject *main_dict = PyModule_GetDict(main_module);
168+
PyObject *builtins_module = PyDict_GetItemString(main_dict, "__builtins__");
169+
PyObject *builtins_dict = PyModule_GetDict(builtins_module);
170+
PyObject *set_cls = PyDict_GetItemString(builtins_dict, "set");
171+
172+
PyObject *py_args = PyTuple_New(1);
173+
PyTuple_SetItem(py_args, 0, set_cls);
174+
PyObject *default_dict = PyObject_CallObject(defaultdict_cls, py_args);
175+
Py_XDECREF(py_args);
176+
177+
self->tags_and_values = default_dict;
178+
if (self->tags_and_values == NULL)
179+
{
180+
Py_DECREF(self);
181+
return NULL;
182+
}
183+
}
184+
185+
return (PyObject *)self;
186+
}
187+
188+
static PyTypeObject ue_PyFARFilterType = {
189+
PyVarObject_HEAD_INIT(NULL, 0)
190+
"unreal_engine.FARFilter", /* tp_name */
191+
sizeof(ue_PyFARFilter), /* tp_basicsize */
192+
0, /* tp_itemsize */
193+
(destructor)ue_py_farfilter_dealloc, /* tp_dealloc */
194+
0, /* tp_print */
195+
0, /* tp_getattr */
196+
0, /* tp_setattr */
197+
0, /* tp_reserved */
198+
0, /* tp_repr */
199+
0, /* tp_as_number */
200+
0, /* tp_as_sequence */
201+
0, /* tp_as_mapping */
202+
0, /* tp_hash */
203+
0, /* tp_call */
204+
0, /* tp_str */
205+
0, /* tp_getattro */
206+
0, /* tp_setattro */
207+
0, /* tp_as_buffer */
208+
Py_TPFLAGS_DEFAULT, /* tp_flags */
209+
"Unreal Engine FARFilter", /* tp_doc */
210+
0, /* tp_traverse */
211+
0, /* tp_clear */
212+
0, /* tp_richcompare */
213+
0, /* tp_weaklistoffset */
214+
0, /* tp_iter */
215+
0, /* tp_iternext */
216+
ue_PyFARFilter_methods, /* tp_methods */
217+
ue_PyFARFilter_members, /* tp_members */
218+
ue_PyFARFilter_getseters, /* tp_getset */
219+
};
220+
221+
void ue_python_init_farfilter(PyObject *ue_module) {
222+
ue_PyFARFilterType.tp_new = ue_py_farfilter_new;
223+
ue_PyFARFilterType.tp_init = (initproc)ue_py_farfilter_init;
224+
if (PyType_Ready(&ue_PyFARFilterType) < 0)
225+
return;
226+
227+
Py_INCREF(&ue_PyFARFilterType);
228+
PyModule_AddObject(ue_module, "FARFilter", (PyObject *)&ue_PyFARFilterType);
229+
}
230+
231+
void py_ue_clear_seq(PyObject *pyseq)
232+
{
233+
if (PyList_Check(pyseq))
234+
{
235+
Py_ssize_t pysize = PyObject_Length(pyseq);
236+
PyObject *pyitem;
237+
for (int i = 0; i < (int)pysize; i++)
238+
{
239+
pyitem = PyList_GetItem(pyseq, i);
240+
PyObject_DelItem(pyseq, pyitem);
241+
}
242+
}
243+
else if(PySet_Check(pyseq))
244+
{
245+
PySet_Clear(pyseq);
246+
}
247+
else if(PyDict_Check(pyseq))
248+
{
249+
PyObject *pykeys = PyDict_Keys(pyseq);
250+
Py_ssize_t pysize = PyObject_Length(pykeys);
251+
PyObject *pykey;
252+
for (int i = 0; i < (int)pysize; i++)
253+
{
254+
pykey = PyList_GetItem(pykeys, i);
255+
PyObject_DelItem(pyseq, pykey);
256+
}
257+
}
258+
}
259+
260+
void py_ue_clear_farfilter(ue_PyFARFilter *pyfilter)
261+
{
262+
py_ue_clear_seq(pyfilter->class_names);
263+
py_ue_clear_seq(pyfilter->object_paths);
264+
py_ue_clear_seq(pyfilter->package_names);
265+
py_ue_clear_seq(pyfilter->package_paths);
266+
py_ue_clear_seq(pyfilter->recursive_classes_exclusion_set);
267+
py_ue_clear_seq(pyfilter->tags_and_values);
268+
}
269+
270+
void ue_sync_farfilter_name_array(PyObject *pylist, TArray<FName> &uelist)
271+
{
272+
Py_ssize_t pylist_len = PyList_Size(pylist);
273+
uelist.Reset(pylist_len);
274+
for (int i = 0; i < (int)pylist_len; i++)
275+
{
276+
PyObject *py_item = PyList_GetItem(pylist, i);
277+
uelist.Add(FName(UTF8_TO_TCHAR(PyUnicode_AsUTF8(py_item))));
278+
}
279+
}
280+
281+
void py_ue_sync_farfilter(PyObject *pyobj)
282+
{
283+
ue_PyFARFilter *pyfilter = py_ue_is_farfilter(pyobj);
284+
ue_sync_farfilter_name_array(pyfilter->class_names, pyfilter->filter.ClassNames);
285+
ue_sync_farfilter_name_array(pyfilter->object_paths, pyfilter->filter.ObjectPaths);
286+
ue_sync_farfilter_name_array(pyfilter->package_names, pyfilter->filter.PackageNames);
287+
ue_sync_farfilter_name_array(pyfilter->package_paths, pyfilter->filter.PackagePaths);
288+
289+
PyObject *pyset = pyfilter->recursive_classes_exclusion_set;
290+
Py_ssize_t pyset_len = PySet_Size(pyset);
291+
PyObject *py_item;
292+
pyfilter->filter.RecursiveClassesExclusionSet.Reset();
293+
for (int i = 0; i < (int)pyset_len; i++)
294+
{
295+
py_item = PyList_GetItem(pyset, i);
296+
pyfilter->filter.RecursiveClassesExclusionSet.Add(FName(UTF8_TO_TCHAR(PyUnicode_AsUTF8(py_item))));
297+
}
298+
299+
PyObject *pykey, *pyvalue;
300+
Py_ssize_t pypos;
301+
FName ukey;
302+
pyfilter->filter.TagsAndValues.Reset();
303+
while(PyDict_Next(pyfilter->tags_and_values, &pypos, &pykey, &pyvalue))
304+
{
305+
ukey = UTF8_TO_TCHAR(PyUnicode_AsUTF8(pykey));
306+
pyset_len = PySet_Size(pyvalue);
307+
for (int i = 0; i < (int)pyset_len; i++)
308+
{
309+
py_item = PyList_GetItem(pyset, i);
310+
pyfilter->filter.TagsAndValues.AddUnique(ukey, UTF8_TO_TCHAR(PyUnicode_AsUTF8(py_item)));
311+
}
312+
}
313+
}
314+
315+
PyObject *py_ue_new_farfilter(FARFilter filter) {
316+
ue_PyFARFilter *ret = (ue_PyFARFilter *)PyObject_New(ue_PyFARFilter, &ue_PyFARFilterType);
317+
ret->filter = filter;
318+
return (PyObject *)ret;
319+
}
320+
321+
ue_PyFARFilter *py_ue_is_farfilter(PyObject *obj) {
322+
if (!PyObject_IsInstance(obj, (PyObject *)&ue_PyFARFilterType))
323+
return nullptr;
324+
return (ue_PyFARFilter *)obj;
325+
}

0 commit comments

Comments
 (0)