// // Copyright 2020 Electronic Arts Inc. // // TiberianDawn.DLL and RedAlert.dll and corresponding source code 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. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed // in the hope that it will be useful, but with permitted additional restrictions // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT // distributed with this program. You should have received a copy of the // GNU General Public License along with permitted additional restrictions // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection /* $Header: F:\projects\c&c\vcs\code\mouse.cpv 2.18 16 Oct 1995 16:49:56 JOE_BOSTIC $ */ /*********************************************************************************************** *** 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 * * * * File Name : MOUSE.CPP * * * * Programmer : Joe L. Bostic * * * * Start Date : 12/15/94 * * * * Last Update : June 30, 1995 [JLB] * * * *---------------------------------------------------------------------------------------------* * Functions: * * MouseClass::AI -- Process player input as it relates to the mouse * * MouseClass::Override_Mouse_Shape -- Alters the shape of the mouse. * * MouseClass::Init_Clear -- Sets the mouse system to a known state * * MouseClass::MouseClass -- Default constructor for the mouse handler class. * * MouseClass::One_Time -- Performs the one time initialization of the mouse system. * * MouseClass::Set_Default_Mouse -- Sets the mouse to match the shape specified. * * MouseClass::Revert_Mouse_Shape -- Reverts the mouse shape to the non overridden shape. * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" /* ** This points to the loaded mouse shapes. */ void const * MouseClass::MouseShapes; /* ** This is the timer that controls the mouse animation. It is always at a fixed ** rate so it uses the constant system timer. */ CountDownTimerClass MouseClass::Timer; /* ** This contains the value of the Virtual Function Table Pointer */ void * MouseClass::VTable; /*********************************************************************************************** * MouseClass::Set_Default_Mouse -- Sets the mouse to match the shape specified. * * * * This routine is used to inform the display system as to which mouse shape is desired. * * * * INPUT: mouse -- The mouse shape number to set the mouse to. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ void MouseClass::Set_Default_Mouse(MouseType mouse, bool size) { NormalMouseShape = mouse; Override_Mouse_Shape(mouse, size); } /*********************************************************************************************** * MouseClass::Revert_Mouse_Shape -- Reverts the mouse shape to the non overridden shape. * * * * Use this routine to cancel the effects of Override_Mouse_Shape(). It will revert the * * mouse back to the original shape. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 03/27/1995 JLB : Created. * *=============================================================================================*/ void MouseClass::Revert_Mouse_Shape(void) { Override_Mouse_Shape(NormalMouseShape, false); } void MouseClass::Mouse_Small(bool wwsmall) { MouseStruct const * control = &MouseControl[CurrentMouseShape]; if (IsSmall == wwsmall) { return; } IsSmall = wwsmall; if (wwsmall) { if (control->SmallFrame != -1) { Set_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, control->SmallFrame + Frame/4)); } else { Set_Mouse_Cursor(MouseControl[MOUSE_NORMAL].X, MouseControl[MOUSE_NORMAL].Y, Extract_Shape(MouseShapes, MOUSE_NORMAL)); } } else { Set_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, control->StartFrame + Frame/4)); } } /*********************************************************************************************** * MouseClass::Override_Mouse_Shape -- Alters the shape of the mouse. * * * * This routine is used to alter the shape of the mouse as needed. * * Typical mouse shape change occurs when scrolling the map or * * selecting targets. * * * * INPUT: mouse -- The mouse shape number to use. * * * * OUTPUT: bool; Was the mouse shape changed? * * * * WARNINGS: This is not intended to be used as a means to hide the * * mouse. Nor will it work correctly if the mouse shape * * file hasn't been loaded. * * * * HISTORY: * * 03/10/1994 JLB : Created. * * 06/03/1994 JLB : Made into member function. * * 12/24/1994 JLB : Added small control parameter. * *=============================================================================================*/ bool MouseClass::Override_Mouse_Shape(MouseType mouse, bool wwsmall) { MouseStruct const * control = &MouseControl[mouse]; static bool startup = false; int baseshp; /* ** Only certain mouse shapes have a small counterpart. If the requested mouse ** shape is not one of these, then force the small size override flag to false. */ if (control->SmallFrame == -1) { wwsmall = false; } /* ** If the mouse shape is going to change, then inform the mouse driver of the ** change. */ if (!startup || (MouseShapes && ((mouse != CurrentMouseShape) || (wwsmall != IsSmall)))) { startup = true; Timer.Set(control->FrameRate); Frame = 0; #ifdef OBSOLETE Control.Set_Stage(0); int rate = Options.Normalize_Delay(control->FrameRate); Control.Set_Rate(MAX(rate, 1)); #endif baseshp = (wwsmall) ? control->SmallFrame : control->StartFrame; Set_Mouse_Cursor(control->X, control->Y, Extract_Shape(MouseShapes, baseshp + Frame/4)); CurrentMouseShape = mouse; IsSmall = wwsmall; return(true); } return(false); } /*********************************************************************************************** * MouseClass::AI -- Process player input as it relates to the mouse * * * * This routine will is to be called once per game tick and is passed the player keyboard * * or mouse input code. It processes this code and updates the mouse shape as appropriate. * * * * INPUT: input -- The player input code as returned from Keyboard::Get(). * * * * x,y -- The mouse coordinate values to use. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/24/1994 JLB : Created. * * 12/31/1994 JLB : Uses mouse coordinate parameters. * * 03/27/1995 JLB : New animation control. * * 05/28/1995 JLB : Moderates animation so is more steady regardless of speed. * * 06/30/1995 JLB : Uses constant timer system. * *=============================================================================================*/ void MouseClass::AI(KeyNumType &input, int x, int y) { // bool doit = false; void *mouse_shape_ptr; MouseStruct const * control = &MouseControl[CurrentMouseShape]; if (control->FrameRate && Timer.Time() == 0) { Frame++; Frame %= control->FrameCount; Timer.Set(control->FrameRate); #ifdef OBSOLETE Control.Set_Stage(Control.Fetch_Stage() % control->FrameCount); #endif if (!IsSmall || control->SmallFrame != -1) { int baseframe = (IsSmall) ? control->SmallFrame : control->StartFrame; mouse_shape_ptr = Extract_Shape(MouseShapes, baseframe + Frame); if (mouse_shape_ptr){ Set_Mouse_Cursor(control->X, control->Y, mouse_shape_ptr); } } } ScrollClass::AI(input, x, y); } /*********************************************************************************************** * MouseClass::MouseClass -- Default constructor for the mouse handler class. * * * * This is the default constructor for the mouse handling class. It merely sets up the * * mouse system to its default state. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/24/1994 JLB : Created. * *=============================================================================================*/ MouseClass::MouseClass(void) { CurrentMouseShape = MOUSE_NORMAL; NormalMouseShape = MOUSE_NORMAL; Timer.Start(); } /*********************************************************************************************** * MouseClass::One_Time -- Performs the one time initialization of the mouse system. * * * * Use this routine to load the mouse data file and perform any other necessary one time * * preparations for the game. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: Only call this routine ONCE. * * * * HISTORY: * * 12/24/1994 JLB : Created. * *=============================================================================================*/ void MouseClass::One_Time(void) { ScrollClass::One_Time(); /* ** Override the mouse shape file with the one in the current directory, but only if there ** is an override file available. */ RawFileClass file("MOUSE.SHP"); if (file.Is_Available()) { MouseShapes = Load_Alloc_Data(file); } else { MouseShapes = MixFileClass::Retrieve("MOUSE.SHP"); } VTable = ((void **)(((char *)this) + sizeof(VectorClass) - 4))[0]; } /*********************************************************************************************** * MouseClass::Init_Clear -- Sets the mouse system to a known state * * * * This routine will reset the mouse handling system. Typically, this routine is called * * when preparing for the beginning of a new scenario. * * * * INPUT: theater -- The theater that the scenario will take place. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 12/24/1994 JLB : Created. * *=============================================================================================*/ void MouseClass::Init_Clear(void) { ScrollClass::Init_Clear(); IsSmall = false; NormalMouseShape = MOUSE_NORMAL; } /* ** This array of structures is used to control the mouse animation ** sequences. */ MouseClass::MouseStruct MouseClass::MouseControl[MOUSE_COUNT] = { {0, 1, 0, 86, 0, 0}, // MOUSE_NORMAL {1, 1, 0, -1, 15, 0}, // MOUSE_N {2, 1, 0, -1, 29, 0}, // MOUSE_NE {3, 1, 0, -1, 29, 12}, // MOUSE_E {4, 1, 0, -1, 29, 23}, // MOUSE_SE {5, 1, 0, -1, 15, 23}, // MOUSE_S {6, 1, 0, -1, 0, 23}, // MOUSE_SW {7, 1, 0, -1, 0, 13}, // MOUSE_W {8, 1, 0, -1, 0, 0}, // MOUSE_NW {130, 1, 0, -1, 15, 0}, // MOUSE_NO_N {131, 1, 0, -1, 29, 0}, // MOUSE_NO_NE {132, 1, 0, -1, 29, 12}, // MOUSE_NO_E {133, 1, 0, -1, 29, 23}, // MOUSE_NO_SE {134, 1, 0, -1, 15, 23}, // MOUSE_NO_S {135, 1, 0, -1, 0, 23}, // MOUSE_NO_SW {136, 1, 0, -1, 0, 13}, // MOUSE_NO_W {137, 1, 0, -1, 0, 0}, // MOUSE_NO_NW {11, 1, 0, 27, 15, 12}, // MOUSE_NO_MOVE {10, 1, 0, 26, 15, 12}, // MOUSE_CAN_MOVE {119, 3, 4, 148, 15, 12}, // MOUSE_ENTER {53, 9, 4, -1, 15, 12}, // MOUSE_DEPLOY {12, 6, 4, -1, 15, 12}, // MOUSE_CAN_SELECT {18, 8, 4, 140, 15, 12}, // MOUSE_CAN_ATTACK {62, 24, 2, -1, 15, 12}, // MOUSE_SELL_BACK {154, 24, 2, -1, 15, 12}, // MOUSE_SELL_UNIT {29, 24, 2, -1, 15, 12}, // MOUSE_REPAIR {126, 1, 0, -1, 15, 12}, // MOUSE_NO_REPAIR {125, 1, 0, -1, 15, 12}, // MOUSE_NO_SELL_BACK {87, 1, 0, 151, 0, 0}, // MOUSE_RADAR_CURSOR {103, 16, 2, -1, 15, 12}, // MOUSE_ION_CANNON {96, 7, 4, -1, 15, 12}, // MOUSE_NUCLEAR_BOMB {88, 8, 2, -1, 15, 12}, // MOUSE_AIR_STRIKE {122, 3, 4, 127, 15, 12}, // MOUSE_DEMOLITIONS {153, 1, 0, 152, 15, 12}, // MOUSE_AREA_GUARD };