|
|
//===== Copyright � 1996-2010, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "inputsystem/iinputstacksystem.h"
#include "tier2/tier2.h"
#include "tier1/utlstack.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// An input context
//-----------------------------------------------------------------------------
struct InputContext_t { InputCursorHandle_t m_hCursorIcon; bool m_bEnabled; bool m_bCursorVisible; bool m_bMouseCaptureEnabled; };
//-----------------------------------------------------------------------------
// Stack system implementation
//-----------------------------------------------------------------------------
class CInputStackSystem : public CTier2AppSystem< IInputStackSystem > { typedef CTier2AppSystem< IInputStackSystem > BaseClass;
// Methods of IAppSystem
public: virtual const AppSystemInfo_t* GetDependencies(); virtual void Shutdown();
// Methods of IInputStackSystem
public: virtual InputContextHandle_t PushInputContext(); virtual void PopInputContext( ); virtual void EnableInputContext( InputContextHandle_t hContext, bool bEnable ); virtual void SetCursorVisible( InputContextHandle_t hContext, bool bVisible ); virtual void SetCursorIcon( InputContextHandle_t hContext, InputCursorHandle_t hCursor ); virtual void SetMouseCapture( InputContextHandle_t hContext, bool bEnable ); virtual void SetCursorPosition( InputContextHandle_t hContext, int x, int y ); virtual bool IsTopmostEnabledContext( InputContextHandle_t hContext ) const;
private: // Updates the cursor based on the current state of the input stack
void UpdateCursorState();
CUtlStack< InputContext_t * > m_ContextStack; };
//-----------------------------------------------------------------------------
// Singleton instance
//-----------------------------------------------------------------------------
static CInputStackSystem s_InputStackSystem; EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CInputStackSystem, IInputStackSystem, INPUTSTACKSYSTEM_INTERFACE_VERSION, s_InputStackSystem );
//-----------------------------------------------------------------------------
// Get dependencies
//-----------------------------------------------------------------------------
static AppSystemInfo_t s_Dependencies[] = { { "inputsystem" DLL_EXT_STRING, INPUTSYSTEM_INTERFACE_VERSION }, { NULL, NULL } };
const AppSystemInfo_t* CInputStackSystem::GetDependencies() { return s_Dependencies; }
//-----------------------------------------------------------------------------
// Shutdown
//-----------------------------------------------------------------------------
void CInputStackSystem::Shutdown() { // Delete any leaked contexts
while( m_ContextStack.Count() ) { InputContext_t *pContext = NULL; m_ContextStack.Pop( pContext ); delete pContext; }
BaseClass::Shutdown(); }
//-----------------------------------------------------------------------------
// Allocates an input context, pushing it on top of the input stack,
// thereby giving it top priority
//-----------------------------------------------------------------------------
InputContextHandle_t CInputStackSystem::PushInputContext() { InputContext_t *pContext = new InputContext_t; pContext->m_bEnabled = true; pContext->m_bCursorVisible = true; pContext->m_bMouseCaptureEnabled = false; pContext->m_hCursorIcon = g_pInputSystem->GetStandardCursor( INPUT_CURSOR_ARROW ); m_ContextStack.Push( pContext );
UpdateCursorState();
return (InputContextHandle_t)pContext; }
//-----------------------------------------------------------------------------
// Pops the top input context off the input stack, and destroys it.
//-----------------------------------------------------------------------------
void CInputStackSystem::PopInputContext( ) { if ( m_ContextStack.Count() == 0 ) return;
InputContext_t *pContext = NULL; m_ContextStack.Pop( pContext ); delete pContext;
UpdateCursorState(); }
//-----------------------------------------------------------------------------
// Enables/disables an input context, allowing something lower on the
// stack to have control of input. Disabling an input context which
// owns mouse capture
//-----------------------------------------------------------------------------
void CInputStackSystem::EnableInputContext( InputContextHandle_t hContext, bool bEnable ) { InputContext_t *pContext = ( InputContext_t* )hContext; if ( !pContext ) return;
if ( pContext->m_bEnabled == bEnable ) return;
// Disabling an input context will deactivate mouse capture, if it's active
if ( !bEnable ) { SetMouseCapture( hContext, false ); }
pContext->m_bEnabled = bEnable;
// Updates the cursor state since the stack changed
UpdateCursorState(); }
//-----------------------------------------------------------------------------
// Allows a context to make the cursor visible;
// the topmost enabled context wins
//-----------------------------------------------------------------------------
void CInputStackSystem::SetCursorVisible( InputContextHandle_t hContext, bool bVisible ) { InputContext_t *pContext = ( InputContext_t* )hContext; if ( !pContext ) return;
if ( pContext->m_bCursorVisible == bVisible ) return;
pContext->m_bCursorVisible = bVisible;
// Updates the cursor state since the stack changed
UpdateCursorState(); }
//-----------------------------------------------------------------------------
// Allows a context to set the cursor icon;
// the topmost enabled context wins
//-----------------------------------------------------------------------------
void CInputStackSystem::SetCursorIcon( InputContextHandle_t hContext, InputCursorHandle_t hCursor ) { InputContext_t *pContext = ( InputContext_t* )hContext; if ( !pContext ) return;
if ( pContext->m_hCursorIcon == hCursor ) return;
pContext->m_hCursorIcon = hCursor;
// Updates the cursor state since the stack changed
UpdateCursorState(); }
//-----------------------------------------------------------------------------
// Allows a context to enable mouse capture. Disabling an input context
// deactivates mouse capture. Capture will occur if it happens on the
// topmost enabled context
//-----------------------------------------------------------------------------
void CInputStackSystem::SetMouseCapture( InputContextHandle_t hContext, bool bEnable ) { InputContext_t *pContext = ( InputContext_t* )hContext; if ( !pContext ) return;
if ( pContext->m_bMouseCaptureEnabled == bEnable ) return;
pContext->m_bMouseCaptureEnabled = bEnable;
// Updates the cursor state since the stack changed
UpdateCursorState(); }
//-----------------------------------------------------------------------------
// Allows a context to set the mouse position. It only has any effect if the
// specified context is the topmost enabled context
//-----------------------------------------------------------------------------
void CInputStackSystem::SetCursorPosition( InputContextHandle_t hContext, int x, int y ) { if ( IsTopmostEnabledContext( hContext ) ) { g_pInputSystem->SetCursorPosition( x, y ); } }
//-----------------------------------------------------------------------------
// This this context the topmost enabled context?
//-----------------------------------------------------------------------------
bool CInputStackSystem::IsTopmostEnabledContext( InputContextHandle_t hContext ) const { InputContext_t *pContext = ( InputContext_t* )hContext; if ( !pContext ) return false;
int nCount = m_ContextStack.Count(); for ( int i = nCount; --i >= 0; ) { InputContext_t *pStackContext = m_ContextStack[i]; if ( !pStackContext->m_bEnabled ) continue;
return ( pStackContext == pContext ); } return false; }
//-----------------------------------------------------------------------------
// Updates the cursor based on the current state of the input stack
//-----------------------------------------------------------------------------
void CInputStackSystem::UpdateCursorState() { int nCount = m_ContextStack.Count(); for ( int i = nCount; --i >= 0; ) { InputContext_t *pContext = m_ContextStack[i]; if ( !pContext->m_bEnabled ) continue;
if ( !pContext->m_bCursorVisible ) { g_pInputSystem->SetCursorIcon( INPUT_CURSOR_HANDLE_INVALID ); } else { g_pInputSystem->SetCursorIcon( pContext->m_hCursorIcon ); }
if ( pContext->m_bMouseCaptureEnabled ) { g_pInputSystem->EnableMouseCapture( g_pInputSystem->GetAttachedWindow() ); } else { g_pInputSystem->DisableMouseCapture( ); } break; } }
|