1006 lines
55 KiB
C++
1006 lines
55 KiB
C++
|
/*
|
||
|
** 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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** 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 <assert.h>
|
||
|
|
||
|
|
||
|
/*
|
||
|
** 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
|
||
|
}
|
||
|
|
||
|
|
||
|
|