LoginSignup
2
2

More than 5 years have passed since last update.

Sequencer改造 2 #UE4Study

Last updated at Posted at 2017-02-21

Sequencer改造 2

前回

Sequencer改造
http://qiita.com/gansaibow/items/d47874de4628ca8fa93d

続き

LOCTEXTの第一引数もPokopenにすることで、Deleteが表示された
どこかにKeyを設定する必要はなさそうなので、重複しなさそうなKey名を設定すれば良さそう。
image

image

1フレームごとにキーを打つ

ToolTipのコメントを検索ワードとして取得する
[Add a new key at the current time]
image

検索範囲をソリューション全体に設定して、検索ワードを入れて検索すると該当箇所が見つかる
image

該当のボタンを追加するソースコード

OnAddKeyClickedというイベントでキーを追加している
OnClicked(this, &SKeyNavigationButtons::OnAddKeyClicked)

SKeyNavigationButtons.h
            // Add key slot
            + SHorizontalBox::Slot()
            .VAlign(VAlign_Center)
            .AutoWidth()
            [
                SNew(SBorder)
                .Padding(0)
                .BorderImage(NoBorder)
                .ColorAndOpacity(HoverTint)
                .IsEnabled(!InDisplayNode->GetSequencer().IsReadOnly())
                [
                    SNew(SButton)
                    .ButtonStyle(FEditorStyle::Get(), "FlatButton")
                    .ToolTipText(LOCTEXT("AddKeyButton", "Add a new key at the current time"))
                    .OnClicked(this, &SKeyNavigationButtons::OnAddKeyClicked)
                    .ForegroundColor( FSlateColor::UseForeground() )
                    .ContentPadding(0)
                    .IsFocusable(false)
                    [
                        SNew(STextBlock)
                        .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.7"))
                        .Text(FText::FromString(FString(TEXT("\xf055"))) /*fa-plus-circle*/)
                    ]
                ]
            ]

OnAddKeyClickedを右クリックして定義に移動
image

SKeyNavigationButtons.h
    FReply OnAddKeyClicked()
    {
        FSequencer& Sequencer = DisplayNode->GetSequencer();
        float CurrentTime = Sequencer.GetLocalTime();

        TSet<TSharedPtr<IKeyArea>> KeyAreas;
        SequencerHelpers::GetAllKeyAreas(DisplayNode, KeyAreas);

        TArray<UMovieSceneSection*> KeyAreaSections;
        for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
        {
            UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
            KeyAreaSections.Add(OwningSection);
        }

        UMovieSceneSection* NearestSection = MovieSceneHelpers::FindNearestSectionAtTime(KeyAreaSections, CurrentTime);
        if (!NearestSection)
        {
            return FReply::Unhandled();
        }

        FScopedTransaction Transaction(LOCTEXT("AddKeys", "Add Keys at Current Time"));
        for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
        {
            UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
            if (OwningSection == NearestSection)
            {
                OwningSection->SetFlags(RF_Transactional);
                if (OwningSection->TryModify())
                {
                    KeyArea->AddKeyUnique(CurrentTime, Sequencer.GetKeyInterpolation());
                }
            }
        }

        Sequencer.UpdatePlaybackRange();

        return FReply::Handled();
    }

テスト用のボタンを追加して
OnAddKeyClickedをコピーして、新しい関数OnAddKeyAllFrameClickedを作成する

SKeyNavigationButtons.h
            // Add key slot
            + SHorizontalBox::Slot()
            .VAlign(VAlign_Center)
            .AutoWidth()
            [
                SNew(SBorder)
                .Padding(0)
                .BorderImage(NoBorder)
                .ColorAndOpacity(HoverTint)
                .IsEnabled(!InDisplayNode->GetSequencer().IsReadOnly())
                [
                    SNew(SButton)
                    .ButtonStyle(FEditorStyle::Get(), "FlatButton")
                    .ToolTipText(LOCTEXT("AddKeyButton", "Add a new key at the current time"))
                    .OnClicked(this, &SKeyNavigationButtons::OnAddKeyClicked)
                    .ForegroundColor( FSlateColor::UseForeground() )
                    .ContentPadding(0)
                    .IsFocusable(false)
                    [
                        SNew(STextBlock)
                        .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.7"))
                        .Text(FText::FromString(FString(TEXT("\xf055"))) /*fa-plus-circle*/)
                    ]
                ]
            ]
            // Add key slot 2
            + SHorizontalBox::Slot()
            .VAlign(VAlign_Center)
            .AutoWidth()
            [
                SNew(SBorder)
                .Padding(0)
                .BorderImage(NoBorder)
                .ColorAndOpacity(HoverTint)
                .IsEnabled(!InDisplayNode->GetSequencer().IsReadOnly())
                [
                    SNew(SButton)
                    .ButtonStyle(FEditorStyle::Get(), "FlatButton")
                    .ToolTipText(LOCTEXT("AddKeyAllButton", "Add a new key All frame"))
                    .OnClicked(this, &SKeyNavigationButtons::OnAddKeyAllFrameClicked)
                    .ForegroundColor( FSlateColor::UseForeground() )
                    .ContentPadding(0)
                    .IsFocusable(false)
                    [
                        SNew(STextBlock)
                        .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.7"))
                        .Text(FText::FromString(FString(TEXT("\xf055"))) /*fa-plus-circle*/)
                    ]
                ]
            ]

CurrentFrameに1を足して、次のフレームにキーを打ってみるように処理を変えてみる

SKeyNavigationButtons.h
    FReply OnAddKeyAllFrameClicked()
    {
        FSequencer& Sequencer = DisplayNode->GetSequencer();

        float CurrentTime = Sequencer.GetGlobalTime();
        CurrentTime = CurrentTime + 1;
        Sequencer.SetGlobalTime(CurrentTime);

        TSet<TSharedPtr<IKeyArea>> KeyAreas;
        SequencerHelpers::GetAllKeyAreas(DisplayNode, KeyAreas);

        TArray<UMovieSceneSection*> KeyAreaSections;
        for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
        {
            UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
            KeyAreaSections.Add(OwningSection);
        }

        UMovieSceneSection* NearestSection = MovieSceneHelpers::FindNearestSectionAtTime(KeyAreaSections, CurrentTime);
        if (!NearestSection)
        {
            return FReply::Unhandled();
        }

        FScopedTransaction Transaction(LOCTEXT("AddKeys", "Add Keys at Current Time"));
        for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
        {
            UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
            if (OwningSection == NearestSection)
            {
                OwningSection->SetFlags(RF_Transactional);
                if (OwningSection->TryModify())
                {
                    KeyArea->AddKeyUnique(CurrentTime, Sequencer.GetKeyInterpolation());
                }
            }
        }

        Sequencer.UpdatePlaybackRange();

        return FReply::Handled();
    }

ボタンが追加されたが、30フレームごとにキーが打たれてしまう
CurrentTime = CurrentTime + 1;
とすると、設定しているFPS x 1が進んでしまう
1フレーム分を取得しないといけない

image

1フレーム分の時間はSequencer.cppでSettings->GetTimeSnapInterval()で取得することが出来るようだ。

Sequencer.hとSequencer.cppにGetOneFrameTimeを追加する

Sequencer.h
public:

    FMovieSceneRootEvaluationTemplateInstance& GetSequenceInstance() { return RootTemplateInstance; }
    float GetOneFrameTime();
Sequencer.cpp
float FSequencer::GetOneFrameTime()
{
    return Settings->GetTimeSnapInterval();
}

OnAddKeyAllFrameClickedを1フレーム次のフレームにキーを打つように変更してみる

SKeyNavigationButtons.h
    FReply OnAddKeyAllFrameClicked()
    {
        FSequencer& Sequencer = DisplayNode->GetSequencer();

        float oneFrameTime = Sequencer.GetOneFrameTime();
        float CurrentTime = Sequencer.GetGlobalTime();
        CurrentTime = CurrentTime + oneFrameTime;
        Sequencer.SetGlobalTime(CurrentTime);

        TSet<TSharedPtr<IKeyArea>> KeyAreas;
        SequencerHelpers::GetAllKeyAreas(DisplayNode, KeyAreas);

        TArray<UMovieSceneSection*> KeyAreaSections;
        for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
        {
            UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
            KeyAreaSections.Add(OwningSection);
        }

        UMovieSceneSection* NearestSection = MovieSceneHelpers::FindNearestSectionAtTime(KeyAreaSections, CurrentTime);
        if (!NearestSection)
        {
            return FReply::Unhandled();
        }

        FScopedTransaction Transaction(LOCTEXT("AddKeys", "Add Keys at Current Time"));
        for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
        {
            UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
            if (OwningSection == NearestSection)
            {
                OwningSection->SetFlags(RF_Transactional);
                if (OwningSection->TryModify())
                {
                    KeyArea->AddKeyUnique(CurrentTime, Sequencer.GetKeyInterpolation());
                }
            }
        }

        Sequencer.UpdatePlaybackRange();

        return FReply::Handled();
    }

1フレームごとキーが設定される
image

全フレームにキーを打つ

あとは開始フレームと終了フレームが取得できれば、全フレームにキーが打てそうだ

開始フレームと終了フレームはGetPlaybackRange()で取得できる

終了フレームのフレームトータル時間は
PlaybackRangeの終了フレーム * (フレームレート * 1フレームの時間)で出せる。
開始トータル時間と終了トータル時間の1フレームごとの時間を配列に入れて戻り値として返す

GetAllFrameTimesをSequencer.h(Public)とSequencer.cppに追加

Sequencer.h
    TArray<float> GetAllFrameTimes();

OnAddKeyAllFrameClickedからGetAllFrameTimesで全フレームのキーフレーム時間配列を取得して、全フレームキーを打つように修正する

Sequencer.cpp
TArray<float> FSequencer::GetAllFrameTimes()
{
    TArray<float> allFrameTimes;
    float frameRate = 1.0f / Settings->GetTimeSnapInterval();
    float oneFrameTime = Settings->GetTimeSnapInterval();

    TRange<float> range = GetPlaybackRange();
    float StartTime = range.GetLowerBoundValue();
    float EndTime = range.GetUpperBoundValue();

    float startFrame = StartTime * (frameRate * oneFrameTime);
    float endFrame = EndTime * (frameRate * oneFrameTime);

    for (float i = startFrame; i < endFrame; i = i + oneFrameTime)
    {
        allFrameTimes.Add(i);
    }

    return allFrameTimes;
}

OnAddKeyAllFrameClickedにGetAllFrameTimesで全フレームの時間を取得して、キーを打つように変更する

SKeyNavigationButtons.h
    FReply OnAddKeyAllFrameClicked()
    {
        FSequencer& Sequencer = DisplayNode->GetSequencer();

        TArray<float> allFrameTimes = Sequencer.GetAllFrameTimes();

        for (float CurrentTime : allFrameTimes)
        {
            Sequencer.SetGlobalTime(CurrentTime);

            TSet<TSharedPtr<IKeyArea>> KeyAreas;
            SequencerHelpers::GetAllKeyAreas(DisplayNode, KeyAreas);

            TArray<UMovieSceneSection*> KeyAreaSections;
            for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
            {
                UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
                KeyAreaSections.Add(OwningSection);
            }

            UMovieSceneSection* NearestSection = MovieSceneHelpers::FindNearestSectionAtTime(KeyAreaSections, CurrentTime);
            if (!NearestSection)
            {
                return FReply::Unhandled();
            }

            FScopedTransaction Transaction(LOCTEXT("AddKeys", "Add Keys at Current Time"));
            for (TSharedPtr<IKeyArea> KeyArea : KeyAreas)
            {
                UMovieSceneSection* OwningSection = KeyArea->GetOwningSection();
                if (OwningSection == NearestSection)
                {
                    OwningSection->SetFlags(RF_Transactional);
                    if (OwningSection->TryModify())
                    {
                        KeyArea->AddKeyUnique(CurrentTime, Sequencer.GetKeyInterpolation());
                    }
                }
            }

        }

        Sequencer.UpdatePlaybackRange();

        return FReply::Handled();
    }

image

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2