1515#include " Tracks/MovieSceneCameraCutTrack.h"
1616#if ENGINE_MINOR_VERSION < 20
1717#include " Sections/IKeyframeSection.h"
18+ #else
19+ #include " Wrappers/UEPyFFrameNumber.h"
1820#endif
1921#include " Sections/MovieSceneFloatSection.h"
2022#include " Sections/MovieSceneBoolSection.h"
3537#include " Runtime/LevelSequence/Public/LevelSequence.h"
3638#include " Engine/World.h"
3739
40+
41+ #if ENGINE_MINOR_VERSION >= 20
42+ static bool magic_get_frame_number (UMovieScene *MovieScene, PyObject *py_obj, FFrameNumber *dest)
43+ {
44+ ue_PyFFrameNumber *py_frame_number = py_ue_is_fframe_number (py_obj);
45+ if (py_frame_number)
46+ {
47+ *dest = py_frame_number->frame_number ;
48+ return true ;
49+ }
50+
51+ if (PyNumber_Check (py_obj))
52+ {
53+ PyObject *f_value = PyNumber_Float (py_obj);
54+ float value = PyFloat_AsDouble (f_value);
55+ Py_DECREF (f_value);
56+ *dest = MovieScene->GetTickResolution ().AsFrameNumber (value);
57+ return true ;
58+ }
59+
60+ return false ;
61+
62+ }
63+ #endif
64+
3865#if WITH_EDITOR
3966PyObject *py_ue_sequencer_changed (ue_PyUObject *self, PyObject * args)
4067{
@@ -745,44 +772,111 @@ PyObject *py_ue_sequencer_set_playback_range(ue_PyUObject *self, PyObject * args
745772
746773 scene->SetPlaybackRange (start_time, end_time);
747774#else
748- unsigned int start_frame ;
749- int duration ;
750- if (!PyArg_ParseTuple (args, " Ii :sequencer_set_playback_range" , &start_frame , &duration ))
775+ PyObject *py_start ;
776+ PyObject *py_end ;
777+ if (!PyArg_ParseTuple (args, " OO :sequencer_set_playback_range" , &py_start , &py_end ))
751778 {
752779 return nullptr ;
753780 }
754781
755- FFrameNumber StartFrame ((int32)start_frame);
756- scene->SetPlaybackRange (StartFrame, duration);
782+ FFrameNumber FrameStart;
783+ FFrameNumber FrameEnd;
784+
785+ if (!magic_get_frame_number (scene, py_start, &FrameStart))
786+ return PyErr_Format (PyExc_Exception, " range must use float or FrameNumber" );
787+
788+ if (!magic_get_frame_number (scene, py_end, &FrameEnd))
789+ return PyErr_Format (PyExc_Exception, " range must use float or FrameNumber" );
790+
791+ scene->SetPlaybackRange (TRange<FFrameNumber>::Inclusive (FrameStart, FrameEnd));
792+
757793#endif
758794
759795 Py_RETURN_NONE;
760796}
761797
762-
763- PyObject *py_ue_sequencer_section_add_key (ue_PyUObject *self, PyObject * args)
798+ PyObject *py_ue_sequencer_set_section_range (ue_PyUObject *self, PyObject * args)
764799{
765800
766801 ue_py_check (self);
767802
768- #if ENGINE_MINOR_VERSION >= 20
769- return PyErr_Format (PyExc_Exception, " for engine >= 4.20 you need to use the reflection api" );
803+ UMovieSceneSection *section = ue_py_check_type<UMovieSceneSection>(self);
804+ if (!section)
805+ return PyErr_Format (PyExc_Exception, " uobject is not a MovieSceneSection" );
806+
807+ #if ENGINE_MINOR_VERSION < 20
808+ float start_time;
809+ float end_time;
810+ if (!PyArg_ParseTuple (args, " ff:sequencer_set_section_range" , &start_time, &end_time))
811+ {
812+ return nullptr ;
813+ }
814+
815+ section->StartTime = start_time;
816+ section->EndTime = end_time;
770817#else
818+ PyObject *py_start;
819+ PyObject *py_end;
820+ if (!PyArg_ParseTuple (args, " OO:sequencer_set_section_range" , &py_start, &py_end))
821+ {
822+ return nullptr ;
823+ }
824+
825+ UMovieSceneTrack *Track = section->GetTypedOuter <UMovieSceneTrack>();
826+ if (!Track)
827+ return PyErr_Format (PyExc_Exception, " unable to retrieve track from section" );
828+ UMovieScene *MovieScene = Track->GetTypedOuter <UMovieScene>();
829+ if (!MovieScene)
830+ return PyErr_Format (PyExc_Exception, " unable to retrieve scene from section" );
831+
832+ FFrameNumber FrameStart;
833+ FFrameNumber FrameEnd;
834+
835+ if (!magic_get_frame_number (MovieScene, py_start, &FrameStart))
836+ return PyErr_Format (PyExc_Exception, " range must use float or FrameNumber" );
837+
838+ if (!magic_get_frame_number (MovieScene, py_end, &FrameEnd))
839+ return PyErr_Format (PyExc_Exception, " range must use float or FrameNumber" );
840+
841+ section->SetRange (TRange<FFrameNumber>::Inclusive (FrameStart, FrameEnd));
842+ #endif
843+
844+ Py_RETURN_NONE;
845+ }
846+
771847
848+ PyObject *py_ue_sequencer_section_add_key (ue_PyUObject *self, PyObject * args)
849+ {
772850
851+ ue_py_check (self);
852+
853+ float time;
773854 PyObject *py_value;
774855 int interpolation = 0 ;
775856 PyObject *py_unwind = nullptr ;
776- float time;
857+
777858 if (!PyArg_ParseTuple (args, " fO|iO:sequencer_section_add_key" , &time, &py_value, &interpolation, &py_unwind))
778859 {
779860 return nullptr ;
780861 }
781862
782- if (!self->ue_object ->IsA <UMovieSceneSection>())
863+ UMovieSceneSection *section = ue_py_check_type<UMovieSceneSection>(self);
864+ if (!section)
783865 return PyErr_Format (PyExc_Exception, " uobject is not a MovieSceneSection" );
784866
785- UMovieSceneSection *section = (UMovieSceneSection *)self->ue_object ;
867+ #if ENGINE_MINOR_VERSION >= 20
868+ UMovieSceneTrack *Track = section->GetTypedOuter <UMovieSceneTrack>();
869+ if (!Track)
870+ return PyErr_Format (PyExc_Exception, " unable to retrieve track from section" );
871+ UMovieScene *MovieScene = Track->GetTypedOuter <UMovieScene>();
872+ if (!MovieScene)
873+ return PyErr_Format (PyExc_Exception, " unable to retrieve scene from section" );
874+
875+ FFrameNumber FrameNumber = MovieScene->GetTickResolution ().AsFrameNumber (time);
876+ EMovieSceneKeyInterpolation InterpolationMode = (EMovieSceneKeyInterpolation)interpolation;
877+
878+ section->Modify ();
879+ #endif
786880
787881 if (auto section_float = Cast<UMovieSceneFloatSection>(section))
788882 {
@@ -791,7 +885,32 @@ PyObject *py_ue_sequencer_section_add_key(ue_PyUObject *self, PyObject * args)
791885 PyObject *f_value = PyNumber_Float (py_value);
792886 float value = PyFloat_AsDouble (f_value);
793887 Py_DECREF (f_value);
888+ #if ENGINE_MINOR_VERSION < 20
794889 section_float->AddKey (time, value, (EMovieSceneKeyInterpolation)interpolation);
890+ #else
891+ FMovieSceneFloatChannel& Channel = (FMovieSceneFloatChannel&)section_float->GetChannel ();
892+ int32 RetValue = -1 ;
893+ switch (InterpolationMode)
894+ {
895+ case (EMovieSceneKeyInterpolation::Auto):
896+ RetValue = Channel.AddCubicKey (FrameNumber, value, RCTM_Auto);
897+ break ;
898+ case (EMovieSceneKeyInterpolation::User):
899+ RetValue = Channel.AddCubicKey (FrameNumber, value, RCTM_User);
900+ case (EMovieSceneKeyInterpolation::Break):
901+ RetValue = Channel.AddCubicKey (FrameNumber, value, RCTM_Break);
902+ break ;
903+ case (EMovieSceneKeyInterpolation::Linear):
904+ RetValue = Channel.AddLinearKey (FrameNumber, value);
905+ break ;
906+ case (EMovieSceneKeyInterpolation::Constant):
907+ RetValue = Channel.AddConstantKey (FrameNumber, value);
908+ break ;
909+ default :
910+ return PyErr_Format (PyExc_Exception, " unsupported interpolation" );
911+ }
912+ return PyLong_FromLong (RetValue);
913+ #endif
795914 Py_RETURN_NONE;
796915 }
797916 }
@@ -803,7 +922,13 @@ PyObject *py_ue_sequencer_section_add_key(ue_PyUObject *self, PyObject * args)
803922 bool value = false ;
804923 if (PyObject_IsTrue (py_value))
805924 value = true ;
925+ #if ENGINE_MINOR_VERSION < 20
806926 section_bool->AddKey (time, value, (EMovieSceneKeyInterpolation)interpolation);
927+ #else
928+ FMovieSceneBoolChannel& Channel = section_bool->GetChannel ();
929+ int32 RetValue = Channel.GetData ().AddKey (FrameNumber, value);
930+ return PyLong_FromLong (RetValue);
931+ #endif
807932 Py_RETURN_NONE;
808933 }
809934 }
@@ -815,6 +940,7 @@ PyObject *py_ue_sequencer_section_add_key(ue_PyUObject *self, PyObject * args)
815940 bool unwind = (py_unwind && PyObject_IsTrue (py_unwind));
816941 FTransform transform = py_transform->transform ;
817942
943+ #if ENGINE_MINOR_VERSION < 20
818944 FTransformKey tx = FTransformKey (EKey3DTransformChannel::Translation, EAxis::X, transform.GetLocation ().X , unwind);
819945 FTransformKey ty = FTransformKey (EKey3DTransformChannel::Translation, EAxis::Y, transform.GetLocation ().Y , unwind);
820946 FTransformKey tz = FTransformKey (EKey3DTransformChannel::Translation, EAxis::Z, transform.GetLocation ().Z , unwind);
@@ -837,6 +963,81 @@ PyObject *py_ue_sequencer_section_add_key(ue_PyUObject *self, PyObject * args)
837963 section_transform->AddKey (time, sy, (EMovieSceneKeyInterpolation)interpolation);
838964 section_transform->AddKey (time, sz, (EMovieSceneKeyInterpolation)interpolation);
839965 Py_RETURN_NONE;
966+ #else
967+ int RetValueTX, RetValueTY, RetValueTZ = -1 ;
968+ int RetValueRX, RetValueRY, RetValueRZ = -1 ;
969+ int RetValueSX, RetValueSY, RetValueSZ = -1 ;
970+ FMovieSceneFloatChannel *ChannelTX = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(0 );
971+ FMovieSceneFloatChannel *ChannelTY = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(1 );
972+ FMovieSceneFloatChannel *ChannelTZ = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(2 );
973+ FMovieSceneFloatChannel *ChannelRX = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(3 );
974+ FMovieSceneFloatChannel *ChannelRY = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(4 );
975+ FMovieSceneFloatChannel *ChannelRZ = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(5 );
976+ FMovieSceneFloatChannel *ChannelSX = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(6 );
977+ FMovieSceneFloatChannel *ChannelSY = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(7 );
978+ FMovieSceneFloatChannel *ChannelSZ = section_transform->GetChannelProxy ().GetChannel <FMovieSceneFloatChannel>(8 );
979+
980+ switch (InterpolationMode)
981+ {
982+ case (EMovieSceneKeyInterpolation::Auto):
983+ RetValueTX = ChannelTX->AddCubicKey (FrameNumber, transform.GetTranslation ().X , RCTM_Auto);
984+ RetValueTY = ChannelTY->AddCubicKey (FrameNumber, transform.GetTranslation ().Y , RCTM_Auto);
985+ RetValueTZ = ChannelTZ->AddCubicKey (FrameNumber, transform.GetTranslation ().Z , RCTM_Auto);
986+ RetValueRX = ChannelRX->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().X , RCTM_Auto);
987+ RetValueRY = ChannelRY->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().Y , RCTM_Auto);
988+ RetValueRZ = ChannelRZ->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().Z , RCTM_Auto);
989+ RetValueSX = ChannelSX->AddCubicKey (FrameNumber, transform.GetScale3D ().X , RCTM_Auto);
990+ RetValueSY = ChannelSY->AddCubicKey (FrameNumber, transform.GetScale3D ().Y , RCTM_Auto);
991+ RetValueSZ = ChannelSZ->AddCubicKey (FrameNumber, transform.GetScale3D ().Z , RCTM_Auto);
992+ break ;
993+ case (EMovieSceneKeyInterpolation::User):
994+ RetValueTX = ChannelTX->AddCubicKey (FrameNumber, transform.GetTranslation ().X , RCTM_User);
995+ RetValueTY = ChannelTY->AddCubicKey (FrameNumber, transform.GetTranslation ().Y , RCTM_User);
996+ RetValueTZ = ChannelTZ->AddCubicKey (FrameNumber, transform.GetTranslation ().Z , RCTM_User);
997+ RetValueRX = ChannelRX->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().X , RCTM_User);
998+ RetValueRY = ChannelRY->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().Y , RCTM_User);
999+ RetValueRZ = ChannelRZ->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().Z , RCTM_User);
1000+ RetValueSX = ChannelSX->AddCubicKey (FrameNumber, transform.GetScale3D ().X , RCTM_User);
1001+ RetValueSY = ChannelSY->AddCubicKey (FrameNumber, transform.GetScale3D ().Y , RCTM_User);
1002+ RetValueSZ = ChannelSZ->AddCubicKey (FrameNumber, transform.GetScale3D ().Z , RCTM_User);
1003+ case (EMovieSceneKeyInterpolation::Break):
1004+ RetValueTX = ChannelTX->AddCubicKey (FrameNumber, transform.GetTranslation ().X , RCTM_Break);
1005+ RetValueTY = ChannelTY->AddCubicKey (FrameNumber, transform.GetTranslation ().Y , RCTM_Break);
1006+ RetValueTZ = ChannelTZ->AddCubicKey (FrameNumber, transform.GetTranslation ().Z , RCTM_Break);
1007+ RetValueRX = ChannelRX->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().X , RCTM_Break);
1008+ RetValueRY = ChannelRY->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().Y , RCTM_Break);
1009+ RetValueRZ = ChannelRZ->AddCubicKey (FrameNumber, transform.GetRotation ().Euler ().Z , RCTM_Break);
1010+ RetValueSX = ChannelSX->AddCubicKey (FrameNumber, transform.GetScale3D ().X , RCTM_Break);
1011+ RetValueSY = ChannelSY->AddCubicKey (FrameNumber, transform.GetScale3D ().Y , RCTM_Break);
1012+ RetValueSZ = ChannelSZ->AddCubicKey (FrameNumber, transform.GetScale3D ().Z , RCTM_Break);
1013+ break ;
1014+ case (EMovieSceneKeyInterpolation::Linear):
1015+ RetValueTX = ChannelTX->AddLinearKey (FrameNumber, transform.GetTranslation ().X );
1016+ RetValueTY = ChannelTY->AddLinearKey (FrameNumber, transform.GetTranslation ().Y );
1017+ RetValueTZ = ChannelTZ->AddLinearKey (FrameNumber, transform.GetTranslation ().Z );
1018+ RetValueRX = ChannelRX->AddLinearKey (FrameNumber, transform.GetRotation ().Euler ().X );
1019+ RetValueRY = ChannelRY->AddLinearKey (FrameNumber, transform.GetRotation ().Euler ().Y );
1020+ RetValueRZ = ChannelRZ->AddLinearKey (FrameNumber, transform.GetRotation ().Euler ().Z );
1021+ RetValueSX = ChannelSX->AddLinearKey (FrameNumber, transform.GetScale3D ().X );
1022+ RetValueSY = ChannelSY->AddLinearKey (FrameNumber, transform.GetScale3D ().Y );
1023+ RetValueSZ = ChannelSZ->AddLinearKey (FrameNumber, transform.GetScale3D ().Z );
1024+ break ;
1025+ case (EMovieSceneKeyInterpolation::Constant):
1026+ RetValueTX = ChannelTX->AddConstantKey (FrameNumber, transform.GetTranslation ().X );
1027+ RetValueTY = ChannelTY->AddConstantKey (FrameNumber, transform.GetTranslation ().Y );
1028+ RetValueTZ = ChannelTZ->AddConstantKey (FrameNumber, transform.GetTranslation ().Z );
1029+ RetValueRX = ChannelRX->AddConstantKey (FrameNumber, transform.GetRotation ().Euler ().X );
1030+ RetValueRY = ChannelRY->AddConstantKey (FrameNumber, transform.GetRotation ().Euler ().Y );
1031+ RetValueRZ = ChannelRZ->AddConstantKey (FrameNumber, transform.GetRotation ().Euler ().Z );
1032+ RetValueSX = ChannelSX->AddConstantKey (FrameNumber, transform.GetScale3D ().X );
1033+ RetValueSY = ChannelSY->AddConstantKey (FrameNumber, transform.GetScale3D ().Y );
1034+ RetValueSZ = ChannelSZ->AddConstantKey (FrameNumber, transform.GetScale3D ().Z );
1035+ break ;
1036+ default :
1037+ return PyErr_Format (PyExc_Exception, " unsupported interpolation" );
1038+ }
1039+ return Py_BuildValue (" ((iii)(iii)(iii))" , RetValueTX, RetValueTY, RetValueTZ, RetValueRX, RetValueRY, RetValueRZ, RetValueSX, RetValueSY, RetValueSZ);
1040+ #endif
8401041 }
8411042 }
8421043
@@ -845,6 +1046,7 @@ PyObject *py_ue_sequencer_section_add_key(ue_PyUObject *self, PyObject * args)
8451046 if (ue_PyFVector *py_vector = py_ue_is_fvector (py_value))
8461047 {
8471048 FVector vec = py_vector->vec ;
1049+ #if ENGINE_MINOR_VERSION < 20
8481050 FVectorKey vx = FVectorKey (EKeyVectorChannel::X, vec.X );
8491051 FVectorKey vy = FVectorKey (EKeyVectorChannel::Y, vec.Y );
8501052 FVectorKey vz = FVectorKey (EKeyVectorChannel::Z, vec.Z );
@@ -853,13 +1055,50 @@ PyObject *py_ue_sequencer_section_add_key(ue_PyUObject *self, PyObject * args)
8531055 section_vector->AddKey (time, vx, (EMovieSceneKeyInterpolation)interpolation);
8541056 section_vector->AddKey (time, vy, (EMovieSceneKeyInterpolation)interpolation);
8551057 section_vector->AddKey (time, vz, (EMovieSceneKeyInterpolation)interpolation);
1058+ #else
1059+ int RetValueVX, RetValueVY, RetValueVZ = -1 ;
1060+
1061+ FMovieSceneFloatChannel& ChannelX = (FMovieSceneFloatChannel&)section_vector->GetChannel (0 );
1062+ FMovieSceneFloatChannel& ChannelY = (FMovieSceneFloatChannel&)section_vector->GetChannel (1 );
1063+ FMovieSceneFloatChannel& ChannelZ = (FMovieSceneFloatChannel&)section_vector->GetChannel (2 );
1064+
1065+ switch (InterpolationMode)
1066+ {
1067+ case (EMovieSceneKeyInterpolation::Auto):
1068+ RetValueVX = ChannelX.AddCubicKey (FrameNumber, vec.X , RCTM_Auto);
1069+ RetValueVY = ChannelY.AddCubicKey (FrameNumber, vec.Y , RCTM_Auto);
1070+ RetValueVZ = ChannelZ.AddCubicKey (FrameNumber, vec.Z , RCTM_Auto);
1071+ break ;
1072+ case (EMovieSceneKeyInterpolation::User):
1073+ RetValueVX = ChannelX.AddCubicKey (FrameNumber, vec.X , RCTM_User);
1074+ RetValueVY = ChannelY.AddCubicKey (FrameNumber, vec.Y , RCTM_User);
1075+ RetValueVZ = ChannelZ.AddCubicKey (FrameNumber, vec.Z , RCTM_User);
1076+ case (EMovieSceneKeyInterpolation::Break):
1077+ RetValueVX = ChannelX.AddCubicKey (FrameNumber, vec.X , RCTM_Break);
1078+ RetValueVY = ChannelY.AddCubicKey (FrameNumber, vec.Y , RCTM_Break);
1079+ RetValueVZ = ChannelZ.AddCubicKey (FrameNumber, vec.Z , RCTM_Break);
1080+ break ;
1081+ case (EMovieSceneKeyInterpolation::Linear):
1082+ RetValueVX = ChannelX.AddLinearKey (FrameNumber, vec.X );
1083+ RetValueVY = ChannelY.AddLinearKey (FrameNumber, vec.Y );
1084+ RetValueVZ = ChannelZ.AddLinearKey (FrameNumber, vec.Z );
1085+ break ;
1086+ case (EMovieSceneKeyInterpolation::Constant):
1087+ RetValueVX = ChannelX.AddConstantKey (FrameNumber, vec.X );
1088+ RetValueVY = ChannelY.AddConstantKey (FrameNumber, vec.Y );
1089+ RetValueVZ = ChannelZ.AddConstantKey (FrameNumber, vec.Z );
1090+ break ;
1091+ default :
1092+ return PyErr_Format (PyExc_Exception, " unsupported interpolation" );
1093+ }
1094+ return Py_BuildValue (" (iii)" , RetValueVX, RetValueVY, RetValueVZ);
1095+ #endif
8561096
8571097 Py_RETURN_NONE;
8581098 }
8591099 }
8601100
8611101 return PyErr_Format (PyExc_Exception, " unsupported section type: %s" , TCHAR_TO_UTF8 (*section->GetClass ()->GetName ()));
862- #endif
8631102}
8641103
8651104PyObject *py_ue_sequencer_add_camera_cut_track (ue_PyUObject *self, PyObject * args)
0 commit comments