|
|
//=========== (C) Copyright Valve, L.L.C. All rights reserved. ===========
#ifndef UI_NUGGET_H
#define UI_NUGGET_H
#include "game_controls/igameuisystemmgr.h"
#include "matchmaking/imatchframework.h"
#include "fmtstr.h"
#include "utlstringmap.h"
class CUiNuggetBase; class CUiNuggetReference; class CUiNuggetFactoryRegistrarBase; class CUiNuggetFactoryRegistrarBaseInstances; class CUiNuggetFactoryRegistrarBaseSingleton;
//////////////////////////////////////////////////////////////////////////
//
// Base class for implementing UI nuggets
//
class CUiNuggetBase : public IGameUIScreenController { public: CUiNuggetBase(); virtual ~CUiNuggetBase();
// IGameUIScreenController
public: // Connects a screen to the controller, returns number of
// remaining connected screens (or 1 for the first connection)
virtual int OnScreenConnected( IGameUISystem *pScreenView );
// Releases the screen from controller, returns number of
// remaining connected screens (returns 0 if no screens are
// connected - new object must be reacquired from factory
// in this case)
virtual int OnScreenDisconnected( IGameUISystem *pScreenView );
// Callback for screen events handling
virtual KeyValues * OnScreenEvent( IGameUISystem *pScreenView, KeyValues *kvEvent );
// Broadcast an event to all connected screens (caller retains ownership of keyvalues)
virtual void BroadcastEventToScreens( KeyValues *kvEvent );
public: // Add a reference to the nugget to be notified upon release
virtual void AddReferenceSink( CUiNuggetReference *pSink ) { m_arrReferences.AddToTail( pSink ); }
protected: // Policy for whether the object should be deleted when no screen references remain
virtual bool ShouldDeleteOnLastScreenDisconnect() { return true; }
protected: struct ConnectionInfo_t { IGameUISystem *m_pScreen; int m_nRefCount;
explicit ConnectionInfo_t( IGameUISystem *pScreen = NULL ) : m_pScreen( pScreen ), m_nRefCount( 0 ) {} bool operator == ( ConnectionInfo_t const &other ) const { return m_pScreen == other.m_pScreen; } }; typedef CUtlVector< ConnectionInfo_t > ConnectedScreens; ConnectedScreens m_arrConnectedScreens; CUtlVector< int > m_arrEventsDisabledScreenHandles;
KeyValues *m_pUiNuggetData; KeyValues::AutoDelete m_autodelete_m_pUiNuggetData;
private: CUtlVector< int * > m_arrBroadcastEventIdxArray; CUtlVector< CUiNuggetReference * > m_arrReferences; };
//////////////////////////////////////////////////////////////////////////
//
// Declaration of UI nuggets factories
//
class CUiNuggetFactoryRegistrarBase : public IGameUIScreenControllerFactory { public: CUiNuggetFactoryRegistrarBase(); ~CUiNuggetFactoryRegistrarBase();
virtual void Register();
virtual char const *GetName() = 0;
public: static void RegisterAll();
private: CUiNuggetFactoryRegistrarBase *m_pPrev, *m_pNext; };
class CUiNuggetFactoryRegistrarBaseGlobalInstance : public CUiNuggetFactoryRegistrarBase { public: // Returns an instance of a controller interface
virtual IGameUIScreenController * GetController( KeyValues *kvRequest ) = 0;
// Access controller instances
virtual int GetControllerInstancesCount() { return 1; } virtual IGameUIScreenController * GetControllerInstance( int iIndex ) = 0; };
class CUiNuggetFactoryRegistrarBaseSingleton : public CUiNuggetFactoryRegistrarBase { friend class CUiNuggetFactoryRegistrarBaseSingletonReferenceTracker; public: CUiNuggetFactoryRegistrarBaseSingleton();
public: // Returns an instance of a controller interface
virtual IGameUIScreenController * GetController( KeyValues *kvRequest );
// Access controller instances
virtual int GetControllerInstancesCount() { return !!m_pSingleton; } virtual IGameUIScreenController * GetControllerInstance( int iIndex ) { return m_pSingleton; }
public: // Creates an instance of a controller interface
virtual CUiNuggetBase * CreateNewController() = 0;
protected: CUiNuggetBase *m_pSingleton; };
class CUiNuggetFactoryRegistrarBaseInstances : public CUiNuggetFactoryRegistrarBase { friend class CUiNuggetFactoryRegistrarBaseInstancesReferenceTracker; public: // Returns an instance of a controller interface
virtual IGameUIScreenController * GetController( KeyValues *kvRequest );
// Access controller instances
virtual int GetControllerInstancesCount() { return m_arrInstances.Count(); } virtual IGameUIScreenController * GetControllerInstance( int iIndex ) { return m_arrInstances.IsValidIndex( iIndex ) ? m_arrInstances[iIndex] : NULL; }
public: // Creates an instance of a controller interface
virtual CUiNuggetBase * CreateNewController() = 0;
protected: // Nugget instances
CUtlVector< CUiNuggetBase * > m_arrInstances; };
//////////////////////////////////////////////////////////////////////////
//
// Macros to be used to declare UI nuggets factories
//
// Global instance factory - a nugget instance always exists in a global variable
// and is always shared with all screens.
#define UI_NUGGET_FACTORY_GLOBAL_INSTANCE( nuggetclassname, instanceptr, scriptname ) \
namespace { \ class Factory_##nuggetclassname##_Class : public CUiNuggetFactoryRegistrarBaseGlobalInstance \ { \ virtual IGameUIScreenController * GetController( KeyValues *kvRequest ) { return static_cast< nuggetclassname * >( instanceptr ); } \ virtual IGameUIScreenController * GetControllerInstance( int iIndex ) { return static_cast< nuggetclassname * >( instanceptr ); } \ virtual char const * GetName() { return scriptname; } \ } \ g_factory_##nuggetclassname##_globalinstance; \ };
// Singleton factory - create a new nugget instance and share it with all screens
// until all references to the nugget are released and nugget is destroyed.
// If nugget policy is not deleting the nugget upon last release, then a single nugget
// instance will be created once and shared with all screens.
#define UI_NUGGET_FACTORY_SINGLETON( nuggetclassname, scriptname ) \
namespace { \ class Factory_##nuggetclassname##_Class : public CUiNuggetFactoryRegistrarBaseSingleton \ { \ virtual CUiNuggetBase * CreateNewController() { return new nuggetclassname; } \ virtual char const * GetName() { return scriptname; } \ } \ g_factory_##nuggetclassname##_singleton; \ };
// Instances factory - create a new nugget instance per each request.
// Screens need to implement own methods of sharing data from a single nugget
// instance. Nugget instance must be marked for delete upon last release.
#define UI_NUGGET_FACTORY_INSTANCES( nuggetclassname, scriptname ) \
namespace { \ class Factory_##nuggetclassname##_Class : public CUiNuggetFactoryRegistrarBaseInstances \ { \ virtual CUiNuggetBase * CreateNewController() { return new nuggetclassname; } \ virtual char const * GetName() { return scriptname; } \ } \ g_factory_##nuggetclassname##_instances; \ };
//////////////////////////////////////////////////////////////////////////
//
// Macros to be used to declare nuggets functions
//
#define DECLARE_NUGGET_FN_MAP( classname, baseclass ) \
typedef classname NuggetEventMapClass; \ typedef baseclass NuggetEventMapBaseClass; \ class NuggetEventMap : \ public CUtlStringMap< KeyValues * (classname::*)( IGameUISystem *pScreenView, KeyValues *args ) > \ {} \ m_NuggetEventMap; \ class NuggetPreBroadcastMap : \ public CUtlStringMap< bool (classname::*)( KeyValues *args ) > \ {} \ m_NuggetPreBroadcastMap; \ virtual KeyValues * OnScreenEvent( IGameUISystem *pScreenView, KeyValues *args ) { \ char const *szEvent = args->GetName(); \ UtlSymId_t sym = m_NuggetEventMap.Find( szEvent ); \ if ( sym != m_NuggetEventMap.InvalidIndex() ) { \ return (this->* (m_NuggetEventMap[sym]) )( pScreenView, args ); \ } \ return NuggetEventMapBaseClass::OnScreenEvent( pScreenView, args ); \ } \ virtual void BroadcastEventToScreens( KeyValues *args ) { \ char const *szEvent = args->GetName(); \ UtlSymId_t sym = m_NuggetPreBroadcastMap.Find( szEvent ); \ if ( sym != m_NuggetPreBroadcastMap.InvalidIndex() ) { \ if ( ! (this->* (m_NuggetPreBroadcastMap[sym]) )( args ) ) return; \ } \ return NuggetEventMapBaseClass::BroadcastEventToScreens( args ); \ }
#define NUGGET_FN( eventname ) \
class eventname##_EventRegistrar { \ public: typedef eventname##_EventRegistrar ThisClass; \ eventname##_EventRegistrar() { \ NuggetEventMapClass *pNugget = reinterpret_cast< NuggetEventMapClass * >( reinterpret_cast< size_t >( this ) - offsetof( NuggetEventMapClass, m_##eventname##_EventRegistrar ) ); \ pNugget->m_NuggetEventMap[ #eventname ] = &NuggetEventMapClass::Event_##eventname; \ COMPILE_TIME_ASSERT( offsetof( NuggetEventMapClass, m_##eventname##_EventRegistrar ) > offsetof( NuggetEventMapClass, m_NuggetEventMap ) ); \ } } m_##eventname##_EventRegistrar; \ KeyValues * Event_##eventname( IGameUISystem *pScreenView, KeyValues *args )
#define NUGGET_BROADCAST_FN( eventname ) \
class eventname##_BroadcastRegistrar { \ public: typedef eventname##_BroadcastRegistrar ThisClass; \ eventname##_BroadcastRegistrar() { \ NuggetEventMapClass *pNugget = reinterpret_cast< NuggetEventMapClass * >( reinterpret_cast< size_t >( this ) - offsetof( NuggetEventMapClass, m_##eventname##_BroadcastRegistrar ) ); \ pNugget->m_NuggetPreBroadcastMap[ #eventname ] = &NuggetEventMapClass::Broadcast_##eventname; \ COMPILE_TIME_ASSERT( offsetof( NuggetEventMapClass, m_##eventname##_BroadcastRegistrar ) > offsetof( NuggetEventMapClass, m_NuggetPreBroadcastMap ) ); \ } } m_##eventname##_BroadcastRegistrar; \ bool Broadcast_##eventname( KeyValues *args )
#endif // UI_NUGGET_H
|