Download

[Solved] Create sequencer events from C++ in 4.20

Hi there!
I’m trying to generate Movie Sequences from C++ from a dialog that I created as a custom asset. I want to call an event everytime a new Dialog Line is supposed to be displayed so I can print the adequate subtitle on screen at the right time. So far I’ve managed to create sequences, event tracks and event keys from C++. My problem come when I want to send the right data to these event keys. From the editor, the keys only accept blueprint created struct, when I try to use mine, I can’t edit anything and the struct is not carried by the event.
Has someone ever done something like that and can help me :frowning: my last option if this does not work is to create my own event track but I’m not sure that it will be easy ^^’.
Here is the code I use :


  // Adds an event track and section
  UMovieSceneEventTrack* EventTrack = CurrentSequence->MovieScene->AddMasterTrack<UMovieSceneEventTrack>();
  check(EventTrack);

  UMovieSceneSection* NewSection = NewObject<UMovieSceneSection>(EventTrack, UMovieSceneEventSection::StaticClass(), NAME_None, RF_Transactional);
  UMovieSceneEventSection* EventSection = Cast<UMovieSceneEventSection>(NewSection);
  check(EventSection);

  EventTrack->AddSection(*EventSection);
  EventTrack->SetDisplayName(LOCTEXT("TrackName", "Events"));

  // Get the event section's data to populate with keys
  FMovieSceneEventSectionData* EventChannel = EventSection->GetChannelProxy().GetChannel<FMovieSceneEventSectionData>(0);
  TMovieSceneChannelData<FEventPayload> EventData = EventChannel->GetData();

  for (int i = 0; i < DialogToGenerate->GetNumberOfLines(); ++i)
  {
    // create an event for this line, giving the speaker and text to the UI
    FEventPayload Payload;
    Payload.EventName = "SEQ_DisplayLine";
    //UDialogEventParams EventParams;
    PayloadProperty = NewObject<UDialogEventParams>(this, UDialogEventParams::StaticClass(), *FString("Sentence"), EObjectFlags::RF_Public);
    PayloadProperty->Parameters.DialogLine = FText::FromString("A line I want to display on screen!");
    PayloadProperty->PrepareCppStructOps();

    FMovieSceneEventParameters Params;
    Params.Reassign(PayloadProperty);

    Payload.Parameters = Params;
    //TODO : get the audio time to set the keyframe
    EventData.AddKey(i * 48000, Payload);
  }
 

Thanks in advance to anyone able to help here :slight_smile:

You don’t show the code for your structures you want exposed to blueprints, so I’m just taking a guess here.

Have you tagged your structures to expose them to blueprints? Make sure you have “BlueprintType” in your USTRUCT macro. You will probably need to make sure your structure properties also have a UPROPERTY macro with the proper options (“EditAnywhere”, “BlueprintReadWrite”).

For example:



USTRUCT(BlueprintType)
struct FEventPayload
{
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FString EventName;

    // Etc...
};


Thanks for the reply!

I indeed forgot to show my structs, here they are : There is a UScriptStruct derived class containing my actual payload because the Reassign method only takes UScriptStruct as input. I’m not sure it is the right way to do it. I didn’t use “EditAnywhere” and “BlueprintReadWrite” before, just UPROPERTY, I added them to try your solution but nothing changed.


USTRUCT(BlueprintType)
struct FDialogEventParamsStruct
{
    GENERATED_BODY()
public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialog")
    FText DialogLine = FText();
};

UCLASS(BlueprintType)
class UDialogEventParams : public UScriptStruct
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DialogParams")
    FDialogEventParamsStruct Parameters;

};

I’ll also show you what I end up with in the editor after generating the event keys. I can see that my events are populated with the event name and the parameter struct but there is no dropdown arrow to display what the struct’s fields are containing.

Event_Struct.png

And then when I try to fire an event called “SEQ_DisplayLine” (be it in Blueprint or C++) with an FText input parameter (like the field in my struct) it isn’t called. But when I remove the input parameter and call “SEQ_DisplayLine” without any parameter, it fires.
It seems like my struct isn’t registered properly, maybe I used the UScriptStruct wrong.

We found the solution. There was no need to create a custom UScriptStruct.

The way to do it was to populate the custom struct containing the parameters with the needed values. Then it is possible to get a UScriptStruct* from this struct by using the StaticStruct() method of the USTRUCT.
After that, one must use Reassign(TheCreatedUScriptStruct) on the FMovieSceneEventParameters. It will create a struct with default values, to get the values that we set before we must use OverWriteWith(TheFilledStruct), the parameter being the struct we populated earlier.

Here is an updated version of the code :


    // Create the parameter struct and fill it
    FEventPayload Payload;
    Payload.EventName = "SEQ_DisplayLine";
    FDialogEventParamsStruct ParamStruct;
    ParamStruct.DialogLine = FText::FromString("A line I want to display on screen!");

    // Get the UScriptStruct from the structure
    UScriptStruct* PayloadProperty = ParamStruct.StaticStruct();

    // Reassign and overwrite the parameter struct for the payload
    FMovieSceneEventParameters Params;
    Params.Reassign(PayloadProperty);
    Params.OverwriteWith((uint8*)&ParamStruct);

    // Create the event key
    Payload.Parameters = Params;
    //TODO : get the audio time to set the keyframe
    EventData.AddKey(i * 48000, Payload);


I hope it can help somone with the same problem as it wasn’t easy to find =)

Hello! I’m late to the party but I’m trying to do something similar.
So far I’ve managed to add a spawnable, add an event track to it and add a section to the event track. I’m now trying to create the event from C++ and I can’t figure how to do. Can anyone give me a hand?

here is my code so far :




// fetch sequence and blueprint to spawn
UEditorAssetLibrary::CheckoutAsset("/Game/Python/PythonSequence");
UObject* mySequenceObject = UEditorAssetLibrary::LoadAsset("/Game/Python/PythonSequence");
UMovieSceneSequence* myMovieSceneSequence = Cast<UMovieSceneSequence>(mySequenceObject);
UMovieScene* myMovieScene = myMovieSceneSequence->GetMovieScene();

// Fetch blueprint and add as spawnable in sequence
UObject* myBlueprintObject = UEditorAssetLibrary::LoadAsset("/Game/Blueprints/BP_RandomNumberGenerator");
FGuid mySpanwableGuid = myMovieSceneSequence->CreateSpawnable(myBlueprintObject);

// Add an event track to the spawnable
UMovieSceneTrack* myTrack = myMovieScene->AddTrack(UMovieSceneEventTrack::StaticClass(), mySpanwableGuid);

// Add a section to the event track
UMovieSceneSection* mySection = myTrack->CreateNewSection();
myTrack->AddSection(*mySection);
UMovieSceneEventSection* myEventSection = Cast<UMovieSceneEventSection>(mySection);

// Add a key to the section
// TODO



Thanks in advance!