Files
UnrealEngine/Engine/Source/Runtime/MovieScene/Private/Compilation/MovieSceneCompilerRules.cpp
2025-05-18 13:04:45 +08:00

103 lines
3.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Compilation/MovieSceneCompilerRules.h"
#include "MovieSceneSection.h"
TOptional<FMovieSceneSegment> MovieSceneSegmentCompiler::EvaluateNearestSegment(const TRange<FFrameNumber>& Range, const FMovieSceneSegment* PreviousSegment, const FMovieSceneSegment* NextSegment)
{
if (PreviousSegment)
{
// There is a preceeding segment
FFrameNumber PreviousSegmentRangeBound = PreviousSegment->Range.GetUpperBoundValue();
FMovieSceneSegment EmptySpace(Range);
for (FSectionEvaluationData Data : PreviousSegment->Impls)
{
EmptySpace.Impls.Add(FSectionEvaluationData(Data.ImplIndex, PreviousSegmentRangeBound));
}
return EmptySpace;
}
else if (NextSegment)
{
// Before any sections
FFrameNumber NextSegmentRangeBound = NextSegment->Range.GetLowerBoundValue();
FMovieSceneSegment EmptySpace(Range);
for (FSectionEvaluationData Data : NextSegment->Impls)
{
EmptySpace.Impls.Add(FSectionEvaluationData(Data.ImplIndex, NextSegmentRangeBound));
}
return EmptySpace;
}
return TOptional<FMovieSceneSegment>();
}
bool MovieSceneSegmentCompiler::AlwaysEvaluateSection(const FMovieSceneSectionData& InSectionData)
{
return InSectionData.Section->GetBlendType().IsValid() || EnumHasAnyFlags(InSectionData.Flags, ESectionEvaluationFlags::PreRoll | ESectionEvaluationFlags::PostRoll);
}
void MovieSceneSegmentCompiler::FilterOutUnderlappingSections(FSegmentBlendData& BlendData)
{
if (!BlendData.Num())
{
return;
}
int32 HighestOverlap = TNumericLimits<int32>::Lowest();
for (const FMovieSceneSectionData& SectionData : BlendData)
{
if (!AlwaysEvaluateSection(SectionData))
{
HighestOverlap = FMath::Max(HighestOverlap, SectionData.Section->GetOverlapPriority());
}
}
// Remove anything that's not the highest priority, (excluding pre/postroll sections)
for (int32 RemoveAtIndex = BlendData.Num() - 1; RemoveAtIndex >= 0; --RemoveAtIndex)
{
const FMovieSceneSectionData& SectionData = BlendData[RemoveAtIndex];
if (SectionData.Section->GetOverlapPriority() != HighestOverlap && !AlwaysEvaluateSection(SectionData))
{
BlendData.RemoveAt(RemoveAtIndex, EAllowShrinking::No);
}
}
}
void MovieSceneSegmentCompiler::ChooseLowestRowIndex(FSegmentBlendData& BlendData)
{
if (!BlendData.Num())
{
return;
}
int32 LowestRowIndex = TNumericLimits<int32>::Max();
for (const FMovieSceneSectionData& SectionData : BlendData)
{
if (!AlwaysEvaluateSection(SectionData))
{
LowestRowIndex = FMath::Min(LowestRowIndex, SectionData.Section->GetRowIndex());
}
}
// Remove anything that's not the highest priority, (excluding pre/postroll sections)
for (int32 RemoveAtIndex = BlendData.Num() - 1; RemoveAtIndex >= 0; --RemoveAtIndex)
{
const FMovieSceneSectionData& SectionData = BlendData[RemoveAtIndex];
if (SectionData.Section->GetRowIndex() > LowestRowIndex && !AlwaysEvaluateSection(SectionData))
{
BlendData.RemoveAt(RemoveAtIndex, EAllowShrinking::No);
}
}
}
// Reduces the evaluated sections to only the section that resides last in the source data. Legacy behaviour from various track instances.
void MovieSceneSegmentCompiler::BlendSegmentLegacySectionOrder(FSegmentBlendData& BlendData)
{
if (BlendData.Num() > 1)
{
Algo::SortBy(BlendData, &FMovieSceneSectionData::TemplateIndex);
BlendData.RemoveAt(1, BlendData.Num() - 1, EAllowShrinking::No);
}
}