Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FILE: Win32DIKeyboard.cpp //////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, June 2001
|
||||
// Desc: Device implementation of the keyboard interface on Win32
|
||||
// using Microsoft Direct Input
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "Common/Debug.h"
|
||||
#include "Common/Language.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/Keyboard.h"
|
||||
#include "Win32Device/GameClient/Win32DIKeyboard.h"
|
||||
#include "WinMain.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////////////////////////
|
||||
enum { KEYBOARD_BUFFER_SIZE = 256 };
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
struct ErrorLookup
|
||||
{
|
||||
HRESULT error;
|
||||
char *string;
|
||||
};
|
||||
static ErrorLookup errorLookup[] =
|
||||
{
|
||||
{ DIERR_ACQUIRED, "DIERR_ACQUIRED" },
|
||||
{ DIERR_ALREADYINITIALIZED, "DIERR_ALREADYINITIALIZED" },
|
||||
{ DIERR_BADDRIVERVER, "DIERR_BADDRIVERVER" },
|
||||
{ DIERR_BETADIRECTINPUTVERSION, "DIERR_BETADIRECTINPUTVERSION" },
|
||||
{ DIERR_DEVICEFULL, "DIERR_DEVICEFULL" },
|
||||
{ DIERR_DEVICENOTREG, "DIERR_DEVICENOTREG" },
|
||||
{ DIERR_EFFECTPLAYING, "DIERR_EFFECTPLAYING" },
|
||||
{ DIERR_GENERIC, "DIERR_GENERIC" },
|
||||
{ DIERR_HANDLEEXISTS, "DIERR_HANDLEEXISTS" },
|
||||
{ DIERR_HASEFFECTS, "DIERR_HASEFFECTS" },
|
||||
{ DIERR_INCOMPLETEEFFECT, "DIERR_INCOMPLETEEFFECT" },
|
||||
{ DIERR_INPUTLOST, "DIERR_INPUTLOST" },
|
||||
{ DIERR_INVALIDPARAM, "DIERR_INVALIDPARAM" },
|
||||
{ DIERR_MAPFILEFAIL, "DIERR_MAPFILEFAIL" },
|
||||
{ DIERR_MOREDATA, "DIERR_MOREDATA" },
|
||||
{ DIERR_NOAGGREGATION, "DIERR_NOAGGREGATION" },
|
||||
{ DIERR_NOINTERFACE, "DIERR_NOINTERFACE" },
|
||||
{ DIERR_NOTACQUIRED, "DIERR_NOTACQUIRED" },
|
||||
{ DIERR_NOTBUFFERED, "DIERR_NOTBUFFERED" },
|
||||
{ DIERR_NOTDOWNLOADED, "DIERR_NOTDOWNLOADED" },
|
||||
{ DIERR_NOTEXCLUSIVEACQUIRED, "DIERR_NOTEXCLUSIVEACQUIRED" },
|
||||
{ DIERR_NOTFOUND, "DIERR_NOTFOUND" },
|
||||
{ DIERR_NOTINITIALIZED, "DIERR_NOTINITIALIZED" },
|
||||
{ DIERR_OBJECTNOTFOUND, "DIERR_OBJECTNOTFOUND" },
|
||||
{ DIERR_OLDDIRECTINPUTVERSION, "DIERR_OLDDIRECTINPUTVERSION" },
|
||||
{ DIERR_OTHERAPPHASPRIO, "DIERR_OTHERAPPHASPRIO" },
|
||||
{ DIERR_OUTOFMEMORY, "DIERR_OUTOFMEMORY" },
|
||||
{ DIERR_READONLY, "DIERR_READONLY" },
|
||||
{ DIERR_REPORTFULL, "DIERR_REPORTFULL" },
|
||||
{ DIERR_UNPLUGGED, "DIERR_UNPLUGGED" },
|
||||
{ DIERR_UNSUPPORTED, "DIERR_UNSUPPORTED" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** For debugging, prints the return code using direct input errors */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void printReturnCode( char *label, HRESULT hr )
|
||||
{
|
||||
ErrorLookup *error = errorLookup;
|
||||
|
||||
while( error->string != NULL )
|
||||
{
|
||||
|
||||
if( error->error == hr )
|
||||
{
|
||||
DEBUG_LOG(( "%s: '%s' - '0x%08x'\n", label, error->string, hr ));
|
||||
break;
|
||||
}
|
||||
error++;
|
||||
|
||||
}
|
||||
|
||||
} // end printReturnCode
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** create our interface to the direct input keybard */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputKeyboard::openKeyboard( void )
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// create our interface to direct input
|
||||
hr = DirectInput8Create( ApplicationHInstance,
|
||||
DIRECTINPUT_VERSION,
|
||||
IID_IDirectInput8,
|
||||
(void **)&m_pDirectInput,
|
||||
NULL );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openKeyboard: DirectInputCreate failed\r\n" ));
|
||||
assert( 0 );
|
||||
closeKeyboard();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// obtain an interface to the system keyboard device
|
||||
hr = m_pDirectInput->CreateDevice( GUID_SysKeyboard,
|
||||
&m_pKeyboardDevice,
|
||||
NULL );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openKeyboard: Unabled to create keyboard device\n" ));
|
||||
assert( 0 );
|
||||
closeKeyboard();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// set the data format for the keyboard
|
||||
hr = m_pKeyboardDevice->SetDataFormat( &c_dfDIKeyboard );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openKeyboard: Unabled to set data format for keyboard\n" ));
|
||||
assert( 0 );
|
||||
closeKeyboard();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
/// @todo Check the cooperative level of keyboard for NT, 2000, DX8 etc ...
|
||||
// set the cooperative level for the keyboard, must be non-exclusive for
|
||||
// NT support, but we should check with the latest versions of DirectX
|
||||
// on 2000 etc
|
||||
//
|
||||
hr = m_pKeyboardDevice->SetCooperativeLevel( ApplicationHWnd,
|
||||
DISCL_FOREGROUND |
|
||||
DISCL_NONEXCLUSIVE );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openKeyboard: Unabled to set cooperative level\n" ));
|
||||
assert( 0 );
|
||||
closeKeyboard();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// set the keyboard buffer size
|
||||
DIPROPDWORD prop;
|
||||
prop.diph.dwSize = sizeof( DIPROPDWORD );
|
||||
prop.diph.dwHeaderSize = sizeof( DIPROPHEADER );
|
||||
prop.diph.dwObj = 0;
|
||||
prop.diph.dwHow = DIPH_DEVICE;
|
||||
prop.dwData = KEYBOARD_BUFFER_SIZE;
|
||||
hr = m_pKeyboardDevice->SetProperty( DIPROP_BUFFERSIZE, &prop.diph );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openKeyboard: Unable to set keyboard buffer size property\n" ));
|
||||
assert( 0 );
|
||||
closeKeyboard();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// acquire the keyboard
|
||||
hr = m_pKeyboardDevice->Acquire();
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openKeyboard: Unable to acquire keyboard device\n" ));
|
||||
// Note - This can happen in windowed mode, and we can re-acquire later. So don't
|
||||
// close the keyboard. jba.
|
||||
// closeKeyboard();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
DEBUG_LOG(( "OK - Keyboard initialized successfully.\n" ));
|
||||
|
||||
} // end openKeyboard
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** close the direct input keyboard */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputKeyboard::closeKeyboard( void )
|
||||
{
|
||||
|
||||
if( m_pKeyboardDevice )
|
||||
{
|
||||
|
||||
m_pKeyboardDevice->Unacquire();
|
||||
m_pKeyboardDevice->Release();
|
||||
m_pKeyboardDevice = NULL;
|
||||
DEBUG_LOG(( "OK - Keyboard deviced closed\n" ));
|
||||
|
||||
} // end if
|
||||
if( m_pDirectInput )
|
||||
{
|
||||
|
||||
m_pDirectInput->Release();
|
||||
m_pDirectInput = NULL;
|
||||
DEBUG_LOG(( "OK - Keyboard direct input interface closed\n" ));
|
||||
|
||||
} // end if
|
||||
|
||||
DEBUG_LOG(( "OK - Keyboard shutdown complete\n" ));
|
||||
|
||||
} // end closeKeyboard
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Get a single keyboard event from direct input */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputKeyboard::getKey( KeyboardIO *key )
|
||||
{
|
||||
static int errs = 0;
|
||||
DIDEVICEOBJECTDATA kbdat;
|
||||
DWORD num = 0;
|
||||
// int done = 0;
|
||||
HRESULT hr;
|
||||
|
||||
assert( key );
|
||||
key->sequence = 0;
|
||||
key->key = KEY_NONE;
|
||||
|
||||
if( m_pKeyboardDevice )
|
||||
{
|
||||
// get 1 key, if available
|
||||
num = 1;
|
||||
hr = m_pKeyboardDevice->Acquire();
|
||||
if (hr == DI_OK || hr == S_FALSE)
|
||||
hr = m_pKeyboardDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ),
|
||||
&kbdat, &num, 0 );
|
||||
switch( hr )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
case DI_OK:
|
||||
break;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
case DIERR_INPUTLOST:
|
||||
case DIERR_NOTACQUIRED:
|
||||
|
||||
// if we lost focus, attempt to re-acquire
|
||||
hr = m_pKeyboardDevice->Acquire();
|
||||
switch( hr )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
//If an error occurs return KEY_NONE
|
||||
case DIERR_INVALIDPARAM:
|
||||
case DIERR_NOTINITIALIZED:
|
||||
case DIERR_OTHERAPPHASPRIO:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// If successful... tell system to loop back
|
||||
case DI_OK:
|
||||
case S_FALSE:
|
||||
{
|
||||
|
||||
// this will tell the system to loop again
|
||||
key->key = KEY_LOST;
|
||||
|
||||
break;
|
||||
|
||||
} // end, got the keyboard back OK
|
||||
|
||||
} // end switch
|
||||
|
||||
return;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
default:
|
||||
return;
|
||||
|
||||
} // end switch( hr )
|
||||
|
||||
// no keys returned
|
||||
if( num == 0 )
|
||||
return;
|
||||
|
||||
// set the key
|
||||
key->key = (UnsignedByte)(kbdat.dwOfs & 0xFF);
|
||||
|
||||
// sequence
|
||||
key->sequence = kbdat.dwSequence;
|
||||
|
||||
//
|
||||
// state of key, note we are setting the key state here with an assignment
|
||||
// and not a bit set of the up/down state, this is the "start"
|
||||
// of building this "key"
|
||||
//
|
||||
key->state = (( kbdat.dwData & 0x0080 ) ? KEY_STATE_DOWN : KEY_STATE_UP);
|
||||
|
||||
// set status as unused (unprocessed)
|
||||
key->status = KeyboardIO::STATUS_UNUSED;
|
||||
|
||||
} // end if, we have a DI keyboard device
|
||||
|
||||
} // end getKey
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DirectInputKeyboard::DirectInputKeyboard( void )
|
||||
{
|
||||
|
||||
m_pDirectInput = NULL;
|
||||
m_pKeyboardDevice = NULL;
|
||||
|
||||
|
||||
if( GetKeyState( VK_CAPITAL ) & 0x01 )
|
||||
{
|
||||
m_modifiers |= KEY_STATE_CAPSLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_modifiers &= ~KEY_STATE_CAPSLOCK;
|
||||
}
|
||||
|
||||
} // end DirectInputKeyboard
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DirectInputKeyboard::~DirectInputKeyboard( void )
|
||||
{
|
||||
|
||||
// close keyboard and release all resource
|
||||
closeKeyboard();
|
||||
|
||||
} // end ~DirectInputKeyboard
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** initialize the keyboard */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputKeyboard::init( void )
|
||||
{
|
||||
|
||||
// extending functionality
|
||||
Keyboard::init();
|
||||
|
||||
// open the direct input keyboard
|
||||
openKeyboard();
|
||||
|
||||
} // end init
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset keyboard system */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputKeyboard::reset( void )
|
||||
{
|
||||
|
||||
// extend functionality
|
||||
Keyboard::reset();
|
||||
|
||||
} // end reset
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** called once per frame to update the keyboard state */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputKeyboard::update( void )
|
||||
{
|
||||
|
||||
// extending functionality
|
||||
Keyboard::update();
|
||||
|
||||
/*
|
||||
// make sure the keyboard buffer is flushed
|
||||
if( m_pKeyboardDevice )
|
||||
{
|
||||
DWORD items = INFINITE;
|
||||
|
||||
m_pKeyboardDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ),
|
||||
NULL, &items, 0 );
|
||||
|
||||
} // end if
|
||||
*/
|
||||
|
||||
} // end update
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Return TRUE if the caps lock key is down/hilighted */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool DirectInputKeyboard::getCapsState( void )
|
||||
{
|
||||
|
||||
return BitTest( GetKeyState( VK_CAPITAL ), 0X01);
|
||||
|
||||
} // end getCapsState
|
|
@ -0,0 +1,513 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// FILE: Win32DIMouse.cpp /////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, June 2001
|
||||
// Desc: Win32 direct input implementation for the mouse
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "Common/Debug.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "Win32Device/GameClient/Win32DIMouse.h"
|
||||
#include "WinMain.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////////////////////////
|
||||
enum { MOUSE_BUFFER_SIZE = 256, };
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Create our direct input object, mouse device, and initialize it to the
|
||||
* data formats we want */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::openMouse( void )
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// create our direct input device for mouse access
|
||||
hr = DirectInput8Create( ApplicationHInstance,
|
||||
DIRECTINPUT_VERSION,
|
||||
IID_IDirectInput8,
|
||||
(void **)&m_pDirectInput,
|
||||
NULL );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openMouse: Unabled to create direct input interface\n" ));
|
||||
assert( 0 );
|
||||
closeMouse();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// create a device for the system mouse
|
||||
hr = m_pDirectInput->CreateDevice( GUID_SysMouse,
|
||||
&m_pMouseDevice,
|
||||
NULL );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openMouse: Unable to create mouse device\n" ));
|
||||
assert( 0 );
|
||||
closeMouse();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// set the data format for the mouse
|
||||
hr = m_pMouseDevice->SetDataFormat( &c_dfDIMouse );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openMouse: Unabled to set mouse data format\n" ));
|
||||
assert( 0 );
|
||||
closeMouse();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// set the mouse cooperative level
|
||||
hr = m_pMouseDevice->SetCooperativeLevel( ApplicationHWnd,
|
||||
DISCL_NONEXCLUSIVE |
|
||||
DISCL_FOREGROUND );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openMouse: Unabled to set coop level\n" ));
|
||||
assert( 0 );
|
||||
closeMouse();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// set the mouse buffer size
|
||||
DIPROPDWORD prop;
|
||||
prop.diph.dwSize = sizeof( DIPROPDWORD );
|
||||
prop.diph.dwHeaderSize = sizeof( DIPROPHEADER );
|
||||
prop.diph.dwObj = 0;
|
||||
prop.diph.dwHow = DIPH_DEVICE;
|
||||
prop.dwData = MOUSE_BUFFER_SIZE;
|
||||
hr = m_pMouseDevice->SetProperty( DIPROP_BUFFERSIZE, &prop.diph );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openMouse: Unabled to set buffer property\n" ));
|
||||
assert( 0 );
|
||||
closeMouse();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// acquire the mouse
|
||||
hr = m_pMouseDevice->Acquire();
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "ERROR - openMouse: Unabled to acquire mouse\n" ));
|
||||
assert( 0 );
|
||||
closeMouse();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// get some information about the mouse
|
||||
DIDEVCAPS diDevCaps;
|
||||
|
||||
diDevCaps.dwSize = sizeof( DIDEVCAPS );
|
||||
hr = m_pMouseDevice->GetCapabilities( &diDevCaps );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "WARNING - openMouse: Cann't get capabilities of mouse for button setup\n" ));
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// keep some data about the mouse we care about
|
||||
m_numButtons = (UnsignedByte)diDevCaps.dwButtons;
|
||||
m_numAxes = (UnsignedByte)diDevCaps.dwAxes;
|
||||
m_forceFeedback = BitTest( diDevCaps.dwFlags, DIDC_FORCEFEEDBACK );
|
||||
|
||||
DEBUG_LOG(( "OK - Mouse info: Buttons = '%d', Force Feedback = '%s', Axes = '%d'\n",
|
||||
m_numButtons, m_forceFeedback ? "Yes" : "No", m_numAxes ));
|
||||
|
||||
} // end else
|
||||
|
||||
DEBUG_LOG(( "OK - Mouse initialized successfully\n" ));
|
||||
|
||||
} // end openMouse
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Release any resources for our direct input mouse */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::closeMouse( void )
|
||||
{
|
||||
|
||||
// release the mouse device
|
||||
if( m_pMouseDevice )
|
||||
{
|
||||
|
||||
m_pMouseDevice->Unacquire();
|
||||
m_pMouseDevice->Release();
|
||||
m_pMouseDevice = NULL;
|
||||
DEBUG_LOG(( "OK - Mouse device closed\n" ));
|
||||
|
||||
} // end if
|
||||
|
||||
// release our direct input interface for the mouse
|
||||
if( m_pDirectInput )
|
||||
{
|
||||
|
||||
m_pDirectInput->Release();
|
||||
m_pDirectInput = NULL;
|
||||
DEBUG_LOG(( "OK - Mouse direct input interface closed\n" ));
|
||||
|
||||
} // end if
|
||||
|
||||
DEBUG_LOG(( "OK - Mouse shutdown complete\n" ));
|
||||
|
||||
} // end closeMouse
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Get a single mouse event from the device */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
UnsignedByte DirectInputMouse::getMouseEvent( MouseIO *result, Bool flush )
|
||||
{
|
||||
HRESULT hr;
|
||||
DIDEVICEOBJECTDATA mdat;
|
||||
UnsignedByte mouseResult = MOUSE_NONE;
|
||||
DWORD num;
|
||||
|
||||
/* set these to defaults */
|
||||
result->leftState = result->middleState = result->rightState = FALSE;
|
||||
result->leftFrame = result->middleFrame = result->rightFrame = 0;
|
||||
result->pos.x = result->pos.y = result->wheelPos = 0;
|
||||
|
||||
if( m_pMouseDevice )
|
||||
{
|
||||
|
||||
// get 1 event, if available
|
||||
num = 1;
|
||||
m_pMouseDevice->Poll();
|
||||
hr = m_pMouseDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ),
|
||||
&mdat,
|
||||
&num,
|
||||
0 );
|
||||
switch( hr )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
case DI_OK:
|
||||
{
|
||||
// nothing returned
|
||||
if( num != 0 )
|
||||
{
|
||||
mapDirectInputMouse( result, &mdat );
|
||||
mouseResult = MOUSE_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
case DIERR_NOTACQUIRED:
|
||||
case DIERR_INPUTLOST:
|
||||
{
|
||||
|
||||
// if we lost focus, attempt to re-acquire
|
||||
hr = m_pMouseDevice->Acquire();
|
||||
switch( hr )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// If successful... tell system to loop back
|
||||
case DI_OK:
|
||||
case S_FALSE:
|
||||
mouseResult = MOUSE_LOST;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
//If an error occurs return MOUSE_NONE
|
||||
case DIERR_INVALIDPARAM:
|
||||
case DIERR_NOTINITIALIZED:
|
||||
case DIERR_OTHERAPPHASPRIO:
|
||||
default:
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
default:
|
||||
// DBGPRINTF(("GetMouseEvent: GetDeviceData Error: %X.\r\n", hr ));
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
|
||||
} // end if
|
||||
|
||||
return mouseResult;
|
||||
|
||||
} // end getMouseEvent
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Map the direct input codes to our own mouse format */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::mapDirectInputMouse( MouseIO *mouse,
|
||||
DIDEVICEOBJECTDATA *mdat )
|
||||
{
|
||||
|
||||
switch( mdat->dwOfs )
|
||||
{
|
||||
case DIMOFS_BUTTON0:
|
||||
mouse->leftState = (( mdat->dwData & 0x0080 ) ? TRUE : FALSE);
|
||||
mouse->leftFrame = mdat->dwSequence;
|
||||
break;
|
||||
|
||||
case DIMOFS_BUTTON1:
|
||||
mouse->rightState = (( mdat->dwData & 0x0080 ) ? TRUE : FALSE);
|
||||
mouse->rightFrame = mdat->dwSequence;
|
||||
break;
|
||||
|
||||
case DIMOFS_BUTTON2:
|
||||
mouse->middleState = (( mdat->dwData & 0x0080 ) ? TRUE : FALSE);
|
||||
mouse->middleFrame = mdat->dwSequence;
|
||||
break;
|
||||
|
||||
case DIMOFS_BUTTON3:
|
||||
break;
|
||||
|
||||
case DIMOFS_X:
|
||||
mouse->pos.x = mdat->dwData;
|
||||
break;
|
||||
|
||||
case DIMOFS_Y:
|
||||
mouse->pos.y = mdat->dwData;
|
||||
break;
|
||||
|
||||
case DIMOFS_Z:
|
||||
mouse->wheelPos = mdat->dwData;
|
||||
break;
|
||||
}
|
||||
|
||||
} // end mapDirectInputMouse
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DirectInputMouse::DirectInputMouse( void )
|
||||
{
|
||||
|
||||
m_pDirectInput = NULL;
|
||||
m_pMouseDevice = NULL;
|
||||
|
||||
} // end DirectInputMouse
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DirectInputMouse::~DirectInputMouse( void )
|
||||
{
|
||||
|
||||
// relase all mouse resources
|
||||
closeMouse();
|
||||
// ShowCursor( TRUE );
|
||||
|
||||
} // end ~DirectInputMouse
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the direct input mouse device */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::init( void )
|
||||
{
|
||||
POINT p;
|
||||
|
||||
// extending functionality from our base class
|
||||
Mouse::init();
|
||||
|
||||
// open the mouse and create the direct input interfaces we need
|
||||
openMouse();
|
||||
|
||||
// move the window mouse to the location we have initialized in our system
|
||||
p.x = m_currMouse.pos.x;
|
||||
p.y = m_currMouse.pos.y;
|
||||
ClientToScreen( ApplicationHWnd, &p );
|
||||
SetCursorPos( p.x, p.y );
|
||||
// ShowCursor( FALSE );
|
||||
|
||||
} // end init
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset direct input mouse */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::reset( void )
|
||||
{
|
||||
|
||||
// extend
|
||||
Mouse::reset();
|
||||
|
||||
} // end reset
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Update the mouse position and button data, this is called once per
|
||||
* frame in the engine. NOTE that this routine is extendion functionality
|
||||
* that we may need that is direct input specific, not replacing */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::update( void )
|
||||
{
|
||||
|
||||
// extendion functionality from our base class
|
||||
Mouse::update();
|
||||
|
||||
//
|
||||
// since we are currently using the windows cursor because it updates at
|
||||
// an independent rate of our application we will always just use the windows
|
||||
// mouse cursor position
|
||||
//
|
||||
|
||||
/** @todo we need to really visit this system and possibly come up with
|
||||
our own multi-threaded cursor etc */
|
||||
POINT p;
|
||||
GetCursorPos( &p );
|
||||
ScreenToClient( ApplicationHWnd, &p );
|
||||
moveMouse( p.x, p.y, MOUSE_MOVE_ABSOLUTE );
|
||||
|
||||
} // end update
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Set the limits which the mouse is allowed to move around in. We
|
||||
* will limit it to the client area, and if we are windowed we will
|
||||
* allow for the mouse to move within the title bar at the top of
|
||||
* the window */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::setMouseLimits( void )
|
||||
{
|
||||
|
||||
//
|
||||
// extending functionality, although we may overwrite the limits set
|
||||
// from the base class
|
||||
//
|
||||
Mouse::setMouseLimits();
|
||||
|
||||
//
|
||||
// when runing windowed we want to keep the mouse within the game
|
||||
// window cause it's annoying to mouse out of the window and click
|
||||
// on a background window.
|
||||
//
|
||||
if( TheDisplay && TheDisplay->getWindowed() == TRUE )
|
||||
{
|
||||
RECT windowRect;
|
||||
|
||||
// get the window rect
|
||||
GetWindowRect( ApplicationHWnd, &windowRect );
|
||||
|
||||
// keep the cursor clipped to these coords when running windowed
|
||||
ClipCursor( &windowRect );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end setMouseLimits
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** set the cursor position for windows OS */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::setPosition( Int x, Int y )
|
||||
{
|
||||
POINT p;
|
||||
|
||||
// extending functionality
|
||||
Mouse::setPosition( x, y );
|
||||
|
||||
// set the windows cursor
|
||||
p.x = x;
|
||||
p.y = y;
|
||||
ClientToScreen( ApplicationHWnd, &p );
|
||||
|
||||
// set the window mouse
|
||||
SetCursorPos( p.x, p.y );
|
||||
|
||||
} // end setPosition
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Super basic simplistic cursor */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::setCursor( MouseCursor cursor )
|
||||
{
|
||||
|
||||
// extend
|
||||
Mouse::setCursor( cursor );
|
||||
|
||||
// if we're already on this cursor ignore
|
||||
if( m_currentCursor == cursor )
|
||||
return;
|
||||
|
||||
switch( cursor )
|
||||
{
|
||||
|
||||
case NONE:
|
||||
SetCursor( NULL );
|
||||
break;
|
||||
|
||||
case NORMAL:
|
||||
case ARROW:
|
||||
SetCursor( LoadCursor( NULL, IDC_ARROW ) );
|
||||
break;
|
||||
|
||||
case SCROLL:
|
||||
SetCursor( LoadCursor( NULL, IDC_SIZEALL ) );
|
||||
break;
|
||||
|
||||
case CROSS:
|
||||
SetCursor( LoadCursor( NULL, IDC_CROSS ) );
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
|
||||
// save current cursor
|
||||
m_currentCursor = cursor;
|
||||
|
||||
} // end setCursor
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Capture the mouse to our application */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::capture( void )
|
||||
{
|
||||
|
||||
SetCapture( ApplicationHWnd );
|
||||
|
||||
} // end capture
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Release the mouse capture for our app window */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DirectInputMouse::releaseCapture( void )
|
||||
{
|
||||
|
||||
ReleaseCapture();
|
||||
|
||||
} // end releaseCapture
|
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FILE: Win32Mouse.cpp ///////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, July 2001
|
||||
// Desc: Interface for the mouse using only the Win32 messages
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include "Common/Debug.h"
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/LocalFileSystem.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "Win32Device/GameClient/Win32Mouse.h"
|
||||
#include "WinMain.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// EXTERN /////////////////////////////////////////////////////////////////////////////////////////
|
||||
extern Win32Mouse *TheWin32Mouse;
|
||||
|
||||
HCURSOR cursorResources[Mouse::NUM_MOUSE_CURSORS][MAX_2D_CURSOR_DIRECTIONS];
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Get a mouse event from the buffer if available, we need to translate
|
||||
* from the windows message meanings to our own internal mouse
|
||||
* structure */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
UnsignedByte Win32Mouse::getMouseEvent( MouseIO *result, Bool flush )
|
||||
{
|
||||
|
||||
// if there is nothing here there is no event data to do
|
||||
if( m_eventBuffer[ m_nextGetIndex ].msg == 0 )
|
||||
return MOUSE_NONE;
|
||||
|
||||
// translate the win32 mouse message to our own system
|
||||
translateEvent( m_nextGetIndex, result );
|
||||
|
||||
// remove this event from the buffer by setting msg to zero
|
||||
m_eventBuffer[ m_nextGetIndex ].msg = 0;
|
||||
|
||||
//
|
||||
// our next get index will now be advanced to the next index, wrapping at
|
||||
// the mad
|
||||
//
|
||||
m_nextGetIndex++;
|
||||
if( m_nextGetIndex >= Mouse::NUM_MOUSE_EVENTS )
|
||||
m_nextGetIndex = 0;
|
||||
|
||||
// got event OK and all done with this one
|
||||
return MOUSE_OK;
|
||||
|
||||
} // end getMouseEvent
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Translate a win32 mouse event to our own event info */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::translateEvent( UnsignedInt eventIndex, MouseIO *result )
|
||||
{
|
||||
UINT msg = m_eventBuffer[ eventIndex ].msg;
|
||||
WPARAM wParam = m_eventBuffer[ eventIndex ].wParam;
|
||||
LPARAM lParam = m_eventBuffer[ eventIndex ].lParam;
|
||||
UnsignedInt frame;
|
||||
|
||||
//
|
||||
// get the current input frame from the client, if we don't have
|
||||
// a client (like in the GUI editor) we just use frame 1 so it
|
||||
// registers with the system
|
||||
//
|
||||
if( TheGameClient )
|
||||
frame = TheGameClient->getFrame();
|
||||
else
|
||||
frame = 1;
|
||||
|
||||
// set these to defaults
|
||||
result->leftState = result->middleState = result->rightState = MBS_Up;
|
||||
result->leftFrame = result->middleFrame = result->rightFrame = 0;
|
||||
result->pos.x = result->pos.y = result->wheelPos = 0;
|
||||
|
||||
// Time is the same for all events
|
||||
result->time = m_eventBuffer[ eventIndex ].time;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_LBUTTONDOWN:
|
||||
{
|
||||
|
||||
result->leftState = MBS_Down;
|
||||
result->leftFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end left button down
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_LBUTTONUP:
|
||||
{
|
||||
|
||||
result->leftState = MBS_Up;
|
||||
result->leftFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end left button up
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
|
||||
result->leftState = MBS_DoubleClick;
|
||||
result->leftFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end left button double click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_MBUTTONDOWN:
|
||||
{
|
||||
|
||||
result->middleState = MBS_Down;
|
||||
result->middleFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end middle button down
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_MBUTTONUP:
|
||||
{
|
||||
|
||||
result->middleState = MBS_Up;
|
||||
result->middleFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end middle button up
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_MBUTTONDBLCLK:
|
||||
{
|
||||
|
||||
result->middleState = MBS_DoubleClick;
|
||||
result->middleFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end middle button double click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_RBUTTONDOWN:
|
||||
{
|
||||
|
||||
result->rightState = MBS_Down;
|
||||
result->rightFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end right button down
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_RBUTTONUP:
|
||||
{
|
||||
|
||||
result->rightState = MBS_Up;
|
||||
result->rightFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end right button up
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_RBUTTONDBLCLK:
|
||||
{
|
||||
|
||||
result->rightState = MBS_DoubleClick;
|
||||
result->rightFrame = frame;
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end right button double click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
|
||||
result->pos.x = LOWORD( lParam );
|
||||
result->pos.y = HIWORD( lParam );
|
||||
break;
|
||||
|
||||
} // end mouse move
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case 0x020A: // WM_MOUSEWHEEL
|
||||
{
|
||||
POINT p;
|
||||
|
||||
// translate the screen mouse position to be relative to the application window
|
||||
p.x = LOWORD( lParam );
|
||||
p.y = HIWORD( lParam );
|
||||
ScreenToClient( ApplicationHWnd, &p );
|
||||
|
||||
// note the short cast here to keep signed information in tact
|
||||
result->wheelPos = (Short)HIWORD( wParam );
|
||||
result->pos.x = p.x;
|
||||
result->pos.y = p.y;
|
||||
break;
|
||||
|
||||
} // end mouse wheel
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "translateEvent: Unknown Win32 mouse event [%d,%d,%d]\n",
|
||||
msg, wParam, lParam ));
|
||||
return;
|
||||
|
||||
} // end default
|
||||
|
||||
} // end switch on message at event index in buffer
|
||||
|
||||
} // end translateEvent
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Win32Mouse::Win32Mouse( void )
|
||||
{
|
||||
|
||||
// zero our event list
|
||||
memset( &m_eventBuffer, 0, sizeof( m_eventBuffer ) );
|
||||
|
||||
m_nextFreeIndex = 0;
|
||||
m_nextGetIndex = 0;
|
||||
m_currentWin32Cursor = NONE;
|
||||
for (Int i=0; i<NUM_MOUSE_CURSORS; i++)
|
||||
for (Int j=0; j<MAX_2D_CURSOR_DIRECTIONS; j++)
|
||||
cursorResources[i][j]=NULL;
|
||||
m_directionFrame=0; //points up.
|
||||
m_lostFocus = FALSE;
|
||||
} // end Win32Mouse
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Win32Mouse::~Win32Mouse( void )
|
||||
{
|
||||
|
||||
// remove our global reference that was for the WndProc() only
|
||||
TheWin32Mouse = NULL;
|
||||
|
||||
} // end ~Win32Mouse
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize our device */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::init( void )
|
||||
{
|
||||
|
||||
// extending functionality
|
||||
Mouse::init();
|
||||
|
||||
//
|
||||
// when we receive messages from a Windows message procedure, the mouse
|
||||
// moves report the current cursor position and not deltas, our mouse
|
||||
// needs to process those positions as absolute and not relative
|
||||
//
|
||||
m_inputMovesAbsolute = TRUE;
|
||||
|
||||
} // end int
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::reset( void )
|
||||
{
|
||||
|
||||
// extend
|
||||
Mouse::reset();
|
||||
|
||||
} // end reset
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Update, called once per frame */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::update( void )
|
||||
{
|
||||
|
||||
// extend
|
||||
Mouse::update();
|
||||
|
||||
} // end update
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Add a window message event along with its WPARAM and LPARAM parameters
|
||||
* to our input storage buffer */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::addWin32Event( UINT msg, WPARAM wParam, LPARAM lParam, DWORD time )
|
||||
{
|
||||
|
||||
//
|
||||
// we can only add this event if our next free index does not already
|
||||
// have an event in it, if it does ... our buffer is full and this input
|
||||
// event will be lost
|
||||
//
|
||||
if( m_eventBuffer[ m_nextFreeIndex ].msg != 0 )
|
||||
return;
|
||||
|
||||
// add to this index
|
||||
m_eventBuffer[ m_nextFreeIndex ].msg = msg;
|
||||
m_eventBuffer[ m_nextFreeIndex ].wParam = wParam;
|
||||
m_eventBuffer[ m_nextFreeIndex ].lParam = lParam;
|
||||
m_eventBuffer[ m_nextFreeIndex ].time = time;
|
||||
|
||||
// wrap index at max
|
||||
m_nextFreeIndex++;
|
||||
if( m_nextFreeIndex >= Mouse::NUM_MOUSE_EVENTS )
|
||||
m_nextFreeIndex = 0;
|
||||
|
||||
} // end addWin32Event
|
||||
|
||||
extern HINSTANCE ApplicationHInstance;
|
||||
|
||||
void Win32Mouse::setVisibility(Bool visible)
|
||||
{
|
||||
//Extend
|
||||
Mouse::setVisibility(visible);
|
||||
//Maybe need to set cursor to force hiding of some cursors.
|
||||
Win32Mouse::setCursor(getMouseCursor());
|
||||
}
|
||||
|
||||
/**Preload all the cursors we may need during the game. This must be done before the D3D device
|
||||
is created to avoid cursor corruption on buggy ATI Radeon cards. */
|
||||
void Win32Mouse::initCursorResources(void)
|
||||
{
|
||||
for (Int cursor=FIRST_CURSOR; cursor<NUM_MOUSE_CURSORS; cursor++)
|
||||
{
|
||||
for (Int direction=0; direction<m_cursorInfo[cursor].numDirections; direction++)
|
||||
{ if (!cursorResources[cursor][direction] && !m_cursorInfo[cursor].textureName.isEmpty())
|
||||
{ //this cursor has never been loaded before.
|
||||
char resourcePath[256];
|
||||
//Check if this is a directional cursor
|
||||
if (m_cursorInfo[cursor].numDirections > 1)
|
||||
sprintf(resourcePath,"data\\cursors\\%s%d.ANI",m_cursorInfo[cursor].textureName.str(),direction);
|
||||
else
|
||||
sprintf(resourcePath,"data\\cursors\\%s.ANI",m_cursorInfo[cursor].textureName.str());
|
||||
|
||||
// check for a MOD cursor.
|
||||
Bool loaded = FALSE;
|
||||
if (TheGlobalData->m_modDir.isNotEmpty())
|
||||
{
|
||||
AsciiString fname;
|
||||
if (m_cursorInfo[cursor].numDirections > 1)
|
||||
fname.format("%sdata\\cursors\\%s%d.ANI", TheGlobalData->m_modDir.str(), m_cursorInfo[cursor].textureName.str(), direction);
|
||||
else
|
||||
fname.format("%sdata\\cursors\\%s.ANI", TheGlobalData->m_modDir.str(), m_cursorInfo[cursor].textureName.str());
|
||||
|
||||
if (TheLocalFileSystem->doesFileExist(fname.str()))
|
||||
{
|
||||
cursorResources[cursor][direction]=LoadCursorFromFile(fname.str());
|
||||
loaded = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!loaded)
|
||||
cursorResources[cursor][direction]=LoadCursorFromFile(resourcePath);
|
||||
DEBUG_ASSERTCRASH(cursorResources[cursor][direction], ("MissingCursor %s\n",resourcePath));
|
||||
}
|
||||
}
|
||||
// SetCursor(cursorResources[cursor][m_directionFrame]);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Super basic simplistic cursor */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::setCursor( MouseCursor cursor )
|
||||
{
|
||||
// extend
|
||||
Mouse::setCursor( cursor );
|
||||
|
||||
if (m_lostFocus)
|
||||
return; //stop messing with mouse cursor if we don't have focus.
|
||||
|
||||
if (cursor == NONE || !m_visible)
|
||||
SetCursor( NULL );
|
||||
else
|
||||
{
|
||||
SetCursor(cursorResources[cursor][m_directionFrame]);
|
||||
} // end switch
|
||||
|
||||
// save current cursor
|
||||
m_currentWin32Cursor=m_currentCursor = cursor;
|
||||
|
||||
} // end setCursor
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Capture the mouse to our application */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::capture( void )
|
||||
{
|
||||
|
||||
// SetCapture( ApplicationHWnd );
|
||||
|
||||
} // end capture
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Release the mouse capture for our app window */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Win32Mouse::releaseCapture( void )
|
||||
{
|
||||
|
||||
// ReleaseCapture();
|
||||
|
||||
} // end releaseCapture
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in a new issue