mouse.c 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940
  1. /*=============================================================================
  2. Name : mouse.c
  3. Purpose : Hardware abstraction for the mouse.
  4. Created 6/26/1997 by lmoloney
  5. Copyright Relic Entertainment, Inc. All rights reserved.
  6. =============================================================================*/
  7. #define WIN32_LEAN_AND_MEAN
  8. #include <windows.h>
  9. #include "DDDFrigate.h"
  10. #include "debug.h"
  11. #include "dock.h"
  12. #include "font.h"
  13. #include "fontreg.h"
  14. #include "glinc.h"
  15. #include "globals.h"
  16. #include "GravWellGenerator.h"
  17. #include "main.h"
  18. #include "mainrgn.h"
  19. #include "mouse.h"
  20. #include "nis.h"
  21. #include "prim2d.h"
  22. #include "select.h"
  23. #include "sensors.h"
  24. #include "shipselect.h"
  25. #include "soundevent.h"
  26. #include "spaceobj.h"
  27. #include "texreg.h"
  28. #include "tweak.h"
  29. #include "types.h"
  30. #include "universe.h"
  31. #include "utility.h"
  32. #include "CommandWrap.h"
  33. #include "strings.h"
  34. #include "demo.h"
  35. #include "feflow.h"
  36. #include "researchGUI.h"
  37. #include "glcaps.h"
  38. #include "render.h"
  39. #include "tutor.h"
  40. #include "singleplayer.h"
  41. #include "glcompat.h"
  42. #include "KeyBindings.h"
  43. #include "InfoOverlay.h"
  44. #include "devstats.h"
  45. #define GLC_STORE 1
  46. extern udword gDevcaps2;
  47. /*=============================================================================
  48. Local Type Definitions:
  49. =============================================================================*/
  50. //flag settings
  51. #define MCF_SpecialOp 0x00000001 //has a special operation
  52. #define MCF_SpecialOpDeployed 0x00000002 //has a special operation already deployed
  53. #define MCF_Dockable 0x00000004 //can dock (big ship)
  54. #define MCF_SmallDockable 0x00000008 //can dock (small ship)
  55. #define MCF_GUICapable 0x00000010 //is associated with a GUI
  56. #define MCF_NonCombat 0x00000020 //ship is non combat ship
  57. #define MCF_SupportOverItself 0x00000040 //the mouse is over a selected repair corvette
  58. #define MCF_SingleClickSpecialActivate 0x00000080 //selection includes 1 or more single-click special activate ships
  59. #define MCF_DisableAll 0x00000100 //disable all cursor bitmaps
  60. #define MCF_DisableMovementMech 0x00000200 //disable cursors when movement pie plate is activated
  61. #define MCF_ShipSelecting 0x00001000 //ships are being selected
  62. #define MCF_BuildGUI 0x00002000 //ship opens the build manager
  63. #define MCF_SensorsGUI 0x00004000 //ship opens the sensors manager
  64. #define MCF_ResearchGUI 0x00008000 //ship opens the research manager
  65. #define MCF_SpecialAttack 0x00010000 //ship has a special attack
  66. #define MCF_SpecialSCSupport 0x00020000 //ship has a special support function for strikecraft
  67. #define MCF_SpecialSupport 0x00040000 //ship has a special support function
  68. #define MCF_SalvageOnly 0x00080000 //shiplist only contains salvage ships
  69. #define MCF_Salvage 0x00100000 //shiplist contains at least one salvage ship
  70. typedef struct
  71. {
  72. udword ship_selected;
  73. udword resource;
  74. udword flags;
  75. mouseCursor cursorover;
  76. } mouseInfoType;
  77. /*=============================================================================
  78. Data:
  79. =============================================================================*/
  80. //we don't want the player to be able to salvage cryotrays in mission1
  81. //so we need to include singlePlayerGameInfo
  82. extern SinglePlayerGameInfo singlePlayerGameInfo;
  83. //extern void (*mrHoldRight)(void);
  84. sdword mouseCursorXPosition, mouseCursorYPosition;
  85. uword mouseButtons;
  86. udword mouseModuleInit;
  87. rectangle mouseClipRect;
  88. bool8 mouseClip = FALSE;
  89. bool8 mouseIsVisible = TRUE;
  90. uword mouseWillBeVisible = 0;
  91. bool8 mouseDisabled = FALSE;
  92. uword mouseInsideClient = FALSE;
  93. static bool mouseGLInitialized;
  94. mouseCursor mouseCursorType = normal_mouse;
  95. udword mouseCursorMode = 0;
  96. MaxSelection mouseCursorSelect;
  97. real32 mouseDoubleClickTime = 0.0;
  98. real32 mouseDoubleClickExpire = REALlyBig;
  99. real32 mouseCursorOverDistance = REALlyBig;
  100. sdword mouseCursorOverShipType = MC_NO_SHIP;
  101. sdword mouseCursorEnemyType = -1;
  102. sdword mouseCursorEnemyPlayer = 1;
  103. real32 mouseCursorTextExpire = 0.0f;
  104. SpaceObj *mouseCursorObjPtr = NULL;
  105. SpaceObj *mouseCursorObjLast = NULL;
  106. real32 mouseCursorLastObjTime = REALlyNegative;
  107. sdword mouseCursorLastX = SDWORD_Max;
  108. sdword mouseCursorLastY = SDWORD_Max;
  109. ubyte mouseCursorOverLODs = 0;
  110. //cursor colors
  111. static color mouseCursorContentColor = MC_ContentColor;
  112. static color mouseCursorEdgeColor = MC_EdgeColor;
  113. //cursor font
  114. fonthandle mouseCursorFont = 0;
  115. //cursor bitmaps
  116. static lifheader *mouseNormalBitmap = NULL;
  117. static lifheader *mouseAddShipsBitmap = NULL;
  118. static lifheader *mouseFocusNoSelectBitmap = NULL;
  119. static lifheader *mouseMovementBitmap = NULL;
  120. static lifheader *mouseBandBoxAttackBitmap = NULL;
  121. static lifheader *mouseForceAttackBitmap = NULL;
  122. static lifheader *mouseGuardBitmap = NULL;
  123. static lifheader *mouseSpecialAttackBitmap = NULL;
  124. static lifheader *mouseSpecialOpActivateBitmap = NULL;
  125. static lifheader *mouseSpecialOpDeactivateBitmap = NULL;
  126. static lifheader *mouseGUIBitmap = NULL;
  127. static lifheader *mouseResourceBitmap = NULL;
  128. static lifheader *mouseDockingBitmap = NULL;
  129. static lifheader *mouseResearchBitmap = NULL;
  130. static lifheader *mouseSensorsBitmap = NULL;
  131. static lifheader *mouseBuildBitmap = NULL;
  132. static lifheader *mouseSalvageBitmap = NULL;
  133. static lifheader *mouseSupportBitmap = NULL;
  134. static lifheader *mouseTradersBitmap = NULL;
  135. static GLuint tex_Normal = 0;
  136. static GLuint tex_AddShips = 0;
  137. static GLuint tex_FocusNoSelect = 0;
  138. static GLuint tex_Movement = 0;
  139. static GLuint tex_BandBoxAttack = 0;
  140. static GLuint tex_ForceAttack = 0;
  141. static GLuint tex_Guard = 0;
  142. static GLuint tex_SpecialAttack = 0;
  143. static GLuint tex_SpecialOpActivate = 0;
  144. static GLuint tex_SpecialOpDeactivate = 0;
  145. static GLuint tex_GUI = 0;
  146. static GLuint tex_Resource = 0;
  147. static GLuint tex_Docking = 0;
  148. static GLuint tex_Research = 0;
  149. static GLuint tex_Sensors = 0;
  150. static GLuint tex_Build = 0;
  151. static GLuint tex_Salvage = 0;
  152. static GLuint tex_Support = 0;
  153. static GLuint tex_Traders = 0;
  154. static mouseInfoType mouseInfo = {0, 0, 0, MC_NO_SHIP};
  155. /*=============================================================================
  156. Functions:
  157. =============================================================================*/
  158. // ============================================================================
  159. // Utility functions
  160. // ============================================================================
  161. /*-----------------------------------------------------------------------------
  162. Name : mouseMirrorBitmap
  163. Description : Flips a bitmap 180 degrees
  164. Inputs : bitmap - pointer to the bitmap data
  165. width - width of the bitmap
  166. height - height of the bitmap
  167. Outputs : replaces "bitmap" with a bitmap flipped 90 degrees clockwise
  168. Return :
  169. ----------------------------------------------------------------------------*/
  170. #define PIXEL(bm, x, y, offset, width) bm[((x) + (y)*(width))+(offset)]
  171. void mouseMirrorBitmap(udword *bitmap, sdword width, sdword height)
  172. {
  173. udword i, j;
  174. udword new_bitmap[1024];
  175. for (i = 0; i < (udword)width; i++)
  176. {
  177. for (j = 0; j < (udword)height; j++)
  178. {
  179. PIXEL(new_bitmap, i, (height - 1) - j, 0, width) = PIXEL(bitmap, i, j, 0, width);
  180. }
  181. }
  182. memcpy(bitmap,new_bitmap,sizeof(udword)*width*height);
  183. }
  184. #undef PIXEL
  185. /*-----------------------------------------------------------------------------
  186. Name : mouseCreateGLHandle
  187. Description : creates a GL texture object for a given liff
  188. Inputs : lif - the lifheader structure of the bitmap
  189. thandle - target for the texture name
  190. Outputs : thandle contains the texture name
  191. Return :
  192. ----------------------------------------------------------------------------*/
  193. void mouseCreateGLHandle(lifheader* lif, GLuint* thandle)
  194. {
  195. sdword y;
  196. ubyte* data;
  197. ubyte* sp;
  198. ubyte* dp;
  199. data = (ubyte*)memAlloc(4 * lif->width * lif->height, "temp mouse texture", 0);
  200. for (y = 0; y < lif->height; y++)
  201. {
  202. dp = data + 4 * lif->width * (lif->height - y - 1);
  203. sp = lif->data + 4 * lif->width * y;
  204. memcpy(dp, sp, 4 * lif->width);
  205. }
  206. if (*thandle != 0)
  207. {
  208. glDeleteTextures(1, thandle);
  209. }
  210. trClearCurrent();
  211. glGenTextures(1, thandle);
  212. glBindTexture(GL_TEXTURE_2D, *thandle);
  213. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  214. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  215. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  216. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  217. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lif->width, lif->height,
  218. 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  219. memFree(data);
  220. }
  221. // ============================================================================
  222. // Mouse functions
  223. // ============================================================================
  224. /*-----------------------------------------------------------------------------
  225. Name : mouseStartup
  226. Description : Start the mouse module
  227. Inputs : void
  228. Outputs : sets the mouse position by getting information from the
  229. Windows mouse system.
  230. Return : OKAY
  231. ----------------------------------------------------------------------------*/
  232. sdword mouseStartup(void)
  233. {
  234. RECT clientRect, windowRect;
  235. POINT mousePoint;
  236. GetWindowRect(ghMainWindow, &windowRect);
  237. GetClientRect(ghMainWindow, &clientRect); //get location of window
  238. GetCursorPos(&mousePoint); //get location of Windows mouse cursor
  239. mouseCursorXPosition = mousePoint.x - windowRect.left; //compute relative coords
  240. mouseCursorYPosition = mousePoint.y - windowRect.top;
  241. mouseNormalBitmap = trLIFFileLoad(MC_NORMAL_BM, NonVolatile);
  242. mouseAddShipsBitmap = trLIFFileLoad(MC_ADD_SHIPS_BM, NonVolatile);
  243. mouseFocusNoSelectBitmap = trLIFFileLoad(MC_FOCUS_NO_SELECT_BM, NonVolatile);
  244. mouseBandBoxAttackBitmap = trLIFFileLoad(MC_BAND_BOX_ATTACK_BM, NonVolatile);
  245. mouseForceAttackBitmap = trLIFFileLoad(MC_FORCE_ATTACK_BM, NonVolatile);
  246. mouseGuardBitmap = trLIFFileLoad(MC_GUARD_BM, NonVolatile);
  247. mouseSpecialAttackBitmap = trLIFFileLoad(MC_SPECIAL_ATTACK_BM, NonVolatile);
  248. mouseSpecialOpActivateBitmap = trLIFFileLoad(MC_SPECIAL_OP_ACTIVATE_BM, NonVolatile);
  249. mouseSpecialOpDeactivateBitmap = trLIFFileLoad(MC_SPECIAL_OP_DEACTIVATE_BM, NonVolatile);
  250. mouseGUIBitmap = trLIFFileLoad(MC_GUI_BM, NonVolatile);
  251. mouseResourceBitmap = trLIFFileLoad(MC_RESOURCE_BM, NonVolatile);
  252. mouseDockingBitmap = trLIFFileLoad(MC_DOCKING_BM, NonVolatile);
  253. mouseResearchBitmap = trLIFFileLoad(MC_RESEARCH_BM, NonVolatile);
  254. mouseSensorsBitmap = trLIFFileLoad(MC_SENSORS_BM, NonVolatile);
  255. mouseBuildBitmap = trLIFFileLoad(MC_BUILD_BM, NonVolatile);
  256. mouseSalvageBitmap = trLIFFileLoad(MC_SALVAGE_BM, NonVolatile);
  257. mouseSupportBitmap = trLIFFileLoad(MC_SUPPORT_BM, NonVolatile);
  258. mouseTradersBitmap = trLIFFileLoad(MC_TRADERS_BM, NonVolatile);
  259. mouseMirrorBitmap((udword *)mouseNormalBitmap->data, mouseNormalBitmap->width, mouseNormalBitmap->height);
  260. mouseMirrorBitmap((udword *)mouseAddShipsBitmap->data, mouseAddShipsBitmap->width, mouseAddShipsBitmap->height);
  261. mouseMirrorBitmap((udword *)mouseFocusNoSelectBitmap->data, mouseFocusNoSelectBitmap->width, mouseFocusNoSelectBitmap->height);
  262. mouseMirrorBitmap((udword *)mouseBandBoxAttackBitmap->data, mouseBandBoxAttackBitmap->width, mouseBandBoxAttackBitmap->height);
  263. mouseMirrorBitmap((udword *)mouseForceAttackBitmap->data, mouseForceAttackBitmap->width, mouseForceAttackBitmap->height);
  264. mouseMirrorBitmap((udword *)mouseGuardBitmap->data, mouseGuardBitmap->width, mouseGuardBitmap->height);
  265. mouseMirrorBitmap((udword *)mouseSpecialAttackBitmap->data, mouseSpecialAttackBitmap->width, mouseSpecialAttackBitmap->height);
  266. mouseMirrorBitmap((udword *)mouseSpecialOpActivateBitmap->data, mouseSpecialOpActivateBitmap->width, mouseSpecialOpActivateBitmap->height);
  267. mouseMirrorBitmap((udword *)mouseSpecialOpDeactivateBitmap->data, mouseSpecialOpDeactivateBitmap->width, mouseSpecialOpDeactivateBitmap->height);
  268. mouseMirrorBitmap((udword *)mouseGUIBitmap->data, mouseGUIBitmap->width, mouseGUIBitmap->height);
  269. mouseMirrorBitmap((udword *)mouseResourceBitmap->data, mouseResourceBitmap->width, mouseResourceBitmap->height);
  270. mouseMirrorBitmap((udword *)mouseDockingBitmap->data, mouseDockingBitmap->width, mouseDockingBitmap->height);
  271. mouseMirrorBitmap((udword *)mouseResearchBitmap->data, mouseResearchBitmap->width, mouseResearchBitmap->height);
  272. mouseMirrorBitmap((udword *)mouseSensorsBitmap->data, mouseSensorsBitmap->width, mouseSensorsBitmap->height);
  273. mouseMirrorBitmap((udword *)mouseBuildBitmap->data, mouseBuildBitmap->width, mouseBuildBitmap->height);
  274. mouseMirrorBitmap((udword *)mouseSalvageBitmap->data, mouseSalvageBitmap->width, mouseSalvageBitmap->height);
  275. mouseMirrorBitmap((udword *)mouseSupportBitmap->data, mouseSupportBitmap->width, mouseSupportBitmap->height);
  276. mouseMirrorBitmap((udword *)mouseTradersBitmap->data, mouseTradersBitmap->width, mouseTradersBitmap->height);
  277. mouseDoubleClickTime = GetDoubleClickTime() / 1000.0f;
  278. mouseCursorFont = frFontRegister(TW_CURSORTEXT_FONT);
  279. mouseGLInitialized = FALSE;
  280. return(OKAY);
  281. }
  282. /*-----------------------------------------------------------------------------
  283. Name : mouseInitGL
  284. Description : initialize the GL texture handles for mouse bitmaps
  285. Inputs :
  286. Outputs :
  287. Return :
  288. ----------------------------------------------------------------------------*/
  289. void mouseInitGL(void)
  290. {
  291. mouseCreateGLHandle(mouseNormalBitmap, &tex_Normal);
  292. mouseCreateGLHandle(mouseAddShipsBitmap, &tex_AddShips);
  293. mouseCreateGLHandle(mouseFocusNoSelectBitmap, &tex_FocusNoSelect);
  294. mouseCreateGLHandle(mouseBandBoxAttackBitmap, &tex_BandBoxAttack);
  295. mouseCreateGLHandle(mouseForceAttackBitmap, &tex_ForceAttack);
  296. mouseCreateGLHandle(mouseGuardBitmap, &tex_Guard);
  297. mouseCreateGLHandle(mouseSpecialAttackBitmap, &tex_SpecialAttack);
  298. mouseCreateGLHandle(mouseSpecialOpActivateBitmap, &tex_SpecialOpActivate);
  299. mouseCreateGLHandle(mouseSpecialOpDeactivateBitmap, &tex_SpecialOpDeactivate);
  300. mouseCreateGLHandle(mouseGUIBitmap, &tex_GUI);
  301. mouseCreateGLHandle(mouseResourceBitmap, &tex_Resource);
  302. mouseCreateGLHandle(mouseDockingBitmap, &tex_Docking);
  303. mouseCreateGLHandle(mouseResearchBitmap, &tex_Research);
  304. mouseCreateGLHandle(mouseSensorsBitmap, &tex_Sensors);
  305. mouseCreateGLHandle(mouseBuildBitmap, &tex_Build);
  306. mouseCreateGLHandle(mouseSalvageBitmap, &tex_Salvage);
  307. mouseCreateGLHandle(mouseSupportBitmap, &tex_Support);
  308. mouseCreateGLHandle(mouseTradersBitmap, &tex_Traders);
  309. }
  310. /*-----------------------------------------------------------------------------
  311. Name : mouseReset
  312. Description : reset mouse module (delete associated GL texture objects)
  313. Inputs :
  314. Outputs :
  315. Return :
  316. ----------------------------------------------------------------------------*/
  317. void mouseReset(void)
  318. {
  319. if (mouseGLInitialized)
  320. {
  321. glDeleteTextures(1, &tex_Normal);
  322. glDeleteTextures(1, &tex_AddShips);
  323. glDeleteTextures(1, &tex_FocusNoSelect);
  324. glDeleteTextures(1, &tex_BandBoxAttack);
  325. glDeleteTextures(1, &tex_ForceAttack);
  326. glDeleteTextures(1, &tex_Guard);
  327. glDeleteTextures(1, &tex_SpecialAttack);
  328. glDeleteTextures(1, &tex_SpecialOpActivate);
  329. glDeleteTextures(1, &tex_SpecialOpDeactivate);
  330. glDeleteTextures(1, &tex_GUI);
  331. glDeleteTextures(1, &tex_Resource);
  332. glDeleteTextures(1, &tex_Docking);
  333. glDeleteTextures(1, &tex_Research);
  334. glDeleteTextures(1, &tex_Sensors);
  335. glDeleteTextures(1, &tex_Build);
  336. glDeleteTextures(1, &tex_Salvage);
  337. glDeleteTextures(1, &tex_Support);
  338. glDeleteTextures(1, &tex_Traders);
  339. tex_Normal = 0;
  340. tex_AddShips = 0;
  341. tex_FocusNoSelect = 0;
  342. tex_BandBoxAttack = 0;
  343. tex_ForceAttack = 0;
  344. tex_Guard = 0;
  345. tex_SpecialAttack = 0;
  346. tex_SpecialOpActivate = 0;
  347. tex_SpecialOpDeactivate = 0;
  348. tex_GUI = 0;
  349. tex_Resource = 0;
  350. tex_Docking = 0;
  351. tex_Research = 0;
  352. tex_Sensors = 0;
  353. tex_Build = 0;
  354. tex_Salvage = 0;
  355. tex_Support = 0;
  356. tex_Traders = 0;
  357. mouseGLInitialized = FALSE;
  358. }
  359. }
  360. /*-----------------------------------------------------------------------------
  361. Name : mouseShutdown
  362. Description : Close mouse module
  363. Inputs : void
  364. Outputs : not much
  365. Return : void
  366. ----------------------------------------------------------------------------*/
  367. void mouseShutdown(void)
  368. {
  369. mouseReset();
  370. }
  371. /*-----------------------------------------------------------------------------
  372. Name : mouseCursorHide
  373. Description : Show the cursor if it is hidden
  374. Inputs : void
  375. Outputs : sets the visibility flag to TRUE. Subsequent mouse
  376. mouseDraw() calls will not display a visible cursor.
  377. Return : void
  378. ----------------------------------------------------------------------------*/
  379. void mouseCursorHide(void)
  380. {
  381. mouseIsVisible = FALSE;
  382. }
  383. /*-----------------------------------------------------------------------------
  384. Name : mouseCursorShow
  385. Description : Show the cursor if it is hidden
  386. Inputs : void
  387. Outputs : sets the visibility flag to TRUE. Subsequent mouse
  388. mouseDraw() calls will not display a visible cursor.
  389. Return : void
  390. ----------------------------------------------------------------------------*/
  391. void mouseCursorShow(void)
  392. {
  393. mouseIsVisible = TRUE;
  394. }
  395. void mouseCursorDelayShow(uword delay)
  396. {
  397. mouseWillBeVisible = delay+1;
  398. }
  399. /*-----------------------------------------------------------------------------
  400. Name : mousePositionSet
  401. Description : Set new mouse position.
  402. Inputs : x, y - new location of mouse. May be clamped to the edge of
  403. the window.
  404. Outputs : Sets the Windows cursor location and the internal cursor location.
  405. Return : void
  406. ----------------------------------------------------------------------------*/
  407. void mousePositionSet(sdword x, sdword y)
  408. {
  409. rectangle clientRect;
  410. // RECT clientRect, windowRect;
  411. POINT mousePoint;
  412. utyClientRectGet(&clientRect); //get window location
  413. // GetWindowRect(ghMainWindow, &windowRect);
  414. // GetClientRect(ghMainWindow, &clientRect); //get location of window
  415. #if MOUSE_CURSOR_CLAMP
  416. //clamp specified mouse location
  417. if (x < 0)
  418. {
  419. x = 0;
  420. }
  421. if (y < 0)
  422. {
  423. y = 0;
  424. }
  425. if (x >= clientRect.x1 - clientRect.x0)
  426. {
  427. x = clientRect.x1 - clientRect.x0 - 1;
  428. }
  429. if (y >= clientRect.y1 - clientRect.y0)
  430. {
  431. y = clientRect.y1 - clientRect.y0 - 1;
  432. }
  433. #endif
  434. mouseCursorXPosition = x; //set internal mouse location
  435. mouseCursorYPosition = y;
  436. mousePoint.x = clientRect.x0 + x; //compute Windows mouse location
  437. mousePoint.y = clientRect.y0 + y;
  438. SetCursorPos(mousePoint.x, mousePoint.y); //set Windows mouse location
  439. }
  440. /*-----------------------------------------------------------------------------
  441. Name : mouseClipToRect
  442. Description : Clips the mouse to a given rectangle.
  443. Inputs : rect - rectangle to clip to. NULL means no rectangle.
  444. Outputs :
  445. Return :
  446. ----------------------------------------------------------------------------*/
  447. void mouseClipToRect(rectangle *rect)
  448. {
  449. if (rect == NULL)
  450. {
  451. mouseClip = FALSE;
  452. }
  453. else
  454. {
  455. mouseClip = TRUE;
  456. mouseClipRect = *rect;
  457. }
  458. }
  459. /*-----------------------------------------------------------------------------
  460. Name : mouseLDoubleClick
  461. Description : Processes a double click on the left mouse button
  462. Inputs : void
  463. Outputs : Very specific depending on the state of mouseInfo
  464. Return : TRUE if some processing has been done (overrides the processing
  465. for a single left click)
  466. FALSE if no processing was done (processing for the single
  467. left click continues)
  468. ----------------------------------------------------------------------------*/
  469. bool mouseLDoubleClick(void)
  470. {
  471. MaxSelection tempSelection;
  472. //if a menu is up, don't do any of this
  473. // if (feStackIndex > 0)
  474. // {
  475. // if (rmGUIActive)
  476. // {
  477. // return TRUE;
  478. // }
  479. // else
  480. // {
  481. // return FALSE;
  482. // }
  483. // }
  484. //**** big chunks taken out because this function is being called
  485. // from mainrgn now.
  486. // if (bitTest(mouseCursorMode, MCM_SingleClick))
  487. // {
  488. // if (bitTest(mouseCursorMode, MCM_DoubleClick))
  489. // {
  490. // bitClear(mouseCursorMode, MCM_DoubleClick);
  491. // bitClear(mouseCursorMode, MCM_SingleClick);
  492. // mouseCursorSelect.numShips = 0;
  493. // }
  494. // else
  495. // {
  496. // bitSet(mouseCursorMode, MCM_DoubleClick);
  497. // mouseDoubleClickExpire = universe.totaltimeelapsed + mouseDoubleClickTime;
  498. // return FALSE;
  499. // }
  500. // }
  501. if (selSelected.numShips)
  502. {
  503. #if !MR_GUI_SINGLECLICK
  504. // if (bitTest(mouseInfo.flags, MCF_BuildGUI))
  505. // {
  506. // tutGameMessage("Game_DoubleClickBuild");
  507. // cmConstructionBegin(ghMainRegion,(sdword)selSelected.ShipPtr[0], 0, 0);
  508. // return TRUE;
  509. // }
  510. // else if (bitTest(mouseInfo.flags, MCF_SensorsGUI))
  511. // {
  512. // tutGameMessage("Game_DoubleClickSensors");
  513. // smSensorsBegin(NULL, NULL);
  514. // return TRUE;
  515. // }
  516. // else if (bitTest(mouseInfo.flags, MCF_ResearchGUI))
  517. // {
  518. // tutGameMessage("Game_DoubleClickResearch");
  519. // rmResearchGUIBegin(ghMainRegion,(sdword)selSelected.ShipPtr[0], 0, 0);
  520. // }
  521. // else
  522. #endif !MR_GUI_SINGLECLICK
  523. // if (ShiptypeInSelection((SelectCommand *)&mouseCursorSelect, RepairCorvette) ||
  524. // ((ShiptypeInSelection((SelectCommand *)&mouseCursorSelect, AdvanceSupportFrigate) ||
  525. // ShiptypeInSelection((SelectCommand *)&mouseCursorSelect, Carrier)) &&
  526. // (mouseCursorObjPtr &&
  527. // (isShipOfClass((Ship *)mouseCursorObjPtr, CLASS_Fighter) ||
  528. // isShipOfClass((Ship *)mouseCursorObjPtr, CLASS_Corvette)))))
  529. if (mouseCursorObjPtr && // if there's an object being clicked on
  530. ((isShipOfClass((Ship *)mouseCursorObjPtr, CLASS_Fighter) || // Carriers only support strikecraft
  531. isShipOfClass((Ship *)mouseCursorObjPtr, CLASS_Corvette)) &&
  532. ShiptypeInSelection((SelectCommand *)&mouseCursorSelect, Carrier)) ||
  533. (ShiptypeInSelection((SelectCommand *)&mouseCursorSelect, RepairCorvette) ||
  534. ShiptypeInSelection((SelectCommand *)&mouseCursorSelect, AdvanceSupportFrigate)))
  535. {
  536. // make a backup of mouseCursorSelect
  537. tempSelection.numShips = 0;
  538. selSelectionCopy((MaxAnySelection *)&tempSelection, (MaxAnySelection *)&mouseCursorSelect);
  539. MakeShipsSpecialTargetCapable((SelectCommand *)&mouseCursorSelect,TRUE);
  540. MakeShipsNotIncludeTheseShips((SelectCommand *)&mouseCursorSelect, (SelectCommand *)&selSelected);
  541. if (mouseCursorSelect.numShips > 0)
  542. {
  543. SelectCommand sel;
  544. selSelectionCopy((MaxAnySelection *)&selSelected,
  545. (MaxAnySelection *)&mouseCursorSelect);
  546. ioUpdateShipTotals();
  547. if (mouseCursorSelect.numShips < tempSelection.numShips)
  548. {
  549. // the selection being activated has other ships as well
  550. tutGameMessage("Game_DoubleClickSpecial");
  551. sel.numShips = 1;
  552. sel.ShipPtr[0] = (Ship *)mouseCursorObjPtr;
  553. clWrapSpecial(&universe.mainCommandLayer, (SelectCommand *)&mouseCursorSelect, (SpecialCommand *)&sel);
  554. selSelectionCopy((MaxAnySelection *)&mouseCursorSelect,
  555. (MaxAnySelection *)&tempSelection);
  556. return FALSE; //we may not be done...
  557. }
  558. else
  559. {
  560. // the selection being activated only contains support ships
  561. mouseCursorSelect.numShips = 0;
  562. tutGameMessage("Game_DoubleClickSpecial");
  563. sel.numShips = 1;
  564. sel.ShipPtr[0] = (Ship *)mouseCursorObjPtr;
  565. clWrapSpecial(&universe.mainCommandLayer, (SelectCommand *)&selSelected,(SpecialCommand *)&sel);
  566. return TRUE;
  567. }
  568. }
  569. bitClear(mouseCursorMode, MCM_DoubleClick);
  570. bitClear(mouseCursorMode, MCM_SingleClick);
  571. }
  572. if (bitTest(mouseInfo.flags, MCF_SpecialOp))
  573. {
  574. MakeShipsSpecialActivateCapable((SelectCommand *)&mouseCursorSelect);
  575. if (mouseCursorSelect.numShips > 0)
  576. {
  577. selSelectionCopy((MaxAnySelection *)&selSelected,
  578. (MaxAnySelection *)&mouseCursorSelect);
  579. ioUpdateShipTotals();
  580. mouseCursorSelect.numShips = 0;
  581. tutGameMessage("Game_DoubleClickSpecial");
  582. clWrapSpecial(&universe.mainCommandLayer, (SelectCommand *)&selSelected,NULL);
  583. return TRUE;
  584. }
  585. bitClear(mouseCursorMode, MCM_DoubleClick);
  586. bitClear(mouseCursorMode, MCM_SingleClick);
  587. }
  588. }
  589. // else if ((mouseCursorObjPtr != NULL) &&
  590. // (mouseCursorObjPtr->objtype != OBJ_ShipType))
  591. // {
  592. // if (mouseCursorSelect.numShips > 0)
  593. // {
  594. // selSelectionCopy((MaxAnySelection *)&selSelected,
  595. // (MaxAnySelection *)&mouseCursorSelect);
  596. // mouseCursorSelect.numShips = 0;
  597. // tutGameMessage("Game_DoubleClickHarvest");
  598. // clWrapCollectResource(&universe.mainCommandLayer, (SelectCommand *)&selSelected, (Resource*)mouseCursorObjPtr);
  599. // }
  600. // return TRUE;
  601. // }
  602. return FALSE;
  603. }
  604. /*-----------------------------------------------------------------------------
  605. Name : mouseDoubleClickCheck
  606. Description : Check to see if the double click time has expired and performs
  607. special tasks if it has
  608. Inputs : void
  609. Outputs : Very specific depending on the state of mouseInfo
  610. Return : TRUE if processing was done, FALSE if not
  611. ----------------------------------------------------------------------------*/
  612. bool mouseDoubleClickCheck(void)
  613. {
  614. if (mouseDoubleClickExpire == 0.0)
  615. {
  616. return FALSE;
  617. }
  618. if (mouseDoubleClickExpire < universe.totaltimeelapsed)
  619. {
  620. if (bitTest(mouseCursorMode, MCM_DoubleClick))
  621. {
  622. bitClear(mouseCursorMode, MCM_DoubleClick);
  623. bitClear(mouseCursorMode, MCM_SingleClick);
  624. mouseDoubleClickExpire = 0.0;
  625. if (mouseCursorObjPtr != NULL)
  626. {
  627. if (mouseCursorSelect.numShips > 0)
  628. {
  629. selSelectionCopy((MaxAnySelection *)&selSelected,
  630. (MaxAnySelection *)&mouseCursorSelect);
  631. mouseCursorSelect.numShips = 0;
  632. makeShipsDockCapable((SelectCommand *)&selSelected); //filter ships that can't dock
  633. clWrapDock(&universe.mainCommandLayer, (SelectCommand *)&selSelected,
  634. DOCK_AT_SPECIFIC_SHIP, (Ship *)mouseCursorObjPtr);
  635. mouseDrawType(small_docking); //may need to have "docking" as well
  636. }
  637. return TRUE;
  638. }
  639. }
  640. mouseCursorSelect.numShips = 0;
  641. mouseDoubleClickExpire = 0.0;
  642. bitClear(mouseCursorMode, MCM_SingleClick);
  643. }
  644. return FALSE;
  645. }
  646. /*-----------------------------------------------------------------------------
  647. Name : mouseLClick
  648. Description : Special processing a single click on the left mouse button
  649. Inputs : void
  650. Outputs : Very specific depending on the state of mouseInfo
  651. Return : void
  652. ----------------------------------------------------------------------------*/
  653. void mouseLClick(void)
  654. {
  655. //if a menu is up, don't do any of this
  656. if (feStackIndex > 0)
  657. {
  658. return;
  659. }
  660. if (!bitTest(mouseCursorMode, MCM_SingleClick))
  661. {
  662. if ((mouseCursorType == docking) ||
  663. (mouseCursorType == small_docking))
  664. {
  665. selSelectionCopy((MaxAnySelection *)&mouseCursorSelect, (MaxAnySelection *)&selSelected);
  666. bitSet(mouseCursorMode, MCM_SingleClick);
  667. mouseDoubleClickExpire = universe.totaltimeelapsed + mouseDoubleClickTime;
  668. }
  669. else if ((mouseCursorType == special_op_activate) ||
  670. (mouseCursorType == special_op_deactivate))
  671. {
  672. selSelectionCopy((MaxAnySelection *)&mouseCursorSelect, (MaxAnySelection *)&selSelected);
  673. mouseDoubleClickExpire = universe.totaltimeelapsed + mouseDoubleClickTime;
  674. }
  675. else if (mouseCursorType == support)
  676. {
  677. selSelectionCopy((MaxAnySelection *)&mouseCursorSelect, (MaxAnySelection *)&selSelected);
  678. mouseDoubleClickExpire = universe.totaltimeelapsed + mouseDoubleClickTime;
  679. }
  680. }
  681. }
  682. /*-----------------------------------------------------------------------------
  683. Name : mouseClickShipDied
  684. Description : Takes care of ships dying at inopportune times by clearing the
  685. ship from any file global selection lists or storage areas
  686. Inputs : deadship - the ship that has just died
  687. Outputs : removes the ship from mouseCursorSelect and the mouseCursorObjPtr
  688. Return : void
  689. ----------------------------------------------------------------------------*/
  690. void mouseClickShipDied(ShipPtr deadship)
  691. {
  692. clRemoveShipFromSelection(&mouseCursorSelect, deadship);
  693. if ((mouseCursorObjPtr != NULL) && (mouseCursorObjPtr == (SpaceObj *)deadship))
  694. {
  695. mouseCursorObjPtr = NULL;
  696. }
  697. if (mouseCursorObjLast == (SpaceObj *)deadship)
  698. {
  699. mouseCursorObjLast = NULL;
  700. }
  701. }
  702. /*-----------------------------------------------------------------------------
  703. Name : mouseDrawTriangle
  704. Description : Draws the mouse triangle on the screen
  705. Inputs : void
  706. Outputs : Draws the mouse triangle on the screen
  707. Return : void
  708. ----------------------------------------------------------------------------*/
  709. void mouseDrawTriangle(void)
  710. {
  711. triangle mouseTri, mouseTri2;
  712. mouseTri.x0 = mouseCursorXPosition + 0;
  713. mouseTri.y0 = mouseCursorYPosition + 0;
  714. mouseTri.x1 = mouseCursorXPosition + 4;
  715. mouseTri.y1 = mouseCursorYPosition + 16;
  716. mouseTri.x2 = mouseCursorXPosition + 14;
  717. mouseTri.y2 = mouseCursorYPosition + 7;
  718. mouseTri2 = mouseTri;
  719. mouseTri2.x2++;
  720. primTriSolid2(&mouseTri2, mouseCursorContentColor); //draw mouse cursor
  721. primTriOutline2(&mouseTri, 1, mouseCursorEdgeColor);
  722. }
  723. /*-----------------------------------------------------------------------------
  724. Name : mouseInfoReset
  725. Description : Resets the mouseInfo structure
  726. Inputs : void
  727. Outputs : Resets the mouseInfo structure
  728. Return : void
  729. ----------------------------------------------------------------------------*/
  730. void mouseInfoReset(void)
  731. {
  732. mouseInfo.ship_selected = 0;
  733. mouseInfo.resource = 0;
  734. mouseInfo.flags = 0;
  735. mouseInfo.cursorover = MC_NO_SHIP;
  736. }
  737. lifheader* mouseGetLIF(void)
  738. {
  739. switch (mouseCursorType)
  740. {
  741. case no_mouse:
  742. case rotate_camera:
  743. case zoom_camera:
  744. return NULL;
  745. case normal_mouse:
  746. case movement:
  747. return mouseNormalBitmap;
  748. case add_ships:
  749. return mouseAddShipsBitmap;
  750. case focus_no_select:
  751. return mouseFocusNoSelectBitmap;
  752. case band_box_attack:
  753. return mouseBandBoxAttackBitmap;
  754. case force_attack:
  755. return mouseForceAttackBitmap;
  756. case m_guard:
  757. return mouseGuardBitmap;
  758. case special_attack:
  759. return mouseSpecialAttackBitmap;
  760. case special_op_activate:
  761. return mouseSpecialOpActivateBitmap;
  762. case special_op_deactivate:
  763. return mouseSpecialOpDeactivateBitmap;
  764. case gui:
  765. return mouseGUIBitmap;
  766. case resource:
  767. return mouseResourceBitmap;
  768. case docking:
  769. case small_docking:
  770. return mouseDockingBitmap;
  771. case research:
  772. return mouseResearchBitmap;
  773. case sensors:
  774. return mouseSensorsBitmap;
  775. case build:
  776. return mouseBuildBitmap;
  777. case salvage:
  778. return mouseSalvageBitmap;
  779. case support:
  780. return mouseSupportBitmap;
  781. case traders:
  782. return mouseTradersBitmap;
  783. default:
  784. return NULL;
  785. }
  786. }
  787. GLubyte cursorUnderContents[4096];
  788. sdword lastUnderWidth = 0, lastUnderHeight = 0;
  789. static sdword lastUnderX = 0, lastUnderY = 0;
  790. void mouseRestoreCursorUnder(void)
  791. {
  792. if (!feShouldSaveMouseCursor())
  793. {
  794. return;
  795. }
  796. if (RGLtype == SWtype)
  797. {
  798. rglRestoreCursorUnder(cursorUnderContents,
  799. lastUnderWidth, lastUnderHeight,
  800. lastUnderX, lastUnderY);
  801. }
  802. #if GLC_STORE
  803. else
  804. {
  805. glcCursorUnder((ubyte*)cursorUnderContents,
  806. lastUnderWidth, lastUnderHeight,
  807. lastUnderX, lastUnderY,
  808. FALSE);
  809. }
  810. #endif
  811. }
  812. void mouseStoreCursorUnder(void)
  813. {
  814. lifheader* texture;
  815. if (!feShouldSaveMouseCursor())
  816. {
  817. return;
  818. }
  819. texture = mouseGetLIF();
  820. if (texture == NULL)
  821. {
  822. memset(cursorUnderContents, 0, 4096);
  823. }
  824. else
  825. {
  826. lastUnderWidth = texture->width + 2;
  827. lastUnderHeight = texture->height + 2;
  828. if (RGLtype == SWtype)
  829. {
  830. lastUnderX = mouseCursorXPosition - 1;
  831. lastUnderY = mouseCursorYPosition - 1;
  832. rglSaveCursorUnder(cursorUnderContents, lastUnderWidth, lastUnderHeight, lastUnderX, lastUnderY);
  833. }
  834. #if GLC_STORE
  835. else
  836. {
  837. lastUnderX = mouseCursorXPosition;
  838. lastUnderY = mouseCursorYPosition;
  839. glcCursorUnder((ubyte*)cursorUnderContents,
  840. lastUnderWidth, lastUnderHeight,
  841. lastUnderX, lastUnderY,
  842. TRUE);
  843. }
  844. #endif
  845. }
  846. }
  847. /*-----------------------------------------------------------------------------
  848. Name : mouseDraw
  849. Description : Update the position of the mouse by polling the system and
  850. draw it at it's new location.
  851. Inputs : void
  852. Outputs : updates mouse cursor position and button states to reflect
  853. new mouse status.
  854. Return : void
  855. Note : because this routine performs drawing operations, it should
  856. be called near the end rendering, before a buffer swap.
  857. Checks to see if the mouse is inside or outside the client area
  858. ----------------------------------------------------------------------------*/
  859. extern regionhandle spHyperspaceRollCallScreen;
  860. #define SX primScreenToGLX
  861. #define SY primScreenToGLY
  862. void mouseDraw(void)
  863. {
  864. bool primModeOn = TRUE;
  865. lifheader *texture = NULL;
  866. GLuint thandle = 0;
  867. bool textureMouse;
  868. static mouseCursor mousehold = normal_mouse;
  869. static real32 mouseholdexpire = 0.0;
  870. if (mouseWillBeVisible > 0)
  871. {
  872. mouseWillBeVisible--;
  873. if (!mouseWillBeVisible)
  874. mouseIsVisible = TRUE;
  875. }
  876. if ((!mouseIsVisible) || (mouseDisabled))
  877. {
  878. return; //don't draw mouse if not visible
  879. }
  880. // glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_LINE_BIT | GL_POINT_BIT | GL_POLYGON_BIT | GL_TEXTURE_BIT | GL_LIGHTING_BIT | GL_HINT_BIT | GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT);
  881. //rndGLStateLog("MouseDraw (start)");
  882. if (RGLtype == SWtype)
  883. {
  884. textureMouse = FALSE;
  885. }
  886. else
  887. {
  888. textureMouse = TRUE;//!glcActive();
  889. }
  890. if (textureMouse && !mouseGLInitialized)
  891. {
  892. mouseInitGL();
  893. mouseGLInitialized = TRUE;
  894. }
  895. //mousePoll();
  896. if (!primModeEnabled)
  897. {
  898. primModeOn = FALSE;
  899. primModeSetFunction2();
  900. }
  901. glEnable(GL_BLEND);
  902. rndAdditiveBlends(FALSE);
  903. rndTextureEnvironment(RTE_Modulate);
  904. if ((mousehold != normal_mouse) && (mouseCursorType == normal_mouse))
  905. {
  906. if (mouseholdexpire >= universe.totaltimeelapsed)
  907. {
  908. mouseCursorType = mousehold;
  909. }
  910. else //mousehold has expired
  911. {
  912. mousehold = normal_mouse;
  913. }
  914. }
  915. //if a front end screen is on (but not the hyperspace roll call screen)
  916. //all mouse settings are overridden
  917. //if the movement pieplate is on, all mouse settings except for
  918. // the focus_no_select setting is overridden
  919. if (((feStackIndex > 0) && (!spHyperspaceRollCallScreen)) ||
  920. ((bitTest(mouseCursorMode, MCM_Pointmode)) && (mouseCursorType != focus_no_select)))
  921. {
  922. mouseCursorType = normal_mouse;
  923. }
  924. switch (mouseCursorType)
  925. {
  926. case no_mouse:
  927. case rotate_camera:
  928. case zoom_camera:
  929. //temporary solution
  930. goto finish;
  931. //do nothing
  932. break;
  933. case normal_mouse:
  934. case movement:
  935. texture = mouseNormalBitmap;
  936. thandle = tex_Normal;
  937. break;
  938. case add_ships:
  939. texture = mouseAddShipsBitmap;
  940. thandle = tex_AddShips;
  941. break;
  942. case focus_no_select:
  943. texture = mouseFocusNoSelectBitmap;
  944. thandle = tex_FocusNoSelect;
  945. break;
  946. case band_box_attack:
  947. texture = mouseBandBoxAttackBitmap;
  948. thandle = tex_BandBoxAttack;
  949. break;
  950. case force_attack:
  951. texture = mouseForceAttackBitmap;
  952. thandle = tex_ForceAttack;
  953. break;
  954. case m_guard:
  955. texture = mouseGuardBitmap;
  956. thandle = tex_Guard;
  957. break;
  958. case special_attack:
  959. if (mousehold == normal_mouse)
  960. {
  961. mousehold = special_attack;
  962. mouseholdexpire = universe.totaltimeelapsed + (real32)MC_MOUSEHOLDTIME;
  963. }
  964. texture = mouseSpecialAttackBitmap;
  965. thandle = tex_SpecialAttack;
  966. break;
  967. case special_op_activate:
  968. texture = mouseSpecialOpActivateBitmap;
  969. thandle = tex_SpecialOpActivate;
  970. break;
  971. case special_op_deactivate:
  972. texture = mouseSpecialOpDeactivateBitmap;
  973. thandle = tex_SpecialOpDeactivate;
  974. break;
  975. case gui:
  976. texture = mouseGUIBitmap;
  977. thandle = tex_GUI;
  978. break;
  979. case resource:
  980. texture = mouseResourceBitmap;
  981. thandle = tex_Resource;
  982. break;
  983. case docking:
  984. case small_docking:
  985. texture = mouseDockingBitmap;
  986. thandle = tex_Docking;
  987. break;
  988. case research:
  989. texture = mouseResearchBitmap;
  990. thandle = tex_Research;
  991. break;
  992. case sensors:
  993. texture = mouseSensorsBitmap;
  994. thandle = tex_Sensors;
  995. break;
  996. case build:
  997. texture = mouseBuildBitmap;
  998. thandle = tex_Build;
  999. break;
  1000. case salvage:
  1001. texture = mouseSalvageBitmap;
  1002. thandle = tex_Salvage;
  1003. break;
  1004. case support:
  1005. texture = mouseSupportBitmap;
  1006. thandle = tex_Support;
  1007. break;
  1008. case traders:
  1009. texture = mouseTradersBitmap;
  1010. thandle = tex_Traders;
  1011. break;
  1012. default:
  1013. break;
  1014. }
  1015. if (texture != NULL)
  1016. {
  1017. if (textureMouse)
  1018. {
  1019. bool texOn;
  1020. trClearCurrent();
  1021. texOn = rndTextureEnable(TRUE);
  1022. glBindTexture(GL_TEXTURE_2D, thandle);
  1023. glColor3ub(255,255,255);
  1024. glBegin(GL_QUADS);
  1025. glTexCoord2f(0.0f, 0.0f);
  1026. glVertex2f(SX(mouseCursorXPosition), SY(mouseCursorYPosition));
  1027. glTexCoord2f(0.0f, 1.0f);
  1028. glVertex2f(SX(mouseCursorXPosition), SY(mouseCursorYPosition + texture->height));
  1029. glTexCoord2f(1.0f, 1.0f);
  1030. glVertex2f(SX(mouseCursorXPosition + texture->width), SY(mouseCursorYPosition + texture->height));
  1031. glTexCoord2f(1.0f, 0.0f);
  1032. glVertex2f(SX(mouseCursorXPosition + texture->width), SY(mouseCursorYPosition));
  1033. glEnd();
  1034. rndTextureEnable(texOn);
  1035. }
  1036. else
  1037. {
  1038. glRasterPos2f(primScreenToGLX(mouseCursorXPosition),
  1039. primScreenToGLY(mouseCursorYPosition + texture->height));
  1040. glDrawPixels(texture->width, texture->height, GL_RGBA, GL_UNSIGNED_BYTE, texture->data);
  1041. }
  1042. }
  1043. else
  1044. {
  1045. mouseDrawTriangle();
  1046. }
  1047. finish:
  1048. glDisable(GL_BLEND);
  1049. if (!primModeOn)
  1050. {
  1051. primModeClearFunction2();
  1052. }
  1053. mouseCursorOverDistance = REALlyBig;
  1054. mouseCursorOverShipType = MC_NO_SHIP;
  1055. if (bitTest(mouseCursorMode, MCM_CursorOverObj))
  1056. {
  1057. bitClear(mouseCursorMode, MCM_CursorOverObj);
  1058. }
  1059. else
  1060. {
  1061. mouseCursorObjPtr = NULL;
  1062. }
  1063. if (mouseCursorObjPtr != NULL)
  1064. { //if the mouse is over an object
  1065. mouseCursorObjLast = mouseCursorObjPtr; //remember where and when it was
  1066. mouseCursorLastObjTime = universe.totaltimeelapsed;
  1067. mouseCursorLastX = mouseCursorX();
  1068. mouseCursorLastY = mouseCursorY();
  1069. }
  1070. //rndGLStateLog("MouseDraw (end)");
  1071. // glPopAttrib();
  1072. }
  1073. #undef SX
  1074. #undef SY
  1075. char *tutMouseDrawMessage[] =
  1076. { "Mouse_NormalMouse",
  1077. "Mouse_RotateCamera",
  1078. "Mouse_ZoomCamera",
  1079. "Mouse_AddShips",
  1080. "Mouse_FocusNoSelect",
  1081. "Mouse_Movement",
  1082. "Mouse_BandBoxAttack",
  1083. "Mouse_ForceAttack",
  1084. "Mouse_Guard",
  1085. "Mouse_SpecialAttack",
  1086. "Mouse_SpecialOpActivate",
  1087. "Mouse_SpecialOpDeactivate",
  1088. "Mouse_Gui",
  1089. "Mouse_Resource",
  1090. "Mouse_Derelict",
  1091. "Mouse_Docking",
  1092. "Mouse_SmallDocking",
  1093. "Mouse_Research",
  1094. "Mouse_Sensors",
  1095. "Mouse_Build",
  1096. "Mouse_Salvage",
  1097. "Mouse_Support",
  1098. "Mouse_Traders",
  1099. "Mouse_EnemyShip",
  1100. "Mouse_AlliedShip",
  1101. };
  1102. /*-----------------------------------------------------------------------------
  1103. Name : mouseDrawType
  1104. Description : Sets the type of mouse cursor to be drawn
  1105. Inputs : cursorType - the type of cursor to draw
  1106. Outputs : Changes the global mouse cursor type variable
  1107. Return : void
  1108. ----------------------------------------------------------------------------*/
  1109. void mouseDrawType(mouseCursor cursorType)
  1110. {
  1111. //mouse messages only happen in the actual tutorial because
  1112. //the overflow the message queue in the single player game
  1113. if((tutorial==TUTORIAL_ONLY) && cursorType != mouseCursorType)
  1114. tutGameMessage( tutMouseDrawMessage[(long)cursorType] );
  1115. mouseCursorType = cursorType;
  1116. }
  1117. /*-----------------------------------------------------------------------------
  1118. Name : mouseCursorSet
  1119. Description : sets the cursor mode for special case cursor settings
  1120. Inputs : mode - the mode to set cursormode to
  1121. Outputs : changes the cursormode flag
  1122. Return : void
  1123. ----------------------------------------------------------------------------*/
  1124. void mouseCursorSet(udword mode)
  1125. {
  1126. bitSet(mouseCursorMode, mode);
  1127. }
  1128. /*-----------------------------------------------------------------------------
  1129. Name : mouseCursorClear
  1130. Description : Clears the cursor mode for special case cursor settings
  1131. Inputs : mode - the mode to clear
  1132. Outputs : changes the cursormode flag
  1133. Return : void
  1134. ----------------------------------------------------------------------------*/
  1135. void mouseCursorClear(udword mode)
  1136. {
  1137. bitClear(mouseCursorMode, mode);
  1138. }
  1139. /*-----------------------------------------------------------------------------
  1140. Name : mouseSelectCursorSetting
  1141. Description : Gathers information about the selected ships, and
  1142. ships under the mouse cursor
  1143. I agree this function is ugly, but you have to consider
  1144. that any number of ships can be selected at one time,
  1145. and the mouse can be over any of those ships, or any
  1146. other ships. This function has to take care of all of
  1147. that. Poor function... overworked, underpaid, ugly,
  1148. unappreciated, just not having a good life.
  1149. Be kind to it...
  1150. Inputs :
  1151. Outputs :
  1152. Return :
  1153. ----------------------------------------------------------------------------*/
  1154. void mouseSelectCursorSetting(void)
  1155. {
  1156. sdword i;
  1157. mouseInfoReset();
  1158. //if there are ships selected
  1159. if (selSelected.numShips)
  1160. {
  1161. Ship *ship;
  1162. mouseInfo.ship_selected = selSelected.numShips;
  1163. //go through the selected list
  1164. for (i = 0; i < selSelected.numShips; i++)
  1165. {
  1166. ship = selSelected.ShipPtr[i];
  1167. //count the number of resource collectors selected
  1168. if (ship->shiptype == ResourceCollector)
  1169. {
  1170. ++mouseInfo.resource;
  1171. bitSet(mouseInfo.flags, MCF_Dockable);
  1172. }
  1173. if (ship->staticinfo->canSingleClickSpecialActivate)
  1174. {
  1175. bitSet(mouseInfo.flags, MCF_SingleClickSpecialActivate);
  1176. }
  1177. //-- Set flags for selected ships under the cursor --//
  1178. //if the cursor is over a selected ship
  1179. if ((mouseCursorObjPtr != NULL) &&
  1180. ((Ship *)mouseCursorObjPtr == selSelected.ShipPtr[i]))
  1181. {
  1182. //set flags for all GUI or special op ships
  1183. switch (ship->shiptype)
  1184. {
  1185. case Carrier:
  1186. case Mothership:
  1187. bitSet(mouseInfo.flags, MCF_GUICapable);
  1188. bitSet(mouseInfo.flags, MCF_BuildGUI);
  1189. break;
  1190. case ResearchShip:
  1191. bitSet(mouseInfo.flags, MCF_GUICapable);
  1192. bitSet(mouseInfo.flags, MCF_ResearchGUI);
  1193. break;
  1194. case SensorArray:
  1195. bitSet(mouseInfo.flags, MCF_GUICapable);
  1196. bitSet(mouseInfo.flags, MCF_SensorsGUI);
  1197. break;
  1198. case CloakGenerator:
  1199. case CloakedFighter:
  1200. if (bitTest(ship->flags, SOF_Cloaked))
  1201. {
  1202. bitSet(mouseInfo.flags, MCF_SpecialOpDeployed);
  1203. }
  1204. bitSet(mouseInfo.flags, MCF_SpecialOp);
  1205. break;
  1206. case DDDFrigate:
  1207. if (((DDDFrigateSpec *)ship->ShipSpecifics)->DDDstate == 3) //DDDSTATE_ALLOUTSIDE
  1208. {
  1209. bitSet(mouseInfo.flags, MCF_SpecialOpDeployed);
  1210. }
  1211. bitSet(mouseInfo.flags, MCF_SpecialOp);
  1212. break;
  1213. case GravWellGenerator:
  1214. if (((GravWellGeneratorSpec *)ship->ShipSpecifics)->GravFieldOn == TRUE)
  1215. {
  1216. bitSet(mouseInfo.flags, MCF_SpecialOpDeployed);
  1217. }
  1218. bitSet(mouseInfo.flags, MCF_SpecialOp);
  1219. break;
  1220. case MinelayerCorvette:
  1221. bitSet(mouseInfo.flags, MCF_SpecialOp);
  1222. break;
  1223. case AdvanceSupportFrigate:
  1224. case RepairCorvette:
  1225. //we don't want the dock cursor to show up when
  1226. //the mouse is over a selected repair corvette
  1227. bitSet(mouseInfo.flags, MCF_SupportOverItself);
  1228. break;
  1229. }
  1230. }
  1231. // -- Set flags for ships that are selected but not under the cursor -- //
  1232. //set flags for dockable ships
  1233. if ((ship->staticinfo->shipclass == CLASS_Corvette) ||
  1234. (ship->staticinfo->shipclass == CLASS_Fighter))
  1235. {
  1236. if (ship->shiptype != RepairCorvette)
  1237. {
  1238. bitSet(mouseInfo.flags, MCF_SmallDockable);
  1239. }
  1240. else
  1241. {
  1242. bitSet(mouseInfo.flags, MCF_Dockable);
  1243. }
  1244. }
  1245. else if ((ship->staticinfo->shipclass == CLASS_Resource) ||
  1246. (ship->staticinfo->shipclass == CLASS_NonCombat))
  1247. {
  1248. bitSet(mouseInfo.flags, MCF_NonCombat);
  1249. }
  1250. //set flags for special attack/support ships
  1251. switch (ship->shiptype)
  1252. {
  1253. case MissileDestroyer:
  1254. case HeavyCorvette:
  1255. bitSet(mouseInfo.flags, MCF_SpecialAttack);
  1256. break;
  1257. case Carrier:
  1258. bitSet(mouseInfo.flags, MCF_SpecialSCSupport);
  1259. break;
  1260. case AdvanceSupportFrigate:
  1261. case RepairCorvette:
  1262. bitSet(mouseInfo.flags, MCF_SpecialSupport);
  1263. break;
  1264. case SalCapCorvette:
  1265. bitSet(mouseInfo.flags, MCF_Salvage);
  1266. //if this is the first ship in the list
  1267. if (i==0)
  1268. {
  1269. bitSet(mouseInfo.flags, MCF_SalvageOnly);
  1270. }
  1271. break;
  1272. }
  1273. //the special salvage cursor bitmap is displayed
  1274. //instead of the attack bitmap if selselected only contains
  1275. //salvage capture corvettes... checking for this here
  1276. if (i>0 && bitTest(mouseInfo.flags, MCF_SalvageOnly))
  1277. {
  1278. if (ship->shiptype != SalCapCorvette)
  1279. {
  1280. bitClear(mouseInfo.flags, MCF_SalvageOnly);
  1281. }
  1282. }
  1283. }
  1284. //if there isn't anything under the cursor, then the rest of this
  1285. //function isn't needed
  1286. if (mouseCursorOverShipType == MC_NO_SHIP)
  1287. {
  1288. return;
  1289. }
  1290. //set cursorover variable depending on the ship under cursor and
  1291. //the value of certain flags.
  1292. switch (mouseCursorOverShipType)
  1293. {
  1294. case Carrier:
  1295. case Mothership:
  1296. if (bitTest(mouseInfo.flags, MCF_Dockable) ||
  1297. bitTest(mouseInfo.flags, MCF_SmallDockable))
  1298. {
  1299. mouseInfo.cursorover = docking;
  1300. }
  1301. else
  1302. {
  1303. mouseInfo.cursorover = build;
  1304. }
  1305. break;
  1306. case ResearchShip:
  1307. mouseInfo.cursorover = research;
  1308. break;
  1309. case SensorArray:
  1310. mouseInfo.cursorover = sensors;
  1311. break;
  1312. case ResourceController:
  1313. mouseInfo.cursorover = docking;
  1314. break;
  1315. case CloakGenerator:
  1316. case CloakedFighter:
  1317. case DDDFrigate:
  1318. case GravWellGenerator:
  1319. case MinelayerCorvette:
  1320. mouseInfo.cursorover = special_op_activate;
  1321. break;
  1322. //drone is not considered as a ship in this case
  1323. case Drone:
  1324. mouseInfo.cursorover = MC_NO_SHIP;
  1325. break;
  1326. case RepairCorvette:
  1327. case ResourceCollector:
  1328. case AdvanceSupportFrigate:
  1329. case JunkYardHQ:
  1330. mouseInfo.cursorover = small_docking;
  1331. break;
  1332. case CryoTray:
  1333. if ((singlePlayerGameInfo.currentMission != 1) &&
  1334. (bitTest(mouseInfo.flags, MCF_SalvageOnly)))
  1335. {
  1336. mouseInfo.cursorover = salvage;
  1337. }
  1338. break;
  1339. case FloatingCity:
  1340. mouseInfo.cursorover = traders;
  1341. break;
  1342. case MC_DERELICT:
  1343. if ((mouseCursorObjPtr) && (((Derelict *)mouseCursorObjPtr)->derelicttype == HyperspaceGate))
  1344. mouseInfo.cursorover = enemy_ship;
  1345. else
  1346. mouseInfo.cursorover = derelict;
  1347. break;
  1348. case MC_RESOURCE:
  1349. mouseInfo.cursorover = resource;
  1350. if (mouseCursorObjPtr && (mouseCursorObjPtr->attributes & (ATTRIBUTES_KillerCollDamage|ATTRIBUTES_HeadShotKillerCollDamage)))
  1351. {
  1352. if (mouseInfo.resource == 0)
  1353. {
  1354. mouseInfo.cursorover = enemy_ship;
  1355. }
  1356. else
  1357. {
  1358. //resouce collectors can't resource killer asteroids
  1359. mouseInfo.cursorover = MC_NO_SHIP;
  1360. }
  1361. }
  1362. break;
  1363. case Ghostship:
  1364. case MC_ENEMY_SHIP:
  1365. mouseInfo.cursorover = enemy_ship;
  1366. break;
  1367. case MC_ALLIED_SHIP:
  1368. mouseInfo.cursorover = allied_ship;
  1369. break;
  1370. default:
  1371. if (mouseCursorObjPtr &&
  1372. ((ShipPtr)mouseCursorObjPtr)->playerowner == selSelected.ShipPtr[0]->playerowner)
  1373. {
  1374. mouseInfo.cursorover = own_ship;
  1375. }
  1376. }
  1377. //if a support ship is selected, and the mouse is over
  1378. //a ship the support ship is capable of supporting, change
  1379. //the mouse cursor
  1380. if (mouseCursorObjPtr &&
  1381. (bitTest(mouseInfo.flags, MCF_SpecialSCSupport) &&
  1382. (isShipOfClass(mouseCursorObjPtr, CLASS_Fighter) ||
  1383. isShipOfClass(mouseCursorObjPtr, CLASS_Corvette))))
  1384. {
  1385. mouseInfo.cursorover = support;
  1386. }
  1387. }
  1388. //if there are ships being selected
  1389. else if (selSelecting.numTargets)
  1390. {
  1391. bitSet(mouseInfo.flags, MCF_ShipSelecting);
  1392. }
  1393. else
  1394. {
  1395. if ((mouseCursorOverShipType == FloatingCity) ||
  1396. ((mouseCursorOverShipType == MC_ALLIED_SHIP) &&
  1397. (mouseCursorEnemyType == FloatingCity)))
  1398. {
  1399. mouseInfo.cursorover = traders;
  1400. }
  1401. }
  1402. }
  1403. /*-----------------------------------------------------------------------------
  1404. Name : mouseKeyCursorSetting
  1405. Description : Sets the mouse cursor depending on key states and how the
  1406. mouseInfo structure is set.
  1407. Inputs : voidorama (uses globals)
  1408. Outputs : Calls mouseDrawType to change the mouse Draw type
  1409. Return : nothing
  1410. ----------------------------------------------------------------------------*/
  1411. void mouseSetCursorSetting(void)
  1412. {
  1413. if (!gameIsRunning)
  1414. {
  1415. return;
  1416. }
  1417. mouseDrawType(normal_mouse);
  1418. //check if a double click task needs to be performed
  1419. //mouse draw type will be set accordingly by this process
  1420. if (mouseDoubleClickCheck())
  1421. {
  1422. return;
  1423. }
  1424. // if the player is disabled, only a few cursor bitmaps are shown
  1425. if (mrDisabled)
  1426. {
  1427. if (keyIsHit(ALTKEY))
  1428. {
  1429. mouseDrawType(focus_no_select);
  1430. return;
  1431. }
  1432. return;
  1433. }
  1434. if (!bitTest(mouseInfo.flags, MCF_DisableAll))
  1435. {
  1436. if (mouseInfo.ship_selected)
  1437. {
  1438. //forced attack
  1439. if (keyIsHit(SHIFTKEY) && keyIsHit(CONTROLKEY))
  1440. {
  1441. mouseDrawType(force_attack);
  1442. return;
  1443. }
  1444. //select multiple ships using the shift key
  1445. if (keyIsHit(SHIFTKEY))
  1446. {
  1447. mouseDrawType(add_ships);
  1448. return;
  1449. }
  1450. //guard ships
  1451. if ((keyIsHit(CONTROLKEY) && keyIsHit(ALTKEY)) || keyIsHit(GKEY))
  1452. {
  1453. mouseDrawType(m_guard);
  1454. return;
  1455. }
  1456. //activate/deactivate special attack
  1457. if (kbCommandKeyIsHit(kbSHIP_SPECIAL))
  1458. {
  1459. if (bitTest(mouseInfo.flags, MCF_SpecialAttack))
  1460. {
  1461. mouseDrawType(special_attack);
  1462. return;
  1463. }
  1464. else if (bitTest(mouseInfo.flags, MCF_SpecialSupport))
  1465. {
  1466. mouseDrawType(support);
  1467. return;
  1468. }
  1469. else if (bitTest(mouseInfo.flags, MCF_Salvage))
  1470. {
  1471. mouseDrawType(salvage);
  1472. return;
  1473. }
  1474. }
  1475. //forced focus
  1476. if (keyIsHit(ALTKEY))
  1477. {
  1478. mouseDrawType(focus_no_select);
  1479. return;
  1480. }
  1481. //attack
  1482. if (keyIsHit(CONTROLKEY))
  1483. {
  1484. if (mouseInfo.ship_selected != mouseInfo.resource)
  1485. {
  1486. mouseDrawType(band_box_attack);
  1487. }
  1488. return;
  1489. }
  1490. //speed things up - if cursorover isn't a special
  1491. //case, don't bother going through all these if statements
  1492. if (mouseInfo.cursorover == MC_NO_SHIP)
  1493. {
  1494. return;
  1495. }
  1496. // if the mouse is over the traders
  1497. if (mouseInfo.cursorover == traders)
  1498. {
  1499. mouseDrawType(traders);
  1500. }
  1501. //if a dockable ship is selected and the mouse cursor is over
  1502. //a ship capable of accepting dockable ships
  1503. else if ((bitTest(mouseInfo.flags, MCF_Dockable)) &&
  1504. (mouseInfo.cursorover == docking))
  1505. {
  1506. mouseDrawType(docking);
  1507. }
  1508. //same as above, but with small dockable ships (fighters & corvettes)
  1509. else if ((bitTest(mouseInfo.flags, MCF_SmallDockable)) &&
  1510. (!bitTest(mouseInfo.flags, MCF_SupportOverItself)) &&
  1511. ((mouseInfo.cursorover == docking) || (mouseInfo.cursorover == small_docking)))
  1512. {
  1513. mouseDrawType(small_docking);
  1514. }
  1515. // if a support capable ship is selected and the mouse is over a ship
  1516. else if (((mouseInfo.cursorover != enemy_ship) &&
  1517. (mouseInfo.cursorover != allied_ship) &&
  1518. (mouseInfo.cursorover != resource) &&
  1519. (mouseInfo.cursorover != derelict) &&
  1520. (mouseInfo.cursorover != traders)) &&
  1521. ((mouseInfo.cursorover == support) ||
  1522. (bitTest(mouseInfo.flags, MCF_SpecialSupport) &&
  1523. !bitTest(mouseInfo.flags, MCF_SupportOverItself))))
  1524. {
  1525. mouseDrawType(support);
  1526. }
  1527. //if the mouse is over a selected ship with a special operation and that
  1528. //special operation has already been deployed
  1529. else if ((bitTest(mouseInfo.flags, MCF_SpecialOpDeployed)) &&
  1530. (mouseInfo.cursorover == special_op_activate))
  1531. {
  1532. mouseDrawType(special_op_deactivate);
  1533. }
  1534. //if the mouse is over a selected ship with a special operation and that
  1535. //special operation has no been deployed
  1536. else if ((bitTest(mouseInfo.flags, MCF_SpecialOp)) &&
  1537. (mouseInfo.cursorover == special_op_activate))
  1538. {
  1539. mouseDrawType(special_op_activate);
  1540. }
  1541. //if the mouse is over a selected ship that has a GUI associated with it
  1542. else if ((bitTest(mouseInfo.flags, MCF_GUICapable)) &&
  1543. (mouseInfo.cursorover == gui))
  1544. {
  1545. mouseDrawType(gui);
  1546. }
  1547. //if the mouse is over a selected build capable ship
  1548. else if ((bitTest(mouseInfo.flags, MCF_BuildGUI)) &&
  1549. (mouseInfo.cursorover == build))
  1550. {
  1551. mouseDrawType(build);
  1552. }
  1553. //if the mouse is over a selected research ship
  1554. else if ((bitTest(mouseInfo.flags, MCF_ResearchGUI)) &&
  1555. (mouseInfo.cursorover == research))
  1556. {
  1557. mouseDrawType(research);
  1558. }
  1559. //if the mouse is over a selected sensors array
  1560. else if ((bitTest(mouseInfo.flags, MCF_SensorsGUI)) &&
  1561. (mouseInfo.cursorover == sensors))
  1562. {
  1563. mouseDrawType(sensors);
  1564. }
  1565. //if a resource ship is selected and the mouse is over a resource
  1566. else if ((mouseInfo.resource) && (mouseInfo.cursorover == resource))
  1567. {
  1568. mouseDrawType(resource);
  1569. }
  1570. //if only salvage corvettes are selected and the mouse is over an enemy ship
  1571. else if (bitTest(mouseInfo.flags, MCF_SalvageOnly) &&
  1572. ((mouseInfo.cursorover == enemy_ship) ||
  1573. (mouseInfo.cursorover == salvage)))
  1574. {
  1575. mouseDrawType(salvage);
  1576. }
  1577. //if a combat ship is selected and the mouse is over an enemy ship
  1578. else if (!(bitTest(mouseInfo.flags, MCF_NonCombat)) &&
  1579. (mouseInfo.cursorover == enemy_ship))
  1580. {
  1581. mouseDrawType(band_box_attack);
  1582. }
  1583. // else if (mouseInfo.cursorover == allied_ship)
  1584. // {
  1585. // mouseDrawType(gui);
  1586. // }
  1587. //if a singleclickspecialactivate ship is selected and the mouse is over a derelict
  1588. else if (bitTest(mouseInfo.flags, MCF_SingleClickSpecialActivate) &&
  1589. (mouseInfo.cursorover == derelict))
  1590. {
  1591. mouseDrawType(salvage);
  1592. }
  1593. }
  1594. //if ships are being selected
  1595. else if (bitTest(mouseInfo.flags, MCF_ShipSelecting) && keyIsHit(SHIFTKEY))
  1596. {
  1597. mouseDrawType(add_ships);
  1598. }
  1599. else
  1600. {
  1601. //forced focus
  1602. if (keyIsHit(ALTKEY))
  1603. {
  1604. mouseDrawType(focus_no_select);
  1605. }
  1606. //if the mouse is over the trader ship
  1607. else if (mouseInfo.cursorover == traders)
  1608. {
  1609. mouseDrawType(traders);
  1610. }
  1611. }
  1612. }
  1613. }
  1614. /*-----------------------------------------------------------------------------
  1615. Cursor Text Code
  1616. ----------------------------------------------------------------------------*/
  1617. /*-----------------------------------------------------------------------------
  1618. Name : mouseCursorTextDraw
  1619. Description : Draws the name of the ship type associated with mouseCursorOverShipType
  1620. Inputs : void
  1621. Outputs : Screen text roughly resembling the name of the ship type
  1622. Return :
  1623. ----------------------------------------------------------------------------*/
  1624. void mouseCursorTextDraw(void)
  1625. {
  1626. static sdword cursortexttype = MC_NO_SHIP;
  1627. fonthandle fhSave;
  1628. if ((!mrRenderMainScreen) || (!gameIsRunning) || (mrWhiteOut) || (nisIsRunning) || (keyIsHit(RMOUSE_BUTTON)))
  1629. {
  1630. return;
  1631. }
  1632. // if there's something in that cool global variable
  1633. if ((mouseCursorOverShipType != MC_NO_SHIP) && (mouseCursorOverShipType != MC_RESOURCE) && (mouseCursorOverShipType != MC_DERELICT))
  1634. {
  1635. cursortexttype = mouseCursorOverShipType;
  1636. }
  1637. else
  1638. {
  1639. if (mouseCursorTextExpire < universe.totaltimeelapsed)
  1640. {
  1641. cursortexttype = MC_NO_SHIP;
  1642. }
  1643. }
  1644. if (cursortexttype != MC_NO_SHIP)
  1645. {
  1646. // display that baby!
  1647. fhSave = fontMakeCurrent(mouseCursorFont);
  1648. if (cursortexttype == MC_ENEMY_SHIP)
  1649. {
  1650. if (mouseCursorOverLODs & MOUSE_IdentifyLODMask)
  1651. { //if it's been seen closely
  1652. if (!singlePlayerGame)
  1653. {
  1654. fontPrintf(TW_CURSORTEXT_X, MAIN_WindowHeight - TW_CURSORTEXT_Y, TW_CURSORTEXT_COLOR, "%s's %s",
  1655. playerNames[mouseCursorEnemyPlayer], ShipTypeToNiceStr(mouseCursorEnemyType));
  1656. }
  1657. else
  1658. {
  1659. fontPrintf(TW_CURSORTEXT_X, MAIN_WindowHeight - TW_CURSORTEXT_Y, TW_CURSORTEXT_COLOR,
  1660. ShipTypeToNiceStr(mouseCursorEnemyType));
  1661. }
  1662. }
  1663. else
  1664. {
  1665. fontPrint(TW_CURSORTEXT_X, MAIN_WindowHeight - TW_CURSORTEXT_Y, TW_CURSORTEXT_COLOR,
  1666. strGetString(strEnemyShip));
  1667. }
  1668. }
  1669. else if (cursortexttype == MC_ALLIED_SHIP)
  1670. {
  1671. if (!singlePlayerGame)
  1672. {
  1673. fontPrintf(TW_CURSORTEXT_X, MAIN_WindowHeight - TW_CURSORTEXT_Y, TW_CURSORTEXT_COLOR, "%s's %s",
  1674. playerNames[mouseCursorEnemyPlayer], ShipTypeToNiceStr(mouseCursorEnemyType));
  1675. }
  1676. else
  1677. {
  1678. // allied ships in the single player game (defector and traders) only
  1679. // display their shiptypes and not the player name
  1680. fontPrint(TW_CURSORTEXT_X, MAIN_WindowHeight - TW_CURSORTEXT_Y, TW_CURSORTEXT_COLOR,
  1681. ShipTypeToNiceStr(mouseCursorEnemyType));
  1682. }
  1683. }
  1684. else
  1685. {
  1686. fontPrint(TW_CURSORTEXT_X, MAIN_WindowHeight - TW_CURSORTEXT_Y, TW_CURSORTEXT_COLOR,
  1687. ShipTypeToNiceStr(cursortexttype));
  1688. }
  1689. fontMakeCurrent(fhSave);
  1690. }
  1691. }
  1692. /*-----------------------------------------------------------------------------
  1693. Name : mouseClipPointToRect
  1694. Description : Clip an x/y coordinate to a rectangle.
  1695. Inputs : x, y - position to clip
  1696. rect - rectangle to clip to
  1697. Outputs : clips x, y to rect
  1698. Return :
  1699. ----------------------------------------------------------------------------*/
  1700. void mouseClipPointToRect(sdword *x, sdword *y, rectangle *rect)
  1701. {
  1702. if (*x < rect->x0)
  1703. {
  1704. *x = rect->x0;
  1705. }
  1706. if (*x >= rect->x1)
  1707. {
  1708. *x = rect->x1 - 1;
  1709. }
  1710. if (*y < rect->y0)
  1711. {
  1712. *y = rect->y0;
  1713. }
  1714. if (*y >= rect->y1)
  1715. {
  1716. *y = rect->y1 - 1;
  1717. }
  1718. }
  1719. /*=============================================================================
  1720. Name : mousePoll
  1721. Purpose : Poll current mouse location and store internally
  1722. Created 7/7/1997 by lmoloney
  1723. Copyright Relic Entertainment, Inc. All rights reserved.
  1724. =============================================================================*/
  1725. void mousePoll(void)
  1726. {
  1727. rectangle clientRect;
  1728. POINT mousePoint;
  1729. if (mouseDisabled)
  1730. {
  1731. return;
  1732. }
  1733. if (demDemoPlaying)
  1734. {
  1735. return;
  1736. }
  1737. utyClientRectGet(&clientRect); //get window location
  1738. GetCursorPos(&mousePoint); //get location of Windows mouse cursor
  1739. mouseCursorXPosition = mousePoint.x - clientRect.x0; //compute relative coords
  1740. mouseCursorYPosition = mousePoint.y - clientRect.y0;
  1741. if (mouseClip)
  1742. {
  1743. mouseClipPointToRect(&mouseCursorXPosition, &mouseCursorYPosition, &mouseClipRect);
  1744. mousePositionSet(mouseCursorXPosition, mouseCursorYPosition);
  1745. }
  1746. //perform client area enter/exit logic to hide/show Windows system cursor
  1747. if (primPointInRectXY2(&clientRect, mousePoint.x, mousePoint.y))
  1748. { //mouse inside window's client area
  1749. if (!mouseInsideClient)
  1750. { //just entered region
  1751. ShowCursor(FALSE);
  1752. mouseInsideClient = TRUE;
  1753. }
  1754. }
  1755. else
  1756. { //else outside region
  1757. if (mouseInsideClient)
  1758. { //just exited region
  1759. ShowCursor(TRUE);
  1760. mouseInsideClient = FALSE;
  1761. }
  1762. }
  1763. }
  1764. /*-----------------------------------------------------------------------------
  1765. Name : mouseDisable/mouseEnable
  1766. Description : Disable and re-enable the mouse
  1767. Inputs : void
  1768. Outputs :
  1769. Return : void
  1770. ----------------------------------------------------------------------------*/
  1771. void mouseDisable(void)
  1772. {
  1773. mouseCursorHide();
  1774. mouseDisabled = TRUE;
  1775. }
  1776. void mouseEnable(void)
  1777. {
  1778. mouseCursorShow();
  1779. mouseDisabled = FALSE;
  1780. }