189 lines
6.4 KiB
C++
189 lines
6.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MovieSceneGeometryCollectionSection.h"
|
|
#include "MovieSceneGeometryCollectionTemplate.h"
|
|
#include "Logging/MessageLog.h"
|
|
#include "MovieScene.h"
|
|
#include "UObject/SequencerObjectVersion.h"
|
|
#include "MovieSceneTimeHelpers.h"
|
|
#include "Misc/FrameRate.h"
|
|
|
|
#include UE_INLINE_GENERATED_CPP_BY_NAME(MovieSceneGeometryCollectionSection)
|
|
|
|
#define LOCTEXT_NAMESPACE "MovieSceneGeometryCollectionSection"
|
|
|
|
namespace
|
|
{
|
|
float GeometryCollectionDeprecatedMagicNumber = TNumericLimits<float>::Lowest();
|
|
}
|
|
|
|
FMovieSceneGeometryCollectionParams::FMovieSceneGeometryCollectionParams()
|
|
{
|
|
PlayRate = 1.f;
|
|
}
|
|
|
|
UMovieSceneGeometryCollectionSection::UMovieSceneGeometryCollectionSection( const FObjectInitializer& ObjectInitializer )
|
|
: Super( ObjectInitializer )
|
|
{
|
|
BlendType = EMovieSceneBlendType::Absolute;
|
|
EvalOptions.EnableAndSetCompletionMode(EMovieSceneCompletionMode::RestoreState);
|
|
|
|
#if WITH_EDITOR
|
|
|
|
PreviousPlayRate = Params.PlayRate;
|
|
|
|
#endif
|
|
}
|
|
|
|
TOptional<FFrameTime> UMovieSceneGeometryCollectionSection::GetOffsetTime() const
|
|
{
|
|
return TOptional<FFrameTime>(Params.StartFrameOffset);
|
|
}
|
|
|
|
void UMovieSceneGeometryCollectionSection::MigrateFrameTimes(FFrameRate SourceRate, FFrameRate DestinationRate)
|
|
{
|
|
if (Params.StartFrameOffset.Value > 0)
|
|
{
|
|
FFrameNumber NewStartFrameOffset = ConvertFrameTime(FFrameTime(Params.StartFrameOffset), SourceRate, DestinationRate).FloorToFrame();
|
|
Params.StartFrameOffset = NewStartFrameOffset;
|
|
}
|
|
|
|
if (Params.EndFrameOffset.Value > 0)
|
|
{
|
|
FFrameNumber NewEndFrameOffset = ConvertFrameTime(FFrameTime(Params.EndFrameOffset), SourceRate, DestinationRate).FloorToFrame();
|
|
Params.EndFrameOffset = NewEndFrameOffset;
|
|
}
|
|
}
|
|
|
|
UObject* UMovieSceneGeometryCollectionSection::GetSourceObject() const
|
|
{
|
|
return Params.GeometryCollectionCache.ResolveObject();
|
|
}
|
|
|
|
FFrameNumber GetStartOffsetAtTrimTime(FQualifiedFrameTime TrimTime, const FMovieSceneGeometryCollectionParams& Params, FFrameNumber StartFrame, FFrameRate FrameRate)
|
|
{
|
|
float AnimPlayRate = FMath::IsNearlyZero(Params.PlayRate) ? 1.0f : Params.PlayRate;
|
|
float AnimPosition = (TrimTime.Time - StartFrame) / TrimTime.Rate * AnimPlayRate;
|
|
float SeqLength = Params.GetSequenceLength() - FrameRate.AsSeconds(Params.StartFrameOffset + Params.EndFrameOffset) / AnimPlayRate;
|
|
|
|
FFrameNumber NewOffset = FrameRate.AsFrameNumber(FMath::Fmod(AnimPosition, SeqLength));
|
|
NewOffset += Params.StartFrameOffset;
|
|
|
|
return NewOffset;
|
|
}
|
|
|
|
|
|
TOptional<TRange<FFrameNumber> > UMovieSceneGeometryCollectionSection::GetAutoSizeRange() const
|
|
{
|
|
FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
|
|
|
|
FFrameTime AnimationLength = Params.GetSequenceLength() * FrameRate;
|
|
|
|
return TRange<FFrameNumber>(GetInclusiveStartFrame(), GetInclusiveStartFrame() + AnimationLength.FrameNumber);
|
|
}
|
|
|
|
|
|
void UMovieSceneGeometryCollectionSection::TrimSection(FQualifiedFrameTime TrimTime, bool bTrimLeft, bool bDeleteKeys)
|
|
{
|
|
SetFlags(RF_Transactional);
|
|
|
|
if (TryModify())
|
|
{
|
|
if (bTrimLeft)
|
|
{
|
|
FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
|
|
|
|
Params.StartFrameOffset = HasStartFrame() ? GetStartOffsetAtTrimTime(TrimTime, Params, GetInclusiveStartFrame(), FrameRate) : 0;
|
|
}
|
|
|
|
Super::TrimSection(TrimTime, bTrimLeft, bDeleteKeys);
|
|
}
|
|
}
|
|
|
|
UMovieSceneSection* UMovieSceneGeometryCollectionSection::SplitSection(FQualifiedFrameTime SplitTime, bool bDeleteKeys)
|
|
{
|
|
const FFrameNumber InitialStartFrameOffset = Params.StartFrameOffset;
|
|
|
|
FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
|
|
|
|
const FFrameNumber NewOffset = HasStartFrame() ? GetStartOffsetAtTrimTime(SplitTime, Params, GetInclusiveStartFrame(), FrameRate) : 0;
|
|
|
|
UMovieSceneSection* NewSection = Super::SplitSection(SplitTime, bDeleteKeys);
|
|
if (NewSection != nullptr)
|
|
{
|
|
UMovieSceneGeometryCollectionSection* NewGeometrySection = Cast<UMovieSceneGeometryCollectionSection>(NewSection);
|
|
NewGeometrySection->Params.StartFrameOffset = NewOffset;
|
|
}
|
|
|
|
// Restore original offset modified by splitting
|
|
Params.StartFrameOffset = InitialStartFrameOffset;
|
|
|
|
return NewSection;
|
|
}
|
|
|
|
|
|
void UMovieSceneGeometryCollectionSection::GetSnapTimes(TArray<FFrameNumber>& OutSnapTimes, bool bGetSectionBorders) const
|
|
{
|
|
Super::GetSnapTimes(OutSnapTimes, bGetSectionBorders);
|
|
|
|
const FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
|
|
const FFrameNumber StartFrame = GetInclusiveStartFrame();
|
|
const FFrameNumber EndFrame = GetExclusiveEndFrame() - 1; // -1 because we don't need to add the end frame twice
|
|
|
|
const float AnimPlayRate = FMath::IsNearlyZero(Params.PlayRate) ? 1.0f : Params.PlayRate;
|
|
const float SeqLengthSeconds = Params.GetSequenceLength() - FrameRate.AsSeconds(Params.StartFrameOffset + Params.EndFrameOffset) / AnimPlayRate;
|
|
|
|
FFrameTime SequenceFrameLength = SeqLengthSeconds * FrameRate;
|
|
if (SequenceFrameLength.FrameNumber > 1)
|
|
{
|
|
// Snap to the repeat times
|
|
FFrameTime CurrentTime = StartFrame;
|
|
while (CurrentTime < EndFrame)
|
|
{
|
|
OutSnapTimes.Add(CurrentTime.FrameNumber);
|
|
CurrentTime += SequenceFrameLength;
|
|
}
|
|
}
|
|
}
|
|
|
|
float UMovieSceneGeometryCollectionSection::MapTimeToAnimation(FFrameTime InPosition, FFrameRate InFrameRate) const
|
|
{
|
|
FMovieSceneGeometryCollectionSectionTemplateParameters TemplateParams(Params, GetInclusiveStartFrame(), GetExclusiveEndFrame());
|
|
return TemplateParams.MapTimeToAnimation(InPosition, InFrameRate);
|
|
}
|
|
|
|
|
|
#if WITH_EDITOR
|
|
void UMovieSceneGeometryCollectionSection::PreEditChange(FProperty* PropertyAboutToChange)
|
|
{
|
|
// Store the current play rate so that we can compute the amount to compensate the section end time when the play rate changes
|
|
PreviousPlayRate = Params.PlayRate;
|
|
|
|
Super::PreEditChange(PropertyAboutToChange);
|
|
}
|
|
|
|
void UMovieSceneGeometryCollectionSection::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
|
{
|
|
// Adjust the duration automatically if the play rate changes
|
|
if (PropertyChangedEvent.Property != nullptr &&
|
|
PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(FMovieSceneGeometryCollectionParams, PlayRate))
|
|
{
|
|
float NewPlayRate = Params.PlayRate;
|
|
|
|
if (!FMath::IsNearlyZero(NewPlayRate))
|
|
{
|
|
float CurrentDuration = UE::MovieScene::DiscreteSize(GetRange());
|
|
float NewDuration = CurrentDuration * (PreviousPlayRate / NewPlayRate);
|
|
SetEndFrame( GetInclusiveStartFrame() + FMath::FloorToInt(NewDuration) );
|
|
|
|
PreviousPlayRate = NewPlayRate;
|
|
}
|
|
}
|
|
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
}
|
|
#endif
|
|
|
|
#undef LOCTEXT_NAMESPACE
|
|
|