2019-12-08 11:28:51 +00:00
/*
* * c_dispatch . cpp
* * Functions for executing console commands and aliases
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 1998 - 2016 Randy Heit
* * Copyright 2003 - 2019 Christoph Oelckers
* * All rights reserved .
* *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* *
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
*/
2019-11-03 17:19:29 +00:00
# include "c_bind.h"
# include "d_event.h"
2019-11-09 22:58:26 +00:00
# include "c_console.h"
2019-11-03 17:19:29 +00:00
# include "d_gui.h"
2019-11-03 23:55:49 +00:00
# include "inputstate.h"
2019-11-21 21:31:46 +00:00
# include "menu.h"
2019-11-03 17:19:29 +00:00
int eventhead ;
int eventtail ;
2019-11-03 23:53:55 +00:00
event_t events [ NUM_EVENTS ] ;
2019-11-03 17:19:29 +00:00
//==========================================================================
//
// G_Responder
// Process the event for the game
//
//==========================================================================
bool G_Responder ( event_t * ev )
{
switch ( ev - > type )
{
case EV_KeyDown :
if ( C_DoKey ( ev , & Bindings , & DoubleBindings ) )
return true ;
break ;
case EV_KeyUp :
C_DoKey ( ev , & Bindings , & DoubleBindings ) ;
break ;
#if 0
// [RH] mouse buttons are sent as key up/down events
case EV_Mouse :
mousex = ( int ) ( ev - > x * mouse_sensitivity ) ;
mousey = ( int ) ( ev - > y * mouse_sensitivity ) ;
break ;
# endif
}
#if 0
2019-12-08 11:28:51 +00:00
// [RH] If the view is active, give the automap a chance at
// the events *last* so that any bound keys get precedence.
// An option for later. Currently the automap is insufficiently separated from the game loop
2019-11-03 17:19:29 +00:00
if ( gamestate = = GS_LEVEL & & viewactive & & primaryLevel - > automap )
return primaryLevel - > automap - > Responder ( ev , true ) ;
# endif
return ( ev - > type = = EV_KeyDown | |
ev - > type = = EV_Mouse ) ;
}
//==========================================================================
//
// D_ProcessEvents
//
// Send all the events of the given timestamp down the responder chain.
// Events are asynchronous inputs generally generated by the game user.
// Events can be discarded if no responder claims them
//
//==========================================================================
void D_ProcessEvents ( void )
{
event_t * ev ;
2019-11-03 23:53:55 +00:00
for ( ; eventtail ! = eventhead ; eventtail = ( eventtail + 1 ) & ( NUM_EVENTS - 1 ) )
2019-11-03 17:19:29 +00:00
{
ev = & events [ eventtail ] ;
if ( ev - > type = = EV_None )
continue ;
if ( ev - > type = = EV_DeviceChange )
( void ) 0 ; //UpdateJoystickMenu(I_UpdateDeviceList());
if ( C_Responder ( ev ) )
continue ; // console ate the event
if ( M_Responder ( ev ) )
continue ; // menu ate the event
G_Responder ( ev ) ;
}
}
//==========================================================================
//
// D_PostEvent
//
// Called by the I/O functions when input is detected.
//
//==========================================================================
2019-11-09 21:22:51 +00:00
void sendKeyForBinding ( int key ) ;
2019-11-03 17:19:29 +00:00
void D_PostEvent ( const event_t * ev )
{
// Do not post duplicate consecutive EV_DeviceChange events.
if ( ev - > type = = EV_DeviceChange & & events [ eventhead ] . type = = EV_DeviceChange )
{
return ;
}
2019-11-10 14:15:14 +00:00
if ( ev - > type = = EV_Mouse & & GUICapture = = 0 & & appactive & & g_mouseGrabbed )
2019-11-03 17:19:29 +00:00
{
2019-11-10 14:15:14 +00:00
inputState . MouseAddToPos ( ev - > x / 3 , - ev - > y / 2 ) ;
return ;
}
else if ( ev - > type = = EV_GUI_Event & & ev - > subtype = = EV_GUI_MouseMove & & appactive & & GUICapture = = 0 & & ! g_mouseGrabbed )
{
inputState . MouseSetAbs ( ev - > data1 , ev - > data2 ) ;
return ;
2019-11-03 17:19:29 +00:00
}
2019-11-09 21:22:51 +00:00
2019-11-03 23:55:49 +00:00
// Add the key to the global keyboard state.
// This is probably the biggest roadblock with the input system as it undermines a proper event driven approach.
// Too much code depends on just checking this instead of waiting for events to happen.
// Here's also definitely not the best place to maintain the keyboard state but right now it's unavoidable to do this outside the event processing because so much code depends on it.
inputState . AddEvent ( ev ) ;
2019-11-10 14:15:14 +00:00
// Also add it to the event queue.
events [ eventhead ] = * ev ;
2019-11-03 23:53:55 +00:00
eventhead = ( eventhead + 1 ) & ( NUM_EVENTS - 1 ) ;
2019-11-03 17:19:29 +00:00
}
//==========================================================================
//
// D_RemoveNextCharEvent
//
// Removes the next EV_GUI_Char event in the input queue. Used by the menu,
// since it (generally) consumes EV_GUI_KeyDown events and not EV_GUI_Char
// events, and it needs to ensure that there is no left over input when it's
// done. If there are multiple EV_GUI_KeyDowns before the EV_GUI_Char, then
// there are dead chars involved, so those should be removed, too. We do
// this by changing the message type to EV_None rather than by actually
// removing the event from the queue.
//
//==========================================================================
void D_RemoveNextCharEvent ( )
{
assert ( events [ eventtail ] . type = = EV_GUI_Event & & events [ eventtail ] . subtype = = EV_GUI_KeyDown ) ;
2019-11-03 23:53:55 +00:00
for ( int evnum = eventtail ; evnum ! = eventhead ; evnum = ( evnum + 1 ) & ( NUM_EVENTS - 1 ) )
2019-11-03 17:19:29 +00:00
{
event_t * ev = & events [ evnum ] ;
if ( ev - > type ! = EV_GUI_Event )
break ;
if ( ev - > subtype = = EV_GUI_KeyDown | | ev - > subtype = = EV_GUI_Char )
{
ev - > type = EV_None ;
if ( ev - > subtype = = EV_GUI_Char )
break ;
}
else
{
break ;
}
}
}
2019-11-03 23:55:49 +00:00