Skip to content

Commit 38e0079

Browse files
author
Roberto De Ioris
committed
first round of sequencer improved patches
1 parent 24aea14 commit 38e0079

5 files changed

Lines changed: 204 additions & 25 deletions

File tree

‎Source/UnrealEnginePython/Private/UEPyModule.cpp‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,12 @@ static PyMethodDef ue_PyUObject_methods[] = {
566566
{ "sequencer_find_possessable", (PyCFunction)py_ue_sequencer_find_possessable, METH_VARARGS, "" },
567567
{ "sequencer_add_master_track", (PyCFunction)py_ue_sequencer_add_master_track, METH_VARARGS, "" },
568568

569+
{ "sequencer_add_track", (PyCFunction)py_ue_sequencer_add_track, METH_VARARGS, "" },
570+
{ "sequencer_add_actor", (PyCFunction)py_ue_sequencer_add_actor, METH_VARARGS, "" },
571+
572+
{ "sequencer_add_possessable", (PyCFunction)py_ue_sequencer_add_possessable, METH_VARARGS, "" },
573+
{ "sequencer_track_add_section", (PyCFunction)py_ue_sequencer_track_add_section, METH_VARARGS, "" },
574+
569575
// Material
570576
{ "set_material", (PyCFunction)py_ue_set_material, METH_VARARGS, "" },
571577
{ "set_material_scalar_parameter", (PyCFunction)py_ue_set_material_scalar_parameter, METH_VARARGS, "" },
@@ -610,8 +616,8 @@ void ue_pydelegates_cleanup(ue_PyUObject *self) {
610616
UE_LOG(LogPython, Warning, TEXT("Removing UPythonDelegate %p from ue_PyUObject %p mapped to UObject %p"), py_delegate, self, self->ue_object);
611617
#endif
612618
py_delegate->RemoveFromRoot();
613-
}
614619
}
620+
}
615621
self->python_delegates_gc->clear();
616622
delete self->python_delegates_gc;
617623
self->python_delegates_gc = nullptr;

‎Source/UnrealEnginePython/Private/UEPySequencer.cpp‎

Lines changed: 178 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@
77
#include "Runtime/MovieScene/Public/MovieSceneNameableTrack.h"
88
#include "Runtime/LevelSequence/Public/LevelSequence.h"
99

10+
#if WITH_EDITOR
11+
#include "Editor/Sequencer/Public/ISequencer.h"
12+
#include "Editor/Sequencer/Public/ISequencerModule.h"
13+
#endif
14+
15+
static void movie_update(UMovieSceneSequence *movie) {
16+
#if WITH_EDITOR
17+
ISequencerModule& sequencer_module = FModuleManager::LoadModuleChecked<ISequencerModule>("Sequencer");
18+
FSequencerInitParams sequencer_params;
19+
sequencer_params.RootSequence = movie;
20+
TSharedRef<ISequencer> sequencer = sequencer_module.CreateSequencer(sequencer_params);
21+
sequencer->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::Unknown);
22+
#endif
23+
}
24+
1025
PyObject *py_ue_sequencer_possessable_tracks(ue_PyUObject *self, PyObject * args) {
1126

1227
ue_py_check(self);
@@ -73,15 +88,92 @@ PyObject *py_ue_sequencer_find_possessable(ue_PyUObject *self, PyObject * args)
7388
UObject *u_obj = seq->FindPossessableObject(f_guid, seq);
7489
if (!u_obj)
7590
return PyErr_Format(PyExc_Exception, "unable to find uobject with GUID \"%s\"", guid);
76-
77-
PyObject *ret = (PyObject *) ue_get_python_wrapper(u_obj);
91+
92+
PyObject *ret = (PyObject *)ue_get_python_wrapper(u_obj);
7893
if (!ret)
7994
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state");
8095

8196
Py_INCREF(ret);
8297
return ret;
8398
}
8499

100+
PyObject *py_ue_sequencer_add_possessable(ue_PyUObject *self, PyObject * args) {
101+
102+
ue_py_check(self);
103+
104+
PyObject *py_obj;
105+
if (!PyArg_ParseTuple(args, "O:sequencer_add_possessable", &py_obj)) {
106+
return NULL;
107+
}
108+
109+
if (!self->ue_object->IsA<ULevelSequence>())
110+
return PyErr_Format(PyExc_Exception, "uobject is not a LevelSequence");
111+
112+
ue_PyUObject *py_ue_obj = ue_is_pyuobject(py_obj);
113+
if (!py_ue_obj)
114+
return PyErr_Format(PyExc_Exception, "argument is not a uobject");
115+
116+
ULevelSequence *seq = (ULevelSequence *)self->ue_object;
117+
118+
FString name = py_ue_obj->ue_object->GetName();
119+
AActor *actor = Cast<AActor>(py_ue_obj->ue_object);
120+
if (actor)
121+
name = actor->GetActorLabel();
122+
123+
FGuid new_guid = seq->MovieScene->AddPossessable(name, py_ue_obj->ue_object->GetClass());
124+
if (!new_guid.IsValid()) {
125+
return PyErr_Format(PyExc_Exception, "unable to possess object");
126+
}
127+
128+
seq->BindPossessableObject(new_guid, *(py_ue_obj->ue_object), py_ue_obj->ue_object->GetWorld());
129+
130+
movie_update(seq);
131+
132+
return PyUnicode_FromString(TCHAR_TO_UTF8(*new_guid.ToString()));
133+
}
134+
135+
PyObject *py_ue_sequencer_add_actor(ue_PyUObject *self, PyObject * args) {
136+
137+
ue_py_check(self);
138+
139+
PyObject *py_obj;
140+
if (!PyArg_ParseTuple(args, "O:sequencer_add_actor", &py_obj)) {
141+
return NULL;
142+
}
143+
144+
if (!self->ue_object->IsA<ULevelSequence>())
145+
return PyErr_Format(PyExc_Exception, "uobject is not a LevelSequence");
146+
147+
ue_PyUObject *py_ue_obj = ue_is_pyuobject(py_obj);
148+
if (!py_ue_obj)
149+
return PyErr_Format(PyExc_Exception, "argument is not a uobject");
150+
151+
if (!py_ue_obj->ue_object->IsA<AActor>())
152+
return PyErr_Format(PyExc_Exception, "argument is not an actor");
153+
154+
ULevelSequence *seq = (ULevelSequence *)self->ue_object;
155+
156+
TArray<TWeakObjectPtr<AActor>> actors;
157+
actors.Add((AActor *)py_ue_obj->ue_object);
158+
159+
ISequencerModule& sequencer_module = FModuleManager::LoadModuleChecked<ISequencerModule>("Sequencer");
160+
FSequencerInitParams sequencer_params;
161+
sequencer_params.RootSequence = seq;
162+
sequencer_params.bEditWithinLevelEditor = false;
163+
sequencer_params.ToolkitHost = nullptr;
164+
165+
FSequencerViewParams view_params;
166+
view_params.InitialScrubPosition = 0;
167+
sequencer_params.ViewParams = view_params;
168+
169+
TSharedRef<ISequencer> sequencer = sequencer_module.CreateSequencer(sequencer_params);
170+
171+
sequencer->AddActors(actors);
172+
173+
Py_INCREF(Py_None);
174+
return Py_None;
175+
}
176+
85177
PyObject *py_ue_sequencer_master_tracks(ue_PyUObject *self, PyObject * args) {
86178

87179
ue_py_check(self);
@@ -119,19 +211,9 @@ PyObject *py_ue_sequencer_possessables(ue_PyUObject *self, PyObject * args) {
119211
UMovieScene *scene = seq->GetMovieScene();
120212

121213
PyObject *py_possessables = PyList_New(0);
122-
for (int32 i = 0; i < scene->GetPossessableCount();i++) {
214+
for (int32 i = 0; i < scene->GetPossessableCount(); i++) {
123215
FMovieScenePossessable possessable = scene->GetPossessable(i);
124-
PyObject *py_possessable = PyTuple_New(3);
125-
PyTuple_SetItem(py_possessable, 0, PyUnicode_FromString(TCHAR_TO_UTF8(*possessable.GetGuid().ToString())));
126-
PyTuple_SetItem(py_possessable, 1, PyUnicode_FromString(TCHAR_TO_UTF8(*possessable.GetName())));
127-
UClass *u_class = (UClass *)possessable.GetPossessedObjectClass();
128-
ue_PyUObject *ret = ue_get_python_wrapper(u_class);
129-
if (!ret) {
130-
// here we will leak memory :(
131-
Py_DECREF(py_possessables);
132-
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state");
133-
}
134-
PyTuple_SetItem(py_possessable, 2, (PyObject *)ret);
216+
PyObject *py_possessable = py_ue_new_uscriptstruct(possessable.StaticStruct(), (uint8 *)&possessable);
135217
PyList_Append(py_possessables, py_possessable);
136218
}
137219

@@ -217,6 +299,37 @@ PyObject *py_ue_sequencer_track_sections(ue_PyUObject *self, PyObject * args) {
217299
return py_sections;
218300
}
219301

302+
PyObject *py_ue_sequencer_track_add_section(ue_PyUObject *self, PyObject * args) {
303+
304+
ue_py_check(self);
305+
306+
PyObject *obj;
307+
if (!PyArg_ParseTuple(args, "O:sequencer_track_add_section", &obj)) {
308+
return NULL;
309+
}
310+
311+
if (!self->ue_object->IsA<UMovieSceneTrack>())
312+
return PyErr_Format(PyExc_Exception, "uobject is not a UMovieSceneTrack");
313+
314+
UMovieSceneTrack *track = (UMovieSceneTrack *)self->ue_object;
315+
316+
ue_PyUObject *py_obj = ue_is_pyuobject(obj);
317+
if (!py_obj)
318+
return PyErr_Format(PyExc_Exception, "argument is not a uobject");
319+
320+
if (!py_obj->ue_object->IsA<UMovieSceneSection>())
321+
return PyErr_Format(PyExc_Exception, "uobject is not a UMovieSceneSection");
322+
323+
UMovieSceneSection *new_section = (UMovieSceneSection *)py_obj->ue_object;
324+
325+
track->AddSection(*new_section);
326+
327+
movie_update((UMovieSceneSequence *)track->GetOuter());
328+
329+
Py_INCREF(Py_None);
330+
return Py_None;
331+
}
332+
220333
PyObject *py_ue_sequencer_add_master_track(ue_PyUObject *self, PyObject * args) {
221334

222335
ue_py_check(self);
@@ -252,6 +365,54 @@ PyObject *py_ue_sequencer_add_master_track(ue_PyUObject *self, PyObject * args)
252365
if (!ret)
253366
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state");
254367

368+
movie_update(seq);
369+
370+
Py_INCREF(ret);
371+
return ret;
372+
}
373+
374+
PyObject *py_ue_sequencer_add_track(ue_PyUObject *self, PyObject * args) {
375+
376+
ue_py_check(self);
377+
378+
PyObject *obj;
379+
char *guid;
380+
if (!PyArg_ParseTuple(args, "Os:sequencer_add_track", &obj, &guid)) {
381+
return NULL;
382+
}
383+
384+
if (!self->ue_object->IsA<ULevelSequence>())
385+
return PyErr_Format(PyExc_Exception, "uobject is not a LevelSequence");
386+
387+
ULevelSequence *seq = (ULevelSequence *)self->ue_object;
388+
UMovieScene *scene = seq->GetMovieScene();
389+
390+
ue_PyUObject *py_obj = ue_is_pyuobject(obj);
391+
if (!py_obj)
392+
return PyErr_Format(PyExc_Exception, "argument is not a uobject");
393+
394+
if (!py_obj->ue_object->IsA<UClass>())
395+
return PyErr_Format(PyExc_Exception, "uobject is not a UClass");
396+
397+
UClass *u_class = (UClass *)py_obj->ue_object;
398+
399+
if (!u_class->IsChildOf<UMovieSceneTrack>())
400+
return PyErr_Format(PyExc_Exception, "uobject is not a UMovieSceneTrack class");
401+
402+
FGuid f_guid;
403+
if (!FGuid::Parse(FString(guid), f_guid)) {
404+
return PyErr_Format(PyExc_Exception, "invalid guid");
405+
}
406+
UMovieSceneTrack *track = scene->AddTrack(u_class, f_guid);
407+
if (!track)
408+
return PyErr_Format(PyExc_Exception, "unable to create new track");
409+
410+
PyObject *ret = (PyObject *)ue_get_python_wrapper(track);
411+
if (!ret)
412+
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state");
413+
414+
movie_update(seq);
415+
255416
Py_INCREF(ret);
256417
return ret;
257418
}
@@ -275,6 +436,8 @@ PyObject *py_ue_sequencer_set_display_name(ue_PyUObject *self, PyObject * args)
275436
return PyErr_Format(PyExc_Exception, "the uobject does not expose the SetDisplayName() method");
276437
}
277438

439+
//movie_update((UMovieSceneSequence *)track->GetOuter());
440+
278441
Py_INCREF(Py_None);
279442
return Py_None;
280443
}
@@ -288,7 +451,7 @@ PyObject *py_ue_sequencer_get_display_name(ue_PyUObject *self, PyObject * args)
288451
FText name = track->GetDefaultDisplayName();
289452
return PyUnicode_FromString(TCHAR_TO_UTF8(*name.ToString()));
290453
}
291-
454+
292455
return PyErr_Format(PyExc_Exception, "the uobject does not expose the GetDefaultDisplayName() method");
293456
}
294457
#endif

‎Source/UnrealEnginePython/Private/UEPySequencer.h‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,10 @@ PyObject *py_ue_sequencer_possessables(ue_PyUObject *, PyObject *);
1717
PyObject *py_ue_sequencer_find_possessable(ue_PyUObject *, PyObject *);
1818

1919
PyObject *py_ue_sequencer_add_master_track(ue_PyUObject *, PyObject *);
20+
21+
PyObject *py_ue_sequencer_add_possessable(ue_PyUObject *, PyObject *);
22+
23+
PyObject *py_ue_sequencer_track_add_section(ue_PyUObject *, PyObject *);
24+
25+
PyObject *py_ue_sequencer_add_track(ue_PyUObject *, PyObject *);
26+
PyObject *py_ue_sequencer_add_actor(ue_PyUObject *, PyObject *);

‎Source/UnrealEnginePython/Public/PythonComponent.cpp‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void UPythonComponent::BeginPlay()
9595
// ...
9696

9797
InitializePythonComponent();
98-
98+
9999
}
100100

101101

@@ -383,12 +383,12 @@ UObject *UPythonComponent::CallPythonComponentMethodObject(FString method_name,
383383
ret = PyObject_CallMethod(py_component_instance, TCHAR_TO_UTF8(*method_name), NULL);
384384
}
385385
else {
386-
PyObject *py_uobject = (PyObject *)ue_get_python_wrapper(arg);
387-
if (!py_uobject) {
388-
unreal_engine_py_log_error();
389-
return nullptr;
390-
}
391-
ret = PyObject_CallMethod(py_component_instance, TCHAR_TO_UTF8(*method_name), (char *)"O", py_uobject);
386+
PyObject *py_arg_uobject = (PyObject *)ue_get_python_wrapper(arg);
387+
if (!py_arg_uobject) {
388+
unreal_engine_py_log_error();
389+
return nullptr;
390+
}
391+
ret = PyObject_CallMethod(py_component_instance, TCHAR_TO_UTF8(*method_name), (char *)"O", py_arg_uobject);
392392
}
393393

394394
if (!ret) {
@@ -466,7 +466,7 @@ UPythonComponent::~UPythonComponent()
466466
}
467467
#endif
468468
Py_XDECREF(py_component_instance);
469-
469+
470470
#if defined(UEPY_MEMORY_DEBUG)
471471
UE_LOG(LogPython, Warning, TEXT("Python UActorComponent %p (mapped to %p) wrapper XDECREF'ed"), this, py_uobject ? py_uobject->ue_object : nullptr);
472472
#endif

‎Source/UnrealEnginePython/UnrealEnginePython.Build.cs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ public UnrealEnginePython(TargetInfo Target)
8989
"UnrealEd",
9090
"LevelEditor",
9191
"BlueprintGraph",
92-
"Projects"
92+
"Projects",
93+
"Sequencer",
94+
"SequencerWidgets",
95+
"UMGEditor",
9396
});
9497
}
9598

0 commit comments

Comments
 (0)