#ifndef utl_h
#define utl_h
#define _exposed
#include "CRC.h"
class UTL;
class List_utl;
class Link_utl;
class Lock_utl;
template<class T, class Sink = NullFunc> class Slist_utl;
template<class T, class Sink = NullFunc> class Slink_utl;
template<class T> class Mlist_utl;
template<class T> class Mlink_utl;
struct FPOINT
{
float x;
float y;
};
class Rotation;
const int c_cbFileNameDB = 12; const int c_cbDescriptionDB = 200;
const int c_cbNameDB = 24;
const int c_cbLocAbrevDB = 8;
const int c_cbFileName = c_cbFileNameDB + 1;
const int c_cbDescription = c_cbDescriptionDB + 1;
const int c_cbName = c_cbNameDB + 1;
const int c_cbLocAbrev = c_cbLocAbrevDB + 1;
const int c_cbCDKey = 32 + 1; const int c_cbPassportName = 256 + 1;
class _exposed List_utl
{
public:
inline int n(void) const
{
return m_n;
}
protected:
List_utl(void);
inline ~List_utl(void)
{
}
void first(Link_utl* f);
inline Link_utl* first(void) const
{
return m_first;
}
void last(Link_utl* l);
inline Link_utl* last(void) const
{
return m_last;
}
Link_utl* operator [] (int index) const;
private:
Link_utl* m_first;
Link_utl* m_last;
int m_n;
friend class Link_utl;
};
class _exposed Link_utl
{
public:
bool unlink(void);
protected:
Link_utl(void);
~Link_utl(void)
{
}
inline List_utl* list(void) const
{
return m_list;
}
bool next(Link_utl* l);
inline Link_utl* next(void) const
{
return m_next;
}
bool txen(Link_utl* l);
inline Link_utl* txen(void) const
{
return m_txen;
}
protected:
List_utl* m_list;
Link_utl* m_next;
Link_utl* m_txen;
friend List_utl;
};
class _exposed Lock_utl
{
public:
Lock_utl(void);
~Lock_utl(void);
void lock(void) const;
void unlock(void) const;
private:
HANDLE m_lockedS;
DWORD m_locking_threadID;
int m_locks;
};
template<class T, class Sink> class Slist_utl : public List_utl
{
protected:
Sink sink;
public:
Slist_utl()
{};
Slist_utl(const Sink& _sink)
: sink(_sink) {}
inline ~Slist_utl(void)
{
purge();
}
void purge(bool deleteF = true);
bool first(const T& t);
bool last(const T& t);
inline void first(Slink_utl<T, Sink>* l)
{
List_utl::first(l);
sink();
}
inline Slink_utl<T, Sink>* first(void) const
{
return (Slink_utl<T, Sink>*)List_utl::first();
}
inline void last(Slink_utl<T, Sink>* l)
{
List_utl::last(l);
sink();
}
inline Slink_utl<T, Sink>* last(void) const
{
return (Slink_utl<T, Sink>*)List_utl::last();
}
inline Slink_utl<T, Sink>* find(const T& e) const
{
Slink_utl<T, Sink>* l;
for (l = first(); ((l != NULL) && (l->data() != e)); l = l->next())
{
}
return l;
}
inline Slink_utl<T, Sink>* operator [](int index) const
{
return (Slink_utl<T, Sink>*)List_utl::operator [](index);
}
friend class Slink_utl<T, Sink>;
};
template<class T, class Sink> class Slink_utl : public Link_utl
{
public:
inline Slink_utl(void)
{
}
inline Slink_utl(const T& t)
:
m_data(t)
{
}
inline ~Slink_utl(void)
{
if (list())
unlink();
}
inline const T& data(void) const
{
return m_data;
}
inline T& data(void)
{
return m_data;
}
inline void data(const T& t)
{
m_data = t;
list()->sink();
}
bool next(const T& t);
bool txen(const T& t);
inline Slist_utl<T, Sink>* list(void) const
{
return (Slist_utl<T, Sink>*)Link_utl::list();
}
inline bool next(Slink_utl<T, Sink>* l)
{
return Link_utl::next(l);
}
inline Slink_utl<T, Sink>* next(void) const
{
return (Slink_utl<T, Sink>*)Link_utl::next();
}
inline bool txen(Slink_utl<T, Sink>* l)
{
return Link_utl::txen(l);
}
inline Slink_utl<T, Sink>* txen(void) const
{
return (Slink_utl<T, Sink>*)Link_utl::txen();
}
__forceinline bool unlink(void)
{
Slist_utl<T, Sink>* plist = list();
bool result = Link_utl::unlink();
plist->sink();
return result;
}
private:
T m_data;
};
template<class T> class Mlist_utl : public List_utl, public Lock_utl
{
public:
inline Mlist_utl(void)
{
}
inline ~Mlist_utl(void)
{
purge();
}
void purge(bool deleteF = true); bool first(const T& t); bool last(const T& t); void first(Mlink_utl<T>* l); Mlink_utl<T>* first(void) const;
void last(Mlink_utl<T>* l); Mlink_utl<T>* last(void) const;
inline Mlink_utl<T>* find(const T& e) const
{
lock();
Mlink_utl<T>* l;
for (l = first(); ((l != NULL) && (l->data() != e)); l = l->next())
{
}
unlock();
return l;
}
Mlink_utl<T>* operator [](int) const;
friend class Mlink_utl<T>;
};
template<class T> class Mlink_utl : public Link_utl
{
public:
inline Mlink_utl(void)
{
}
inline Mlink_utl(const T& t)
:
m_data(t)
{
}
inline ~Mlink_utl(void)
{
if (list())
unlink();
}
inline const T& data(void) const
{
return m_data;
}
inline T& data(void)
{
return m_data;
}
inline void data(const T& t)
{
m_data = t;
}
bool next(const T& t);
bool txen(const T& t);
inline Mlist_utl<T>* list(void) const
{
return (Mlist_utl<T>*)Link_utl::list();
}
inline bool next(Mlink_utl<T>* l)
{
return Link_utl::next(l);
}
inline Mlink_utl<T>* next(void) const
{
return (Mlink_utl<T>*)Link_utl::next();
}
inline bool txen(Mlink_utl<T>* l)
{
return Link_utl::txen(l);
}
inline Mlink_utl<T>* txen(void) const
{
return (Mlink_utl<T>*)Link_utl::txen();
}
private:
T m_data;
};
class Rotation
{
public:
Rotation(void);
Rotation(float x, float y, float z, float a)
:
m_axis(x, y, z),
m_angle(a)
{
}
Rotation(const Vector& xyz, float a)
:
m_axis(xyz),
m_angle(a)
{
}
Rotation(const Rotation&);
void reset(void);
void set(const Vector& axis,
float angle);
Rotation& operator = (const Rotation&);
inline float x(void) const
{
return m_axis.x;
}
inline float y(void) const
{
return m_axis.y;
}
inline float z(void) const
{
return m_axis.z;
}
inline float angle(void) const
{
return m_angle;
}
inline const Vector& axis(void) const
{
return m_axis;
}
void axis(const Vector& v);
void angle(float r);
void x(float t);
void y(float t);
void z(float t);
private:
Vector m_axis;
float m_angle;
};
const int c_cbFrameName = 20;
class FrameDataUTL
{
public:
char szName[c_cbFrameName];
Vector position;
Vector forward;
friend bool operator!=(const FrameDataUTL& fd1, const FrameDataUTL& fd2)
{
return false;
}
};
typedef Slist_utl<FrameDataUTL> FrameList;
typedef Slink_utl<FrameDataUTL> FrameLink;
const int c_nAxes = 3;
const int c_maxHitTests = 100;
const int c_minNodeSize = 5;
const int c_minRootSize = 10;
class Interval;
class BoundingBox;
class Endpoint;
class HitTest;
class KDnode;
class KDroot;
class CollisionEntry;
class CollisionQueue;
class Interval
{
public:
float values[2]; };
class BoundingBox
{
public:
Interval axes[c_nAxes];
};
class Endpoint
{
public:
float value;
HitTest* pHitTest;
bool highF;
static void shortSort(Endpoint** lo,
Endpoint** hi);
static void longSort(Endpoint** lo,
Endpoint** hi);
};
class Transform44
{
public:
inline Transform44(void)
:
m_position(Vector::GetZero()),
m_orientation(Orientation::GetIdentity()),
m_modifiedF(true)
{
}
inline const Vector& GetPosition(void) const
{
return m_position;
}
inline void SetPosition(const Vector& xyz)
{
assert(xyz.Length() < 100000);
m_position = xyz;
m_modifiedF = true;
}
inline const Orientation& GetOrientation(void) const
{
return m_orientation;
}
inline void SetOrientation(const Orientation& o)
{
m_orientation = o;
m_modifiedF = true;
}
inline const Matrix& GetMatrix(void)
{
if (m_modifiedF)
{
m_modifiedF = false;
}
return m_matrix;
}
private:
Matrix m_matrix;
Vector m_position;
Orientation m_orientation;
bool m_modifiedF;
};
typedef char HitTestShape;
const HitTestShape c_htsPoint = -4;
const HitTestShape c_htsSphere = -3;
const HitTestShape c_htsEllipse = -2;
const HitTestShape c_htsCone = -1;
const HitTestShape c_htsConvexHullMin = 0;
const HitTestShape c_htsConvexHullMax = 127;
typedef void* HitTestID;
HitTestID const c_htidStaticObject = (HitTestID)(-1);
class MultiHullBase
{
public:
MultiHullBase(const Vector& ellipseEquation,
float originalRadius)
:
m_ellipseEquation(ellipseEquation),
m_originalRadius(originalRadius)
{
}
const Vector& GetFrameOffset(const char* pszFrameName) const
{
const FrameDataUTL* pfd = GetFrame(pszFrameName);
return pfd ? pfd->position : Vector::GetZero();
}
const Vector& GetFrameForward(const char* pszFrameName) const
{
static const Vector z(0.0f, 0.0f, 1.0f);
const FrameDataUTL* pfd = GetFrame(pszFrameName);
return pfd ? pfd->forward : z;
}
const FrameDataUTL* GetFrame(const char* pszFrameName) const
{
for (FrameLink* pfl = m_frames.first();
(pfl != NULL);
pfl = pfl->next())
{
const FrameDataUTL& fd = pfl->data();
if (strcmp(pszFrameName, fd.szName) == 0)
{
return &fd;
}
}
return NULL;
}
const float GetOriginalRadius(void) const
{
return m_originalRadius;
}
const Vector& GetEllipseEquation(void) const
{
return m_ellipseEquation;
}
protected:
FrameList m_frames;
float m_originalRadius;
Vector m_ellipseEquation;
};
class HitTest : public Transform44
{
public:
static MultiHullBase* Load(const char* pszFileName);
static HitTest* Create(const char* pszFileName,
IObject* data,
bool staticF,
HitTestShape htsDefault = c_htsSphere);
HitTest(IObject* data,
float radius,
bool staticF,
HitTestShape shape)
:
m_cRefs(1),
m_id(NULL),
m_data(data),
m_radius(radius),
m_shape(shape),
m_shapeTrue(shape),
m_noHit(NULL),
m_pvUseTrueShapeSelf(NULL),
m_pvUseTrueShapeOther(NULL),
m_deadF(true),
m_deletedF(false),
m_staticF(staticF),
m_velocity(Vector::GetZero()),
m_timeStart(0),
m_timeStop(0),
m_pkdrRoot(NULL)
{
assert (data);
data->AddRef();
m_endpoints[0][0].highF =
m_endpoints[1][0].highF =
m_endpoints[2][0].highF = false;
m_endpoints[0][1].highF =
m_endpoints[1][1].highF =
m_endpoints[2][1].highF = true;
m_endpoints[0][0].pHitTest = m_endpoints[0][1].pHitTest =
m_endpoints[1][0].pHitTest = m_endpoints[1][1].pHitTest =
m_endpoints[2][0].pHitTest = m_endpoints[2][1].pHitTest = this;
}
~HitTest(void)
{
assert (m_data);
m_data->Release();
}
ULONG __stdcall AddRef(void)
{
return ++m_cRefs;
}
ULONG __stdcall Release(void)
{
ULONG cRefs = --m_cRefs;
if (cRefs == 0)
delete this;
return cRefs;
}
void SetStaticF(bool staticF)
{
m_staticF = staticF;
}
void SetBB(Time start, Time stop, float dt);
void SetStopPosition(void)
{
m_stopPosition = GetPosition();
if (m_tStop > 0.0f)
m_stopPosition += m_tStop * m_velocity;
assert (m_stopPosition.LengthSquared() >= 0.0f);
assert (m_stopPosition.LengthSquared() < 1.0e12f);
}
void Move(float t)
{
if (!m_staticF)
{
SetPosition(GetPosition() + m_velocity * t);
if (m_tStart <= t)
m_tStart = 0.0f;
else
m_tStart -= t;
m_tStop -= t;
assert (GetPosition() * GetPosition() >= 0.0f);
}
}
void AdjustTimes(float t)
{
if (!m_staticF)
{
if (m_tStart <= t)
m_tStart = 0.0f;
else
m_tStart -= t;
m_tStop -= t;
}
}
void Move(void)
{
if (!m_staticF)
SetPosition(m_stopPosition);
}
virtual void UpdateStaticBB(void)
{
UpdateStaticBB(m_radius);
}
void UpdateStaticBB(float r)
{
assert (m_staticF);
assert (c_nAxes == 3);
for (int i = 0; (i < c_nAxes); i++)
{
float v = GetPosition()[i];
m_boundingBox.axes[i].values[0] = v - r;
m_boundingBox.axes[i].values[1] = v + r;
m_endpoints[i][0].value = m_boundingBox.axes[i].values[0];
m_endpoints[i][1].value = m_boundingBox.axes[i].values[1];
}
}
void UpdateBB(void);
void Collide(HitTest* pHitTest,
CollisionQueue* pQueue);
HitTestShape GetShape(void) const
{
return m_shape;
}
HitTestShape GetTrueShape(void) const
{
return m_shapeTrue;
}
virtual void SetShape(HitTestShape shape)
{
if (shape <= m_shapeTrue)
m_shape = shape;
}
virtual const Vector* GetEllipseEquation(void) const
{
return NULL;
}
float GetRadius(void) const
{
return m_radius;
}
virtual void SetRadius(float r)
{
m_radius = r;
}
virtual float GetScale(void) const
{
return 1.0f;
}
bool GetDeadF(void) const
{
return m_deadF;
}
void SetDeadF(bool d)
{
m_deadF = d;
}
bool GetDeletedF(void) const
{
return m_deletedF;
}
void SetDeletedF(bool d)
{
m_deletedF = d;
}
IObject* GetData(void) const
{
return m_data;
}
HitTest* GetLastTest(void) const
{
return m_lastTest;
}
void SetLastTest(HitTest* ht)
{
m_lastTest = ht;
}
const Vector& GetVelocity(void) const
{
return m_velocity;
}
void SetVelocity(const Vector& v)
{
if (!(v.LengthSquared() < (100000.0f * 100000.0f))) {
debugf("mmf Utility.h SetVelocity: v.LengthSquared debug build would have called assert and exited, commented out and set to zero for now\n");
m_velocity.x = 0.0f; m_velocity.y = 0.0f; m_velocity.z = 0.0f;
} else {
m_velocity = v;
}
if (!(v * v >= 0.0f)) {
debugf("mmf Utility.h SetVelocity: v^2 debug build would have called assert and exited, commented out and set to zero for now\n");
m_velocity.x = 0.0f; m_velocity.y = 0.0f; m_velocity.z = 0.0f;
} else {
m_velocity = v;
}
}
HitTestID GetID(void) const
{
return m_id;
}
void SetID(HitTestID id)
{
m_id = id;
}
HitTest* GetNoHit(void) const
{
return m_noHit;
}
void SetUseTrueShapeSelf(void* pvUseTrueShapeSelf)
{
m_pvUseTrueShapeSelf = pvUseTrueShapeSelf;
}
void SetUseTrueShapeOther(void* pvUseTrueShapeOther)
{
m_pvUseTrueShapeOther = pvUseTrueShapeOther;
}
void SetNoHit(HitTest* ht)
{
m_noHit = ht;
}
void SetTimeStart(Time t)
{
m_timeStart = t;
}
void SetTimeStop(Time t)
{
m_timeStop = t;
}
static bool HullCollide(float* tCollision,
float tMax,
HitTest* phtHullA,
HitTestShape* phtsA,
HitTest* phtHullB,
HitTestShape* phtsB,
const Vector& dP,
const Vector& dV); static bool IntervalCollide(float tStart,
float tStop,
float maxDeltaT,
HitTest* phtHullA,
HitTestShape htsA,
HitTest* phtHullB,
HitTestShape htsB,
const Vector& dP,
const Vector& dV, const Orientation& orientationA,
float* tCollision);
Vector GetMinExtreme(HitTestShape hts,
const Vector& position,
const Orientation& orientation,
const Vector& direction);
Vector GetMaxExtreme(HitTestShape hts,
const Vector& direction);
virtual Vector GetCenter(HitTestShape hts) const
{
assert (false); return Vector::GetZero();
}
void SetKDRoot(KDroot* pkdr)
{
m_pkdrRoot = pkdr;
}
KDroot* GetKDRoot(void) const
{
return m_pkdrRoot;
}
virtual const Vector GetFrameOffset(const char* pszFrameName) const
{
return Vector::GetZero();
}
virtual const Vector& GetFrameForward(const char* pszFrameName) const
{
static const Vector z(0.0f, 0.0f, 1.0f);
return z;
}
virtual const FrameDataUTL* GetFrame(const char* pszFrameName) const
{
return NULL;
}
float GetTstop(void) const
{
return m_tStop;
}
protected:
ULONG m_cRefs;
IObject* m_data;
void* m_pvUseTrueShapeSelf; void* m_pvUseTrueShapeOther; KDroot* m_pkdrRoot;
HitTest* m_noHit;
HitTestID m_id;
BoundingBox m_boundingBox;
Vector m_stopPosition;
Vector m_velocity;
float m_radius;
float m_tStart;
float m_tStop;
Time m_timeStart;
Time m_timeStop;
Endpoint m_endpoints[c_nAxes][2];
HitTest* m_lastTest;
HitTestShape m_shape;
HitTestShape m_shapeTrue;
bool m_deletedF;
bool m_deadF;
bool m_activeF;
bool m_staticF;
friend class KDnode;
friend class KDroot;
};
typedef Slist_utl<HitTest*> HitTestList;
typedef Slink_utl<HitTest*> HitTestLink;
class KDnode
{
public:
KDnode(KDnode* parent);
~KDnode(void);
void reset(bool highF);
void pivot(void);
void test(HitTest* pHitTest,
CollisionQueue* pQueue) const;
protected:
int m_pivotAxis;
float m_pivotValue;
KDnode* m_parent;
KDnode* m_children[2];
void allocHitTestsEndpoints(int n);
int m_nHitTests;
int m_maxHitTests;
HitTest** m_ppHitTests;
Endpoint** m_ppEndpoints[c_nAxes];
};
class KDroot : public KDnode
{
public:
KDroot(bool bStatic);
~KDroot(void);
void addHitTest(HitTest* pHitTest);
void deleteHitTest(HitTest* pHitTest);
void flush(void);
void update(void);
private:
int m_nAdded;
int m_nDeleted;
bool m_bStatic;
};
class CollisionEntry
{
public:
float m_tCollision;
HitTest* m_pHitTest1;
HitTest* m_pHitTest2;
HitTestShape m_hts1;
HitTestShape m_hts2;
static void shortSort(CollisionEntry* lo,
CollisionEntry* hi);
static void longSort(CollisionEntry* lo,
CollisionEntry* hi);
};
class CollisionQueue
{
public:
CollisionQueue(void);
CollisionQueue(int m_maxCollisions,
CollisionEntry* pCollisions);
~CollisionQueue(void);
inline int n(void) const
{
return m_nCollisions;
}
inline CollisionEntry& operator [] (int i)
{
return m_pCollisions[i];
}
void sort(int start);
void flush(int start,
HitTest* pHitTest1,
HitTest* pHitTest2);
void purge(void);
void addCollision(float tCollision,
HitTest* pHitTest1,
HitTestShape hts1,
HitTest* pHitTest2,
HitTestShape hts2);
private:
int m_nCollisions;
CollisionEntry* m_pCollisions;
int m_maxCollisions;
bool m_fDelete;
};
class UTL
{
public:
static void SetArtPath(const char* szArtwork);
static HRESULT getFile( const char* name,
const char* extension,
OUT char* artwork,
bool downloadF,
bool createF);
static bool SaveFile( const char * szFilename,
const void *pData,
unsigned cLen,
OUT char * szErrorMsg,
bool bCreateAsTemp);
static bool AppendFile(const char * szFileName, const void * data, unsigned bytes);
static int SearchAndReplace(char * szDest, const char * szSource, const char * szNewWord, const char * szOldWord);
static void SetUrlRoot(const char * szUrlRoot);
static char* strdup(const char* s);
static void putFileName(char* name, const char* newVal);
static void putName(char* name, const char* newVal);
static const char* artworkPath(void)
{
return s_artworkPath;
}
static LONG GetPathFromReg(IN HKEY hkey,
IN const char * szSubKey,
OUT char * szPath);
static int hextoi(const char * pHex);
private:
static char s_artworkPath[MAX_PATH];
static char s_szUrlRoot[MAX_PATH];
};
class BytePercentage
{
public:
enum
{
Divisor = 240 };
BytePercentage(void)
{
}
BytePercentage(const BytePercentage& p)
:
m_percentage(p.m_percentage)
{
}
BytePercentage(float f)
:
m_percentage((unsigned char)(f * (float)Divisor + 0.5f))
{
assert ((f * (float)Divisor + 0.5f) >= 0.0f);
assert ((f * (float)Divisor + 0.5f) < (float)(Divisor + 1));
}
unsigned char GetChar(void) const
{
return m_percentage;
}
void SetChar(unsigned char p)
{
m_percentage = p;
}
BytePercentage& operator = (float f)
{
assert ((f * (float)Divisor + 0.5f) >= 0.0f);
assert ((f * (float)Divisor + 0.5f) < (float)(Divisor + 1));
m_percentage = (unsigned char)(f * (float)Divisor + 0.5f);
return *this;
}
operator float (void) const
{
return ((float)m_percentage) / ((float)Divisor);
}
private:
unsigned char m_percentage;
};
extern const Rotation c_rotationZero;
#include "utility.hxx"
#undef _exposed
static char * Strcpy(char * szDst, const char * szSrc)
{
assert(szDst);
return lstrcpyA(szDst, szSrc ? szSrc : "");
}
static char * Strncpy(char * szDst, const char * szSrc, size_t cb)
{
assert(szDst);
return strncpy(szDst, szSrc ? szSrc : "", cb);
}
static int Strcmp(const char * szDst, const char * szSrc)
{
return lstrcmpA(szDst ? szDst : "", szSrc ? szSrc : "");
}
#define IMPLIES(x, y) (!(x) || (y))
#define IFF(x, y) (!!(x) == !!(y))
#include "listwrappers.h"
template <class Func> class CTempFuncDll
{
public:
CTempFuncDll(LPSTR szDLL, LPSTR szFunc)
{
hmod = LoadLibrary(szDLL);
pfunc = (Func) ((hmod) ? GetProcAddress(hmod, szFunc) : 0);
}
~CTempFuncDll()
{
FreeLibrary(hmod);
}
Func Call()
{
assert(pfunc);
assert(!IsBadCodePtr((FARPROC)pfunc));
return pfunc;
}
private:
HMODULE hmod;
Func pfunc;
};
class CTempTimer_OptimizedOut {
public:
CTempTimer_OptimizedOut(const char * szName, float dtWarning) {}
void Start() {}
bool Stop(const char* format = NULL, ...) {return false;}
DWORD LastInterval() {return 0;}
};
class CTimer
{
public:
CTimer(const char * szName, float dtWarning) :
m_szname(szName),
m_time(0),
m_dtWarning((DWORD)(1000.0f * dtWarning)),
m_dtimemax(0),
m_dtTotal(0)
{
}
void Start()
{
m_time = Time::Now();
}
bool Stop(const char* format = NULL, ...) {
m_dtimelast = Time::Now().clock() - m_time.clock();
m_dtTotal += m_dtimelast;
bool fExtra = false;
bool fRecord = false;
if (m_dtimelast > m_dtimemax)
{
debugf("Timer: %fs spent %s, %fs total (longest so far)\n", (float) m_dtimelast / 1000.f, m_szname, (float)m_dtTotal / 1000.f);
m_dtimemax = m_dtimelast;
fRecord = true;
fExtra = true;
}
else if (m_dtimelast >= m_dtWarning)
{
debugf("Timer: %fs spent %s, %fs total\n", (float) m_dtimelast / 1000.0f, m_szname, (float)m_dtTotal / 1000.f);
fExtra = true;
}
if (fExtra && format)
{
const size_t size = 256;
char bfr[size];
va_list vl;
va_start(vl, format);
_vsnprintf(bfr, size, format, vl);
va_end(vl);
debugf("^--%s\n", bfr);
}
return fRecord;
}
DWORD LastInterval() {
return m_dtimelast;
}
private:
const char * m_szname;
Time m_time;
DWORD m_dtimelast;
DWORD m_dtimemax;
DWORD m_dtWarning;
DWORD m_dtTotal;
};
#ifdef NDEBUG
#define CTempTimer CTempTimer_OptimizedOut
#else
#define CTempTimer CTimer
#endif
#endif