Sequencer改造 2
前回
Sequencer改造
http://qiita.com/gansaibow/items/d47874de4628ca8fa93d
続き
LOCTEXTの第一引数もPokopenにすることで、Deleteが表示された
どこかにKeyを設定する必要はなさそうなので、重複しなさそうなKey名を設定すれば良さそう。
1フレームごとにキーを打つ
ToolTipのコメントを検索ワードとして取得する
[Add a new key at the current time]
検索範囲をソリューション全体に設定して、検索ワードを入れて検索すると該当箇所が見つかる
該当のボタンを追加するソースコード
OnAddKeyClickedというイベントでキーを追加している
OnClicked(this, &SKeyNavigationButtons::OnAddKeyClicked)
// 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*/)
]
]
]
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を作成する
// 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を足して、次のフレームにキーを打ってみるように処理を変えてみる
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フレーム分を取得しないといけない
1フレーム分の時間はSequencer.cppでSettings->GetTimeSnapInterval()で取得することが出来るようだ。
Sequencer.hとSequencer.cppにGetOneFrameTimeを追加する
public:
FMovieSceneRootEvaluationTemplateInstance& GetSequenceInstance() { return RootTemplateInstance; }
float GetOneFrameTime();
float FSequencer::GetOneFrameTime()
{
return Settings->GetTimeSnapInterval();
}
OnAddKeyAllFrameClickedを1フレーム次のフレームにキーを打つように変更してみる
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();
}
全フレームにキーを打つ
あとは開始フレームと終了フレームが取得できれば、全フレームにキーが打てそうだ
開始フレームと終了フレームはGetPlaybackRange()で取得できる
終了フレームのフレームトータル時間は
PlaybackRangeの終了フレーム * (フレームレート * 1フレームの時間)で出せる。
開始トータル時間と終了トータル時間の1フレームごとの時間を配列に入れて戻り値として返す
GetAllFrameTimesをSequencer.h(Public)とSequencer.cppに追加
TArray<float> GetAllFrameTimes();
OnAddKeyAllFrameClickedからGetAllFrameTimesで全フレームのキーフレーム時間配列を取得して、全フレームキーを打つように修正する
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で全フレームの時間を取得して、キーを打つように変更する
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();
}