Skip to content

Commit d167ca0

Browse files
author
Roberto De Ioris
committed
2 parents de9cafa + f8f120b commit d167ca0

File tree

2 files changed

+133
-9
lines changed

2 files changed

+133
-9
lines changed

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Once the plugin is installed and enabled, you get access to the 'PythonConsole'
2424

2525
All of the exposed engine features are under the 'unreal_engine' virtual module (it is completely coded in c into the plugin, so do not expect to run 'import unreal_engine' from a standard python shell)
2626

27-
The currently supported Unreal Engine versions are 4.12, 4.13, 4.14, 4.15, 4.16, 4.17 and 4.18.
27+
The currently supported Unreal Engine versions are 4.12, 4.13, 4.14, 4.15, 4.16, 4.17, 4.18 and 4.19
2828

2929
We support official python.org releases as well as IntelPython and Anaconda distributions.
3030

@@ -487,6 +487,30 @@ To access the fields of a struct just call the fields() method.
487487

488488
A good example of struct usage is available here: https://github.com/20tab/UnrealEnginePython/blob/master/docs/Settings.md
489489

490+
As structs are passed by value, you need to pay attention when manipulating structs fields that are structs by themselves:
491+
492+
```python
493+
from unreal_engine.structs import TerrificStruct, DumbStruct
494+
495+
ts = TerrificStruct()
496+
ts.dumb = DumbStruct(Foo=17, Bar=22)
497+
498+
# will not modify the original DumbStruct but a copy of it !!!
499+
ts.dumb.Foo = 22
500+
```
501+
502+
You can eventually force structs to be passed by ref (extremely dangerous as the internal C pointer could be a dangling one) using the ref() function:
503+
504+
```python
505+
from unreal_engine.structs import TerrificStruct, DumbStruct
506+
507+
ts = TerrificStruct()
508+
ts.dumb = DumbStruct(Foo=17, Bar=22)
509+
510+
# ref() will return a pointer to a struct
511+
ts.ref().dumb.foo().Foo = 22
512+
```
513+
490514
The ue_site.py file
491515
-------------------
492516

@@ -808,15 +832,9 @@ Memory management
808832

809833
Dealing with 2 different GC's is really challenging.
810834

811-
PyActor, PyPawn and PythonComponent automatically DECREF's the mapped classes. This should be enough unless you hold references
812-
in the python modules themselves. As this would be a bad programming practice, the current approach should be safe enough.
813-
814-
In addition to this, every time a uobject has to return its UObject mapping, it checks for its validity and safety:
835+
Starting from release 20180226 a new memory management system has been added (FUnrealEnginePythonHouseKeeper, available here https://github.com/20tab/UnrealEnginePython/blob/master/Source/UnrealEnginePython/Public/PythonHouseKeeper.h). This new system is completely integrated with the Unreal Engine reflection-based GC and will hold track of each ue_PyUObject abd the related UObject to understand when a python object can be safely destroyed.
815836

816-
```c
817-
#define ue_py_check(py_u) if (!py_u->ue_object || !py_u->ue_object->IsValidLowLevel() || py_u->ue_object->IsPendingKillOrUnreachable())\
818-
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state")
819-
```
837+
The same system works for delegates, as well as Slate.
820838

821839

822840
Unit Testing

Source/UnrealEnginePython/Private/Fbx/UEPyFbxObject.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,108 @@ static PyObject *py_ue_fbx_object_key_get_seconds(ue_PyFbxObject *self, PyObject
138138
return PyFloat_FromDouble(fbx_anim_curve->KeyGetTime(index).GetSecondDouble());
139139
}
140140

141+
static PyObject *py_ue_fbx_object_key_get_left_tangent(ue_PyFbxObject *self, PyObject *args) {
142+
int index;
143+
if (!PyArg_ParseTuple(args, "i", &index)) {
144+
return nullptr;
145+
}
146+
FbxAnimCurve *fbx_anim_curve = FbxCast<FbxAnimCurve>(self->fbx_object);
147+
if (!fbx_anim_curve)
148+
return PyErr_Format(PyExc_Exception, "object is not a FbxAnimCurve");
149+
return PyFloat_FromDouble(fbx_anim_curve->KeyGetLeftDerivative(index));
150+
}
151+
152+
static PyObject *py_ue_fbx_object_key_get_right_tangent(ue_PyFbxObject *self, PyObject *args) {
153+
int index;
154+
if (!PyArg_ParseTuple(args, "i", &index)) {
155+
return nullptr;
156+
}
157+
FbxAnimCurve *fbx_anim_curve = FbxCast<FbxAnimCurve>(self->fbx_object);
158+
if (!fbx_anim_curve)
159+
return PyErr_Format(PyExc_Exception, "object is not a FbxAnimCurve");
160+
return PyFloat_FromDouble(fbx_anim_curve->KeyGetRightDerivative(index));
161+
}
162+
163+
static PyObject *py_ue_fbx_object_key_get_interp_mode(ue_PyFbxObject *self, PyObject *args) {
164+
int index;
165+
if (!PyArg_ParseTuple(args, "i", &index)) {
166+
return nullptr;
167+
}
168+
FbxAnimCurve *fbx_anim_curve = FbxCast<FbxAnimCurve>(self->fbx_object);
169+
if (!fbx_anim_curve)
170+
return PyErr_Format(PyExc_Exception, "object is not a FbxAnimCurve");
171+
172+
ERichCurveInterpMode Mode = RCIM_Linear;
173+
// Convert the interpolation type from FBX to Unreal.
174+
switch (fbx_anim_curve->KeyGetInterpolation(index))
175+
{
176+
case FbxAnimCurveDef::eInterpolationCubic:
177+
Mode = RCIM_Cubic;
178+
break;
179+
180+
case FbxAnimCurveDef::eInterpolationConstant:
181+
if (fbx_anim_curve->KeyGetTangentMode(index) != (FbxAnimCurveDef::ETangentMode)FbxAnimCurveDef::eConstantStandard)
182+
{
183+
// warning not support
184+
;
185+
}
186+
Mode = RCIM_Constant;
187+
break;
188+
189+
case FbxAnimCurveDef::eInterpolationLinear:
190+
Mode = RCIM_Linear;
191+
break;
192+
}
193+
194+
return PyLong_FromUnsignedLong(uint64(Mode));
195+
}
196+
197+
static PyObject *py_ue_fbx_object_key_get_tangent_mode(ue_PyFbxObject *self, PyObject *args) {
198+
int index;
199+
if (!PyArg_ParseTuple(args, "i", &index)) {
200+
return nullptr;
201+
}
202+
FbxAnimCurve *fbx_anim_curve = FbxCast<FbxAnimCurve>(self->fbx_object);
203+
if (!fbx_anim_curve)
204+
return PyErr_Format(PyExc_Exception, "object is not a FbxAnimCurve");
205+
206+
ERichCurveTangentMode Mode = RCTM_Auto;
207+
// Convert the interpolation type from FBX to Unreal.
208+
if ( fbx_anim_curve->KeyGetInterpolation(index) ==
209+
FbxAnimCurveDef::eInterpolationCubic )
210+
{
211+
switch (fbx_anim_curve->KeyGetTangentMode(index))
212+
{
213+
// Auto tangents will now be imported as user tangents to allow the
214+
// user to modify them without inadvertently resetting other tangents
215+
// case KFbxAnimCurveDef::eTANGENT_AUTO:
216+
// if ((KFbxAnimCurveDef::eTANGENT_GENERIC_CLAMP & FbxKey.GetTangentMode(true)))
217+
// {
218+
// Mode = CIM_CurveAutoClamped;
219+
// }
220+
// else
221+
// {
222+
// Mode = CIM_CurveAuto;
223+
// }
224+
// break;
225+
case FbxAnimCurveDef::eTangentBreak:
226+
Mode = RCTM_Break;
227+
break;
228+
case FbxAnimCurveDef::eTangentAuto:
229+
Mode = RCTM_Auto;
230+
break;
231+
case FbxAnimCurveDef::eTangentUser:
232+
case FbxAnimCurveDef::eTangentTCB:
233+
Mode = RCTM_User;
234+
break;
235+
default:
236+
break;
237+
}
238+
}
239+
240+
return PyLong_FromUnsignedLong(uint64(Mode));
241+
}
242+
141243
static PyMethodDef ue_PyFbxObject_methods[] = {
142244
{ "get_member_count", (PyCFunction)py_ue_fbx_object_get_member_count, METH_VARARGS, "" },
143245
{ "get_member", (PyCFunction)py_ue_fbx_object_get_member, METH_VARARGS, "" },
@@ -153,6 +255,10 @@ static PyMethodDef ue_PyFbxObject_methods[] = {
153255
{ "key_get_count", (PyCFunction)py_ue_fbx_object_key_get_count, METH_VARARGS, "" },
154256
{ "key_get_value", (PyCFunction)py_ue_fbx_object_key_get_value, METH_VARARGS, "" },
155257
{ "key_get_seconds", (PyCFunction)py_ue_fbx_object_key_get_seconds, METH_VARARGS, "" },
258+
{ "key_get_left_tangent", (PyCFunction)py_ue_fbx_object_key_get_left_tangent, METH_VARARGS, "" },
259+
{ "key_get_right_tangent", (PyCFunction)py_ue_fbx_object_key_get_right_tangent, METH_VARARGS, "" },
260+
{ "key_get_interp_mode", (PyCFunction)py_ue_fbx_object_key_get_interp_mode, METH_VARARGS, "" },
261+
{ "key_get_tangent_mode", (PyCFunction)py_ue_fbx_object_key_get_tangent_mode, METH_VARARGS, "" },
156262
{ NULL } /* Sentinel */
157263
};
158264

0 commit comments

Comments
 (0)