UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
FrameTime.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Misc/FrameNumber.h"
9
16{
17
18 static CORE_API const float MaxSubframe;
19
23 FFrameTime();
24
28 template<typename T, typename = typename TEnableIf<std::is_same_v<T, int32>>::Type>
29 FFrameTime(T /* int32 */ InFrameNumber);
30
35
40
45
49 bool Serialize(FArchive& Ar);
50
51public:
52
60
65 {
66 return SubFrame;
67 }
68
73
78
83
88 double AsDecimal() const;
89
95
99
100private:
101
103 float SubFrame;
104
105public:
106
114 friend FArchive& operator<<(FArchive& Ar, FFrameTime& FrameTime)
115 {
116 FrameTime.Serialize(Ar);
117 return Ar;
118 }
119
121 {
122 return A.FrameNumber == B.FrameNumber && A.SubFrame == B.SubFrame;
123 }
124
125
127 {
128 return A.FrameNumber != B.FrameNumber || A.SubFrame != B.SubFrame;
129 }
130
131
133 {
134 return A.FrameNumber > B.FrameNumber || ( A.FrameNumber == B.FrameNumber && A.SubFrame > B.SubFrame );
135 }
136
137
139 {
140 return A.FrameNumber > B.FrameNumber || ( A.FrameNumber == B.FrameNumber && A.SubFrame >= B.SubFrame );
141 }
142
143
145 {
146 return A.FrameNumber < B.FrameNumber || ( A.FrameNumber == B.FrameNumber && A.SubFrame < B.SubFrame );
147 }
148
149
151 {
152 return A.FrameNumber < B.FrameNumber || ( A.FrameNumber == B.FrameNumber && A.SubFrame <= B.SubFrame );
153 }
154
155
157 {
158 float NewSubFrame = LHS.SubFrame + RHS.SubFrame;
159 const int64 NewFrameNumber = int64(LHS.FrameNumber.Value) + int64(RHS.FrameNumber.Value) + FMath::FloorToInt(NewSubFrame);
160
161 LHS.FrameNumber = static_cast<int32>(NewFrameNumber);
162 LHS.SubFrame = FMath::Frac(NewSubFrame);
163
164 return LHS;
165 }
166
167
169 {
170 const float NewSubFrame = A.SubFrame + B.SubFrame;
171 const int64 NewFrameNumber = int64(A.FrameNumber.Value) + int64(B.FrameNumber.Value) + FMath::FloorToInt(NewSubFrame);
172
173 return FFrameTime(static_cast<int32>(NewFrameNumber), FMath::Frac(NewSubFrame));
174 }
175
176
178 {
179 // Ensure SubFrame is always between 0 and 1
180 // Note that the difference between frame -1.5 and 1.5 is 2, not 3, since sub frame positions are always positive
181 const float NewSubFrame = LHS.SubFrame - RHS.SubFrame;
182 const float FlooredSubFrame = FMath::FloorToFloat(NewSubFrame);
183 const int64 NewFrameNumber = int64(LHS.FrameNumber.Value) - int64(RHS.FrameNumber.Value) + FMath::TruncToInt(FlooredSubFrame);
184
185 LHS.FrameNumber.Value = static_cast<int32>(NewFrameNumber);
186 LHS.SubFrame = NewSubFrame - FlooredSubFrame;
187
188 return LHS;
189 }
190
191
193 {
194 // Ensure SubFrame is always between 0 and 1
195 // Note that the difference between frame -1.5 and 1.5 is 2, not 3, since sub frame positions are always positive
196 const float NewSubFrame = A.SubFrame - B.SubFrame;
197 const float FlooredSubFrame = FMath::FloorToFloat(NewSubFrame);
198 const int64 NewFrameNumber = int64(A.FrameNumber.Value) - int64(B.FrameNumber.Value) + FMath::TruncToInt(FlooredSubFrame);
199
201 }
202
203
205 {
206 check(B.FrameNumber.Value != 0 || B.GetSubFrame() != 0.f);
207
208 if (A.SubFrame == 0.f && B.SubFrame == 0.f)
209 {
210 return FFrameTime(A.FrameNumber % B.FrameNumber);
211 }
212 else
213 {
214 FFrameTime Result = A;
215 while (Result >= B)
216 {
217 Result = Result - B;
218 }
219 return Result;
220 }
221 }
222
223
225 {
226 return A.GetSubFrame() == 0.f
227 ? FFrameTime(-A.FrameNumber)
228 : FFrameTime(-A.FrameNumber - 1, 1.f-A.GetSubFrame());
229 }
230
231
233 {
234 return FFrameTime::FromDecimal(A.AsDecimal() * Scalar);
235 }
236
238 {
239 return FFrameTime::FromDecimal(A.AsDecimal() * Scalar);
240 }
241
243 {
244 return FFrameTime::FromDecimal(A.AsDecimal() / Scalar);
245 }
246};
247
248
250 : FrameNumber(0), SubFrame(0.f)
251{}
252
253
254template<typename T, typename>
256 : FrameNumber(InFrameNumber), SubFrame(0.f)
257{}
258
259
261 : FrameNumber(InFrameNumber), SubFrame(0.f)
262{}
263
264
266 : FrameNumber(InFrameNumber), SubFrame(InSubFrame)
267{
268 // Hack to ensure that SubFrames are in a sensible range of precision to work around
269 // problems with FloorToXYZ returning the wrong thing for very small negative numbers
270 SubFrame = FMath::Clamp(InSubFrame + 0.5f - 0.5f, 0.f, MaxSubframe);
271 checkSlow(InSubFrame >= 0.f && InSubFrame < 1.f);
272}
273
274
276{
277 Ar << FrameNumber;
278 Ar << SubFrame;
279 return true;
280}
281
282
284{
286 SubFrame = 0.f;
287 return *this;
288}
289
294
295
297{
298 return SubFrame == 0.f ? FrameNumber : FrameNumber+1;
299}
300
301
303{
304 return SubFrame < .5f ? FrameNumber : FrameNumber+1;
305}
306
307
309{
310 return double(FrameNumber.Value) + SubFrame;
311}
312
314{
315 int32 NewFrame = static_cast<int32>(FMath::Clamp(FMath::FloorToDouble(InDecimalFrame), (double)TNumericLimits<int32>::Min(), (double)TNumericLimits<int32>::Max()));
316
317 // Ensure fractional parts above the highest sub frame float precision do not round to 0.0
318 double Fraction = InDecimalFrame - FMath::FloorToDouble(InDecimalFrame);
319 return FFrameTime(NewFrame, FMath::Clamp((float)Fraction, 0.0f, MaxSubframe));
320}
321
323inline FString LexToString(const FFrameTime InTime)
324{
325 return FString::Printf(TEXT("Frame: %d Subframe: %f"), InTime.GetFrame().Value, InTime.GetSubFrame());
326}
327
329inline FString LexToShortString(const FFrameTime InTime)
330{
331 return FString::Printf(TEXT("%d.%f"), InTime.GetFrame().Value, InTime.GetSubFrame());
332}
333
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
FString LexToShortString(const FFrameTime InTime)
Definition FrameTime.h:329
FString LexToString(const FFrameTime InTime)
Definition FrameTime.h:323
Definition Archive.h:1208
Definition FrameNumber.h:18
int32 Value
Definition FrameNumber.h:77
Definition FrameTime.h:16
friend UE_FORCEINLINE_HINT bool operator>=(FFrameTime A, FFrameTime B)
Definition FrameTime.h:138
friend UE_FORCEINLINE_HINT bool operator>(FFrameTime A, FFrameTime B)
Definition FrameTime.h:132
friend UE_FORCEINLINE_HINT FFrameTime operator*(FFrameTime A, double Scalar)
Definition FrameTime.h:232
friend FFrameTime operator-(FFrameTime A)
Definition FrameTime.h:224
friend FFrameTime operator-(FFrameTime A, FFrameTime B)
Definition FrameTime.h:192
friend FArchive & operator<<(FArchive &Ar, FFrameTime &FrameTime)
Definition FrameTime.h:114
FFrameTime()
Definition FrameTime.h:249
static FFrameTime FromDecimal(double InDecimalFrame)
Definition FrameTime.h:313
FFrameNumber FrameNumber
Definition FrameTime.h:98
FFrameNumber FloorToFrame() const
Definition FrameTime.h:290
bool Serialize(FArchive &Ar)
Definition FrameTime.h:275
double AsDecimal() const
Definition FrameTime.h:308
UE_FORCEINLINE_HINT float GetSubFrame() const
Definition FrameTime.h:64
friend UE_FORCEINLINE_HINT bool operator!=(FFrameTime A, FFrameTime B)
Definition FrameTime.h:126
friend UE_FORCEINLINE_HINT FFrameTime operator/(FFrameTime A, double Scalar)
Definition FrameTime.h:242
friend FFrameTime & operator+=(FFrameTime &LHS, FFrameTime RHS)
Definition FrameTime.h:156
friend FFrameTime & operator-=(FFrameTime &LHS, FFrameTime RHS)
Definition FrameTime.h:177
FFrameTime & operator=(FFrameNumber InFrameNumber)
Definition FrameTime.h:283
friend UE_FORCEINLINE_HINT FFrameTime operator*(double Scalar, FFrameTime A)
Definition FrameTime.h:237
FFrameNumber CeilToFrame() const
Definition FrameTime.h:296
FFrameNumber RoundToFrame() const
Definition FrameTime.h:302
static CORE_API const float MaxSubframe
Definition FrameTime.h:18
UE_FORCEINLINE_HINT FFrameNumber GetFrame() const
Definition FrameTime.h:56
friend UE_FORCEINLINE_HINT bool operator<=(FFrameTime A, FFrameTime B)
Definition FrameTime.h:150
friend UE_FORCEINLINE_HINT bool operator==(FFrameTime A, FFrameTime B)
Definition FrameTime.h:120
friend FFrameTime operator+(FFrameTime A, FFrameTime B)
Definition FrameTime.h:168
friend UE_FORCEINLINE_HINT bool operator<(FFrameTime A, FFrameTime B)
Definition FrameTime.h:144
friend FFrameTime operator%(FFrameTime A, FFrameTime B)
Definition FrameTime.h:204
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592
Definition NumericLimits.h:41