summaryrefslogtreecommitdiff
path: root/public/movieobjects/timeutils.h
blob: caf063351ccca89130f79f38d24403f64cc75a71 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================

#ifndef TIMEUTILS_H
#define TIMEUTILS_H
#ifdef _WIN32
#pragma once
#endif

#include <limits.h>
#include <math.h>
#include "platform.h"
#include "tier0/dbg.h"


class DmeTime_t;
#define DMETIME_TO_SECONDS( t ) ((t) * 0.0001f)

class DmeFramerate_t
{
public:
	DmeFramerate_t( float fps );
	DmeFramerate_t( int fps = 0 );
	DmeFramerate_t( const DmeFramerate_t& src ) : m_num( src.m_num ), m_den( src.m_den ) {}

	void SetFramerate( float flFrameRate );
	void SetFramerate( int fps );
	// other (uncommon) options besides 30(29.97 - ntsc video) are 24 (23.976 - ntsc film) and 60 (59.94 - ntsc progressive)
	void SetFramerateNTSC( int multiplier = 30 );

	float GetFramesPerSecond() const;

	bool operator==( DmeFramerate_t f ) const { return m_num == f.m_num && m_den == f.m_den; }
	bool operator!=( DmeFramerate_t f ) const { return m_num != f.m_num && m_den != f.m_den; }
	bool operator< ( DmeFramerate_t f ) const { return m_num * ( int )f.m_den <  f.m_num * ( int )m_den; }
	bool operator> ( DmeFramerate_t f ) const { return m_num * ( int )f.m_den >  f.m_num * ( int )m_den; }
	bool operator<=( DmeFramerate_t f ) const { return m_num * ( int )f.m_den <= f.m_num * ( int )m_den; }
	bool operator>=( DmeFramerate_t f ) const { return m_num * ( int )f.m_den >= f.m_num * ( int )m_den; }

	DmeFramerate_t operator*( int i ) const { return DmeFramerate_t( m_num * i, m_den ); }
	DmeFramerate_t operator/( int i ) const { return DmeFramerate_t( m_num, m_den * i ); }

	unsigned short abs( unsigned short i ) { return i >= 0 ? i : -i; }

	DmeFramerate_t operator*=( int i ) { Assert( abs( m_num * i ) <= USHRT_MAX ); m_num *= ( unsigned short )i; return *this; }
	DmeFramerate_t operator/=( int i ) { Assert( abs( m_den * i ) <= USHRT_MAX ); m_den *= ( unsigned short )i; return *this; }

private:
	DmeFramerate_t( int nNumerator, int nDenominator );

	unsigned short m_num;
	unsigned short m_den;

	friend class DmeTime_t;
};

#define DMETIME_ZERO		DmeTime_t(0)
#define DMETIME_MINDELTA	DmeTime_t::MinTimeDelta()
#define DMETIME_MINTIME		DmeTime_t::MinTime()
#define DMETIME_MAXTIME		DmeTime_t::MaxTime()
#define DMETIME_INVALID		DmeTime_t::InvalidTime()

class DmeTime_t
{
public:
	DmeTime_t() : m_tms( INT_MIN ) {} // invalid time
	explicit DmeTime_t( int tms ) : m_tms( tms ) {}
	explicit DmeTime_t( float  sec ) : m_tms( RoundSecondsToTMS( sec ) ) {}
	explicit DmeTime_t( double sec ) : m_tms( RoundSecondsToTMS( sec ) ) {}
	DmeTime_t( int frame, DmeFramerate_t framerate );


	// time operators

	bool operator==( DmeTime_t t ) const { return m_tms == t.m_tms; }
	bool operator!=( DmeTime_t t ) const { return m_tms != t.m_tms; }
	bool operator< ( DmeTime_t t ) const { return m_tms <  t.m_tms; }
	bool operator> ( DmeTime_t t ) const { return m_tms >  t.m_tms; }
	bool operator<=( DmeTime_t t ) const { return m_tms <= t.m_tms; }
	bool operator>=( DmeTime_t t ) const { return m_tms >= t.m_tms; }

	DmeTime_t operator%( DmeTime_t t ) const { return DmeTime_t( m_tms % t.m_tms ); }
	DmeTime_t operator+( DmeTime_t t ) const { return DmeTime_t( m_tms + t.m_tms ); }
	DmeTime_t operator-( DmeTime_t t ) const { return DmeTime_t( m_tms - t.m_tms ); }
	DmeTime_t operator-() const { return DmeTime_t( -m_tms ); }

	DmeTime_t operator+=( DmeTime_t t ) { m_tms += t.m_tms; return *this; }
	DmeTime_t operator-=( DmeTime_t t ) { m_tms -= t.m_tms; return *this; }

	// float operators - comment these out to find potentially incorrect uses of DmeTime_t

	friend DmeTime_t operator*( DmeTime_t t, float f ) { t *= f; return t; }
	friend DmeTime_t operator*( float f, DmeTime_t t ) { t *= f; return t; }
	friend DmeTime_t operator/( DmeTime_t t, float f ) { t /= f; return t; }
	friend float     operator/( DmeTime_t n, DmeTime_t d ) { return float( n.m_tms / double( d.m_tms ) ); }

	DmeTime_t operator*=( float f );
	DmeTime_t operator/=( float f );


	// limits, special values and validity

	bool IsValid() const { return m_tms != INT_MIN; }

	static DmeTime_t InvalidTime() { return DmeTime_t( INT_MIN ); }
	static DmeTime_t MinTime() { return DmeTime_t( INT_MIN + 1 ); }
	static DmeTime_t MaxTime() { return DmeTime_t( INT_MAX ); }
	static DmeTime_t MinTimeDelta() { return DmeTime_t( 1 ); }


	// conversions between other time representations

	int GetTenthsOfMS() const { return m_tms; }
	float GetSeconds() const { return DMETIME_TO_SECONDS( m_tms ); }
	void SetTenthsOfMS( int tms ) { m_tms = tms; }
	void SetSeconds( float sec ) { m_tms = RoundSecondsToTMS( sec ); }


	// helper methods

	void Clamp( DmeTime_t lo, DmeTime_t hi );
	bool IsInRange( DmeTime_t lo, DmeTime_t hi ) const;


	// helper functions
	friend float GetFractionOfTime( DmeTime_t t, DmeTime_t duration, bool bClamp );
	friend int FrameForTime( DmeTime_t t, DmeFramerate_t framerate );


	// standard arithmetic methods

	friend DmeTime_t abs( DmeTime_t t ) { return t.m_tms >= 0 ? t : -t; }


	// framerate-dependent conversions to/from frames

	int CurrentFrame( DmeFramerate_t framerate, bool bRoundDown = true ) const;
	DmeTime_t TimeAtCurrentFrame( DmeFramerate_t framerate, bool bRoundDown = true ) const;
	DmeTime_t TimeAtNextFrame( DmeFramerate_t framerate ) const;
	DmeTime_t TimeAtPrevFrame( DmeFramerate_t framerate ) const;

private:
	DmeTime_t( int64 tms ) : m_tms( int( tms ) ) {}

	// conversion helper methods - implementation
	static int RoundSecondsToTMS( float sec );
	static int RoundSecondsToTMS( double sec );

	int m_tms;
};

float GetFractionOfTimeBetween( DmeTime_t t, DmeTime_t start, DmeTime_t end, bool bClamp = false );


#endif // TIMEUTILS_H