/*
** Command & Conquer Generals Zero Hour(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 .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (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
#include "Common/Debug.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= 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 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());
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