2014-12-07 19:09:38 -05:00
|
|
|
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
#include "MovieSceneToolsPrivatePCH.h"
|
|
|
|
|
#include "PropertyEditing.h"
|
|
|
|
|
#include "MovieScene.h"
|
|
|
|
|
#include "MovieSceneTrack.h"
|
|
|
|
|
#include "MovieSceneFloatTrack.h"
|
|
|
|
|
#include "MovieSceneVectorTrack.h"
|
|
|
|
|
#include "MovieSceneBoolTrack.h"
|
2015-04-21 10:08:36 -04:00
|
|
|
#include "MovieSceneByteTrack.h"
|
2014-03-14 14:13:41 -04:00
|
|
|
#include "MovieSceneColorTrack.h"
|
|
|
|
|
#include "ScopedTransaction.h"
|
|
|
|
|
#include "MovieSceneSection.h"
|
|
|
|
|
#include "ISequencerObjectChangeListener.h"
|
|
|
|
|
#include "ISequencerSection.h"
|
|
|
|
|
#include "ISectionLayoutBuilder.h"
|
|
|
|
|
#include "IKeyArea.h"
|
|
|
|
|
#include "MovieSceneFloatSection.h"
|
|
|
|
|
#include "MovieSceneVectorSection.h"
|
|
|
|
|
#include "MovieSceneBoolSection.h"
|
2015-04-21 10:08:36 -04:00
|
|
|
#include "MovieSceneByteSection.h"
|
2014-03-14 14:13:41 -04:00
|
|
|
#include "MovieSceneColorSection.h"
|
|
|
|
|
#include "MovieSceneToolHelpers.h"
|
|
|
|
|
#include "PropertyTrackEditor.h"
|
|
|
|
|
#include "CommonMovieSceneTools.h"
|
2014-06-18 14:57:34 -04:00
|
|
|
#include "PropertySection.h"
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A color section implementation
|
|
|
|
|
*/
|
|
|
|
|
class FColorPropertySection : public FPropertySection
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FColorPropertySection( UMovieSceneSection& InSectionObject, FName SectionName )
|
|
|
|
|
: FPropertySection(InSectionObject, SectionName) {}
|
|
|
|
|
|
2014-06-13 06:14:46 -04:00
|
|
|
virtual void GenerateSectionLayout( class ISectionLayoutBuilder& LayoutBuilder ) const override
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
UMovieSceneColorSection* ColorSection = Cast<UMovieSceneColorSection>(&SectionObject);
|
|
|
|
|
|
2015-02-16 11:59:08 -05:00
|
|
|
LayoutBuilder.AddKeyArea("R", NSLOCTEXT("FColorPropertySection", "RedArea", "Red"), MakeShareable(new FFloatCurveKeyArea(&ColorSection->GetRedCurve(), ColorSection)));
|
|
|
|
|
LayoutBuilder.AddKeyArea("G", NSLOCTEXT("FColorPropertySection", "GreenArea", "Green"), MakeShareable(new FFloatCurveKeyArea(&ColorSection->GetGreenCurve(), ColorSection)));
|
|
|
|
|
LayoutBuilder.AddKeyArea("B", NSLOCTEXT("FColorPropertySection", "BlueArea", "Blue"), MakeShareable(new FFloatCurveKeyArea(&ColorSection->GetBlueCurve(), ColorSection)));
|
|
|
|
|
LayoutBuilder.AddKeyArea("A", NSLOCTEXT("FColorPropertySection", "OpacityArea", "Opacity"), MakeShareable(new FFloatCurveKeyArea(&ColorSection->GetAlphaCurve(), ColorSection)));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2014-06-13 06:14:46 -04:00
|
|
|
virtual int32 OnPaintSection( const FGeometry& AllottedGeometry, const FSlateRect& SectionClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, bool bParentEnabled ) const override
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
const UMovieSceneColorSection* ColorSection = Cast<const UMovieSceneColorSection>(&SectionObject);
|
|
|
|
|
|
|
|
|
|
float StartTime = ColorSection->GetStartTime();
|
|
|
|
|
float EndTime = ColorSection->GetEndTime();
|
|
|
|
|
float SectionDuration = EndTime - StartTime;
|
2014-07-24 23:52:28 -04:00
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
if (!FMath::IsNearlyZero(SectionDuration))
|
|
|
|
|
{
|
2014-07-24 23:52:28 -04:00
|
|
|
LayerId = FPropertySection::OnPaintSection( AllottedGeometry, SectionClippingRect, OutDrawElements, LayerId, bParentEnabled );
|
|
|
|
|
|
|
|
|
|
FVector2D GradientSize = FVector2D(AllottedGeometry.Size.X, (AllottedGeometry.Size.Y / 4)-3.0f);
|
|
|
|
|
|
|
|
|
|
FPaintGeometry PaintGeometry = AllottedGeometry.ToPaintGeometry(FVector2D(0,0), GradientSize );
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
// If we are showing a background pattern and the colors is transparent, draw a checker pattern
|
|
|
|
|
const FSlateBrush* CheckerBrush = FEditorStyle::GetBrush( "Checker" );
|
2014-07-24 23:52:28 -04:00
|
|
|
FSlateDrawElement::MakeBox(OutDrawElements, LayerId, PaintGeometry, CheckerBrush, SectionClippingRect);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
TArray<FSlateGradientStop> GradientStops;
|
|
|
|
|
|
|
|
|
|
TArray< TKeyValuePair<float, FLinearColor> > ColorKeys;
|
|
|
|
|
ConsolidateColorCurves(ColorKeys, ColorSection);
|
|
|
|
|
|
|
|
|
|
for (int32 i = 0; i < ColorKeys.Num(); ++i)
|
|
|
|
|
{
|
|
|
|
|
float Time = ColorKeys[i].Key;
|
|
|
|
|
FLinearColor Color = ColorKeys[i].Value;
|
|
|
|
|
float TimeFraction = (Time - StartTime) / SectionDuration;
|
|
|
|
|
|
|
|
|
|
GradientStops.Add(FSlateGradientStop(FVector2D(TimeFraction * AllottedGeometry.Size.X, 0),
|
|
|
|
|
Color ));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GradientStops.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
FSlateDrawElement::MakeGradient(
|
|
|
|
|
OutDrawElements,
|
|
|
|
|
LayerId + 1,
|
2014-07-24 23:52:28 -04:00
|
|
|
PaintGeometry,
|
2014-03-14 14:13:41 -04:00
|
|
|
GradientStops,
|
|
|
|
|
Orient_Vertical,
|
|
|
|
|
SectionClippingRect
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LayerId + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void ConsolidateColorCurves(TArray< TKeyValuePair<float, FLinearColor> >& OutColorKeys, const UMovieSceneColorSection* Section) const
|
|
|
|
|
{
|
|
|
|
|
// @todo Sequencer Optimize - This could all get cached, instead of recalculating everything every OnPaint
|
|
|
|
|
|
|
|
|
|
const FRichCurve* Curves[4] = {
|
|
|
|
|
&Section->GetRedCurve(),
|
|
|
|
|
&Section->GetGreenCurve(),
|
|
|
|
|
&Section->GetBlueCurve(),
|
|
|
|
|
&Section->GetAlphaCurve()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// @todo Sequencer Optimize - This is a O(n^2) loop!
|
|
|
|
|
// Our times are floats, which means we can't use a map and
|
|
|
|
|
// do a quick lookup to see if the keys already exist
|
|
|
|
|
// because the keys are ordered, we could take advantage of that, however
|
|
|
|
|
TArray<float> TimesWithKeys;
|
|
|
|
|
for (int32 i = 0; i < 4; ++i)
|
|
|
|
|
{
|
|
|
|
|
const FRichCurve* Curve = Curves[i];
|
|
|
|
|
for (auto It(Curve->GetKeyIterator()); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
float KeyTime = It->Time;
|
|
|
|
|
|
|
|
|
|
bool bShouldAddKey = true;
|
|
|
|
|
|
|
|
|
|
int32 InsertKeyIndex = INDEX_NONE;
|
|
|
|
|
for (int32 k = 0; k < TimesWithKeys.Num(); ++k)
|
|
|
|
|
{
|
|
|
|
|
if (FMath::IsNearlyEqual(TimesWithKeys[k], KeyTime))
|
|
|
|
|
{
|
|
|
|
|
bShouldAddKey = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (TimesWithKeys[k] > KeyTime)
|
|
|
|
|
{
|
|
|
|
|
InsertKeyIndex = k;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-28 15:15:42 -04:00
|
|
|
if (InsertKeyIndex == INDEX_NONE && bShouldAddKey)
|
|
|
|
|
{
|
|
|
|
|
InsertKeyIndex = TimesWithKeys.Num();
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
if (bShouldAddKey)
|
|
|
|
|
{
|
|
|
|
|
TimesWithKeys.Insert(KeyTime, InsertKeyIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// @todo Sequencer Optimize - This another O(n^2) loop, since Eval is O(n)!
|
|
|
|
|
for (int32 i = 0; i < TimesWithKeys.Num(); ++i)
|
|
|
|
|
{
|
2014-07-28 15:15:42 -04:00
|
|
|
OutColorKeys.Add( TKeyValuePair<float, FLinearColor>(TimesWithKeys[i], Section->Eval(TimesWithKeys[i], FLinearColor(0,0,0,0) ) ) );
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An implementation of float property sections
|
|
|
|
|
*/
|
|
|
|
|
class FFloatPropertySection : public FPropertySection
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FFloatPropertySection( UMovieSceneSection& InSectionObject, FName SectionName )
|
|
|
|
|
: FPropertySection(InSectionObject, SectionName) {}
|
|
|
|
|
|
2014-06-13 06:14:46 -04:00
|
|
|
virtual void GenerateSectionLayout( class ISectionLayoutBuilder& LayoutBuilder ) const override
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
UMovieSceneFloatSection* FloatSection = Cast<UMovieSceneFloatSection>( &SectionObject );
|
2015-02-16 11:59:08 -05:00
|
|
|
LayoutBuilder.SetSectionAsKeyArea( MakeShareable( new FFloatCurveKeyArea( &FloatSection->GetFloatCurve(), FloatSection ) ) );
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An implementation of vector property sections
|
|
|
|
|
*/
|
|
|
|
|
class FVectorPropertySection : public FPropertySection
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FVectorPropertySection( UMovieSceneSection& InSectionObject, FName SectionName )
|
|
|
|
|
: FPropertySection(InSectionObject, SectionName) {}
|
|
|
|
|
|
2014-06-13 06:14:46 -04:00
|
|
|
virtual void GenerateSectionLayout( class ISectionLayoutBuilder& LayoutBuilder ) const override
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
UMovieSceneVectorSection* VectorSection = Cast<UMovieSceneVectorSection>( &SectionObject );
|
|
|
|
|
int32 ChannelsUsed = VectorSection->GetChannelsUsed();
|
|
|
|
|
check(ChannelsUsed >= 2 && ChannelsUsed <= 4);
|
|
|
|
|
|
2015-02-16 11:59:08 -05:00
|
|
|
LayoutBuilder.AddKeyArea("Vector.X", NSLOCTEXT("FVectorPropertySection", "XArea", "X"), MakeShareable(new FFloatCurveKeyArea(&VectorSection->GetCurve(0), VectorSection)));
|
|
|
|
|
LayoutBuilder.AddKeyArea("Vector.Y", NSLOCTEXT("FVectorPropertySection", "YArea", "Y"), MakeShareable(new FFloatCurveKeyArea(&VectorSection->GetCurve(1), VectorSection)));
|
2014-03-14 14:13:41 -04:00
|
|
|
if (ChannelsUsed >= 3)
|
2014-06-18 14:57:34 -04:00
|
|
|
{
|
2015-02-16 11:59:08 -05:00
|
|
|
LayoutBuilder.AddKeyArea("Vector.Z", NSLOCTEXT("FVectorPropertySection", "ZArea", "Z"), MakeShareable(new FFloatCurveKeyArea(&VectorSection->GetCurve(2), VectorSection)));
|
2014-06-18 14:57:34 -04:00
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
if (ChannelsUsed >= 4)
|
2014-06-18 14:57:34 -04:00
|
|
|
{
|
2015-02-16 11:59:08 -05:00
|
|
|
LayoutBuilder.AddKeyArea("Vector.W", NSLOCTEXT("FVectorPropertySection", "WArea", "W"), MakeShareable(new FFloatCurveKeyArea(&VectorSection->GetCurve(3), VectorSection)));
|
2014-06-18 14:57:34 -04:00
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An implementation of bool property sections
|
|
|
|
|
*/
|
|
|
|
|
class FBoolPropertySection : public FPropertySection
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FBoolPropertySection( UMovieSceneSection& InSectionObject, FName SectionName )
|
|
|
|
|
: FPropertySection(InSectionObject, SectionName) {}
|
|
|
|
|
|
2014-06-13 06:14:46 -04:00
|
|
|
virtual void GenerateSectionLayout( class ISectionLayoutBuilder& LayoutBuilder ) const override
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
UMovieSceneBoolSection* BoolSection = Cast<UMovieSceneBoolSection>( &SectionObject );
|
|
|
|
|
LayoutBuilder.SetSectionAsKeyArea( MakeShareable( new FIntegralKeyArea( BoolSection->GetCurve() ) ) );
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-13 06:14:46 -04:00
|
|
|
virtual int32 OnPaintSection( const FGeometry& AllottedGeometry, const FSlateRect& SectionClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, bool bParentEnabled ) const override
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
FTimeToPixel TimeToPixelConverter( AllottedGeometry, TRange<float>( SectionObject.GetStartTime(), SectionObject.GetEndTime() ) );
|
|
|
|
|
|
|
|
|
|
// custom drawing for bool curves
|
|
|
|
|
UMovieSceneBoolSection* BoolSection = Cast<UMovieSceneBoolSection>( &SectionObject );
|
|
|
|
|
|
|
|
|
|
TArray<float> SectionSwitchTimes;
|
|
|
|
|
SectionSwitchTimes.Add(SectionObject.GetStartTime());
|
|
|
|
|
FIntegralCurve& BoolCurve = BoolSection->GetCurve();
|
|
|
|
|
for (TArray<FIntegralKey>::TConstIterator It(BoolCurve.GetKeyIterator()); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
float Time = It->Time;
|
|
|
|
|
if (Time > SectionObject.GetStartTime() && Time < SectionObject.GetEndTime())
|
|
|
|
|
{
|
|
|
|
|
SectionSwitchTimes.Add(Time);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SectionSwitchTimes.Add(SectionObject.GetEndTime());
|
|
|
|
|
|
|
|
|
|
for (int32 i = 0; i < SectionSwitchTimes.Num() - 1; ++i)
|
|
|
|
|
{
|
|
|
|
|
float FirstTime = SectionSwitchTimes[i];
|
|
|
|
|
float NextTime = SectionSwitchTimes[i+1];
|
|
|
|
|
float FirstTimeInPixels = TimeToPixelConverter.TimeToPixel(FirstTime);
|
|
|
|
|
float NextTimeInPixels = TimeToPixelConverter.TimeToPixel(NextTime);
|
|
|
|
|
if (BoolSection->Eval(FirstTime))
|
|
|
|
|
{
|
|
|
|
|
FSlateDrawElement::MakeBox(
|
|
|
|
|
OutDrawElements,
|
|
|
|
|
LayerId,
|
|
|
|
|
AllottedGeometry.ToPaintGeometry(FVector2D(FirstTimeInPixels, 0), FVector2D(NextTimeInPixels - FirstTimeInPixels, AllottedGeometry.Size.Y)),
|
|
|
|
|
FEditorStyle::GetBrush("Sequencer.GenericSection.Background"),
|
|
|
|
|
SectionClippingRect,
|
|
|
|
|
ESlateDrawEffect::None,
|
|
|
|
|
FLinearColor(0.f, 1.f, 0.f, 1.f)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FSlateDrawElement::MakeBox(
|
|
|
|
|
OutDrawElements,
|
|
|
|
|
LayerId,
|
|
|
|
|
AllottedGeometry.ToPaintGeometry(FVector2D(FirstTimeInPixels, 0), FVector2D(NextTimeInPixels - FirstTimeInPixels, AllottedGeometry.Size.Y)),
|
|
|
|
|
FEditorStyle::GetBrush("Sequencer.GenericSection.Background"),
|
|
|
|
|
SectionClippingRect,
|
|
|
|
|
ESlateDrawEffect::None,
|
|
|
|
|
FLinearColor(1.f, 0.f, 0.f, 1.f)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LayerId+1;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-04-21 10:08:36 -04:00
|
|
|
/**
|
|
|
|
|
* An implementation of byte property sections
|
|
|
|
|
*/
|
|
|
|
|
class FBytePropertySection : public FPropertySection
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FBytePropertySection(UMovieSceneSection& InSectionObject, FName SectionName)
|
|
|
|
|
: FPropertySection(InSectionObject, SectionName) {}
|
|
|
|
|
|
|
|
|
|
virtual void GenerateSectionLayout(class ISectionLayoutBuilder& LayoutBuilder) const override
|
|
|
|
|
{
|
|
|
|
|
UMovieSceneByteSection* ByteSection = Cast<UMovieSceneByteSection>(&SectionObject);
|
|
|
|
|
LayoutBuilder.SetSectionAsKeyArea(MakeShareable(new FIntegralKeyArea(ByteSection->GetCurve())));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
FPropertyTrackEditor::FPropertyTrackEditor( TSharedRef<ISequencer> InSequencer )
|
|
|
|
|
: FMovieSceneTrackEditor( InSequencer )
|
|
|
|
|
{
|
|
|
|
|
// Get the object change listener for the sequencer and register a delegates for when properties change that we care about
|
|
|
|
|
ISequencerObjectChangeListener& ObjectChangeListener = InSequencer->GetObjectChangeListener();
|
2014-06-20 14:28:07 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_FloatProperty ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedPropertyChanged<float, UMovieSceneFloatTrack> );
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_BoolProperty ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedPropertyChanged<bool, UMovieSceneBoolTrack> );
|
2015-04-21 10:08:36 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_ByteProperty ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedPropertyChanged<uint8, UMovieSceneByteTrack>);
|
2014-06-20 14:28:07 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_Vector ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedVectorPropertyChanged );
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_Vector4 ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedVectorPropertyChanged );
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_Vector2D ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedVectorPropertyChanged );
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_Color ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedColorPropertyChanged );
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( NAME_LinearColor ).AddRaw( this, &FPropertyTrackEditor::OnAnimatedColorPropertyChanged );
|
2014-10-24 13:51:35 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged( "SlateColor").AddRaw( this, &FPropertyTrackEditor::OnAnimatedColorPropertyChanged );
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FPropertyTrackEditor::~FPropertyTrackEditor()
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<ISequencer> Sequencer = GetSequencer();
|
|
|
|
|
if( Sequencer.IsValid() )
|
|
|
|
|
{
|
|
|
|
|
ISequencerObjectChangeListener& ObjectChangeListener = Sequencer->GetObjectChangeListener();
|
2014-06-20 14:28:07 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_FloatProperty).RemoveAll(this);
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_BoolProperty).RemoveAll(this);
|
2015-04-21 10:08:36 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_ByteProperty).RemoveAll(this);
|
2014-06-20 14:28:07 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_Vector).RemoveAll(this);
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_Vector4).RemoveAll(this);
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_Vector2D).RemoveAll(this);
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_Color).RemoveAll(this);
|
|
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged(NAME_LinearColor).RemoveAll(this);
|
2014-10-24 15:21:57 -04:00
|
|
|
ObjectChangeListener.GetOnAnimatablePropertyChanged("SlateColor").RemoveAll(this);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TSharedRef<FMovieSceneTrackEditor> FPropertyTrackEditor::CreateTrackEditor( TSharedRef<ISequencer> InSequencer )
|
|
|
|
|
{
|
|
|
|
|
return MakeShareable( new FPropertyTrackEditor( InSequencer ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FPropertyTrackEditor::SupportsType( TSubclassOf<UMovieSceneTrack> Type ) const
|
|
|
|
|
{
|
|
|
|
|
// We support animatable floats and bools and colors
|
|
|
|
|
return Type == UMovieSceneFloatTrack::StaticClass() ||
|
|
|
|
|
Type == UMovieSceneBoolTrack::StaticClass() ||
|
2015-04-21 10:08:36 -04:00
|
|
|
Type == UMovieSceneByteTrack::StaticClass() ||
|
2014-03-14 14:13:41 -04:00
|
|
|
Type == UMovieSceneVectorTrack::StaticClass() ||
|
|
|
|
|
Type == UMovieSceneColorTrack::StaticClass();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedRef<ISequencerSection> FPropertyTrackEditor::MakeSectionInterface( UMovieSceneSection& SectionObject, UMovieSceneTrack* Track )
|
|
|
|
|
{
|
|
|
|
|
check( SupportsType( SectionObject.GetOuter()->GetClass() ) );
|
|
|
|
|
|
|
|
|
|
UClass* SectionClass = SectionObject.GetOuter()->GetClass();
|
|
|
|
|
|
|
|
|
|
TSharedRef<ISequencerSection> NewSection = TSharedRef<ISequencerSection>(
|
|
|
|
|
SectionClass == UMovieSceneColorTrack::StaticClass() ? new FColorPropertySection( SectionObject, Track->GetTrackName() ) :
|
|
|
|
|
SectionClass == UMovieSceneBoolTrack::StaticClass() ? new FBoolPropertySection( SectionObject, Track->GetTrackName() ) :
|
2015-04-21 10:08:36 -04:00
|
|
|
SectionClass == UMovieSceneByteTrack::StaticClass() ? new FBytePropertySection(SectionObject, Track->GetTrackName()) :
|
2014-03-14 14:13:41 -04:00
|
|
|
SectionClass == UMovieSceneVectorTrack::StaticClass() ? new FVectorPropertySection( SectionObject, Track->GetTrackName() ) :
|
|
|
|
|
SectionClass == UMovieSceneFloatTrack::StaticClass() ? new FFloatPropertySection( SectionObject, Track->GetTrackName() ) :
|
|
|
|
|
new FPropertySection( SectionObject, Track->GetTrackName() )
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return NewSection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FPropertyTrackEditor::AddKey(const FGuid& ObjectGuid, UObject* AdditionalAsset)
|
|
|
|
|
{
|
|
|
|
|
ISequencerObjectChangeListener& ObjectChangeListener = GetSequencer()->GetObjectChangeListener();
|
|
|
|
|
|
|
|
|
|
TArray<UObject*> OutObjects;
|
|
|
|
|
GetSequencer()->GetRuntimeObjects( GetSequencer()->GetFocusedMovieSceneInstance(), ObjectGuid, OutObjects);
|
|
|
|
|
for (int32 i = 0; i < OutObjects.Num(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ObjectChangeListener.TriggerAllPropertiesChanged(OutObjects[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename Type, typename TrackType>
|
2014-07-24 23:52:28 -04:00
|
|
|
void FPropertyTrackEditor::OnAnimatedPropertyChanged(const FKeyPropertyParams& KeyPropertyParams )
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// Get the value from the property
|
|
|
|
|
Type Value;
|
2014-07-24 23:52:28 -04:00
|
|
|
FPropertyAccess::Result Result = KeyPropertyParams.PropertyHandle->GetValue( Value );
|
2014-03-14 14:13:41 -04:00
|
|
|
check( Result == FPropertyAccess::Success );
|
|
|
|
|
|
2014-07-24 23:52:28 -04:00
|
|
|
AnimatablePropertyChanged(TrackType::StaticClass(), KeyPropertyParams.bRequireAutoKey,
|
|
|
|
|
FOnKeyProperty::CreateRaw(this, &FPropertyTrackEditor::OnKeyProperty<Type, TrackType>, KeyPropertyParams, Value) );
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2014-07-24 23:52:28 -04:00
|
|
|
|
|
|
|
|
void FPropertyTrackEditor::OnAnimatedVectorPropertyChanged(const FKeyPropertyParams& KeyPropertyParams)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
bool bIsVector2D = false, bIsVector = false, bIsVector4 = false;
|
2014-07-24 23:52:28 -04:00
|
|
|
const UStructProperty* StructProp = Cast<const UStructProperty>(KeyPropertyParams.PropertyHandle->GetProperty());
|
2014-03-14 14:13:41 -04:00
|
|
|
if (StructProp && StructProp->Struct)
|
|
|
|
|
{
|
|
|
|
|
FName StructName = StructProp->Struct->GetFName();
|
|
|
|
|
|
|
|
|
|
bIsVector2D = StructName == NAME_Vector2D;
|
|
|
|
|
bIsVector = StructName == NAME_Vector;
|
|
|
|
|
bIsVector4 = StructName == NAME_Vector4;
|
|
|
|
|
}
|
2014-07-24 23:52:28 -04:00
|
|
|
if (!bIsVector2D && !bIsVector && !bIsVector4)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get the vector value from the property
|
|
|
|
|
FPropertyAccess::Result Result = FPropertyAccess::Fail;
|
2014-07-24 23:52:28 -04:00
|
|
|
const bool bRequiresAutoKey = KeyPropertyParams.bRequireAutoKey;
|
|
|
|
|
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
if (bIsVector2D)
|
|
|
|
|
{
|
2014-07-24 23:52:28 -04:00
|
|
|
FVectorKey<FVector2D> NewKey;
|
|
|
|
|
NewKey.CurveName = KeyPropertyParams.InnerStructPropertyName;
|
|
|
|
|
NewKey.bAddKeyEvenIfUnchanged = !bRequiresAutoKey;
|
|
|
|
|
|
|
|
|
|
Result = KeyPropertyParams.PropertyHandle->GetValue( NewKey.Value );
|
|
|
|
|
|
|
|
|
|
FOnKeyProperty OnKeyPropertyDelegate = FOnKeyProperty::CreateRaw( this, &FPropertyTrackEditor::OnKeyProperty<FVectorKey<FVector2D>, UMovieSceneVectorTrack>, KeyPropertyParams, NewKey );
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
check( Result == FPropertyAccess::Success );
|
2014-07-24 23:52:28 -04:00
|
|
|
AnimatablePropertyChanged(UMovieSceneVectorTrack::StaticClass(), bRequiresAutoKey, OnKeyPropertyDelegate );
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
else if (bIsVector)
|
|
|
|
|
{
|
2014-07-24 23:52:28 -04:00
|
|
|
FVectorKey<FVector> NewKey;
|
|
|
|
|
NewKey.CurveName = KeyPropertyParams.InnerStructPropertyName;
|
|
|
|
|
NewKey.bAddKeyEvenIfUnchanged = !bRequiresAutoKey;
|
|
|
|
|
|
|
|
|
|
Result = KeyPropertyParams.PropertyHandle->GetValue(NewKey.Value);
|
|
|
|
|
|
|
|
|
|
FOnKeyProperty OnKeyPropertyDelegate = FOnKeyProperty::CreateRaw(this, &FPropertyTrackEditor::OnKeyProperty<FVectorKey<FVector>, UMovieSceneVectorTrack>, KeyPropertyParams, NewKey );
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
check( Result == FPropertyAccess::Success );
|
2014-07-24 23:52:28 -04:00
|
|
|
AnimatablePropertyChanged( UMovieSceneVectorTrack::StaticClass(),bRequiresAutoKey, OnKeyPropertyDelegate );
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
else if (bIsVector4)
|
|
|
|
|
{
|
2014-07-24 23:52:28 -04:00
|
|
|
FVectorKey<FVector4> NewKey;
|
|
|
|
|
NewKey.CurveName = KeyPropertyParams.InnerStructPropertyName;
|
|
|
|
|
NewKey.bAddKeyEvenIfUnchanged = !bRequiresAutoKey;
|
|
|
|
|
|
|
|
|
|
Result = KeyPropertyParams.PropertyHandle->GetValue(NewKey.Value);
|
|
|
|
|
|
|
|
|
|
FOnKeyProperty OnKeyPropertyDelegate = FOnKeyProperty::CreateRaw(this, &FPropertyTrackEditor::OnKeyProperty<FVectorKey<FVector4>, UMovieSceneVectorTrack>, KeyPropertyParams, NewKey );
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
check( Result == FPropertyAccess::Success );
|
2014-07-24 23:52:28 -04:00
|
|
|
AnimatablePropertyChanged(UMovieSceneVectorTrack::StaticClass(),bRequiresAutoKey, OnKeyPropertyDelegate );
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 23:52:28 -04:00
|
|
|
void FPropertyTrackEditor::OnAnimatedColorPropertyChanged(const FKeyPropertyParams& KeyPropertyParams )
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-10-24 13:51:35 -04:00
|
|
|
bool bIsFColor = false, bIsFLinearColor = false, bIsSlateColor = false;
|
2014-07-24 23:52:28 -04:00
|
|
|
const UStructProperty* StructProp = Cast<const UStructProperty>(KeyPropertyParams.PropertyHandle->GetProperty());
|
2014-03-14 14:13:41 -04:00
|
|
|
if (StructProp && StructProp->Struct)
|
|
|
|
|
{
|
|
|
|
|
FName StructName = StructProp->Struct->GetFName();
|
|
|
|
|
|
|
|
|
|
bIsFColor = StructName == NAME_Color;
|
|
|
|
|
bIsFLinearColor = StructName == NAME_LinearColor;
|
2014-10-24 13:51:35 -04:00
|
|
|
bIsSlateColor = StructName == FName("SlateColor");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!bIsFColor && !bIsFLinearColor && !bIsSlateColor)
|
|
|
|
|
{
|
|
|
|
|
return;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-24 23:52:28 -04:00
|
|
|
FName PropertyName = KeyPropertyParams.PropertyHandle->GetProperty()->GetFName();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-07-24 23:52:28 -04:00
|
|
|
const UClass* PropertyClass = KeyPropertyParams.PropertyHandle->GetPropertyClass();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
TSharedPtr<IPropertyHandle> ChildProperties[4] = {
|
2014-07-24 23:52:28 -04:00
|
|
|
KeyPropertyParams.PropertyHandle->GetChildHandle("R"),
|
|
|
|
|
KeyPropertyParams.PropertyHandle->GetChildHandle("G"),
|
|
|
|
|
KeyPropertyParams.PropertyHandle->GetChildHandle("B"),
|
|
|
|
|
KeyPropertyParams.PropertyHandle->GetChildHandle("A")
|
2014-03-14 14:13:41 -04:00
|
|
|
};
|
|
|
|
|
|
2014-07-17 00:07:27 -04:00
|
|
|
uint8 FColorChannels[4];
|
2014-03-14 14:13:41 -04:00
|
|
|
float FLinearColorChannels[4];
|
|
|
|
|
for (int32 i = 0; i < 4; ++i)
|
|
|
|
|
{
|
|
|
|
|
FPropertyAccess::Result Result = bIsFColor ?
|
|
|
|
|
ChildProperties[i]->GetValue(FColorChannels[i]) :
|
|
|
|
|
ChildProperties[i]->GetValue(FLinearColorChannels[i]);
|
|
|
|
|
check( Result == FPropertyAccess::Success );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FLinearColor ColorValue;
|
|
|
|
|
if (bIsFColor)
|
|
|
|
|
{
|
|
|
|
|
ColorValue = FColor(FColorChannels[0], FColorChannels[1], FColorChannels[2], FColorChannels[3]).ReinterpretAsLinear();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ColorValue = FLinearColor(FLinearColorChannels[0], FLinearColorChannels[1], FLinearColorChannels[2], FLinearColorChannels[3]);
|
|
|
|
|
}
|
2014-07-24 23:52:28 -04:00
|
|
|
|
2014-07-17 00:07:27 -04:00
|
|
|
if( StructProp->HasMetaData("HideAlphaChannel") )
|
|
|
|
|
{
|
|
|
|
|
ColorValue.A = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 23:52:28 -04:00
|
|
|
|
|
|
|
|
FColorKey Key;
|
|
|
|
|
Key.Value = ColorValue;
|
|
|
|
|
Key.CurveName = KeyPropertyParams.InnerStructPropertyName;
|
|
|
|
|
Key.bAddKeyEvenIfUnchanged = !KeyPropertyParams.bRequireAutoKey;
|
2014-10-24 13:51:35 -04:00
|
|
|
Key.bIsSlateColor = bIsSlateColor;
|
2014-07-24 23:52:28 -04:00
|
|
|
|
|
|
|
|
AnimatablePropertyChanged(UMovieSceneColorTrack::StaticClass(), KeyPropertyParams.bRequireAutoKey, FOnKeyProperty::CreateRaw(this, &FPropertyTrackEditor::OnKeyProperty<FColorKey, UMovieSceneColorTrack>, KeyPropertyParams, Key) );
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Type, typename TrackType>
|
2014-07-24 23:52:28 -04:00
|
|
|
void FPropertyTrackEditor::OnKeyProperty( float KeyTime, FKeyPropertyParams KeyPropertyParams, Type Value )
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-07-24 23:52:28 -04:00
|
|
|
for( UObject* Object : KeyPropertyParams.ObjectsThatChanged )
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-16 16:37:22 -04:00
|
|
|
FGuid ObjectHandle = FindOrCreateHandleToObject( Object );
|
|
|
|
|
if (ObjectHandle.IsValid())
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-07-24 23:52:28 -04:00
|
|
|
FName PropertyName = KeyPropertyParams.PropertyHandle->GetProperty()->GetFName();
|
|
|
|
|
|
2014-06-16 16:37:22 -04:00
|
|
|
UMovieSceneTrack* Track = GetTrackForObject( ObjectHandle, TrackType::StaticClass(), PropertyName );
|
2014-03-14 14:13:41 -04:00
|
|
|
if( ensure( Track ) )
|
|
|
|
|
{
|
|
|
|
|
TrackType* TypedTrack = CastChecked<TrackType>(Track);
|
2014-07-24 23:52:28 -04:00
|
|
|
|
2014-07-28 15:15:42 -04:00
|
|
|
TypedTrack->SetPropertyNameAndPath( PropertyName, KeyPropertyParams.PropertyPath );
|
2014-03-14 14:13:41 -04:00
|
|
|
// Find or add a new section at the auto-key time and changing the property same property
|
|
|
|
|
// AddKeyToSection is not actually a virtual, it's redefined in each class with a different type
|
2014-07-24 23:52:28 -04:00
|
|
|
bool bSuccessfulAdd = TypedTrack->AddKeyToSection( KeyTime, Value );
|
2014-06-16 16:37:22 -04:00
|
|
|
if (bSuccessfulAdd)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
TypedTrack->SetAsShowable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-16 16:37:22 -04:00
|
|
|
|