etqw-sdk/source/game/guis/UIObject.h

354 lines
12 KiB
C
Raw Permalink Normal View History

2008-05-29 00:00:00 +00:00
// Copyright (C) 2007 Id Software, Inc.
//
#ifndef __GAME_GUIS_USERINTERFACEOBJECT_H__
#define __GAME_GUIS_USERINTERFACEOBJECT_H__
#include "UserInterfaceTypes.h"
#include "UITimeline.h"
#include "UIObjectScriptState.h"
class sdUIObject;
class sdUITypeInfo;
template< class T >
struct sdClass_StaticClassInitialization {
sdClass_StaticClassInitialization() {
T::InitClass();
}
~sdClass_StaticClassInitialization() {
T::ShutdownClass();
}
};
#define SD_UI_DECLARE_CLASS_STATIC_INIT( ClassName ) \
private: \
static sdClass_StaticClassInitialization< ClassName > sdClass_ClassInit;
#define SD_UI_DECLARE_TYPE_INFO \
static sdUITypeInfo Type; \
virtual bool IsType( const sdUITypeInfo& rhs ) const { return Type.IsType( rhs ); } \
virtual const sdUITypeInfo& GetType() const { return Type; } \
#define SD_UI_IMPLEMENT_CLASS_STATIC_INIT( ClassName ) \
sdClass_StaticClassInitialization< ClassName > ClassName ::sdClass_ClassInit;
#define SD_UI_DECLARE_CLASS( ClassName ) \
public: \
SD_UI_DECLARE_TYPE_INFO
#define SD_UI_DECLARE_ABSTRACT_CLASS( ClassName ) \
public: \
SD_UI_DECLARE_TYPE_INFO
#define SD_UI_IMPLEMENT_TYPE_INFO( ClassName, SuperClassName ) \
sdUITypeInfo ClassName::Type( #ClassName, #SuperClassName );
#define SD_UI_IMPLEMENT_CLASS( ClassName, SuperClassName ) \
SD_UI_IMPLEMENT_TYPE_INFO( ClassName, SuperClassName )
#define SD_UI_IMPLEMENT_ABSTRACT_CLASS( ClassName, SuperClassName ) \
SD_UI_IMPLEMENT_TYPE_INFO( ClassName, SuperClassName )
/*
============
sdUITypeInfo
============
*/
class sdUITypeInfo {
public:
typedef idHierarchy< sdUITypeInfo > node_t;
typedef sdUITypeInfo* Ptr;
typedef idList< sdUITypeInfo::Ptr > typeList_t;
sdUITypeInfo( const char* name_, const char* superName_ ) : typeBegin( 0 ), typeEnd( 0 ), name( name_ ), superName( superName_ ) {
Ptr existing = FindType( name, true );
if( existing ) {
throw idException( va( "Type '%s' is already defined", name ));
}
GetTypeList().Append( this );
node.SetOwner( this );
}
~sdUITypeInfo() {}
bool operator==( const char* rhs ) const {
return idStr::Cmp( rhs, name ) == 0;
}
bool IsType( const sdUITypeInfo& rhs ) const {
return typeBegin >= rhs.typeBegin && typeEnd <= rhs.typeEnd;
}
const char* GetName() const { return name; }
node_t& GetNode() { return node; }
static void Init();
static void Shutdown();
static void ListClasses();
static int NumTypes() { return GetTypeList().Num(); }
private:
const char* name;
const char* superName;
size_t typeBegin;
size_t typeEnd;
node_t node;
static bool initialized;
private:
static void ListClasses( node_t& root );
static void NumberTypes( node_t& root, size_t& id );
static Ptr FindType( const char* typeName, bool allowNotFound = false );
static typeList_t& GetTypeList();
static Ptr GetTypeRoot( Ptr root = NULL );
};
extern const char sdUITemplateFunctionInstance_IdentifierWindow[];
extern const char sdUITemplateFunctionInstance_IdentifierObject[];
/*
============
sdUIObject
============
*/
SD_UI_PROPERTY_TAG(
alias = "object";
)
class sdUIObject {
public:
SD_UI_DECLARE_ABSTRACT_CLASS( sdUIObject )
typedef idHierarchy< sdUIObject > hierarchyNode_t;
typedef enum windowEvent_e {
OE_NOOP,
OE_CONSTRUCTOR,
OE_CREATE,
OE_NAMED,
OE_PROPCHANGED,
OE_CVARCHANGED,
OE_NUM_EVENTS,
} windowEvent_t;
template< class T >
T* Cast() {
if( this == NULL ) {
return NULL;
}
if( !GetType().IsType( T::Type )) {
return NULL;
}
return static_cast< T* >( this );
}
template< class T >
const T* Cast() const {
if( this == NULL ) {
return NULL;
}
if( !GetType().IsType( T::Type )) {
return NULL;
}
return static_cast< const T* >( this );
}
enum eZOrder { ZO_FRONT, ZO_BACK };
enum objectFlag_t {
OF_FIXED_LAYOUT = BITT< 0 >::VALUE, // Object should be immune to any potential layout changes
// Make sure to update NEXT_OBJECT_FLAG below!
};
static const int NEXT_OBJECT_FLAG = 1; // derived classes should use bit fields from this bit up to avoid conflicts
sdUIObject();
virtual ~sdUIObject();
virtual const char* GetName( void ) const { return name.GetValue().c_str(); }
virtual void OnCreate() {}
virtual void LayoutChanged() {}
virtual bool PostEvent( const sdSysEvent* event ) { return false; }
virtual bool HandleFocus( const sdSysEvent* event ) { return false; }
virtual void OnActivate() {}
virtual void OnGainFocus() {}
virtual void OnLoseFocus() {}
virtual void MakeLayoutDirty() {}
// doesn't invalidate the layout of the parent parameter
static void MakeLayoutDirty_r( sdUIObject* parent );
virtual void OnLanguageInit() {}
virtual void OnLanguageShutdown() {}
static void OnLanguageInit_r( sdUIObject* parent );
static void OnLanguageShutdown_r( sdUIObject* parent );
// this should be called by derived versions AFTER they have done any necessary work
virtual void ApplyLayout();
virtual sdUIObject* UpdateToolTip( const idVec2& cursor ) { return NULL; }
bool TestFlag( const int flag ) const { return ( idMath::Ftoi( flags ) & flag ) != 0; }
static sdProperties::ePropertyType PropertyTypeForName( const char* typeName );
static void SetupProperties( sdProperties::sdPropertyHandler& handler, const idList< sdDeclGUIProperty* >& properties, sdUserInterfaceLocal* ui, const idTokenCache& tokenCache );
virtual void CreateProperties( sdUserInterfaceLocal* _ui, const sdDeclGUIWindow* windowParms, const idTokenCache& tokenCache );
void InitEvents();
virtual void CreateEvents( sdUserInterfaceLocal* _ui, const sdDeclGUIWindow* windowParms, idTokenCache& tokenCache );
virtual void CreateTimelines( sdUserInterfaceLocal* _ui, const sdDeclGUIWindow* windowParms, idTokenCache& tokenCache );
virtual void CacheEvents() {}
virtual void EnumerateEvents( const char* name, const idList<unsigned short>& flags, idList< sdUIEventInfo >& events, const idTokenCache& tokenCache );
virtual const char* GetScopeClassName() const = 0;
virtual sdUserInterfaceScope& GetScope( void ) { return scriptState; }
void Script_SetParent( sdUIFunctionStack& stack );
void Script_IsChild( sdUIFunctionStack& stack );
void Script_ChangeZOrder( sdUIFunctionStack& stack );
void Script_PostNamedEvent( sdUIFunctionStack& stack );
void Script_PostOptionalNamedEvent( sdUIFunctionStack& stack );
sdUserInterfaceLocal* GetUI( void ) { return ui; }
const sdUserInterfaceLocal* GetUI( void ) const { return ui; }
sdUITimelineManager* GetTimelineManager() { return timelines.Get(); }
virtual sdUIFunctionInstance* GetFunction( const char* name );
virtual bool RunNamedMethod( const char* name, sdUIFunctionStack& stack );
bool RunEventHandle( const sdUIEventHandle handle );
bool RunEvent( const sdUIEventInfo& info );
// Events
int GetNumEvents( const sdUIEventHandle type ) { return events.Num( type ); }
virtual sdUIEventHandle GetEvent( const sdUIEventInfo& info ) const;
virtual void AddEvent( const sdUIEventInfo& info, sdUIEventHandle scriptHandle );
virtual int GetFirstEventType() const { return 2; }
virtual int GetNextEventType( int event ) const { return ++event; }
virtual int GetMaxEventTypes( void ) const { return OE_NUM_EVENTS; }
virtual const char* GetEventNameForType( int event ) const { return eventNames[ event ]; }
hierarchyNode_t& GetNode( void ) { return hierarchyNode; }
const hierarchyNode_t& GetNode( void ) const { return hierarchyNode; }
void SetParent( sdUIObject* parent );
int NamedEventHandleForString( const char* name );
bool PostNamedEvent( const char* event, bool optional );
virtual void EndLevelLoad() {}
static const sdUITemplateFunction< sdUIObject >* FindFunction( const char* name );
static void InitFunctions( void );
static void ShutdownFunctions( void ) { objectFunctions.DeleteContents(); }
SD_UI_PROPERTY_TAG(
title = "1. Common/Name";
desc = "Name of the window. Must be unique within a GUI.";
editor = "edit";
option1 = "{editorSpecial} {name}";
datatype = "string";
)
sdStringProperty name;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "1. Behavior/Flags";
desc = "A bitfield of behaviors.";
editor = "edit";
datatype = "float";
)
sdFloatProperty flags;
// ===========================================
protected:
typedef sdPair< sdProperties::sdProperty*, sdProperties::CallbackHandle > callbackHandler_t;
void ConnectGlobalCallback( const callbackHandler_t& cb ) {
toDisconnect.Append( cb );
}
virtual void InitProperties() {}
void SetWindowFlag( const int flag ) { flags = idMath::Ftoi( flags ) | flag; }
void ClearWindowFlag( const int flag ) { flags = idMath::Ftoi( flags ) & ~flag; }
bool FlagActivated( const float oldValue, const float newValue, const int flag ) const { return ( !( idMath::Ftoi( oldValue ) & flag ) && ( idMath::Ftoi( newValue ) & flag ) ); }
bool FlagDeactivated( const float oldValue, const float newValue, const int flag ) const { return ( ( idMath::Ftoi( oldValue ) & flag ) && !( idMath::Ftoi( newValue ) & flag ) ); }
bool FlagChanged( const float oldValue, const float newValue, const int flag ) const { return FlagActivated( oldValue, newValue, flag ) || FlagDeactivated( oldValue, newValue, flag ); }
public:
// this should be called explicitly in all derived destructors
void DisconnectGlobalCallbacks() {
for( int i = 0; i < toDisconnect.Num(); i++ ) {
toDisconnect[ i ].first->RemoveOnChangeHandler( toDisconnect[ i ].second );
}
toDisconnect.Clear();
cvarCallbacks.DeleteContents( true );
}
private:
void OnStringPropertyChanged( int event, const idStr& oldValue, const idStr& newValue );
void OnWStringPropertyChanged( int event, const idWStr& oldValue, const idWStr& newValue );
void OnIntPropertyChanged( int event, const int oldValue, const int newValue );
void OnFloatPropertyChanged( int event, const float oldValue, const float newValue );
void OnVec4PropertyChanged( int event, const idVec4& oldValue, const idVec4& newValue );
void OnVec3PropertyChanged( int event, const idVec3& oldValue, const idVec3& newValue );
void OnVec2PropertyChanged( int event, const idVec2& oldValue, const idVec2& newValue );
void OnCVarChanged( idCVar& cvar, int id );
protected:
sdUserInterfaceLocal* ui;
sdUIWindowState scriptState;
sdUIEventTable events;
hierarchyNode_t hierarchyNode;
int lastClickTime;
sdAutoPtr< sdUITimelineManager > timelines;
idStrList namedEvents;
private:
typedef sdUICVarCallback< sdUIObject > cvarCallback_t;
friend class sdUICVarCallback< sdUIObject >;
idList< cvarCallback_t* > cvarCallbacks;
idList< callbackHandler_t > toDisconnect;
static idHashMap< sdUITemplateFunction< sdUIObject >* > objectFunctions;
static const char* eventNames[ OE_NUM_EVENTS ];
};
/*
============
sdUIObject_Drawable
============
*/
class sdUIObject_Drawable :
public sdUIObject {
public:
SD_UI_DECLARE_ABSTRACT_CLASS( sdUIObject_Drawable )
virtual ~sdUIObject_Drawable() {}
virtual void Draw() = 0;
virtual void FinalDraw() {};
};
#endif // __GAME_GUIS_USERINTERFACEOBJECT_H__