/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/Library/wwmouse.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 8/11/97 10:14a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Callback_Process_Mouse -- Mouse O/S callback function. *
* WWMouseClass::WWMouseClass -- Constructor for mouse handler object. *
* WWMouseClass::~WWMouseClass -- Destructor for mouse handler object. *
* WWMouseClass::Get_Mouse_State -- Fetch the current mouse visibility state. *
* WWMouseClass::Set_Cursor -- Set the mouse cursor shape. *
* WWMouseClass::Is_Data_Valid -- Determines if there is valid shape image data. *
* WWMouseClass::Validate_Copy_Buffer -- Checks for and validates the background copy buffer.*
* WWMouseClass::Matching_Rect -- Finds rectangle of current cursor position & size. *
* WWMouseClass::Save_Background -- Saves the background to a copy buffer. *
* WWMouseClass::Restore_Background -- Restores the image back where it came from. *
* WWMouseClass::Draw_Mouse -- Manually draw the mouse to the surface specified. *
* WWMouseClass::Erase_Mouse -- Restores the surface after a Draw_Mouse call. *
* WWMouseClass::Raw_Draw_Mouse -- Draws the mouse to the surface specified. *
* WWMouseClass::Low_Show_Mouse -- Shows the mouse and saves the background. *
* WWMouseClass::Low_Hide_Mouse -- Restores the surface image in order to hide the mouse. *
* WWMouseClass::Show_Mouse -- Shows the mouse on the visible surface. *
* WWMouseClass::Hide_Mouse -- Hides the mouse from the visible surface. *
* WWMouseClass::Capture_Mouse -- Capture the mouse into the mouse handler region. *
* WWMouseClass::Release_Mouse -- Release the mouse back to the O/S. *
* WWMouseClass::Conditional_Hide_Mouse -- Hides the mouse if it would overlap the region spe*
* WWMouseClass::Conditional_Show_Mouse -- Releases the mouse hiding region tracking. *
* WWMouseClass::Convert_Coordinate -- Convert an O/S coordinate into a logical coordinate. *
* WWMouseClass::Get_Bounded_Position -- Fetches the mouse position from the O/S. *
* WWMouseClass::Update_Mouse_Position -- Updates the mouse position to match that specified.*
* WWMouseClass::Process_Mouse -- Mouse processing callback routine. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "_convert.h"
#include "_mono.h"
#include "blit.h"
#include "bsurface.h"
#include "draw.h"
#include "shapeset.h"
#include "surface.h"
#include "win.h"
#include "wwmouse.h"
#include
/*
** Persistant mouse object pointer that is used to facilitate access to the mouse
** handler object outside of the context of a member function. This will be set to the
** mouse object most recently created.
*/
static WWMouseClass * _MousePtr = NULL;
/***********************************************************************************************
* Callback_Process_Mouse -- Mouse O/S callback function. *
* *
* This routine is called periodically by the operating system. It handles updating the *
* mouse cursor position to match the mouse movement. *
* *
* INPUT: n/a *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void CALLBACK Callback_Process_Mouse( UINT, UINT, DWORD, DWORD, DWORD )
{
if (_MousePtr != NULL) {
_MousePtr->Process_Mouse();
}
}
/***********************************************************************************************
* WWMouseClass::WWMouseClass -- Constructor for mouse handler object. *
* *
* This is the constructor for the mouse handler object. It is assigned to a surface and *
* given a confining rectangle. The mouse begins in a non-captured state. *
* *
* INPUT: surfaceptr -- Pointer to the visible display surface that will show the mouse. *
* *
* confine -- The confining rectangle within the visible surface. The mouse *
* coordinates are bound to this rectangle. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
WWMouseClass::WWMouseClass(Surface * surfaceptr, HWND window) :
Blocked(false),
MouseState(-1),
IsCaptured(false),
MouseX(0),
MouseY(0),
SurfacePtr(surfaceptr),
Window(window),
MouseShape(NULL),
ShapeNumber(0),
MouseXHot(0),
MouseYHot(0),
Background(NULL),
Alternate(NULL),
SidebarAlternate(NULL),
ConditionalRect(0,0,0,0),
ConditionalState(-1),
TimerHandle(0)
{
_MousePtr = this;
TimerHandle = timeSetEvent(1000/60, 1, Callback_Process_Mouse, 0, TIME_PERIODIC);
Calc_Confining_Rect();
MouseXHot = ConfiningRect.X + (ConfiningRect.Width/2);
MouseYHot = ConfiningRect.Y + (ConfiningRect.Height/2);
}
/***********************************************************************************************
* WWMouseClass::~WWMouseClass -- Destructor for mouse handler object. *
* *
* This will remove the mouse handler object from being processed. It returns the mouse *
* back to O/S control. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
WWMouseClass::~WWMouseClass(void)
{
if (TimerHandle != 0) {
timeKillEvent(TimerHandle);
_MousePtr = NULL;
}
delete Background;
Background = NULL;
delete Alternate;
Alternate = NULL;
delete SidebarAlternate;
SidebarAlternate = NULL;
}
void WWMouseClass::Calc_Confining_Rect(void)
{
RECT rect;
GetClientRect(Window, &rect);
POINT point;
point.x = rect.left;
point.y = rect.top;
ClientToScreen(Window, &point);
POINT lr;
lr.x = rect.right;
lr.y = rect.bottom;
ClientToScreen(Window, &lr);
ConfiningRect = Rect(point.x, point.y, lr.x-point.x, lr.y-point.y);
// ConfiningRect = Rect(point.x, point.y, lr.x-point.x+1, lr.y-point.y+1);
}
/***********************************************************************************************
* WWMouseClass::Get_Mouse_State -- Fetch the current mouse visibility state. *
* *
* This routine is used to retrieve the current mouse state as it relates to visiblity. *
* By using this routine it is possible to determine if the mouse is visible. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with the current mouse visibility state. If the return value is less than *
* 0 (i.e., negative), then the mouse is hidden. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
int WWMouseClass::Get_Mouse_State(void) const
{
if (!Is_Captured()) {
ShowCursor(FALSE);
int state = ShowCursor(TRUE);
return(state);
}
return(MouseState);
}
/***********************************************************************************************
* WWMouseClass::Set_Cursor -- Set the mouse cursor shape. *
* *
* This routine sets the mouse cursor image and hot-spot. The shape only applies to the *
* mouse when it is captured (the normal case). Repeated calls to this routine is used *
* to give the mouse animation. *
* *
* INPUT: xhotspot, yhotspot -- The X,Y offset from the upper left corner of the shape *
* that specifies the hot-spot of the image. Positive values *
* are right and down from the upper left corner. *
* *
* cursor -- Pointer to the shape data. *
* *
* shape -- The shape number to use within the shape data set specified. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, ShapeSet const * cursor, int shape)
{
if (cursor != NULL) {
if (Is_Captured()) {
Block_Mouse();
if (!Is_Hidden()) Low_Hide_Mouse();
MouseShape = cursor;
ShapeNumber = shape;
MouseXHot = xhotspot;
MouseYHot = yhotspot;
if (!Is_Hidden()) Low_Show_Mouse();
Unblock_Mouse();
} else {
MouseShape = cursor;
ShapeNumber = shape;
MouseXHot = xhotspot;
MouseYHot = yhotspot;
}
}
}
/***********************************************************************************************
* WWMouseClass::Is_Data_Valid -- Determines if there is valid shape image data. *
* *
* This routine does a simple check to determine if the shape handler has been supplied *
* a pointer to shape imagery. Any internal routine that requires the data to be present *
* should call this routine to be sure it actually is. *
* *
* INPUT: none *
* *
* OUTPUT: bool; Has a shape image data pointer been supplied to this mouse handler? *
* *
* WARNINGS: When the mouse object is first created, no image data has been assigned. The *
* Set_Cursor must be called before this routine will return TRUE. *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
bool WWMouseClass::Is_Data_Valid(void) const
{
if (MouseShape != NULL) {
return(true);
}
return(false);
}
/***********************************************************************************************
* WWMouseClass::Validate_Copy_Buffer -- Checks for and validates the background copy buffer. *
* *
* This routine checks and allocates if necessary a buffer that is big enough to hold the *
* background image under the mouse. Whenever the background buffer is needed, this routine *
* should be called to ensure that it is valid. *
* *
* INPUT: none *
* *
* OUTPUT: bool; Is the buffer valid? *
* *
* WARNINGS: This routine might fail if there was insufficient memory. *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
bool WWMouseClass::Validate_Copy_Buffer(void)
{
if (Is_Data_Valid()) {
/*
** If there is a background buffer already allocated, then verify that
** it is large enough for the current shape data. If not, then free the
** buffer and reallocate it at the larger size.
*/
if (Background != NULL) {
if (MouseShape->Get_Width() > Background->Get_Width() ||
MouseShape->Get_Height() > Background->Get_Height()) {
delete Background;
Background = NULL;
}
}
if (Alternate != NULL) {
if (MouseShape->Get_Width() > Alternate->Get_Width() ||
MouseShape->Get_Height() > Alternate->Get_Height()) {
delete Alternate;
Alternate = NULL;
}
}
if (SidebarAlternate != NULL) {
if (MouseShape->Get_Width() > SidebarAlternate->Get_Width() ||
MouseShape->Get_Height() > SidebarAlternate->Get_Height()) {
delete SidebarAlternate;
SidebarAlternate = NULL;
}
}
/*
** Allocate a new background buffer if necessary. This must be big enough to
** hold the largest sized shape from the currently assigned shape set data.
*/
if (Background == NULL) {
Background = new BSurface(MouseShape->Get_Width(), MouseShape->Get_Height(), SurfacePtr->Bytes_Per_Pixel());
}
if (Alternate == NULL) {
Alternate = new BSurface(MouseShape->Get_Width(), MouseShape->Get_Height(), SurfacePtr->Bytes_Per_Pixel());
}
if (SidebarAlternate == NULL) {
SidebarAlternate = new BSurface(MouseShape->Get_Width(), MouseShape->Get_Height(), SurfacePtr->Bytes_Per_Pixel());
}
return(Background != NULL && Alternate != NULL && SidebarAlternate != NULL);
}
return(false);
}
/***********************************************************************************************
* WWMouseClass::Matching_Rect -- Finds rectangle of current cursor position & size. *
* *
* This routine will return the logical rectangle that exactly encloses the cursor. This *
* routine is typically used when drawing the cursor and manipulating the background buffer *
* under it. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with the rectangle that surrounds the cursor. *
* *
* WARNINGS: The rectangle is in logical coordinates. It may have to be biased to O/S *
* coordinates if necessary. *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
Rect WWMouseClass::Matching_Rect(void) const
{
Rect rect;
if (Is_Data_Valid()) {
((WWMouseClass *)this)->Block_Mouse();
/*
** Build the rectangle that the mouse shape will consume.
*/
rect = MouseShape->Get_Rect(ShapeNumber);
rect.X += MouseX - MouseXHot;
rect.Y += MouseY - MouseYHot;
((WWMouseClass *)this)->Unblock_Mouse();
}
return(rect);
}
/***********************************************************************************************
* WWMouseClass::Save_Background -- Saves the background to a copy buffer. *
* *
* This routine will save the region under the mouse (or where the mouse would appear at) *
* to a copy buffer. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: The previous contents of the copy buffer will be overwritten by this routine. *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Save_Background(void)
{
if (Validate_Copy_Buffer()) {
/*
** Build the rectangle that the mouse shape will consume.
*/
SavedRegion = Matching_Rect();
Rect rect = SavedRegion;
rect.X += ConfiningRect.X;
rect.Y += ConfiningRect.Y;
/*
** Blit the background from the surface to the holding buffer.
*/
// Rect old = SurfacePtr->Get_Rect();
// SurfacePtr->Window.Reset();
Background->Blit_From(Rect(0, 0, rect.Width, rect.Height), *SurfacePtr, rect);
// SurfacePtr->Window.Set(old);
}
}
/***********************************************************************************************
* WWMouseClass::Restore_Background -- Restores the image back where it came from. *
* *
* This is the counterpart routine to the Save_Background function. It will restore the *
* image from the copy buffer back to the screen where it came from. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Restore_Background(void)
{
if (SavedRegion.Is_Valid()) {
Rect rect = SavedRegion;
rect.X += ConfiningRect.X;
rect.Y += ConfiningRect.Y;
/*
** Blit the background from the holding buffer to the surface.
*/
// Rect old = SurfacePtr->Get_Rect();
// SurfacePtr->Window.Reset();
SurfacePtr->Blit_From(rect, *Background, Rect(0, 0, rect.Width, rect.Height));
// SurfacePtr->Window.Set(old);
}
}
/***********************************************************************************************
* WWMouseClass::Draw_Mouse -- Manually draw the mouse to the surface specified. *
* *
* This is a kludge function that can be used to reduce mouse flicker. Normally the mouse *
* must be hidden before an image is copied to the visible surface. By drawing the mouse *
* in the correct position on the source image prior to the copy, the mouse doesn't need *
* to be hidden and no mouse flicker occurs. This routine handles this manual draw process. *
* *
* INPUT: surface -- Pointer to the surface that the mouse will be drawn to. *
* *
* OUTPUT: none *
* *
* WARNINGS: The destination surface is presumed to be the exact dimensions of the bouding *
* rectangle specified in the mouse constructor. The call to Erase_Mouse must *
* occur as soon as possible since the mouse is frozen until it is called. *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Draw_Mouse(Surface * surface, bool issidebarsurface)
{
BSurface *savesurface;
Rect *savedregion;
int xoffset;
int yoffset;
if (issidebarsurface){
xoffset = -480;
yoffset = 0;
savesurface = SidebarAlternate;
savedregion = &SidebarAltRegion;
}else{
xoffset = 0;
yoffset = 0;
savesurface = Alternate;
savedregion = &AltRegion;
}
if (!Is_Hidden() && surface != NULL && surface != SurfacePtr && savesurface != NULL) {
Block_Mouse();
/*
** Blit the background from the surface to the holding buffer.
*/
//Rect old = surface->Window.Get_Rect();
//surface->Window.Reset();
*savedregion = SavedRegion;
savedregion->X += xoffset;
savedregion->Y += yoffset;
savesurface->Blit_From(Rect(0, 0, savedregion->Width, savedregion->Height), *surface, *savedregion);
if (issidebarsurface){
if (savedregion->X < 0 && -savedregion->X < Background->Get_Width()){
Background->Blit_From(Rect(-savedregion->X, 0, savedregion->Width, savedregion->Height),
*surface, Rect(0,savedregion->Y, savedregion->Width, savedregion->Height));
}
}else{
Background->Blit_From(Rect(0, 0, savedregion->Width, savedregion->Height), *surface, *savedregion);
}
//surface->Window.Set(old);
Raw_Draw_Mouse(surface, xoffset, yoffset);
Unblock_Mouse();
} else {
savedregion->Width = 0;
}
}
/***********************************************************************************************
* WWMouseClass::Erase_Mouse -- Restores the surface after a Draw_Mouse call. *
* *
* This is the counterpart routine to Draw_Mouse. It will restore the specified surface *
* back to its original state. The mouse is frozen between the calls to Draw_Mouse and *
* Erase_Mouse, so it is imperative to call this routine at the first legal opportunity. *
* *
* INPUT: surface -- Pointer to the surface that the mouse was previously drawn to. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Erase_Mouse(Surface * surface, bool issidebarsurface)
{
if (!Is_Hidden() && surface != NULL && surface != SurfacePtr && Alternate != NULL && SidebarAlternate != NULL) {
BSurface *savesurface;
Rect savedregion;
if (issidebarsurface){
savesurface = SidebarAlternate;
savedregion = SidebarAltRegion;
}else{
savesurface = Alternate;
savedregion = AltRegion;
}
/*
** Blit the background from the holding buffer to the surface.
*/
Block_Mouse();
//Rect old = surface->Window.Get_Rect();
//surface->Window.Reset();
surface->Blit_From(savedregion, *savesurface, Rect(0, 0, savedregion.Width, savedregion.Height));
//surface->Window.Set(old);
Unblock_Mouse();
}
}
/***********************************************************************************************
* WWMouseClass::Raw_Draw_Mouse -- Draws the mouse to the surface specified. *
* *
* This will draw the mouse image to the surface specified. It does not do any checking *
* except to make sure that the mouse image data is nominally valid. *
* *
* INPUT: surface -- The surface to draw the mouse upon. *
* *
* OUTPUT: none *
* *
* WARNINGS: The background is not preserved by this routine. *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Raw_Draw_Mouse(Surface * surface, int xoffset, int yoffset)
{
if (Is_Data_Valid() && surface != NULL) {
/*
** Determine the rectangle that the mouse will be drawn
** to.
*/
Rect rect = SavedRegion;
rect.X += xoffset;
rect.Y += yoffset;
// if (surface == SurfacePtr) {
// rect.X += ConfiningRect.X;
// rect.Y += ConfiningRect.Y;
// }
// Rect old = surface->Get_Rect();
// surface->Window.Reset();
BSurface mdata(rect.Width, rect.Height, 1, MouseShape->Get_Data(ShapeNumber));
if (surface == SurfacePtr) {
Blit_Block(*surface, *NormalDrawer, mdata, Rect(0, 0, rect.Width, rect.Height), Point2D(rect.X, rect.Y), ConfiningRect);
} else {
Blit_Block(*surface, *NormalDrawer, mdata, Rect(0, 0, rect.Width, rect.Height), Point2D(rect.X, rect.Y), surface->Get_Rect());
}
//surface->Window.Set(old);
}
}
/***********************************************************************************************
* WWMouseClass::Low_Show_Mouse -- Shows the mouse and saves the background. *
* *
* This routine will save the background and then draw the mouse to the visible surface. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Low_Show_Mouse(void)
{
Block_Mouse();
Save_Background();
Raw_Draw_Mouse(SurfacePtr, 0, 0);
Unblock_Mouse();
}
/***********************************************************************************************
* WWMouseClass::Low_Hide_Mouse -- Restores the surface image in order to hide the mouse. *
* *
* This routine will hide the mouse on the visible surface. It does this by restoring the *
* pixels under where the mouse was previously drawn. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Low_Hide_Mouse(void)
{
Block_Mouse();
Restore_Background();
Unblock_Mouse();
}
/***********************************************************************************************
* WWMouseClass::Show_Mouse -- Shows the mouse on the visible surface. *
* *
* This routine is called when the mouse can be shown on the visible surface. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Show_Mouse(void)
{
if (!Is_Captured()) {
ShowCursor(TRUE);
} else {
Block_Mouse();
InterlockedIncrement(&MouseState);
if (MouseState == 0) {
Low_Show_Mouse();
}
assert(MouseState != 1);
if (MouseState > 0) MouseState = 0;
Unblock_Mouse();
}
}
/***********************************************************************************************
* WWMouseClass::Hide_Mouse -- Hides the mouse from the visible surface. *
* *
* This routine is called when the mouse is desired to be hidden from the visible surface. *
* Typically, this must occur if the pixels where the mouse is located will be accessed. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Hide_Mouse(void)
{
if (!Is_Captured()) {
ShowCursor(FALSE);
} else {
Block_Mouse();
InterlockedDecrement(&MouseState);
if (MouseState == -1) {
Low_Hide_Mouse();
}
Unblock_Mouse();
}
}
/***********************************************************************************************
* WWMouseClass::Capture_Mouse -- Capture the mouse into the mouse handler region. *
* *
* This routine will confine the mouse to the confining rectangle and take over drawing *
* of the mouse image from the operating system. The typical state is to keep the mouse *
* captured throughout the lifetime of the owning program. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Capture_Mouse(void)
{
if (this != NULL && !Is_Captured()) {
Block_Mouse();
while (ShowCursor(FALSE) > -1) {}
while (ShowCursor(TRUE) < -1) {}
Hide_Mouse();
IsCaptured = true;
Show_Mouse();
Unblock_Mouse();
}
}
/***********************************************************************************************
* WWMouseClass::Release_Mouse -- Release the mouse back to the O/S. *
* *
* This is the counterpart routine to Capture_Mouse. This routine will return the drawing *
* and movement controls back to the operating system. Although the mouse will probably *
* be able to roam outside the confining rectangle, the coordinates returned by this class *
* are clipped to the confining rectangle anyway. This gives the impression that the mouse *
* is still at a legal position. The presumption is that the mouse needs to be released to *
* the O/S for reasons outside of the game itself. As such, the shouldn't detect any *
* illegal mouse position. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: All mouse shape changes won't be relected while the mouse is released. The O/S *
* handles drawing the mouse in that case. *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Release_Mouse(void)
{
if (this != NULL && Is_Captured()) {
Block_Mouse();
Hide_Mouse();
IsCaptured = false;
while (ShowCursor(FALSE) > -1) {}
while (ShowCursor(TRUE) < -1) {}
Show_Mouse();
Unblock_Mouse();
}
}
/***********************************************************************************************
* WWMouseClass::Conditional_Hide_Mouse -- Hides the mouse if it would overlap the region spec *
* *
* This routine will hide the mouse if it lies within the region specified or if it moves *
* within the region. *
* *
* INPUT: rect -- The rectangle that the mouse should not be drawn within. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Conditional_Hide_Mouse(Rect )
{
Hide_Mouse();
}
/***********************************************************************************************
* WWMouseClass::Conditional_Show_Mouse -- Releases the mouse hiding region tracking. *
* *
* This routine will release the region hiding tracking that was set up with a previous *
* call to Conditional_Hide_Mouse(). *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Conditional_Show_Mouse(void)
{
Show_Mouse();
}
/***********************************************************************************************
* WWMouseClass::Convert_Coordinate -- Convert an O/S coordinate into a logical coordinate. *
* *
* Sometimes you come across system mouse coordinates and they need to be converted into *
* game logical coordinates. This routine will perform this function. *
* *
* INPUT: x,y -- Reference to the coordinates that will be converted into game logical *
* coordinates. *
* *
* OUTPUT: none *
* *
* WARNINGS: The coordinates will be bound as well as transformed by the confining rectangle.*
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Convert_Coordinate(int & x, int & y) const
{
/*
** Convert the mouse position to legal bounds.
*/
x -= ConfiningRect.X;
y -= ConfiningRect.Y;
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= ConfiningRect.Width) x = ConfiningRect.Width-1;
if (y >= ConfiningRect.Height) y = ConfiningRect.Height-1;
}
/***********************************************************************************************
* WWMouseClass::Get_Bounded_Position -- Fetches the mouse position from the O/S. *
* *
* Fetches the mouse coordinates from the O/S and converts them into logical coordinates. *
* *
* INPUT: x,y -- Reference to the coordinates that will be set by this routine. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Get_Bounded_Position(int & x, int & y) const
{
/*
** Get the mouse's current real cursor position
*/
POINT pt;
GetCursorPos(&pt); // get the current cursor position
x = pt.x;
y = pt.y;
Convert_Coordinate(x, y);
}
/***********************************************************************************************
* WWMouseClass::Update_Mouse_Position -- Updates the mouse position to match that specified. *
* *
* This routine will update the mouse to match the position speicifed. *
* *
* INPUT: x,y -- The coordinates to position the mouse (hot spot). The coordinates are *
* specified as logical not O/S relative. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Update_Mouse_Position(int x, int y)
{
/*
** If the desired position is not the same as the current
** position, then hide the mouse, reposition it, then show
** the mouse.
*/
Block_Mouse();
if (x != MouseX || y != MouseY) {
if (Is_Captured() && !Is_Hidden()) Low_Hide_Mouse();
MouseX = x;
MouseY = y;
if (Is_Captured() && !Is_Hidden()) Low_Show_Mouse();
}
Unblock_Mouse();
}
/***********************************************************************************************
* WWMouseClass::Process_Mouse -- Mouse processing callback routine. *
* *
* This routine should be called periodically (recommended 15 times per second). It will *
* examine the operating system mouse position and then update the visible mouse to match. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1997 JLB : Created. *
*=============================================================================================*/
void WWMouseClass::Process_Mouse(void)
{
if (!Is_Blocked()) {
Block_Mouse();
/*
** Fetch and update the mouse position.
*/
int x;
int y;
Get_Bounded_Position(x, y);
Update_Mouse_Position(x, y);
Unblock_Mouse();
}
}
/***********************************************************************************************
* WWMouseClass::Set_Mouse_XY -- Sets the cursor position *
* *
* This routine will convert the position passed into screen coordinates and tell Windows *
* to position the mouse cursor there *
* *
* INPUT: x and y in game coordinates *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/11/1997 BG : Created. *
*=============================================================================================*/
void WWMouseClass::Set_Mouse_XY( int x, int y )
{
if (x < 0) x = 0; // clamp to game coordinates
if (y < 0) y = 0;
if (x >= ConfiningRect.Width) x = ConfiningRect.Width-1;
if (y >= ConfiningRect.Height) y = ConfiningRect.Height-1;
x += ConfiningRect.X; // convert to screen coordinates
y += ConfiningRect.Y;
SetCursorPos( x, y ); // set the current cursor position
}