// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CurveKeyEditors/SequencerKeyEditor.h" #include "Framework/MultiBox/MultiBoxExtender.h" #include "ISequencerChannelInterface.h" #include "Misc/NotifyHook.h" #include "MovieSceneSection.h" #include "TimeToPixel.h" #include "Widgets/Input/NumericTypeInterface.h" #include "Widgets/SCompoundWidget.h" #include "Widgets/Text/STextBlock.h" class FMenuBuilder; template class SNumericTextBlockKeyEditor : public SCompoundWidget { using FKeyEditor = TSequencerKeyEditor; FKeyEditor KeyEditor; TSharedPtr> Interface; SLATE_BEGIN_ARGS(SNumericTextBlockKeyEditor){} SLATE_END_ARGS() void Construct(const FArguments& InArgs, const FKeyEditor& InKeyEditor) { KeyEditor = InKeyEditor; Interface = MakeShareable(new TDefaultNumericTypeInterface); ChildSlot [ SNew(STextBlock) .Text(this, &SNumericTextBlockKeyEditor::GetValueAsText) ]; } FText GetValueAsText() const { const FString ValueString = Interface->ToString(KeyEditor.GetCurrentValue()); return FText::FromString(ValueString); } }; struct FPerlinNoiseChannelSectionMenuExtension : TSharedFromThis, ISidebarChannelExtension { FPerlinNoiseChannelSectionMenuExtension(TArrayView InChannelHandles, const TArray>& InWeakSections); virtual ~FPerlinNoiseChannelSectionMenuExtension() {} virtual TSharedPtr ExtendMenu(FMenuBuilder& MenuBuilder, const bool bInSubMenu) override; private: void Initialize(); void BuildChannelsMenu(FMenuBuilder& MenuBuilder); void BuildParametersMenu(FMenuBuilder& MenuBuilder, int32 ChannelHandleIndex); private: struct FChannelNotifyHook : FNotifyHook { TWeakObjectPtr WeakObjectToModify; FChannelNotifyHook(UObject* InObjectToModify) : WeakObjectToModify(InObjectToModify) {} virtual void NotifyPreChange(FProperty* PropertyAboutToChange) override; virtual void NotifyPostChange(const FPropertyChangedEvent& PropertyChangedEvent, FProperty* PropertyThatChanged) override; }; TArray ChannelHandles; TArray ChannelHandleSectionIndexes; TArray> WeakSections; TArray NotifyHooks; }; template struct TPerlinNoiseChannelInterface : ISequencerChannelInterface { using ChannelType = typename ChannelContainerType::ChannelType; virtual FKeyHandle AddOrUpdateKey_Raw(FMovieSceneChannel* Channel, UMovieSceneSection* SectionToKey, const void* ExtendedEditorData, FFrameNumber InTime, ISequencer& InSequencer, const FGuid& ObjectBindingID, FTrackInstancePropertyBindings* PropertyBindings) const override { return FKeyHandle::Invalid(); } virtual void DeleteKeys_Raw(FMovieSceneChannel* Channel, TArrayView InHandles, FFrameNumber InTime) const override { } virtual void CopyKeys_Raw(FMovieSceneChannel* Channel, const UMovieSceneSection* Section, FName KeyAreaName, FMovieSceneClipboardBuilder& ClipboardBuilder, TArrayView KeyMask) const override { } virtual void PasteKeys_Raw(FMovieSceneChannel* Channel, UMovieSceneSection* Section, const FMovieSceneClipboardKeyTrack& KeyTrack, const FMovieSceneClipboardEnvironment& SrcEnvironment, const FSequencerPasteEnvironment& DstEnvironment, TArray& OutPastedKeys) const override { } virtual TSharedPtr GetKeyStruct_Raw(FMovieSceneChannelHandle Channel, FKeyHandle KeyHandle) const override { return nullptr; } virtual bool CanCreateKeyEditor_Raw(const FMovieSceneChannel* Channel) const override { return true; } virtual TSharedRef CreateKeyEditor_Raw(const FMovieSceneChannelHandle& Channel, const UE::Sequencer::FCreateKeyEditorParams& Params) const override { const TMovieSceneExternalValue* ExternalValue = Channel.Cast().GetExtendedEditorData(); if (!ExternalValue) { return SNullWidget::NullWidget; } TSequencerKeyEditor KeyEditor( Params.ObjectBindingID, Channel.Cast(), Params.OwningSection, Params.Sequencer, Params.PropertyBindings, ExternalValue->OnGetExternalValue ); using KeyEditorType = SNumericTextBlockKeyEditor; return SNew(KeyEditorType, KeyEditor); } virtual void ExtendKeyMenu_Raw(FMenuBuilder& MenuBuilder, TSharedPtr MenuExtender, TArrayView Parameters, TWeakPtr InSequencer) const override { } virtual void ExtendSectionMenu_Raw(FMenuBuilder& MenuBuilder, TSharedPtr InMenuExtender, TArrayView InChannels, const TArray>& InWeakSections, TWeakPtr InWeakSequencer) const override { TSharedRef Extension = MakeShared(InChannels, InWeakSections); InMenuExtender->AddMenuExtension(TEXT("SequencerChannels"), EExtensionHook::First, nullptr , FMenuExtensionDelegate::CreateLambda([Extension](FMenuBuilder& MenuBuilder) { Extension->ExtendMenu(MenuBuilder, true); })); } virtual TSharedPtr ExtendSidebarMenu_Raw(FMenuBuilder& MenuBuilder, TSharedPtr InMenuExtender, TArrayView InChannels, const TArray>& InWeakSections, TWeakPtr InWeakSequencer) const override { const TSharedRef Extension = MakeShared(InChannels, InWeakSections); Extension->ExtendMenu(MenuBuilder, false); return Extension; } virtual void DrawKeys_Raw(FMovieSceneChannel* Channel, TArrayView InKeyHandles, const UMovieSceneSection* InOwner, TArrayView OutKeyDrawParams) const override { } virtual bool ShouldShowCurve_Raw(const FMovieSceneChannel* Channel, UMovieSceneSection* InSection) const override { return true; } virtual bool SupportsCurveEditorModels_Raw(const FMovieSceneChannelHandle& InChannel) const override { return false; } virtual TUniquePtr CreateCurveEditorModel_Raw(const FMovieSceneChannelHandle& Channel, const UE::Sequencer::FCreateCurveEditorModelParams& Params) const override { return nullptr; } virtual int32 DrawExtra_Raw(FMovieSceneChannel* InChannel, const UMovieSceneSection* InOwner, const FSequencerChannelPaintArgs& PaintArgs, int32 LayerId) const override { using namespace UE::Sequencer; FLinearColor FillColor(1, 1, 1, 0.334f); ChannelType* TypedChannel = static_cast(InChannel); TArray CurvePoints; CurvePoints.Reserve(PaintArgs.Geometry.Size.X / 2.0); const double Amplitude = TypedChannel->PerlinNoiseParams.Amplitude; const double YOffset = PaintArgs.Geometry.Size.Y / 2.0; const double YScale = (Amplitude != 0) ? (PaintArgs.Geometry.Size.Y / Amplitude / 2.0) : 1; for (double X = 0; X < PaintArgs.Geometry.Size.X; X += 2.f) { double Seconds = PaintArgs.TimeToPixel.PixelToSeconds(X); double Y = (double)TypedChannel->Evaluate(Seconds); CurvePoints.Add(FVector2D(X, YOffset - (Y * YScale))); } FSlateDrawElement::MakeLines( PaintArgs.DrawElements, LayerId, PaintArgs.Geometry.ToPaintGeometry(), CurvePoints, ESlateDrawEffect::PreMultipliedAlpha, FillColor, true); return LayerId + 1; } virtual TSharedPtr CreateChannelModel_Raw(const FMovieSceneChannelHandle& InChannelHandle, const UE::Sequencer::FSectionModel& InSection, FName InChannelName) const override { return nullptr; } virtual TSharedPtr CreateChannelView_Raw(const FMovieSceneChannelHandle& InChannelHandle, TWeakPtr InWeakModel, const UE::Sequencer::FCreateTrackLaneViewParams& Parameters) const override { return nullptr; } };