CCursorHandler.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * CCursorHandler.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "CCursorHandler.h"
  12. #include <SDL.h>
  13. #include "SDL_Extensions.h"
  14. #include "CGuiHandler.h"
  15. #include "../widgets/Images.h"
  16. #include "../CMT.h"
  17. void CCursorHandler::initCursor()
  18. {
  19. xpos = ypos = 0;
  20. type = ECursor::DEFAULT;
  21. dndObject = nullptr;
  22. cursors =
  23. {
  24. make_unique<CAnimImage>("CRADVNTR", 0),
  25. make_unique<CAnimImage>("CRCOMBAT", 0),
  26. make_unique<CAnimImage>("CRDEFLT", 0),
  27. make_unique<CAnimImage>("CRSPELL", 0)
  28. };
  29. currentCursor = cursors.at(int(ECursor::DEFAULT)).get();
  30. help = CSDL_Ext::newSurface(40,40);
  31. //No blending. Ensure, that we are copying pixels during "screen restore draw"
  32. SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
  33. SDL_ShowCursor(SDL_DISABLE);
  34. changeGraphic(ECursor::ADVENTURE, 0);
  35. }
  36. void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index)
  37. {
  38. if(type != this->type)
  39. {
  40. this->type = type;
  41. this->frame = index;
  42. currentCursor = cursors.at(int(type)).get();
  43. currentCursor->setFrame(index);
  44. }
  45. else if(index != this->frame)
  46. {
  47. this->frame = index;
  48. currentCursor->setFrame(index);
  49. }
  50. }
  51. void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object)
  52. {
  53. dndObject = std::move(object);
  54. }
  55. void CCursorHandler::cursorMove(const int & x, const int & y)
  56. {
  57. xpos = x;
  58. ypos = y;
  59. }
  60. void CCursorHandler::drawWithScreenRestore()
  61. {
  62. if(!showing) return;
  63. int x = xpos, y = ypos;
  64. shiftPos(x, y);
  65. SDL_Rect temp_rect1 = genRect(40,40,x,y);
  66. SDL_Rect temp_rect2 = genRect(40,40,0,0);
  67. SDL_BlitSurface(screen, &temp_rect1, help, &temp_rect2);
  68. if (dndObject)
  69. {
  70. dndObject->moveTo(Point(x - dndObject->pos.w/2, y - dndObject->pos.h/2));
  71. dndObject->showAll(screen);
  72. }
  73. else
  74. {
  75. currentCursor->moveTo(Point(x,y));
  76. currentCursor->showAll(screen);
  77. }
  78. }
  79. void CCursorHandler::drawRestored()
  80. {
  81. if(!showing)
  82. return;
  83. int x = xpos, y = ypos;
  84. shiftPos(x, y);
  85. SDL_Rect temp_rect = genRect(40, 40, x, y);
  86. SDL_BlitSurface(help, nullptr, screen, &temp_rect);
  87. }
  88. void CCursorHandler::shiftPos( int &x, int &y )
  89. {
  90. if(( type == ECursor::COMBAT && frame != ECursor::COMBAT_POINTER) || type == ECursor::SPELLBOOK)
  91. {
  92. x-=16;
  93. y-=16;
  94. // Properly align the melee attack cursors.
  95. if (type == ECursor::COMBAT)
  96. {
  97. switch (frame)
  98. {
  99. case 7: // Bottom left
  100. x -= 6;
  101. y += 16;
  102. break;
  103. case 8: // Left
  104. x -= 16;
  105. y += 10;
  106. break;
  107. case 9: // Top left
  108. x -= 6;
  109. y -= 6;
  110. break;
  111. case 10: // Top right
  112. x += 16;
  113. y -= 6;
  114. break;
  115. case 11: // Right
  116. x += 16;
  117. y += 11;
  118. break;
  119. case 12: // Bottom right
  120. x += 16;
  121. y += 16;
  122. break;
  123. case 13: // Below
  124. x += 9;
  125. y += 16;
  126. break;
  127. case 14: // Above
  128. x += 9;
  129. y -= 15;
  130. break;
  131. }
  132. }
  133. }
  134. else if(type == ECursor::ADVENTURE)
  135. {
  136. if (frame == 0); //to exclude
  137. else if(frame == 2)
  138. {
  139. x -= 12;
  140. y -= 10;
  141. }
  142. else if(frame == 3)
  143. {
  144. x -= 12;
  145. y -= 12;
  146. }
  147. else if(frame < 27)
  148. {
  149. int hlpNum = (frame - 4)%6;
  150. if(hlpNum == 0)
  151. {
  152. x -= 15;
  153. y -= 13;
  154. }
  155. else if(hlpNum == 1)
  156. {
  157. x -= 13;
  158. y -= 13;
  159. }
  160. else if(hlpNum == 2)
  161. {
  162. x -= 20;
  163. y -= 20;
  164. }
  165. else if(hlpNum == 3)
  166. {
  167. x -= 13;
  168. y -= 16;
  169. }
  170. else if(hlpNum == 4)
  171. {
  172. x -= 8;
  173. y -= 9;
  174. }
  175. else if(hlpNum == 5)
  176. {
  177. x -= 14;
  178. y -= 16;
  179. }
  180. }
  181. else if(frame == 41)
  182. {
  183. x -= 14;
  184. y -= 16;
  185. }
  186. else if(frame < 31 || frame == 42)
  187. {
  188. x -= 20;
  189. y -= 20;
  190. }
  191. }
  192. }
  193. void CCursorHandler::centerCursor()
  194. {
  195. this->xpos = (screen->w / 2.) - (currentCursor->pos.w / 2.);
  196. this->ypos = (screen->h / 2.) - (currentCursor->pos.h / 2.);
  197. SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
  198. SDL_WarpMouse(this->xpos, this->ypos);
  199. SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
  200. }
  201. void CCursorHandler::render()
  202. {
  203. drawWithScreenRestore();
  204. CSDL_Ext::update(screen);
  205. drawRestored();
  206. }
  207. CCursorHandler::CCursorHandler() = default;
  208. CCursorHandler::~CCursorHandler()
  209. {
  210. if(help)
  211. SDL_FreeSurface(help);
  212. }