Skip to content

Commit 397d45c

Browse files
author
Roberto De Ioris
committed
improved get_outer() and get_outermost()
1 parent c405a85 commit 397d45c

4 files changed

Lines changed: 73 additions & 10 deletions

File tree

‎Source/UnrealEnginePython/Private/UEPyModule.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ static PyMethodDef ue_PyUObject_methods[] = {
588588

589589

590590
{ "get_class", (PyCFunction)py_ue_get_class, METH_VARARGS, "" },
591+
{ "class_generated_by", (PyCFunction)py_ue_class_generated_by, METH_VARARGS, "" },
591592
{ "get_actor_components", (PyCFunction)py_ue_actor_components, METH_VARARGS, "" },
592593
{ "components", (PyCFunction)py_ue_actor_components, METH_VARARGS, "" },
593594
{ "get_components", (PyCFunction)py_ue_actor_components, METH_VARARGS, "" },

‎Source/UnrealEnginePython/Private/UObject/UEPyObject.cpp‎

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@ PyObject *py_ue_get_class(ue_PyUObject * self, PyObject * args)
2121
return (PyObject *)ret;
2222
}
2323

24+
PyObject *py_ue_class_generated_by(ue_PyUObject * self, PyObject * args)
25+
{
26+
27+
ue_py_check(self);
28+
29+
UClass *u_class = ue_py_check_type<UClass>(self);
30+
if (!u_class)
31+
return PyErr_Format(PyExc_Exception, "uobject is a not a UClass");
32+
33+
UObject *u_object = u_class->ClassGeneratedBy;
34+
if (!u_object)
35+
Py_RETURN_NONE;
36+
37+
ue_PyUObject *ret = ue_get_python_wrapper(u_object);
38+
if (!ret)
39+
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state");
40+
Py_INCREF(ret);
41+
return (PyObject *)ret;
42+
}
43+
2444
PyObject *py_ue_get_property_struct(ue_PyUObject * self, PyObject * args)
2545
{
2646

@@ -81,7 +101,11 @@ PyObject *py_ue_get_outer(ue_PyUObject *self, PyObject * args)
81101

82102
ue_py_check(self);
83103

84-
ue_PyUObject *ret = ue_get_python_wrapper(self->ue_object->GetOuter());
104+
UObject *outer = self->ue_object->GetOuter();
105+
if (!outer)
106+
Py_RETURN_NONE;
107+
108+
ue_PyUObject *ret = ue_get_python_wrapper(outer);
85109
if (!ret)
86110
return PyErr_Format(PyExc_Exception, "uobject is in invalid state");
87111
Py_INCREF(ret);
@@ -93,7 +117,11 @@ PyObject *py_ue_get_outermost(ue_PyUObject *self, PyObject * args)
93117

94118
ue_py_check(self);
95119

96-
ue_PyUObject *ret = ue_get_python_wrapper(self->ue_object->GetOutermost());
120+
UObject *outermost = self->ue_object->GetOutermost();
121+
if (!outermost)
122+
Py_RETURN_NONE;
123+
124+
ue_PyUObject *ret = ue_get_python_wrapper(outermost);
97125
if (!ret)
98126
return PyErr_Format(PyExc_Exception, "uobject is in invalid state");
99127
Py_INCREF(ret);
@@ -497,8 +525,7 @@ PyObject *py_ue_save_config(ue_PyUObject *self, PyObject * args)
497525

498526
self->ue_object->SaveConfig();
499527

500-
Py_INCREF(Py_None);
501-
return Py_None;
528+
Py_RETURN_NONE;
502529
}
503530

504531
PyObject *py_ue_set_property(ue_PyUObject *self, PyObject * args)
@@ -534,8 +561,7 @@ PyObject *py_ue_set_property(ue_PyUObject *self, PyObject * args)
534561
return PyErr_Format(PyExc_Exception, "unable to set property %s", property_name);
535562
}
536563

537-
Py_INCREF(Py_None);
538-
return Py_None;
564+
Py_RETURN_NONE;
539565

540566
}
541567

@@ -676,8 +702,7 @@ PyObject *py_ue_call(ue_PyUObject *self, PyObject * args)
676702
return PyErr_Format(PyExc_Exception, "error while calling \"%s\"", call_args);
677703
}
678704

679-
Py_INCREF(Py_None);
680-
return Py_None;
705+
Py_RETURN_NONE;
681706
}
682707

683708
PyObject *py_ue_broadcast(ue_PyUObject *self, PyObject *args)
@@ -707,8 +732,7 @@ PyObject *py_ue_broadcast(ue_PyUObject *self, PyObject *args)
707732
return PyErr_Format(PyExc_Exception, "property is not a UMulticastDelegateProperty");
708733
}
709734

710-
Py_INCREF(Py_None);
711-
return Py_None;
735+
Py_RETURN_NONE;
712736
}
713737

714738
PyObject *py_ue_get_property(ue_PyUObject *self, PyObject * args)

‎Source/UnrealEnginePython/Private/UObject/UEPyObject.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ PyObject *py_ue_post_edit_change(ue_PyUObject *, PyObject *);
6060
PyObject *py_ue_pre_edit_change(ue_PyUObject *, PyObject *);
6161
PyObject *py_ue_modify(ue_PyUObject *, PyObject *);
6262

63+
PyObject *py_ue_class_generated_by(ue_PyUObject *, PyObject *);
64+
6365

6466
#if WITH_EDITOR
6567
PyObject *py_ue_save_package(ue_PyUObject *, PyObject *);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import unreal_engine as ue
2+
from unreal_engine.classes import Object, Blueprint
3+
4+
levels = []
5+
level_packages = []
6+
7+
# get all loaded worlds
8+
for world in ue.all_worlds():
9+
# retrieve the world levels (first persistent then streaming)
10+
levels.append(world.PersistentLevel)
11+
level_packages.append(world.PersistentLevel.get_outermost())
12+
13+
for streaming_level in world.StreamingLevels:
14+
levels.append(streaming_level.LoadedLevel)
15+
level_packages.append(streaming_level.LoadedLevel.get_outermost())
16+
17+
found_uobjects = []
18+
19+
# iterate all the loaded uobjects
20+
for uobject in ue.tobject_iterator(Object):
21+
# compare outermosts
22+
if uobject.get_outermost() in level_packages:
23+
# recursively check outers of object to find
24+
# the ones contained in a level
25+
outer = uobject.get_outer()
26+
while outer:
27+
if outer in levels:
28+
found_uobjects.append(outer)
29+
# check if the uobject has been generated by a blueprint
30+
# in such a case add the blueprint too
31+
generator = outer.get_class().class_generated_by()
32+
if generator and generator.is_a(Blueprint):
33+
found_uobjects.append(generator)
34+
outer = outer.get_outer()
35+
36+
print(found_uobjects)

0 commit comments

Comments
 (0)