fixed issue
This commit is contained in:
@ -0,0 +1,185 @@
|
||||
// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2023.
|
||||
|
||||
#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/SEnumCombo.h"
|
||||
#include "EditorStyleSet.h"
|
||||
#include "Channels/MovieSceneChannelTraits.h"
|
||||
|
||||
class SFMODEventControlKeyEditor : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SFMODEventControlKeyEditor) {}
|
||||
SLATE_END_ARGS();
|
||||
|
||||
void Construct(const FArguments &InArgs, TMovieSceneChannelHandle<FFMODEventControlChannel> 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 UE::MovieScene;
|
||||
|
||||
FFMODEventControlChannel *Channel = ChannelHandle.Get();
|
||||
ISequencer *Sequencer = WeakSequencer.Pin().Get();
|
||||
UMovieSceneSection *OwningSection = WeakSection.Get();
|
||||
uint8 Result = 0;
|
||||
|
||||
if (Channel && Sequencer && OwningSection)
|
||||
{
|
||||
const FFrameTime CurrentTime = UE::MovieScene::ClampToDiscreteRange(Sequencer->GetLocalTime().Time, OwningSection->GetRange());
|
||||
EvaluateChannel(Channel, CurrentTime, Result);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void SetValue(uint8 InValue)
|
||||
{
|
||||
using namespace UE::MovieScene;
|
||||
|
||||
UMovieSceneSection *OwningSection = WeakSection.Get();
|
||||
if (!OwningSection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OwningSection->SetFlags(RF_Transactional);
|
||||
|
||||
FFMODEventControlChannel *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<FFMODEventControlChannel> ChannelHandle;
|
||||
TWeakObjectPtr<UMovieSceneSection> WeakSection;
|
||||
TWeakPtr<ISequencer> WeakSequencer;
|
||||
};
|
||||
|
||||
bool CanCreateKeyEditor(const FFMODEventControlChannel *Channel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> CreateKeyEditor(const TMovieSceneChannelHandle<FFMODEventControlChannel> &Channel, UMovieSceneSection *Section,
|
||||
const FGuid &InObjectBindingID, TWeakPtr<FTrackInstancePropertyBindings> PropertyBindings, TWeakPtr<ISequencer> InSequencer)
|
||||
{
|
||||
const FFMODEventControlChannel *RawChannel = Channel.Get();
|
||||
|
||||
if (!RawChannel)
|
||||
{
|
||||
return SNullWidget::NullWidget;
|
||||
}
|
||||
|
||||
UEnum *Enum = RawChannel->GetEnum();
|
||||
return SNew(SFMODEventControlKeyEditor, Channel, Section, InSequencer, Enum);
|
||||
}
|
||||
|
||||
void DrawKeys(FFMODEventControlChannel *Channel, TArrayView<const FKeyHandle> InKeyHandles, const UMovieSceneSection* InOwner, TArrayView<FKeyDrawParams> OutKeyDrawParams)
|
||||
{
|
||||
static const FName KeyLeftBrushName("Sequencer.KeyLeft");
|
||||
static const FName KeyRightBrushName("Sequencer.KeyRight");
|
||||
static const FName KeyDiamondBrushName("Sequencer.KeyDiamond");
|
||||
|
||||
const FSlateBrush *LeftKeyBrush = FAppStyle::GetBrush(KeyLeftBrushName);
|
||||
const FSlateBrush *RightKeyBrush = FAppStyle::GetBrush(KeyRightBrushName);
|
||||
const FSlateBrush *DiamondBrush = FAppStyle::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;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "MVVM/Views/KeyDrawParams.h"
|
||||
#include "Channels/MovieSceneChannelHandle.h"
|
||||
#include "Sequencer/FMODEventControlSection.h"
|
||||
|
||||
/** Key editor overrides */
|
||||
bool CanCreateKeyEditor(const FFMODEventControlChannel* Channel);
|
||||
|
||||
TSharedRef<SWidget> CreateKeyEditor(const TMovieSceneChannelHandle<FFMODEventControlChannel>& Channel, UMovieSceneSection* Section,
|
||||
const FGuid& InObjectBindingID, TWeakPtr<FTrackInstancePropertyBindings> PropertyBindings, TWeakPtr<ISequencer> InSequencer);
|
||||
|
||||
/** Key drawing overrides */
|
||||
void DrawKeys(FFMODEventControlChannel *Channel, TArrayView<const FKeyHandle> InKeyHandles, const UMovieSceneSection* InOwner, TArrayView<FKeyDrawParams> OutKeyDrawParams);
|
@ -0,0 +1,194 @@
|
||||
// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2023.
|
||||
|
||||
#include "FMODEventControlTrackEditor.h"
|
||||
#include "Rendering/DrawElements.h"
|
||||
#include "Framework/MultiBox/MultiBoxBuilder.h"
|
||||
#include "Curves/IntegralCurve.h"
|
||||
#include "SequencerSectionPainter.h"
|
||||
#include "EditorStyleSet.h"
|
||||
#include "Editor/UnrealEdEngine.h"
|
||||
#include "Sequencer/FMODEventControlSection.h"
|
||||
#include "Sequencer/FMODEventControlTrack.h"
|
||||
#include "ISectionLayoutBuilder.h"
|
||||
#include "FMODAmbientSound.h"
|
||||
#include "CommonMovieSceneTools.h"
|
||||
#include "Channels/MovieSceneChannelProxy.h"
|
||||
#include "Channels/MovieSceneChannelEditorData.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FFMODEventControlTrackEditor"
|
||||
|
||||
FFMODEventControlSection::FFMODEventControlSection(UMovieSceneSection &InSection, TSharedRef<ISequencer> InOwningSequencer)
|
||||
: Section(InSection)
|
||||
, OwningSequencerPtr(InOwningSequencer)
|
||||
{
|
||||
}
|
||||
|
||||
UMovieSceneSection *FFMODEventControlSection::GetSectionObject()
|
||||
{
|
||||
return &Section;
|
||||
}
|
||||
|
||||
float FFMODEventControlSection::GetSectionHeight() const
|
||||
{
|
||||
static const float SectionHeight = 20.f;
|
||||
return SectionHeight;
|
||||
}
|
||||
|
||||
int32 FFMODEventControlSection::OnPaintSection(FSequencerSectionPainter &InPainter) const
|
||||
{
|
||||
TSharedPtr<ISequencer> OwningSequencer = OwningSequencerPtr.Pin();
|
||||
|
||||
if (!OwningSequencer.IsValid())
|
||||
{
|
||||
return InPainter.LayerId + 1;
|
||||
}
|
||||
|
||||
const ESlateDrawEffect DrawEffects = InPainter.bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;
|
||||
const FTimeToPixel &TimeToPixelConverter = InPainter.GetTimeConverter();
|
||||
|
||||
FLinearColor TrackColor;
|
||||
|
||||
// TODO: Set / clip stop time based on event length
|
||||
UFMODEventControlSection *ControlSection = Cast<UFMODEventControlSection>(&Section);
|
||||
if (IsValid(ControlSection))
|
||||
{
|
||||
UFMODEventControlTrack *ParentTrack = Cast<UFMODEventControlTrack>(ControlSection->GetOuter());
|
||||
if (IsValid(ParentTrack))
|
||||
{
|
||||
TrackColor = ParentTrack->GetColorTint();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This should only draw the visible ranges.
|
||||
TArray<TRange<float>> DrawRanges;
|
||||
TOptional<float> CurrentRangeStart;
|
||||
|
||||
if (ControlSection != nullptr)
|
||||
{
|
||||
TMovieSceneChannelData<const uint8> ChannelData = ControlSection->ControlKeys.GetData();
|
||||
TArrayView<const FFrameNumber> Times = ChannelData.GetTimes();
|
||||
TArrayView<const uint8> Values = ChannelData.GetValues();
|
||||
|
||||
for (int32 Index = 0; Index < Times.Num(); ++Index)
|
||||
{
|
||||
const double Time = Times[Index] / TimeToPixelConverter.GetTickResolution();
|
||||
const EFMODEventControlKey Value = (EFMODEventControlKey)Values[Index];
|
||||
|
||||
if (Value == EFMODEventControlKey::Play)
|
||||
{
|
||||
if (CurrentRangeStart.IsSet() == false)
|
||||
{
|
||||
CurrentRangeStart = Time;
|
||||
}
|
||||
}
|
||||
if (Value == EFMODEventControlKey::Stop)
|
||||
{
|
||||
if (CurrentRangeStart.IsSet())
|
||||
{
|
||||
DrawRanges.Add(TRange<float>(CurrentRangeStart.GetValue(), Time));
|
||||
CurrentRangeStart.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentRangeStart.IsSet())
|
||||
{
|
||||
DrawRanges.Add(TRange<float>(CurrentRangeStart.GetValue(), OwningSequencer->GetViewRange().GetUpperBoundValue()));
|
||||
}
|
||||
|
||||
for (const TRange<float> &DrawRange : DrawRanges)
|
||||
{
|
||||
float XOffset = TimeToPixelConverter.SecondsToPixel(DrawRange.GetLowerBoundValue());
|
||||
float XSize = TimeToPixelConverter.SecondsToPixel(DrawRange.GetUpperBoundValue()) - XOffset;
|
||||
FSlateDrawElement::MakeBox(InPainter.DrawElements, InPainter.LayerId,
|
||||
InPainter.SectionGeometry.ToPaintGeometry(
|
||||
FVector2D(XOffset, (InPainter.SectionGeometry.GetLocalSize().Y - SequencerSectionConstants::KeySize.Y) / 2),
|
||||
FVector2D(XSize, SequencerSectionConstants::KeySize.Y)),
|
||||
FAppStyle::GetBrush("Sequencer.Section.Background"), DrawEffects);
|
||||
FSlateDrawElement::MakeBox(InPainter.DrawElements, InPainter.LayerId,
|
||||
InPainter.SectionGeometry.ToPaintGeometry(
|
||||
FVector2D(XOffset, (InPainter.SectionGeometry.GetLocalSize().Y - SequencerSectionConstants::KeySize.Y) / 2),
|
||||
FVector2D(XSize, SequencerSectionConstants::KeySize.Y)),
|
||||
FAppStyle::GetBrush("Sequencer.Section.BackgroundTint"), DrawEffects, TrackColor);
|
||||
}
|
||||
|
||||
return InPainter.LayerId + 1;
|
||||
}
|
||||
|
||||
FFMODEventControlTrackEditor::FFMODEventControlTrackEditor(TSharedRef<ISequencer> InSequencer)
|
||||
: FMovieSceneTrackEditor(InSequencer)
|
||||
{
|
||||
}
|
||||
|
||||
TSharedRef<ISequencerTrackEditor> FFMODEventControlTrackEditor::CreateTrackEditor(TSharedRef<ISequencer> InSequencer)
|
||||
{
|
||||
return MakeShareable(new FFMODEventControlTrackEditor(InSequencer));
|
||||
}
|
||||
|
||||
bool FFMODEventControlTrackEditor::SupportsType(TSubclassOf<UMovieSceneTrack> Type) const
|
||||
{
|
||||
return Type == UFMODEventControlTrack::StaticClass();
|
||||
}
|
||||
|
||||
TSharedRef<ISequencerSection> FFMODEventControlTrackEditor::MakeSectionInterface(
|
||||
UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding)
|
||||
{
|
||||
check(SupportsType(SectionObject.GetOuter()->GetClass()));
|
||||
const TSharedPtr<ISequencer> OwningSequencer = GetSequencer();
|
||||
return MakeShareable(new FFMODEventControlSection(SectionObject, OwningSequencer.ToSharedRef()));
|
||||
}
|
||||
|
||||
void FFMODEventControlTrackEditor::BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray<FGuid> &ObjectBindings, const UClass *ObjectClass)
|
||||
{
|
||||
if (ObjectClass->IsChildOf(AFMODAmbientSound::StaticClass()) || ObjectClass->IsChildOf(UFMODAudioComponent::StaticClass()))
|
||||
{
|
||||
const TSharedPtr<ISequencer> ParentSequencer = GetSequencer();
|
||||
|
||||
MenuBuilder.AddMenuEntry(LOCTEXT("AddFMODEventControlTrack", "FMOD Event Control Track"),
|
||||
LOCTEXT("FMODEventControlTooltip", "Adds a track for controlling FMOD event."), FSlateIcon(),
|
||||
FUIAction(FExecuteAction::CreateSP(this, &FFMODEventControlTrackEditor::AddControlKey, ObjectBindings)));
|
||||
}
|
||||
}
|
||||
|
||||
void FFMODEventControlTrackEditor::AddControlKey(TArray<FGuid> ObjectGuids)
|
||||
{
|
||||
TSharedPtr<ISequencer> SequencerPtr = GetSequencer();
|
||||
for (FGuid ObjectGuid : ObjectGuids)
|
||||
{
|
||||
UObject *Object = SequencerPtr.IsValid() ? SequencerPtr->FindSpawnedObjectOrTemplate(ObjectGuid) : nullptr;
|
||||
|
||||
if (Object)
|
||||
{
|
||||
AnimatablePropertyChanged(FOnKeyProperty::CreateRaw(this, &FFMODEventControlTrackEditor::AddKeyInternal, Object));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FKeyPropertyResult FFMODEventControlTrackEditor::AddKeyInternal(FFrameNumber KeyTime, UObject *Object)
|
||||
{
|
||||
FKeyPropertyResult KeyPropertyResult;
|
||||
|
||||
FFindOrCreateHandleResult HandleResult = FindOrCreateHandleToObject(Object);
|
||||
FGuid ObjectHandle = HandleResult.Handle;
|
||||
KeyPropertyResult.bHandleCreated |= HandleResult.bWasCreated;
|
||||
|
||||
if (ObjectHandle.IsValid())
|
||||
{
|
||||
FFindOrCreateTrackResult TrackResult = FindOrCreateTrackForObject(ObjectHandle, UFMODEventControlTrack::StaticClass());
|
||||
UMovieSceneTrack *Track = TrackResult.Track;
|
||||
KeyPropertyResult.bTrackCreated |= TrackResult.bWasCreated;
|
||||
|
||||
if (KeyPropertyResult.bTrackCreated && ensure(Track))
|
||||
{
|
||||
UFMODEventControlTrack *EventTrack = Cast<UFMODEventControlTrack>(Track);
|
||||
EventTrack->AddNewSection(KeyTime);
|
||||
EventTrack->SetDisplayName(LOCTEXT("TrackName", "FMOD Event"));
|
||||
KeyPropertyResult.bTrackModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
return KeyPropertyResult;
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
@ -0,0 +1,59 @@
|
||||
// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2023.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Misc/Guid.h"
|
||||
#include "Templates/SubclassOf.h"
|
||||
#include "Curves/KeyHandle.h"
|
||||
#include "ISequencer.h"
|
||||
#include "MovieSceneTrack.h"
|
||||
#include "ISequencerSection.h"
|
||||
#include "ISequencerTrackEditor.h"
|
||||
#include "MovieSceneTrackEditor.h"
|
||||
|
||||
class FMenuBuilder;
|
||||
class FSequencerSectionPainter;
|
||||
|
||||
/** FMOD Event control track */
|
||||
class FFMODEventControlTrackEditor : public FMovieSceneTrackEditor
|
||||
{
|
||||
public:
|
||||
FFMODEventControlTrackEditor(TSharedRef<ISequencer> InSequencer);
|
||||
|
||||
static TSharedRef<ISequencerTrackEditor> CreateTrackEditor(TSharedRef<ISequencer> OwningSequencer);
|
||||
|
||||
void AddControlKey(TArray<FGuid> ObjectGuids);
|
||||
|
||||
// Begin ISequencerTrackEditor interface
|
||||
virtual void BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray<FGuid> &ObjectBindings, const UClass *ObjectClass) override;
|
||||
virtual TSharedRef<ISequencerSection> MakeSectionInterface(
|
||||
UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding) override;
|
||||
virtual bool SupportsType(TSubclassOf<UMovieSceneTrack> Type) const override;
|
||||
// End ISequencerTrackEditor interface
|
||||
|
||||
private:
|
||||
/** Delegate for AnimatablePropertyChanged in AddKey. */
|
||||
virtual FKeyPropertyResult AddKeyInternal(FFrameNumber KeyTime, UObject *Object);
|
||||
};
|
||||
|
||||
/** Class for event control sections. */
|
||||
class FFMODEventControlSection : public ISequencerSection, public TSharedFromThis<FFMODEventControlSection>
|
||||
{
|
||||
public:
|
||||
FFMODEventControlSection(UMovieSceneSection &InSection, TSharedRef<ISequencer> InOwningSequencer);
|
||||
|
||||
// Begin ISequencerSection interface
|
||||
virtual UMovieSceneSection *GetSectionObject() override;
|
||||
virtual float GetSectionHeight() const override;
|
||||
virtual int32 OnPaintSection(FSequencerSectionPainter &InPainter) const override;
|
||||
virtual bool SectionIsResizable() const override { return false; }
|
||||
// End ISequencerSection interface
|
||||
|
||||
private:
|
||||
/** The section we are visualizing. */
|
||||
UMovieSceneSection &Section;
|
||||
|
||||
/** The sequencer that owns this section */
|
||||
TWeakPtr<ISequencer> OwningSequencerPtr;
|
||||
};
|
@ -0,0 +1,156 @@
|
||||
// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2023.
|
||||
|
||||
#include "FMODEventParameterTrackEditor.h"
|
||||
#include "FMODAmbientSound.h"
|
||||
#include "FMODEvent.h"
|
||||
#include "FMODStudioModule.h"
|
||||
#include "Framework/MultiBox/MultiBoxBuilder.h"
|
||||
#include "Sequencer/FMODEventParameterTrack.h"
|
||||
#include "Sections/MovieSceneParameterSection.h"
|
||||
#include "Sequencer/FMODParameterSection.h"
|
||||
#include "SequencerUtilities.h"
|
||||
#include "fmod_studio.hpp"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FMODEeventParameterTrackEditor"
|
||||
|
||||
FName FFMODEventParameterTrackEditor::TrackName("FMODEventParameter");
|
||||
|
||||
FFMODEventParameterTrackEditor::FFMODEventParameterTrackEditor(TSharedRef<ISequencer> InSequencer)
|
||||
: FMovieSceneTrackEditor(InSequencer)
|
||||
{
|
||||
}
|
||||
|
||||
TSharedRef<ISequencerTrackEditor> FFMODEventParameterTrackEditor::CreateTrackEditor(TSharedRef<ISequencer> OwningSequencer)
|
||||
{
|
||||
return MakeShareable(new FFMODEventParameterTrackEditor(OwningSequencer));
|
||||
}
|
||||
|
||||
TSharedRef<ISequencerSection> FFMODEventParameterTrackEditor::MakeSectionInterface(
|
||||
UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding)
|
||||
{
|
||||
UMovieSceneParameterSection *ParameterSection = Cast<UMovieSceneParameterSection>(&SectionObject);
|
||||
checkf(ParameterSection != nullptr, TEXT("Unsupported section type."));
|
||||
return MakeShareable(new FFMODParameterSection(*ParameterSection));
|
||||
}
|
||||
|
||||
TSharedPtr<SWidget> FFMODEventParameterTrackEditor::BuildOutlinerEditWidget(
|
||||
const FGuid &ObjectBinding, UMovieSceneTrack *Track, const FBuildEditWidgetParams &Params)
|
||||
{
|
||||
UFMODEventParameterTrack *EventParameterTrack = Cast<UFMODEventParameterTrack>(Track);
|
||||
|
||||
// Create a container edit box
|
||||
return FSequencerUtilities::MakeAddButton(LOCTEXT("ParameterText", "Parameter"),
|
||||
FOnGetContent::CreateSP(this, &FFMODEventParameterTrackEditor::OnGetAddParameterMenuContent, ObjectBinding, EventParameterTrack),
|
||||
Params.NodeIsHovered,
|
||||
GetSequencer());
|
||||
}
|
||||
|
||||
void FFMODEventParameterTrackEditor::BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray<FGuid> &ObjectBindings, const UClass *ObjectClass)
|
||||
{
|
||||
if (ObjectClass->IsChildOf(AFMODAmbientSound::StaticClass()) || ObjectClass->IsChildOf(UFMODAudioComponent::StaticClass()))
|
||||
{
|
||||
const TSharedPtr<ISequencer> ParentSequencer = GetSequencer();
|
||||
|
||||
MenuBuilder.AddMenuEntry(LOCTEXT("AddFMODParameterTrack", "FMOD Event Parameter Track"),
|
||||
LOCTEXT("AddFMODParameterTrackTooltip", "Adds a track for controlling FMOD event parameter values."), FSlateIcon(),
|
||||
FUIAction(FExecuteAction::CreateSP(this, &FFMODEventParameterTrackEditor::AddEventParameterTrack, ObjectBindings[0]),
|
||||
FCanExecuteAction::CreateSP(this, &FFMODEventParameterTrackEditor::CanAddEventParameterTrack, ObjectBindings[0])));
|
||||
}
|
||||
}
|
||||
|
||||
bool FFMODEventParameterTrackEditor::SupportsType(TSubclassOf<UMovieSceneTrack> Type) const
|
||||
{
|
||||
return Type == UFMODEventParameterTrack::StaticClass();
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> FFMODEventParameterTrackEditor::OnGetAddParameterMenuContent(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack)
|
||||
{
|
||||
TSharedPtr<ISequencer> SequencerPtr = GetSequencer();
|
||||
AFMODAmbientSound *Sound = SequencerPtr.IsValid() ? Cast<AFMODAmbientSound>(SequencerPtr->FindSpawnedObjectOrTemplate(ObjectBinding)) : nullptr;
|
||||
UFMODAudioComponent *AudioComponent;
|
||||
|
||||
if (IsValid(Sound))
|
||||
{
|
||||
AudioComponent = Sound->AudioComponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioComponent = SequencerPtr.IsValid() ? Cast<UFMODAudioComponent>(SequencerPtr->FindSpawnedObjectOrTemplate(ObjectBinding)) : nullptr;
|
||||
}
|
||||
return BuildParameterMenu(ObjectBinding, EventParameterTrack, AudioComponent);
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> FFMODEventParameterTrackEditor::BuildParameterMenu(
|
||||
FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, UFMODAudioComponent *AudioComponent)
|
||||
{
|
||||
FMenuBuilder AddParameterMenuBuilder(true, nullptr);
|
||||
|
||||
if (IsValid(AudioComponent) && AudioComponent->Event)
|
||||
{
|
||||
TArray<FParameterNameAndAction> ParameterNamesAndActions;
|
||||
TArray<FMOD_STUDIO_PARAMETER_DESCRIPTION> ParameterDescriptions;
|
||||
AudioComponent->Event->GetParameterDescriptions(ParameterDescriptions);
|
||||
|
||||
for (FMOD_STUDIO_PARAMETER_DESCRIPTION &ParameterDescription : ParameterDescriptions)
|
||||
{
|
||||
FName ParameterName(ParameterDescription.name);
|
||||
FExecuteAction InitAction =
|
||||
FExecuteAction::CreateSP(this, &FFMODEventParameterTrackEditor::AddParameter, ObjectBinding, EventParameterTrack, ParameterName);
|
||||
FUIAction AddParameterMenuAction(InitAction);
|
||||
FParameterNameAndAction NameAndAction(ParameterName, AddParameterMenuAction);
|
||||
ParameterNamesAndActions.Add(NameAndAction);
|
||||
}
|
||||
|
||||
// Sort and generate menu.
|
||||
ParameterNamesAndActions.Sort();
|
||||
for (FParameterNameAndAction NameAndAction : ParameterNamesAndActions)
|
||||
{
|
||||
AddParameterMenuBuilder.AddMenuEntry(FText::FromName(NameAndAction.ParameterName), FText(), FSlateIcon(), NameAndAction.Action);
|
||||
}
|
||||
}
|
||||
return AddParameterMenuBuilder.MakeWidget();
|
||||
}
|
||||
|
||||
bool FFMODEventParameterTrackEditor::CanAddEventParameterTrack(FGuid ObjectBinding)
|
||||
{
|
||||
return GetSequencer()->GetFocusedMovieSceneSequence()->GetMovieScene()->FindTrack(
|
||||
UFMODEventParameterTrack::StaticClass(), ObjectBinding, TrackName) == nullptr;
|
||||
}
|
||||
|
||||
void FFMODEventParameterTrackEditor::AddEventParameterTrack(FGuid ObjectBinding)
|
||||
{
|
||||
FindOrCreateTrackForObject(ObjectBinding, UFMODEventParameterTrack::StaticClass(), TrackName, true);
|
||||
GetSequencer()->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::MovieSceneStructureItemAdded);
|
||||
}
|
||||
|
||||
void FFMODEventParameterTrackEditor::AddParameter(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, FName ParameterName)
|
||||
{
|
||||
UMovieSceneSequence *MovieSceneSequence = GetMovieSceneSequence();
|
||||
FFrameNumber KeyTime = GetTimeForKey();
|
||||
|
||||
for (TWeakObjectPtr<> Object : GetSequencer()->FindObjectsInCurrentSequence(ObjectBinding))
|
||||
{
|
||||
AFMODAmbientSound *Sound = Cast<AFMODAmbientSound>(Object.Get());
|
||||
UFMODAudioComponent *AudioComponent = nullptr;
|
||||
|
||||
if (IsValid(Sound))
|
||||
{
|
||||
AudioComponent = Sound->AudioComponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioComponent = Cast<UFMODAudioComponent>(Object.Get());
|
||||
}
|
||||
|
||||
if (IsValid(AudioComponent))
|
||||
{
|
||||
float Value = AudioComponent->GetParameter(ParameterName);
|
||||
const FScopedTransaction Transaction(LOCTEXT("AddEventParameter", "Add event parameter"));
|
||||
EventParameterTrack->Modify();
|
||||
EventParameterTrack->AddParameterKey(ParameterName, KeyTime, Value);
|
||||
}
|
||||
}
|
||||
GetSequencer()->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::MovieSceneStructureItemAdded);
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
@ -0,0 +1,77 @@
|
||||
// Taken from ParticleParameterTrackEditor
|
||||
|
||||
#pragma once
|
||||
#include "CoreMinimal.h"
|
||||
#include "Misc/Guid.h"
|
||||
#include "Templates/SubclassOf.h"
|
||||
#include "Widgets/SWidget.h"
|
||||
#include "ISequencer.h"
|
||||
#include "MovieSceneTrack.h"
|
||||
#include "ISequencerSection.h"
|
||||
#include "Framework/Commands/UIAction.h"
|
||||
#include "ISequencerTrackEditor.h"
|
||||
#include "MovieSceneTrackEditor.h"
|
||||
|
||||
class FMenuBuilder;
|
||||
class UFMODEventParameterTrack;
|
||||
class UFMODAudioComponent;
|
||||
struct FMOD_STUDIO_PARAMETER_DESCRIPTION;
|
||||
|
||||
/**
|
||||
* Track editor for material parameters.
|
||||
*/
|
||||
class FFMODEventParameterTrackEditor : public FMovieSceneTrackEditor
|
||||
{
|
||||
public:
|
||||
/** Constructor. */
|
||||
FFMODEventParameterTrackEditor(TSharedRef<ISequencer> InSequencer);
|
||||
|
||||
/** Virtual destructor. */
|
||||
virtual ~FFMODEventParameterTrackEditor() {}
|
||||
|
||||
/**
|
||||
* Creates an instance of this class. Called by a sequencer.
|
||||
*
|
||||
* @param OwningSequencer The sequencer instance to be used by this tool.
|
||||
* @return The new instance of this class.
|
||||
*/
|
||||
static TSharedRef<ISequencerTrackEditor> CreateTrackEditor(TSharedRef<ISequencer> OwningSequencer);
|
||||
|
||||
// ISequencerTrackEditor interface
|
||||
|
||||
virtual TSharedPtr<SWidget> BuildOutlinerEditWidget(
|
||||
const FGuid &ObjectBinding, UMovieSceneTrack *Track, const FBuildEditWidgetParams &Params) override;
|
||||
virtual TSharedRef<ISequencerSection> MakeSectionInterface(
|
||||
UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding) override;
|
||||
virtual bool SupportsType(TSubclassOf<UMovieSceneTrack> Type) const override;
|
||||
|
||||
private:
|
||||
static FName TrackName;
|
||||
|
||||
// Struct used for building the parameter menu.
|
||||
struct FParameterNameAndAction
|
||||
{
|
||||
FName ParameterName;
|
||||
FUIAction Action;
|
||||
|
||||
FParameterNameAndAction(FName InParameterName, FUIAction InAction)
|
||||
{
|
||||
ParameterName = InParameterName;
|
||||
Action = InAction;
|
||||
}
|
||||
|
||||
bool operator<(FParameterNameAndAction const &Other) const { return ParameterName.FastLess(Other.ParameterName); }
|
||||
};
|
||||
|
||||
void BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray<FGuid> &ObjectBindings, const UClass *ObjectClass);
|
||||
|
||||
/** Provides the contents of the add parameter menu. */
|
||||
TSharedRef<SWidget> OnGetAddParameterMenuContent(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack);
|
||||
TSharedRef<SWidget> BuildParameterMenu(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, UFMODAudioComponent *AudioComponent);
|
||||
|
||||
bool CanAddEventParameterTrack(FGuid ObjectBinding);
|
||||
void AddEventParameterTrack(FGuid ObjectBinding);
|
||||
|
||||
/** Adds an event parameter and initial key to a track. */
|
||||
void AddParameter(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, FName ParameterName);
|
||||
};
|
@ -0,0 +1,25 @@
|
||||
// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2023.
|
||||
|
||||
#include "FMODParameterSection.h"
|
||||
#include "ISectionLayoutBuilder.h"
|
||||
#include "ScopedTransaction.h"
|
||||
#include "Sections/MovieSceneParameterSection.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FMODParameterSection"
|
||||
|
||||
bool FFMODParameterSection::RequestDeleteKeyArea(const TArray<FName> &KeyAreaNamePath)
|
||||
{
|
||||
if (KeyAreaNamePath.Num() == 1)
|
||||
{
|
||||
const FScopedTransaction Transaction(LOCTEXT("DeleteEventParameter", "Delete event parameter"));
|
||||
UMovieSceneParameterSection *ParameterSection = Cast<UMovieSceneParameterSection>(WeakSection.Get());
|
||||
if (ParameterSection->TryModify())
|
||||
{
|
||||
return ParameterSection->RemoveScalarParameter(KeyAreaNamePath[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
@ -0,0 +1,21 @@
|
||||
// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2023.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ISequencerSection.h"
|
||||
|
||||
class UMovieSceneSection;
|
||||
|
||||
/** A movie scene section for Event parameters. */
|
||||
class FFMODParameterSection : public FSequencerSection
|
||||
{
|
||||
public:
|
||||
FFMODParameterSection(UMovieSceneSection &InSectionObject)
|
||||
: FSequencerSection(InSectionObject)
|
||||
{
|
||||
}
|
||||
|
||||
// Begin ISequencerSection interface
|
||||
virtual bool RequestDeleteKeyArea(const TArray<FName> &KeyAreaNamePath) override;
|
||||
// End ISequencerSection interface
|
||||
};
|
Reference in New Issue
Block a user