diff --git a/stepmania/src/Screen.cpp b/stepmania/src/Screen.cpp index 82c17dcae4..ab9c095077 100644 --- a/stepmania/src/Screen.cpp +++ b/stepmania/src/Screen.cpp @@ -105,6 +105,15 @@ void Screen::MenuBack( PlayerNumber pn, const InputEventType type ) MenuBack(pn); } +/* ScreenManager sends input here first. Overlay screens can use it to get a first + * pass at input. Return true if the input was handled and should not be passed + * to lower screens, or false if not handled. If true is returned, Input() will + * not be called, either. Normal screens should not overload this function. */ +bool Screen::OverlayInput( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ) +{ + return false; +} + void Screen::Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ) { /* Don't send release messages with the default handler. */ diff --git a/stepmania/src/Screen.h b/stepmania/src/Screen.h index dd0031506f..38bac17fa6 100644 --- a/stepmania/src/Screen.h +++ b/stepmania/src/Screen.h @@ -30,6 +30,7 @@ public: * exist. */ virtual void Init() { } virtual void Update( float fDeltaTime ); + virtual bool OverlayInput( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); virtual void HandleScreenMessage( const ScreenMessage SM ); diff --git a/stepmania/src/ScreenManager.cpp b/stepmania/src/ScreenManager.cpp index 0279afd1b7..1d1f2b4b73 100644 --- a/stepmania/src/ScreenManager.cpp +++ b/stepmania/src/ScreenManager.cpp @@ -247,13 +247,20 @@ void ScreenManager::Input( const DeviceInput& DeviceI, const InputEventType type // LOG->Trace( "ScreenManager::Input( %d-%d, %d-%d, %d-%d, %d-%d )", // DeviceI.device, DeviceI.button, GameI.controller, GameI.button, MenuI.player, MenuI.button, StyleI.player, StyleI.col ); - // pass input only to topmost state - Screen *pInputFocus = NULL; - if( !m_ScreenStack.empty() ) - pInputFocus = m_ScreenStack.back(); + // First, give overlay screens a shot at the input. If OverlayInput returns + // true, it handled the input, so don't pass it further. OverlayInput could + // probably be merged with Input, but that would require changing all Input + // overloads, as well as all MenuLeft, etc. overloads. + for( unsigned i = 0; i < m_OverlayScreens.size(); ++i ) + { + Screen *pScreen = m_OverlayScreens[i]; + if( pScreen->OverlayInput(DeviceI, type, GameI, MenuI, StyleI) ) + return; + } - if( pInputFocus != NULL ) - pInputFocus->Input( DeviceI, type, GameI, MenuI, StyleI ); + // pass input to topmost state + if( !m_ScreenStack.empty() ) + m_ScreenStack.back()->Input( DeviceI, type, GameI, MenuI, StyleI ); } /* Just create a new screen; don't do any associated cleanup. */