You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
6.9 KiB
275 lines
6.9 KiB
//=========== (C) Copyright Valve, L.L.C. All rights reserved. ===========
|
|
|
|
#include "cbase.h"
|
|
#include "ui_nugget.h"
|
|
#include "vstdlib/ikeyvaluessystem.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CUiNuggetReference implementation
|
|
//
|
|
|
|
class CUiNuggetReference
|
|
{
|
|
public:
|
|
virtual void OnNuggetReleased( CUiNuggetBase *pNugget ) = 0;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CUiNuggetBase implementation
|
|
//
|
|
|
|
CUiNuggetBase::CUiNuggetBase() :
|
|
m_pUiNuggetData( new KeyValues( "" ) ),
|
|
m_autodelete_m_pUiNuggetData( m_pUiNuggetData )
|
|
{
|
|
}
|
|
|
|
CUiNuggetBase::~CUiNuggetBase()
|
|
{
|
|
while ( m_arrReferences.Count() )
|
|
{
|
|
CUiNuggetReference *pSink = m_arrReferences.Head();
|
|
m_arrReferences.RemoveMultipleFromHead( 1 );
|
|
pSink->OnNuggetReleased( this );
|
|
}
|
|
}
|
|
|
|
int CUiNuggetBase::OnScreenConnected( IGameUISystem *pScreenView )
|
|
{
|
|
ConnectionInfo_t ci( pScreenView );
|
|
int idx = m_arrConnectedScreens.Find( ci );
|
|
if ( idx != m_arrConnectedScreens.InvalidIndex() )
|
|
{
|
|
++ m_arrConnectedScreens[idx].m_nRefCount;
|
|
}
|
|
else
|
|
{
|
|
ci.m_nRefCount = 1;
|
|
m_arrConnectedScreens.AddToTail( ci );
|
|
}
|
|
return m_arrConnectedScreens.Count();
|
|
}
|
|
|
|
int CUiNuggetBase::OnScreenDisconnected( IGameUISystem *pScreenView )
|
|
{
|
|
ConnectionInfo_t ci( pScreenView );
|
|
int idx = m_arrConnectedScreens.Find( ci );
|
|
if ( idx != m_arrConnectedScreens.InvalidIndex() )
|
|
{
|
|
if ( -- m_arrConnectedScreens[idx].m_nRefCount )
|
|
return m_arrConnectedScreens.Count();
|
|
|
|
// Otherwise this screen must be released
|
|
m_arrConnectedScreens.Remove( idx );
|
|
|
|
// Assert that screen is not disconnecting in the middle of
|
|
// event broadcast (otherwise need to implement index adjustment
|
|
// so that broadcast could succeed)
|
|
Assert( !m_arrBroadcastEventIdxArray.Count() );
|
|
|
|
// Check if we need to delete us
|
|
int numRemaining = m_arrConnectedScreens.Count();
|
|
if ( !numRemaining && ShouldDeleteOnLastScreenDisconnect() )
|
|
{
|
|
delete this;
|
|
}
|
|
return numRemaining;
|
|
}
|
|
else
|
|
{
|
|
Warning( "CUiNuggetBase::OnScreenDisconnected %p for not connected screen!\n", pScreenView );
|
|
Assert( !"OnScreenDisconnected" );
|
|
return m_arrConnectedScreens.Count();
|
|
}
|
|
}
|
|
|
|
KeyValues * CUiNuggetBase::OnScreenEvent( IGameUISystem *pScreenView, KeyValues *kvEvent )
|
|
{
|
|
int nEvent = kvEvent->GetNameSymbol();
|
|
|
|
static int const s_nGetData = KeyValuesSystem()->GetSymbolForString( "GetData" );
|
|
if ( nEvent == s_nGetData )
|
|
{
|
|
return m_pUiNuggetData->MakeCopy();
|
|
}
|
|
|
|
static int const s_nEnableEvents = KeyValuesSystem()->GetSymbolForString( "EnableEvents" );
|
|
if ( nEvent == s_nEnableEvents )
|
|
{
|
|
int nScriptHandle = kvEvent->GetInt( "scripthandle" );
|
|
bool bEnabled = kvEvent->GetBool( "enable", true );
|
|
m_arrEventsDisabledScreenHandles.FindAndFastRemove( nScriptHandle );
|
|
if ( !bEnabled )
|
|
m_arrEventsDisabledScreenHandles.AddToTail( nScriptHandle );
|
|
return NULL;
|
|
}
|
|
|
|
DevWarning( "CUiNuggetBase(%p)::OnScreenEvent for unknown command %s!\n", this, kvEvent->GetName() );
|
|
return NULL;
|
|
}
|
|
|
|
void CUiNuggetBase::BroadcastEventToScreens( KeyValues *kvEvent )
|
|
{
|
|
int idx = 0;
|
|
m_arrBroadcastEventIdxArray.AddToTail( &idx );
|
|
|
|
for ( ; idx < m_arrConnectedScreens.Count(); ++ idx )
|
|
{
|
|
IGameUISystem *pUI = m_arrConnectedScreens[idx].m_pScreen;
|
|
int iScriptHandle = pUI->GetScriptHandle();
|
|
if ( m_arrEventsDisabledScreenHandles.Find( iScriptHandle ) != m_arrEventsDisabledScreenHandles.InvalidIndex() )
|
|
continue;
|
|
pUI->ExecuteScript( kvEvent );
|
|
}
|
|
|
|
m_arrBroadcastEventIdxArray.RemoveMultipleFromTail( 1 );
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CUiNuggetFactoryRegistrarBase implementation
|
|
//
|
|
|
|
static CUiNuggetFactoryRegistrarBase *g_pUiNuggetFactoriesCircularList = NULL;
|
|
|
|
CUiNuggetFactoryRegistrarBase::CUiNuggetFactoryRegistrarBase()
|
|
{
|
|
// Add us to list
|
|
CUiNuggetFactoryRegistrarBase *pLeft = this;
|
|
CUiNuggetFactoryRegistrarBase *pRight = this;
|
|
|
|
if ( g_pUiNuggetFactoriesCircularList )
|
|
{
|
|
pLeft = g_pUiNuggetFactoriesCircularList;
|
|
pRight = g_pUiNuggetFactoriesCircularList->m_pNext;
|
|
|
|
pLeft->m_pNext = this;
|
|
pRight->m_pPrev = this;
|
|
}
|
|
|
|
g_pUiNuggetFactoriesCircularList = this;
|
|
m_pNext = pRight;
|
|
m_pPrev = pLeft;
|
|
}
|
|
|
|
CUiNuggetFactoryRegistrarBase::~CUiNuggetFactoryRegistrarBase()
|
|
{
|
|
// Remove us from list
|
|
if ( m_pPrev == this || m_pNext == this )
|
|
{
|
|
Assert( m_pPrev == this && m_pNext == this && g_pUiNuggetFactoriesCircularList == this );
|
|
g_pUiNuggetFactoriesCircularList = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_pPrev->m_pNext = m_pNext;
|
|
m_pNext->m_pPrev = m_pPrev;
|
|
if ( g_pUiNuggetFactoriesCircularList == this )
|
|
g_pUiNuggetFactoriesCircularList = m_pPrev;
|
|
}
|
|
}
|
|
|
|
void CUiNuggetFactoryRegistrarBase::Register()
|
|
{
|
|
Assert( g_pGameUISystemMgr );
|
|
g_pGameUISystemMgr->RegisterScreenControllerFactory( GetName(), this );
|
|
}
|
|
|
|
void CUiNuggetFactoryRegistrarBase::RegisterAll()
|
|
{
|
|
CUiNuggetFactoryRegistrarBase *p = g_pUiNuggetFactoriesCircularList;
|
|
if ( !p )
|
|
return;
|
|
|
|
do
|
|
{
|
|
p->Register();
|
|
p = p->m_pNext;
|
|
}
|
|
while ( p != g_pUiNuggetFactoriesCircularList );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// factories implementation
|
|
//
|
|
|
|
CUiNuggetFactoryRegistrarBaseSingleton::CUiNuggetFactoryRegistrarBaseSingleton() :
|
|
m_pSingleton( NULL )
|
|
{
|
|
}
|
|
|
|
class CUiNuggetFactoryRegistrarBaseSingletonReferenceTracker : public CUiNuggetReference
|
|
{
|
|
public:
|
|
CUiNuggetFactoryRegistrarBaseSingletonReferenceTracker( CUiNuggetBase *pNugget, CUiNuggetFactoryRegistrarBaseSingleton *pFactory )
|
|
{
|
|
m_pFactory = pFactory;
|
|
m_pFactory->m_pSingleton = pNugget;
|
|
pNugget->AddReferenceSink( this );
|
|
}
|
|
|
|
private:
|
|
virtual void OnNuggetReleased( CUiNuggetBase *pNugget )
|
|
{
|
|
m_pFactory->m_pSingleton = NULL;
|
|
delete this;
|
|
}
|
|
|
|
private:
|
|
CUiNuggetFactoryRegistrarBaseSingleton *m_pFactory;
|
|
};
|
|
|
|
IGameUIScreenController * CUiNuggetFactoryRegistrarBaseSingleton::GetController( KeyValues *kvRequest )
|
|
{
|
|
if ( Q_stricmp( GetName(), kvRequest->GetName() ) )
|
|
return NULL;
|
|
|
|
if ( !m_pSingleton )
|
|
{
|
|
m_pSingleton = CreateNewController();
|
|
new CUiNuggetFactoryRegistrarBaseSingletonReferenceTracker( m_pSingleton, this );
|
|
}
|
|
|
|
return m_pSingleton;
|
|
}
|
|
|
|
class CUiNuggetFactoryRegistrarBaseInstancesReferenceTracker : public CUiNuggetReference
|
|
{
|
|
public:
|
|
CUiNuggetFactoryRegistrarBaseInstancesReferenceTracker( CUiNuggetBase *pNugget, CUiNuggetFactoryRegistrarBaseInstances *pFactory )
|
|
{
|
|
m_pFactory = pFactory;
|
|
m_pFactory->m_arrInstances.AddToTail( pNugget );
|
|
pNugget->AddReferenceSink( this );
|
|
}
|
|
|
|
private:
|
|
virtual void OnNuggetReleased( CUiNuggetBase *pNugget )
|
|
{
|
|
m_pFactory->m_arrInstances.FindAndRemove( pNugget );
|
|
delete this;
|
|
}
|
|
|
|
private:
|
|
CUiNuggetFactoryRegistrarBaseInstances *m_pFactory;
|
|
};
|
|
|
|
IGameUIScreenController * CUiNuggetFactoryRegistrarBaseInstances::GetController( KeyValues *kvRequest )
|
|
{
|
|
if ( Q_stricmp( GetName(), kvRequest->GetName() ) )
|
|
return NULL;
|
|
|
|
CUiNuggetBase *pInstance = CreateNewController();
|
|
if ( !pInstance )
|
|
return NULL;
|
|
|
|
new CUiNuggetFactoryRegistrarBaseInstancesReferenceTracker( pInstance, this );
|
|
return pInstance;
|
|
}
|
|
|