Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
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"
6#include "Misc/AssertionMacros.h"
7#include "Templates/EnableIf.h"
8#include "Containers/UnrealString.h"
9
10/**
11 * Structure representing a time by a context-free frame number, plus a sub frame value in the range [0:1)
12 * Conversion to and from time in seconds is achieved in combination with FFrameRate.
13 * Only the frame number part of this representation can be negative, sub frames are always a positive value between the frame number and its next logical frame
14 */
16{
17
18 static const float MaxSubframe;
19
20 /**
21 * Default constructor initializing to zero
22 */
23 FFrameTime();
24
25 /**
26 * Implicit construction from a single integer, while disallowing implicit conversion from any other numeric type
27 */
28 template<typename T, typename = typename TEnableIf<std::is_same_v<T, int32>>::Type>
29 FFrameTime(T /* int32 */ InFrameNumber);
30
31 /**
32 * Implicit construction from a type-safe frame number
33 */
34 FFrameTime(FFrameNumber InFrameNumber);
35
36 /**
37 * Construction from a frame number and a sub frame
38 */
39 FFrameTime(FFrameNumber InFrameNumber, float InSubFrame);
40
41 /**
42 * Assignment from a type-safe frame number
43 */
44 FFrameTime& operator=(FFrameNumber InFrameNumber);
45
46public:
47
48 /**
49 * Access this time's frame number
50 */
52 {
53 return FrameNumber;
54 }
55
56 /**
57 * Access this time's sub frame
58 */
60 {
61 return SubFrame;
62 }
63
64 /**
65 * Return the first frame number less than or equal to this frame time
66 */
68
69 /**
70 * Return the next frame number greater than or equal to this frame time
71 */
73
74 /**
75 * Round to the nearest frame number
76 */
78
79 /**
80 * Retrieve a decimal representation of this frame time
81 * Sub frames are always added to the current frame number, so for negative frame times, a time of -10 [sub frame 0.25] will yield a decimal value of -9.75.
82 */
83 double AsDecimal() const;
84
85 /**
86 * Convert a decimal representation to a frame time
87 * Note that sub frames are always positive, so negative decimal representations result in an inverted sub frame and floored frame number
88 */
89 static FFrameTime FromDecimal(double InDecimalFrame);
90
92
93private:
94
95 /** Must be 0.f <= SubFrame < 1.f */
96 float SubFrame;
97
98
100 {
102 }
103
104
106 {
108 }
109
110
112 {
114 }
115
116
118 {
120 }
121
122
124 {
126 }
127
128
130 {
132 }
133
134
136 {
137 float NewSubFrame = LHS.SubFrame + RHS.SubFrame;
138
139 LHS.FrameNumber = LHS.FrameNumber + RHS.FrameNumber + FFrameNumber(FMath::FloorToInt(NewSubFrame));
140 LHS.SubFrame = FMath::Frac(NewSubFrame);
141
142 return LHS;
143 }
144
145
147 {
148 const float NewSubFrame = A.SubFrame + B.SubFrame;
149 const FFrameNumber NewFrameNumber = A.FrameNumber + B.FrameNumber + FFrameNumber(FMath::FloorToInt(NewSubFrame));
150
151 return FFrameTime(NewFrameNumber, FMath::Frac(NewSubFrame));
152 }
153
154
156 {
157 // Ensure SubFrame is always between 0 and 1
158 // Note that the difference between frame -1.5 and 1.5 is 2, not 3, since sub frame positions are always positive
159 const float NewSubFrame = LHS.SubFrame - RHS.SubFrame;
160 const float FlooredSubFrame = FMath::FloorToFloat(NewSubFrame);
161 LHS.FrameNumber = LHS.FrameNumber - RHS.FrameNumber + FFrameNumber(FMath::TruncToInt(FlooredSubFrame));
162 LHS.SubFrame = NewSubFrame - FlooredSubFrame;
163
164 return LHS;
165 }
166
167
169 {
170 // Ensure SubFrame is always between 0 and 1
171 // Note that the difference between frame -1.5 and 1.5 is 2, not 3, since sub frame positions are always positive
172 const float NewSubFrame = A.SubFrame - B.SubFrame;
173 const float FlooredSubFrame = FMath::FloorToFloat(NewSubFrame);
174 const FFrameNumber NewFrameNumber = A.FrameNumber - B.FrameNumber + FFrameNumber(FMath::TruncToInt(FlooredSubFrame));
175
176 return FFrameTime(NewFrameNumber, NewSubFrame - FlooredSubFrame);
177 }
178
179
181 {
182 check(B.FrameNumber.Value != 0 || B.GetSubFrame() != 0.f);
183
184 if (A.SubFrame == 0.f && B.SubFrame == 0.f)
185 {
187 }
188 else
189 {
190 FFrameTime Result = A;
191 while (Result >= B)
192 {
193 Result = Result - B;
194 }
195 return Result;
196 }
197 }
198
199
201 {
202 return A.GetSubFrame() == 0.f
205 }
206
207
208 friend FORCEINLINE FFrameTime operator*(FFrameTime A, float Scalar)
209 {
211 }
212
213 friend FORCEINLINE FFrameTime operator*(float Scalar, FFrameTime A)
214 {
216 }
217
218 friend FORCEINLINE FFrameTime operator/(FFrameTime A, float Scalar)
219 {
221 }
222};
223
224
226 : FrameNumber(0), SubFrame(0.f)
227{}
228
229
230template<typename T, typename>
231FFrameTime::FFrameTime(T InFrameNumber)
232 : FrameNumber(InFrameNumber), SubFrame(0.f)
233{}
234
235
236inline FFrameTime::FFrameTime(FFrameNumber InFrameNumber)
237 : FrameNumber(InFrameNumber), SubFrame(0.f)
238{}
239
240
241inline FFrameTime::FFrameTime(FFrameNumber InFrameNumber, float InSubFrame)
242 : FrameNumber(InFrameNumber), SubFrame(InSubFrame)
243{
244 // Hack to ensure that SubFrames are in a sensible range of precision to work around
245 // problems with FloorToXYZ returning the wrong thing for very small negative numbers
247 checkSlow(InSubFrame >= 0.f && InSubFrame < 1.f);
248}
249
250
252{
253 FrameNumber = InFrameNumber;
254 SubFrame = 0.f;
255 return *this;
256}
257
259{
260 return FrameNumber;
261}
262
263
265{
266 return SubFrame == 0.f ? FrameNumber : FrameNumber+1;
267}
268
269
271{
272 return SubFrame < .5f ? FrameNumber : FrameNumber+1;
273}
274
275
277{
278 return double(FrameNumber.Value) + SubFrame;
279}
280
282{
283 int32 NewFrame = static_cast<int32>(FMath::Clamp(FMath::FloorToDouble(InDecimalFrame), (double)TNumericLimits<int32>::Min(), (double)TNumericLimits<int32>::Max()));
284
285 // Ensure fractional parts above the highest sub frame float precision do not round to 0.0
286 double Fraction = InDecimalFrame - FMath::FloorToDouble(InDecimalFrame);
287 return FFrameTime(NewFrame, FMath::Clamp((float)Fraction, 0.0f, MaxSubframe));
288}
289
290/** Convert a FFrameTime into a string */
291inline FString LexToString(const FFrameTime InTime)
292{
293 return FString::Printf(TEXT("Frame: %d Subframe: %f"), InTime.GetFrame().Value, InTime.GetSubFrame());
294}
#define checkSlow(expr)
#define check(expr)
#define FORCEINLINE_DEBUGGABLE
FString LexToString(const FFrameTime InTime)
Definition FrameTime.h:291
#define TEXT(x)
Definition Platform.h:1108
#define FORCEINLINE
Definition Platform.h:644
friend FFrameNumber operator-(FFrameNumber A)
Definition FrameNumber.h:64
friend bool operator<(FFrameNumber A, FFrameNumber B)
Definition FrameNumber.h:55
friend bool operator>(FFrameNumber A, FFrameNumber B)
Definition FrameNumber.h:56
friend bool operator==(FFrameNumber A, FFrameNumber B)
Definition FrameNumber.h:52
friend bool operator!=(FFrameNumber A, FFrameNumber B)
Definition FrameNumber.h:53
friend FFrameNumber operator%(FFrameNumber A, FFrameNumber B)
Definition FrameNumber.h:62
friend FORCEINLINE_DEBUGGABLE bool operator<=(FFrameTime A, FFrameTime B)
Definition FrameTime.h:129
friend FORCEINLINE_DEBUGGABLE bool operator>=(FFrameTime A, FFrameTime B)
Definition FrameTime.h:117
friend FORCEINLINE FFrameTime operator*(float Scalar, FFrameTime A)
Definition FrameTime.h:213
friend FORCEINLINE_DEBUGGABLE FFrameTime operator%(FFrameTime A, FFrameTime B)
Definition FrameTime.h:180
friend FORCEINLINE_DEBUGGABLE bool operator==(FFrameTime A, FFrameTime B)
Definition FrameTime.h:99
FFrameTime(FFrameNumber InFrameNumber, float InSubFrame)
Definition FrameTime.h:241
float SubFrame
Definition FrameTime.h:96
double AsDecimal() const
Definition FrameTime.h:276
friend FORCEINLINE_DEBUGGABLE FFrameTime operator+(FFrameTime A, FFrameTime B)
Definition FrameTime.h:146
friend FORCEINLINE_DEBUGGABLE bool operator!=(FFrameTime A, FFrameTime B)
Definition FrameTime.h:105
friend FORCEINLINE FFrameTime operator*(FFrameTime A, float Scalar)
Definition FrameTime.h:208
friend FORCEINLINE_DEBUGGABLE bool operator<(FFrameTime A, FFrameTime B)
Definition FrameTime.h:123
friend FORCEINLINE_DEBUGGABLE FFrameTime & operator+=(FFrameTime &LHS, FFrameTime RHS)
Definition FrameTime.h:135
friend FORCEINLINE_DEBUGGABLE bool operator>(FFrameTime A, FFrameTime B)
Definition FrameTime.h:111
FFrameNumber RoundToFrame() const
Definition FrameTime.h:270
FFrameNumber FrameNumber
Definition FrameTime.h:91
FORCEINLINE FFrameNumber GetFrame() const
Definition FrameTime.h:51
friend FORCEINLINE FFrameTime operator/(FFrameTime A, float Scalar)
Definition FrameTime.h:218
FORCEINLINE float GetSubFrame() const
Definition FrameTime.h:59
FFrameTime(FFrameNumber InFrameNumber)
Definition FrameTime.h:236
friend FORCEINLINE_DEBUGGABLE FFrameTime & operator-=(FFrameTime &LHS, FFrameTime RHS)
Definition FrameTime.h:155
FFrameTime & operator=(FFrameNumber InFrameNumber)
Definition FrameTime.h:251
FFrameNumber CeilToFrame() const
Definition FrameTime.h:264
FFrameNumber FloorToFrame() const
Definition FrameTime.h:258
FFrameTime(T InFrameNumber)
Definition FrameTime.h:231
friend FORCEINLINE_DEBUGGABLE FFrameTime operator-(FFrameTime A)
Definition FrameTime.h:200
static const float MaxSubframe
Definition FrameTime.h:18
static FFrameTime FromDecimal(double InDecimalFrame)
Definition FrameTime.h:281
friend FORCEINLINE_DEBUGGABLE FFrameTime operator-(FFrameTime A, FFrameTime B)
Definition FrameTime.h:168
static UE_NODISCARD constexpr FORCEINLINE float Clamp(const float X, const float Min, const float Max)