ef2gamesource/dlls/game/class.h
2012-12-31 21:19:39 +01:00

448 lines
10 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /Code/DLLs/game/class.h $
// $Revision:: 18 $
// $Author:: Steven $
// $Date:: 10/13/03 9:43a $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
//
// DESCRIPTION:
// Base class that all classes that are used in conjunction with the game should
// be based off of. Class gives run-time type information about any class
// derived from it. This is really handy when you have a pointer to an object
// that you need to know if it supports certain behaviour.
//
// WARNING: This file is shared between game, cgame and possibly the user interface.
// It is instanced in each one of these directories because of the way that SourceSafe works.
//
class Class;
class Event;
#ifndef __CLASS_H__
#define __CLASS_H__
#if defined( GAME_DLL )
//
// game dll specific defines
//
#include "g_local.h"
#include "Linklist.h"
#define CLASS_DPrintf gi.DPrintf
#define CLASS_Printf gi.Printf
#define CLASS_WDPrintf gi.WDPrintf
#define CLASS_WPrintf gi.WPrintf
#define CLASS_Error gi.Error
class Archiver;
#elif defined ( CGAME_DLL )
//
// cgame dll specific defines
//
#include "../../DLLs/game/q_shared.h"
#include "Linklist.h"
#define CLASS_DPrintf cgi.DPrintf
#define CLASS_Printf cgi.Printf
#define CLASS_WDPrintf cgi.WDPrintf
#define CLASS_WPrintf cgi.WPrintf
#define CLASS_Error cgi.Error
#else
//
// client specific defines
//
#include "../../DLLs/game/q_shared.h"
#include "Linklist.h"
#define CLASS_DPrintf Com_DPrintf
#define CLASS_Printf Com_Printf
#define CLASS_WDPrintf Com_WDPrintf
#define CLASS_WPrintf Com_WPrintf
#define CLASS_Error Com_Error
#endif
// Flags used for the Output class
#define EVENT_TIKI_ONLY 1
#define EVENT_SCRIPT_ONLY 2
#define EVENT_ALL 3
#define OUTPUT_HTML 1
#define OUTPUT_CMD 2
#define OUTPUT_ALL 3
#define MAX_CLASSES 1024
typedef void ( Class::*Response )( Event *event );
template< class Type >
struct ResponseDef
{
Event* event;
void ( Type::*response )( Event *event );
};
/***********************************************************************
ClassDef
***********************************************************************/
class ClassDef
{
public:
const char* classname;
const char* classID;
const char* superclass;
void* ( *newInstance )( void );
int classSize;
ResponseDef<Class>* responses;
int numEvents;
Response** responseLookup;
ClassDef* super;
ClassDef* next;
ClassDef* prev;
ClassDef();
~ClassDef();
ClassDef( const char* classname, const char* classID, const char* superclass, ResponseDef<Class>* responses, void* ( *newInstance )( void ), int classSize );
void BuildResponseList( void );
void Shutdown( void );
};
/***********************************************************************
SafePtr
***********************************************************************/
class SafePtrBase;
class Class;
class SafePtrBase
{
private:
void AddReference( Class* ptr );
void RemoveReference( Class* ptr );
protected:
SafePtrBase* prevSafePtr;
SafePtrBase* nextSafePtr;
Class* ptr;
public:
SafePtrBase();
virtual ~SafePtrBase();
void InitSafePtr( Class* newptr );
Class* Pointer( void );
void Clear( void );
};
/***********************************************************************
Class
***********************************************************************/
#define CLASS_DECLARATION( nameofsuperclass, nameofclass, classid ) \
ClassDef nameofclass::ClassInfo \
( \
#nameofclass, classid, #nameofsuperclass, \
( ResponseDef<Class>* )nameofclass::Responses, \
nameofclass::_newInstance, sizeof( nameofclass ) \
); \
void* nameofclass::_newInstance( void ) \
{ \
return new nameofclass; \
} \
ClassDef* nameofclass::classinfo( void ) const \
{ \
return &( nameofclass::ClassInfo ); \
} \
ResponseDef<nameofclass> nameofclass::Responses[] =
#define CLASS_PROTOTYPE( nameofclass ) \
public: \
static ClassDef ClassInfo; \
static void* _newInstance( void ); \
virtual ClassDef* classinfo( void ) const; \
static ResponseDef<nameofclass> Responses[]
class Class
{
private:
SafePtrBase* SafePtrList;
friend class SafePtrBase;
protected:
void ClearSafePointers( void );
public:
CLASS_PROTOTYPE( Class );
void* operator new( size_t );
void operator delete( void* );
Class();
virtual ~Class();
void warning( const char* function, const char* fmt, ... );
void error( const char* function, const char* fmt, ... );
qboolean inheritsFrom( ClassDef* c ) const;
qboolean inheritsFrom( const char* name ) const;
qboolean isInheritedBy( const char* name ) const;
qboolean isInheritedBy( ClassDef* c ) const;
const char* getClassname( void );
const char* getClassID( void );
const char* getSuperclass( void );
void* newInstance( void );
#ifdef GAME_DLL
virtual void Archive( Archiver &arc );
#endif
};
void BuildEventResponses( void );
ClassDef* getClassForID( const char* name );
ClassDef* getClass( const char* name );
ClassDef* getClassList( void );
void listAllClasses( void );
void listInheritanceOrder( const char* classname );
qboolean checkInheritance( const ClassDef* const superclass, const ClassDef* const subclass );
qboolean checkInheritance( ClassDef* const superclass, const char* const subclass );
qboolean checkInheritance( const char* const superclass, const char* const subclass );
void DisplayMemoryUsage( void );
void ClassEvents( const char* classname, qboolean dump = false );
void DumpAllClasses( int typeFlag = EVENT_ALL, int outputType = OUTPUT_ALL, const char* filename = NULL);
void DumpClass( FILE* class_file, const char* className, int typeFlag = 0);
inline qboolean Class::inheritsFrom(ClassDef* c) const
{
return checkInheritance( c, classinfo() );
}
inline qboolean Class::isInheritedBy(ClassDef*c ) const
{
return checkInheritance( classinfo(), c );
}
// The lack of a space between the ")" and "inheritsFrom" is intentional.
// It allows the macro to compile like a function call. However, this
// may cause problems in some compilers (like gcc), so we may have to
// change this to work like a normal macro with the object passed in
// as a parameter to the macro.
#define isSubclassOf( classname )inheritsFrom( &classname::ClassInfo )
#define isSuperclassOf( classname )isInheritedBy( &classname::ClassInfo )
/***********************************************************************
SafePtr
***********************************************************************/
inline void SafePtrBase::AddReference(Class* ptr)
{
if ( !ptr->SafePtrList )
{
ptr->SafePtrList = this;
LL_Reset( this, nextSafePtr, prevSafePtr );
}
else
{
LL_Add( ptr->SafePtrList, this, nextSafePtr, prevSafePtr );
}
}
inline void SafePtrBase::RemoveReference(Class* ptr)
{
if ( ptr->SafePtrList == this )
{
if ( ptr->SafePtrList->nextSafePtr == this )
{
ptr->SafePtrList = NULL;
}
else
{
ptr->SafePtrList = nextSafePtr;
LL_Remove( this, nextSafePtr, prevSafePtr );
}
}
else
{
LL_Remove( this, nextSafePtr, prevSafePtr );
}
}
inline void SafePtrBase::Clear(void)
{
if ( ptr )
{
RemoveReference( ptr );
ptr = NULL;
}
}
inline SafePtrBase::SafePtrBase()
{
prevSafePtr = NULL;
nextSafePtr = NULL;
ptr = NULL;
}
inline SafePtrBase::~SafePtrBase()
{
Clear();
}
inline Class* SafePtrBase::Pointer(void)
{
return ptr;
}
inline void SafePtrBase::InitSafePtr(Class* newptr)
{
if ( ptr != newptr )
{
if ( ptr )
{
RemoveReference( ptr );
}
ptr = newptr;
if ( ptr == NULL )
{
return;
}
AddReference( ptr );
}
}
template<class T>
class SafePtr : public SafePtrBase
{
public:
SafePtr( T* objptr = 0 );
SafePtr( const SafePtr& obj );
SafePtr& operator=( const SafePtr& obj );
SafePtr& operator=( T* const obj );
template <class F> friend int operator==( SafePtr<F> a, F* b );
template <class F> friend int operator!=( SafePtr<F> a, F* b );
template <class F> friend int operator==( F* a, SafePtr<F> b );
template <class F> friend int operator!=( F* a, SafePtr<F> b );
template <class F> friend int operator==( SafePtr<F> a, SafePtr<F> b );
template <class F> friend int operator!=( SafePtr<F> a, SafePtr<F> b );
operator T*() const;
T* operator->() const;
T& operator*() const;
};
template<class T>
inline SafePtr<T>::SafePtr( T* objptr )
{
InitSafePtr( objptr );
}
template<class T>
inline SafePtr<T>::SafePtr( const SafePtr& obj )
{
InitSafePtr( obj.ptr );
}
template<class T>
inline SafePtr<T>& SafePtr<T>::operator=( const SafePtr& obj )
{
InitSafePtr( obj.ptr );
return *this;
}
template<class T>
inline SafePtr<T>& SafePtr<T>::operator=( T* const obj )
{
InitSafePtr( obj );
return *this;
}
template<class T>
inline int operator==(SafePtr<T> a, T* b)
{
return a.ptr == b;
}
template<class T>
inline int operator!=(SafePtr<T> a, T* b)
{
return a.ptr != b;
}
template<class T>
inline int operator==(T* a, SafePtr<T> b)
{
return a == b.ptr;
}
template<class T>
inline int operator!=(T* a, SafePtr<T> b)
{
return a != b.ptr;
}
template<class T>
inline int operator==(SafePtr<T> a, SafePtr<T> b)
{
return a.ptr == b.ptr;
}
template<class T>
inline int operator!=(SafePtr<T> a,SafePtr<T> b)
{
return a.ptr != b.ptr;
}
template<class T>
inline SafePtr<T>::operator T*() const
{
return ( T * )ptr;
}
template<class T>
inline T* SafePtr<T>::operator->() const
{
return ( T * )ptr;
}
template<class T>
inline T& SafePtr<T>::operator*() const
{
return *( T * )ptr;
}
typedef SafePtr<Class> ClassPtr;
#ifdef GAME_DLL
#include "archive.h"
#endif
// used by listener for event allocation
extern int totalmemallocated;
#ifndef GAME_DLL
extern "C"
{
// interface functions
void ShutdownClasses( void );
}
#endif
#endif /* class.h */