Skip to content

Commit 61400a5

Browse files
author
Roberto De Ioris
committed
improved foliage api
1 parent 5dcd225 commit 61400a5

File tree

7 files changed

+273
-65
lines changed

7 files changed

+273
-65
lines changed

Source/UnrealEnginePython/Private/UEPyModule.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "UObject/UEPyUserDefinedStruct.h"
3737
#include "UObject/UEPyDataTable.h"
3838
#include "UObject/UEPyExporter.h"
39+
#include "UObject/UEPyFoliage.h"
3940

4041

4142
#include "UEPyAssetUserData.h"
@@ -74,6 +75,8 @@
7475
#include "Wrappers/UEPyFEditorViewportClient.h"
7576
#endif
7677

78+
#include "Wrappers/UEPyFFoliageInstance.h"
79+
7780
#include "UEPyCallable.h"
7881
#include "UEPyUClassesImporter.h"
7982
#include "UEPyEnumsImporter.h"
@@ -785,9 +788,12 @@ static PyMethodDef ue_PyUObject_methods[] = {
785788

786789
#if WITH_EDITOR
787790
{ "add_foliage_asset", (PyCFunction)py_ue_add_foliage_asset, METH_VARARGS, "" },
791+
{ "get_foliage_instances", (PyCFunction)py_ue_get_foliage_instances, METH_VARARGS, "" },
788792
#endif
789793
{ "get_instanced_foliage_actor_for_current_level", (PyCFunction)py_ue_get_instanced_foliage_actor_for_current_level, METH_VARARGS, "" },
790-
794+
{ "get_instanced_foliage_actor_for_level", (PyCFunction)py_ue_get_instanced_foliage_actor_for_level, METH_VARARGS, "" },
795+
{ "get_foliage_types", (PyCFunction)py_ue_get_foliage_types, METH_VARARGS, "" },
796+
791797

792798
{ "add_actor_component", (PyCFunction)py_ue_add_actor_component, METH_VARARGS, "" },
793799
{ "add_instance_component", (PyCFunction)py_ue_add_instance_component, METH_VARARGS, "" },
@@ -1518,6 +1524,7 @@ void unreal_engine_init_py_module()
15181524
ue_python_init_enumsimporter(new_unreal_engine_module);
15191525
ue_python_init_ustructsimporter(new_unreal_engine_module);
15201526

1527+
ue_python_init_ffoliage_instance(new_unreal_engine_module);
15211528

15221529
#if WITH_EDITOR
15231530
ue_python_init_fslowtask(new_unreal_engine_module);
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#include "UEPyFoliage.h"
2+
3+
#include "Runtime/Foliage/Public/FoliageType.h"
4+
#include "Runtime/Foliage/Public/InstancedFoliageActor.h"
5+
#include "Wrappers/UEPyFFoliageInstance.h"
6+
7+
PyObject *py_ue_get_instanced_foliage_actor_for_current_level(ue_PyUObject *self, PyObject * args)
8+
{
9+
ue_py_check(self);
10+
11+
UWorld *world = ue_get_uworld(self);
12+
if (!world)
13+
return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject");
14+
15+
Py_RETURN_UOBJECT(AInstancedFoliageActor::GetInstancedFoliageActorForCurrentLevel(world, true));
16+
}
17+
18+
PyObject *py_ue_get_instanced_foliage_actor_for_level(ue_PyUObject *self, PyObject * args)
19+
{
20+
ue_py_check(self);
21+
22+
ULevel *level = ue_py_check_type<ULevel>(self);
23+
if (!level)
24+
return PyErr_Format(PyExc_Exception, "uobject is not a ULevel");
25+
26+
Py_RETURN_UOBJECT(AInstancedFoliageActor::GetInstancedFoliageActorForLevel(level, true));
27+
}
28+
29+
PyObject *py_ue_get_foliage_types(ue_PyUObject *self, PyObject * args)
30+
{
31+
ue_py_check(self);
32+
33+
AInstancedFoliageActor *foliage_actor = ue_py_check_type<AInstancedFoliageActor>(self);
34+
if (!foliage_actor)
35+
return PyErr_Format(PyExc_Exception, "uobject is not a AInstancedFoliageActor");
36+
37+
PyObject *py_list = PyList_New(0);
38+
39+
TArray<UFoliageType *> FoliageTypes;
40+
41+
foliage_actor->FoliageMeshes.GetKeys(FoliageTypes);
42+
43+
for (UFoliageType *FoliageType : FoliageTypes)
44+
{
45+
PyList_Append(py_list, (PyObject*)ue_get_python_uobject(FoliageType));
46+
}
47+
48+
return py_list;
49+
}
50+
51+
#if WITH_EDITOR
52+
PyObject *py_ue_get_foliage_instances(ue_PyUObject *self, PyObject * args)
53+
{
54+
ue_py_check(self);
55+
56+
PyObject *py_foliage_type;
57+
58+
if (!PyArg_ParseTuple(args, "O:get_foliage_instances", &py_foliage_type))
59+
{
60+
return nullptr;
61+
}
62+
63+
AInstancedFoliageActor *foliage_actor = ue_py_check_type<AInstancedFoliageActor>(self);
64+
if (!foliage_actor)
65+
return PyErr_Format(PyExc_Exception, "uobject is not a AInstancedFoliageActor");
66+
67+
UFoliageType *foliage_type = ue_py_check_type<UFoliageType>(py_foliage_type);
68+
if (!foliage_type)
69+
return PyErr_Format(PyExc_Exception, "argument is not a UFoliageType");
70+
71+
if (!foliage_actor->FoliageMeshes.Contains(foliage_type))
72+
{
73+
return PyErr_Format(PyExc_Exception, "specified UFoliageType not found in AInstancedFoliageActor");
74+
}
75+
76+
FFoliageMeshInfo& info = foliage_actor->FoliageMeshes[foliage_type].Get();
77+
78+
PyObject *py_list = PyList_New(0);
79+
80+
for (FFoliageInstance& instance : info.Instances)
81+
{
82+
PyList_Append(py_list, py_ue_new_ffoliage_instance(instance));
83+
}
84+
85+
return py_list;
86+
}
87+
88+
89+
PyObject *py_ue_add_foliage_asset(ue_PyUObject *self, PyObject * args)
90+
{
91+
92+
ue_py_check(self);
93+
94+
PyObject *py_uobject;
95+
96+
if (!PyArg_ParseTuple(args, "O:add_foliage_asset", &py_uobject))
97+
{
98+
return nullptr;
99+
}
100+
101+
UWorld *world = ue_get_uworld(self);
102+
if (!world)
103+
return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject");
104+
105+
UObject *u_object = ue_py_check_type<UObject>(py_uobject);
106+
if (!u_object)
107+
return PyErr_Format(PyExc_Exception, "argument is not a UObject");
108+
109+
UFoliageType *foliage_type = nullptr;
110+
111+
AInstancedFoliageActor *ifa = AInstancedFoliageActor::GetInstancedFoliageActorForCurrentLevel(world, true);
112+
if (u_object->IsA<UStaticMesh>())
113+
{
114+
foliage_type = ifa->GetLocalFoliageTypeForMesh((UStaticMesh *)u_object);
115+
if (!foliage_type)
116+
{
117+
ifa->AddMesh((UStaticMesh *)u_object, &foliage_type);
118+
}
119+
}
120+
else if (u_object->IsA<UFoliageType>())
121+
{
122+
foliage_type = (UFoliageType *)u_object;
123+
ifa->AddFoliageType(foliage_type);
124+
125+
}
126+
127+
if (!foliage_type)
128+
return PyErr_Format(PyExc_Exception, "unable to add foliage asset");
129+
130+
Py_RETURN_UOBJECT(foliage_type);
131+
132+
}
133+
#endif
134+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#include "UEPyModule.h"
4+
5+
PyObject *py_ue_get_instanced_foliage_actor_for_current_level(ue_PyUObject *, PyObject *);
6+
PyObject *py_ue_get_instanced_foliage_actor_for_level(ue_PyUObject *, PyObject *);
7+
PyObject *py_ue_get_foliage_types(ue_PyUObject *, PyObject *);
8+
#if WITH_EDITOR
9+
PyObject *py_ue_get_foliage_instances(ue_PyUObject *, PyObject *);
10+
PyObject *py_ue_add_foliage_asset(ue_PyUObject *, PyObject *);
11+
#endif

Source/UnrealEnginePython/Private/UObject/UEPyWorld.cpp

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include "UEPyWorld.h"
22

33
#include "Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h"
4-
#include "Runtime/Foliage/Public/FoliageType.h"
5-
#include "Runtime/Foliage/Public/InstancedFoliageActor.h"
64
#include "EngineUtils.h"
75
#include "Kismet/GameplayStatics.h"
86

@@ -316,61 +314,3 @@ PyObject *py_ue_set_current_level(ue_PyUObject *self, PyObject * args)
316314
Py_RETURN_FALSE;
317315
}
318316

319-
PyObject *py_ue_get_instanced_foliage_actor_for_current_level(ue_PyUObject *self, PyObject * args)
320-
{
321-
ue_py_check(self);
322-
323-
UWorld *world = ue_get_uworld(self);
324-
if (!world)
325-
return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject");
326-
327-
Py_RETURN_UOBJECT(AInstancedFoliageActor::GetInstancedFoliageActorForCurrentLevel(world, true));
328-
}
329-
330-
#if WITH_EDITOR
331-
PyObject *py_ue_add_foliage_asset(ue_PyUObject *self, PyObject * args)
332-
{
333-
334-
ue_py_check(self);
335-
336-
PyObject *py_uobject;
337-
338-
if (!PyArg_ParseTuple(args, "O:add_foliage_asset", &py_uobject))
339-
{
340-
return nullptr;
341-
}
342-
343-
UWorld *world = ue_get_uworld(self);
344-
if (!world)
345-
return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject");
346-
347-
UObject *u_object = ue_py_check_type<UObject>(py_uobject);
348-
if (!u_object)
349-
return PyErr_Format(PyExc_Exception, "argument is not a UObject");
350-
351-
UFoliageType *foliage_type = nullptr;
352-
353-
AInstancedFoliageActor *ifa = AInstancedFoliageActor::GetInstancedFoliageActorForCurrentLevel(world, true);
354-
if (u_object->IsA<UStaticMesh>())
355-
{
356-
foliage_type = ifa->GetLocalFoliageTypeForMesh((UStaticMesh *)u_object);
357-
if (!foliage_type)
358-
{
359-
ifa->AddMesh((UStaticMesh *)u_object, &foliage_type);
360-
}
361-
}
362-
else if (u_object->IsA<UFoliageType>())
363-
{
364-
foliage_type = (UFoliageType *)u_object;
365-
ifa->AddFoliageType(foliage_type);
366-
367-
}
368-
369-
if (!foliage_type)
370-
return PyErr_Format(PyExc_Exception, "unable to add foliage asset");
371-
372-
Py_RETURN_UOBJECT(foliage_type);
373-
374-
}
375-
#endif
376-

Source/UnrealEnginePython/Private/UObject/UEPyWorld.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,3 @@ PyObject *py_ue_set_current_level(ue_PyUObject *, PyObject *);
3030

3131
PyObject *py_ue_get_world_type(ue_PyUObject *, PyObject *);
3232

33-
PyObject *py_ue_get_instanced_foliage_actor_for_current_level(ue_PyUObject *, PyObject *);
34-
#if WITH_EDITOR
35-
PyObject *py_ue_add_foliage_asset(ue_PyUObject *, PyObject *);
36-
#endif
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include "UEPyFFoliageInstance.h"
2+
3+
#include "Wrappers/UEPyFVector.h"
4+
#include "Wrappers/UEPyFRotator.h"
5+
6+
static PyObject *ue_PyFFoliageInstance_str(ue_PyFFoliageInstance *self)
7+
{
8+
return PyUnicode_FromFormat("<unreal_engine.FFoliageInstance %p>",
9+
&self->instance);
10+
}
11+
12+
static PyObject *py_ue_ffoliage_instance_get_location(ue_PyFFoliageInstance *self, void *closure)
13+
{
14+
return py_ue_new_fvector(self->instance.Location);
15+
}
16+
17+
static PyObject *py_ue_ffoliage_instance_get_draw_scale3d(ue_PyFFoliageInstance *self, void *closure)
18+
{
19+
return py_ue_new_fvector(self->instance.DrawScale3D);
20+
}
21+
22+
static PyObject *py_ue_ffoliage_instance_get_flags(ue_PyFFoliageInstance *self, void *closure)
23+
{
24+
return PyLong_FromUnsignedLong(self->instance.Flags);
25+
}
26+
27+
static PyObject *py_ue_ffoliage_instance_get_pre_align_rotation(ue_PyFFoliageInstance *self, void *closure)
28+
{
29+
return py_ue_new_frotator(self->instance.PreAlignRotation);
30+
}
31+
32+
static PyObject *py_ue_ffoliage_instance_get_rotation(ue_PyFFoliageInstance *self, void *closure)
33+
{
34+
return py_ue_new_frotator(self->instance.Rotation);
35+
}
36+
37+
static PyObject *py_ue_ffoliage_instance_get_zoffset(ue_PyFFoliageInstance *self, void *closure)
38+
{
39+
return PyFloat_FromDouble(self->instance.ZOffset);
40+
}
41+
42+
43+
static PyGetSetDef ue_PyFFoliageInstance_getseters[] = {
44+
{ (char *)"location", (getter)py_ue_ffoliage_instance_get_location, nullptr, (char *)"", NULL },
45+
{ (char *)"draw_scale3d", (getter)py_ue_ffoliage_instance_get_draw_scale3d, nullptr, (char *)"", NULL },
46+
{ (char *)"flags", (getter)py_ue_ffoliage_instance_get_flags, nullptr, (char *)"", NULL },
47+
{ (char *)"pre_align_rotation", (getter)py_ue_ffoliage_instance_get_pre_align_rotation, nullptr, (char *)"", NULL },
48+
{ (char *)"rotation", (getter)py_ue_ffoliage_instance_get_rotation, nullptr, (char *)"", NULL },
49+
{ (char *)"zoffset", (getter)py_ue_ffoliage_instance_get_zoffset, nullptr, (char *)"", NULL },
50+
{ NULL } /* Sentinel */
51+
};
52+
53+
static PyTypeObject ue_PyFFoliageInstanceType = {
54+
PyVarObject_HEAD_INIT(NULL, 0)
55+
"unreal_engine.FFoliageInstance", /* tp_name */
56+
sizeof(ue_PyFFoliageInstance), /* tp_basicsize */
57+
0, /* tp_itemsize */
58+
0, /* tp_dealloc */
59+
0, /* tp_print */
60+
0, /* tp_getattr */
61+
0, /* tp_setattr */
62+
0, /* tp_reserved */
63+
0, /* tp_repr */
64+
0, /* tp_as_number */
65+
0, /* tp_as_sequence */
66+
0, /* tp_as_mapping */
67+
0, /* tp_hash */
68+
0, /* tp_call */
69+
(reprfunc)ue_PyFFoliageInstance_str, /* tp_str */
70+
0, /* tp_getattro */
71+
0, /* tp_setattro */
72+
0, /* tp_as_buffer */
73+
#if PY_MAJOR_VERSION < 3
74+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
75+
#else
76+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
77+
#endif
78+
"Unreal Engine FFoliageInstance", /* tp_doc */
79+
0, /* tp_traverse */
80+
0, /* tp_clear */
81+
0, /* tp_richcompare */
82+
0, /* tp_weaklistoffset */
83+
0, /* tp_iter */
84+
0, /* tp_iternext */
85+
0, /* tp_methods */
86+
0,
87+
ue_PyFFoliageInstance_getseters,
88+
};
89+
90+
void ue_python_init_ffoliage_instance(PyObject *ue_module)
91+
{
92+
ue_PyFFoliageInstanceType.tp_new = PyType_GenericNew;
93+
94+
if (PyType_Ready(&ue_PyFFoliageInstanceType) < 0)
95+
return;
96+
97+
Py_INCREF(&ue_PyFFoliageInstanceType);
98+
PyModule_AddObject(ue_module, "FoliageInstance", (PyObject *)&ue_PyFFoliageInstanceType);
99+
}
100+
101+
PyObject *py_ue_new_ffoliage_instance(FFoliageInstance instance)
102+
{
103+
ue_PyFFoliageInstance *ret = (ue_PyFFoliageInstance *)PyObject_New(ue_PyFFoliageInstance, &ue_PyFFoliageInstanceType);
104+
ret->instance = instance;
105+
return (PyObject *)ret;
106+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
#include "UnrealEnginePython.h"
3+
4+
#include "InstancedFoliage.h"
5+
6+
typedef struct
7+
{
8+
PyObject_HEAD
9+
FFoliageInstance instance;
10+
} ue_PyFFoliageInstance;
11+
12+
void ue_python_init_ffoliage_instance(PyObject *);
13+
14+
PyObject *py_ue_new_ffoliage_instance(FFoliageInstance instance);

0 commit comments

Comments
 (0)