Jam-Teacher/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODChannelEditors.cpp
2020-08-01 13:48:17 +02:00

211 lines
7.5 KiB
C++

// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020.
#include "Sequencer/FMODChannelEditors.h"
#include "ISequencerChannelInterface.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SCompoundWidget.h"
#include "MovieSceneTimeHelpers.h"
#include "MovieSceneToolHelpers.h"
#include "ScopedTransaction.h"
#include "EditorWidgets/Public/SEnumCombobox.h"
#include "EditorStyleSet.h"
class SFMODEventControlKeyEditor : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SFMODEventControlKeyEditor) {}
SLATE_END_ARGS();
void Construct(const FArguments &InArgs, TMovieSceneChannelHandle<FMovieSceneByteChannel> InChannelHandle,
TWeakObjectPtr<UMovieSceneSection> InWeakSection, TWeakPtr<ISequencer> InWeakSequencer, UEnum *InEnum)
{
ChannelHandle = InChannelHandle;
WeakSection = InWeakSection;
WeakSequencer = InWeakSequencer;
ChildSlot[MovieSceneToolHelpers::MakeEnumComboBox(InEnum,
TAttribute<int32>::Create(TAttribute<int32>::FGetter::CreateSP(this, &SFMODEventControlKeyEditor::OnGetCurrentValueAsInt)),
SEnumComboBox::FOnEnumSelectionChanged::CreateSP(this, &SFMODEventControlKeyEditor::OnChangeKey))];
}
private:
int32 OnGetCurrentValueAsInt() const
{
using namespace MovieScene;
FMovieSceneByteChannel *Channel = ChannelHandle.Get();
ISequencer *Sequencer = WeakSequencer.Pin().Get();
UMovieSceneSection *OwningSection = WeakSection.Get();
uint8 Result = 0;
if (Channel && Sequencer && OwningSection)
{
const FFrameTime CurrentTime = MovieScene::ClampToDiscreteRange(Sequencer->GetLocalTime().Time, OwningSection->GetRange());
EvaluateChannel(Channel, CurrentTime, Result);
}
return Result;
}
void SetValue(uint8 InValue)
{
using namespace MovieScene;
using namespace Sequencer;
UMovieSceneSection *OwningSection = WeakSection.Get();
if (!OwningSection)
{
return;
}
OwningSection->SetFlags(RF_Transactional);
FMovieSceneByteChannel *Channel = ChannelHandle.Get();
ISequencer *Sequencer = WeakSequencer.Pin().Get();
if (!OwningSection->TryModify() || !Channel || !Sequencer)
{
return;
}
const FFrameNumber CurrentTime = Sequencer->GetLocalTime().Time.FloorToFrame();
const bool bAutoSetTrackDefaults = Sequencer->GetAutoSetTrackDefaults();
EMovieSceneKeyInterpolation Interpolation = Sequencer->GetKeyInterpolation();
TArray<FKeyHandle> KeysAtCurrentTime;
Channel->GetKeys(TRange<FFrameNumber>(CurrentTime), nullptr, &KeysAtCurrentTime);
if (KeysAtCurrentTime.Num() > 0)
{
AssignValue(Channel, KeysAtCurrentTime[0], InValue);
}
else
{
const bool bHasAnyKeys = Channel->GetNumKeys() != 0;
if (bHasAnyKeys || bAutoSetTrackDefaults == false)
{
// When auto setting track defaults are disabled, add a key even when it's empty so that the changed
// value is saved and is propagated to the property.
AddKeyToChannel(Channel, CurrentTime, InValue, Interpolation);
}
if (bHasAnyKeys)
{
TRange<FFrameNumber> KeyRange = TRange<FFrameNumber>(CurrentTime);
TRange<FFrameNumber> SectionRange = OwningSection->GetRange();
if (!SectionRange.Contains(KeyRange))
{
OwningSection->SetRange(TRange<FFrameNumber>::Hull(KeyRange, SectionRange));
}
}
}
// Always update the default value when auto-set default values is enabled so that the last changes
// are always saved to the track.
if (bAutoSetTrackDefaults)
{
SetChannelDefault(Channel, InValue);
}
}
void OnChangeKey(int32 Selection, ESelectInfo::Type SelectionType)
{
FScopedTransaction Transaction(FText::FromString("Set FMOD Event Control Key Value"));
SetValue(Selection);
if (ISequencer *Sequencer = WeakSequencer.Pin().Get())
{
Sequencer->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::TrackValueChangedRefreshImmediately);
}
}
TMovieSceneChannelHandle<FMovieSceneByteChannel> ChannelHandle;
TWeakObjectPtr<UMovieSceneSection> WeakSection;
TWeakPtr<ISequencer> WeakSequencer;
};
bool CanCreateKeyEditor(const FMovieSceneByteChannel *Channel)
{
return true;
}
TSharedRef<SWidget> CreateKeyEditor(const TMovieSceneChannelHandle<FMovieSceneByteChannel> &Channel, UMovieSceneSection *Section,
const FGuid &InObjectBindingID, TWeakPtr<FTrackInstancePropertyBindings> PropertyBindings, TWeakPtr<ISequencer> InSequencer)
{
const FMovieSceneByteChannel *RawChannel = Channel.Get();
if (!RawChannel)
{
return SNullWidget::NullWidget;
}
UEnum *Enum = RawChannel->GetEnum();
return SNew(SFMODEventControlKeyEditor, Channel, Section, InSequencer, Enum);
}
TSharedPtr<FStructOnScope> GetKeyStruct(const TMovieSceneChannelHandle<FFMODEventControlChannel> &ChannelHandle, FKeyHandle InHandle)
{
FFMODEventControlChannel *Channel = ChannelHandle.Get();
if (!Channel)
{
return nullptr;
}
TMovieSceneChannelData<uint8> ChannelData = Channel->GetData();
const int32 KeyIndex = ChannelData.GetIndex(InHandle);
if (KeyIndex == INDEX_NONE)
{
return nullptr;
}
TSharedPtr<FStructOnScope> KeyStruct = MakeShared<FStructOnScope>(FFMODEventControlKeyStruct::StaticStruct());
FFMODEventControlKeyStruct *Struct = reinterpret_cast<FFMODEventControlKeyStruct *>(KeyStruct->GetStructMemory());
Struct->Time = ChannelData.GetTimes()[KeyIndex];
Struct->Value = (EFMODEventControlKey)ChannelData.GetValues()[KeyIndex];
Struct->KeyStructInterop.Add(FMovieSceneChannelValueHelper(ChannelHandle, &Struct->Value, MakeTuple(InHandle, Struct->Time)));
return KeyStruct;
}
void DrawKeys(FFMODEventControlChannel *Channel, TArrayView<const FKeyHandle> InKeyHandles, TArrayView<FKeyDrawParams> OutKeyDrawParams)
{
static const FName KeyLeftBrushName("Sequencer.KeyLeft");
static const FName KeyRightBrushName("Sequencer.KeyRight");
static const FName KeyDiamondBrushName("Sequencer.KeyDiamond");
const FSlateBrush *LeftKeyBrush = FEditorStyle::GetBrush(KeyLeftBrushName);
const FSlateBrush *RightKeyBrush = FEditorStyle::GetBrush(KeyRightBrushName);
const FSlateBrush *DiamondBrush = FEditorStyle::GetBrush(KeyDiamondBrushName);
TMovieSceneChannelData<uint8> ChannelData = Channel->GetData();
for (int32 Index = 0; Index < InKeyHandles.Num(); ++Index)
{
FKeyHandle Handle = InKeyHandles[Index];
FKeyDrawParams Params;
Params.BorderBrush = Params.FillBrush = DiamondBrush;
const int32 KeyIndex = ChannelData.GetIndex(Handle);
if (KeyIndex != INDEX_NONE)
{
const EFMODEventControlKey Value = (EFMODEventControlKey)ChannelData.GetValues()[KeyIndex];
if (Value == EFMODEventControlKey::Play)
{
Params.BorderBrush = Params.FillBrush = LeftKeyBrush;
Params.FillOffset = FVector2D(-1.0f, 1.0f);
}
else if (Value == EFMODEventControlKey::Stop)
{
Params.BorderBrush = Params.FillBrush = RightKeyBrush;
Params.FillOffset = FVector2D(1.0f, 1.0f);
}
}
OutKeyDrawParams[Index] = Params;
}
}