afxTSCtrl.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  2. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  3. // Copyright (C) 2015 Faust Logic, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //
  23. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  24. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  25. // Some of the object selection code in this file is based on functionality described
  26. // in the following resource:
  27. //
  28. // Object Selection in Torque by Dave Myers
  29. // http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7335
  30. //
  31. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  32. #include "afx/arcaneFX.h"
  33. #include "console/engineAPI.h"
  34. #include "gui/core/guiCanvas.h"
  35. #include "T3D/gameBase/gameConnection.h"
  36. #include "T3D/gameFunctions.h"
  37. #include "afx/ui/afxTSCtrl.h"
  38. #include "afx/afxSpellBook.h"
  39. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  40. IMPLEMENT_CONOBJECT(afxTSCtrl);
  41. ConsoleDocClass( afxTSCtrl,
  42. "@brief A customized variation of GameTSCtrl.\n\n"
  43. "@ingroup afxGUI\n"
  44. "@ingroup AFX\n"
  45. );
  46. afxTSCtrl::afxTSCtrl()
  47. {
  48. mMouse3DVec.zero();
  49. mMouse3DPos.zero();
  50. mouse_dn_timestamp = 0;
  51. spellbook = NULL;
  52. clearTargetingMode();
  53. }
  54. bool afxTSCtrl::processCameraQuery(CameraQuery *camq)
  55. {
  56. GameUpdateCameraFov();
  57. return GameProcessCameraQuery(camq);
  58. }
  59. void afxTSCtrl::renderWorld(const RectI &updateRect)
  60. {
  61. GameRenderWorld();
  62. }
  63. void afxTSCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent)
  64. {
  65. Parent::getCursor(cursor, showCursor, lastGuiEvent);
  66. GameConnection* conn = GameConnection::getConnectionToServer();
  67. if (!conn || !conn->getRolloverObj())
  68. return;
  69. GuiCanvas *pRoot = getRoot();
  70. if( !pRoot )
  71. return;
  72. PlatformWindow* pWindow = pRoot->getPlatformWindow();
  73. AssertFatal(pWindow != NULL, "GuiControl without owning platform window! This should not be possible.");
  74. PlatformCursorController* pController = pWindow->getCursorController();
  75. AssertFatal(pController != NULL, "PlatformWindow without an owned CursorController!");
  76. if(pRoot->mCursorChanged != PlatformCursorController::curHand)
  77. {
  78. // We've already changed the cursor, so set it back before we change it again.
  79. if(pRoot->mCursorChanged != -1)
  80. pController->popCursor();
  81. // Now change the cursor shape
  82. pController->pushCursor(PlatformCursorController::curHand);
  83. pRoot->mCursorChanged = PlatformCursorController::curHand;
  84. }
  85. else if(pRoot->mCursorChanged != -1)
  86. {
  87. // Restore the cursor we changed
  88. pController->popCursor();
  89. pRoot->mCursorChanged = -1;
  90. }
  91. }
  92. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  93. void afxTSCtrl::onMouseDown(const GuiEvent &evt)
  94. {
  95. //Con::printf("#### afxTSCtrl::onLeftMouseDown() ####");
  96. // save a timestamp so we can measure how long the button is down
  97. mouse_dn_timestamp = Platform::getRealMilliseconds();
  98. GuiCanvas* Canvas = getRoot();
  99. // clear button down status because the ActionMap is going to capture
  100. // the mouse and the button up will never happen
  101. Canvas->clearMouseButtonDown();
  102. // indicate that processing of event should continue (pass down to ActionMap)
  103. Canvas->setConsumeLastInputEvent(false);
  104. }
  105. void afxTSCtrl::onRightMouseDown(const GuiEvent& evt)
  106. {
  107. //Con::printf("#### afxTSCtrl::onRightMouseDown() ####");
  108. GuiCanvas* Canvas = getRoot();
  109. // clear right button down status because the ActionMap is going to capture
  110. // the mouse and the right button up will never happen
  111. Canvas->clearMouseRightButtonDown();
  112. // indicate that processing of event should continue (pass down to ActionMap)
  113. Canvas->setConsumeLastInputEvent(false);
  114. }
  115. void afxTSCtrl::onMouseMove(const GuiEvent& evt)
  116. {
  117. AssertFatal(!targeting_mode.empty(), "Error, undefined targeting mode.");
  118. Targeting targeting = targeting_mode.last();
  119. if (targeting.mode == arcaneFX::TARGETING_OFF || targeting.check != arcaneFX::TARGET_CHECK_ON_MOUSE_MOVE)
  120. return;
  121. performTargeting(evt.mousePoint, targeting.mode);
  122. }
  123. void afxTSCtrl::onRender(Point2I offset, const RectI &updateRect)
  124. {
  125. GameConnection* con = GameConnection::getConnectionToServer();
  126. #if defined(BROKEN_DAMAGEFLASH_WHITEOUT_BLACKOUT)
  127. bool skipRender = (!con);
  128. #else
  129. bool skipRender = (!con ||
  130. (con->getWhiteOut() >= 1.f) ||
  131. (con->getDamageFlash() >= 1.f) ||
  132. (con->getBlackOut() >= 1.f));
  133. #endif
  134. if (!skipRender)
  135. Parent::onRender(offset, updateRect);
  136. GFX->setViewport(updateRect);
  137. }
  138. void afxTSCtrl::advanceTime(F32 dt)
  139. {
  140. AssertFatal(!targeting_mode.empty(), "Error, undefined targeting mode.");
  141. Targeting targeting = targeting_mode.last();
  142. if (targeting.mode == arcaneFX::TARGETING_OFF || targeting.check != arcaneFX::TARGET_CHECK_POLL)
  143. return;
  144. GuiCanvas* Canvas = getRoot();
  145. Point2I cursor_pos;
  146. if (Canvas && Canvas->getLastCursorPoint(cursor_pos))
  147. {
  148. performTargeting(cursor_pos, targeting.mode);
  149. }
  150. };
  151. void afxTSCtrl::performTargeting(const Point2I& mousePoint, U8 mode)
  152. {
  153. GuiCanvas* Canvas = getRoot();
  154. if (mode != arcaneFX::TARGETING_FREE && !Canvas->isCursorON())
  155. return;
  156. MatrixF cam_xfm;
  157. Point3F dummy_pt;
  158. if (GameGetCameraTransform(&cam_xfm, &dummy_pt))
  159. {
  160. // get cam pos
  161. Point3F cameraPoint; cam_xfm.getColumn(3,&cameraPoint);
  162. // construct 3D screen point from mouse coords
  163. Point3F screen_pt((F32)mousePoint.x, (F32)mousePoint.y, 1.0f);
  164. // convert screen point to world point
  165. bool bad_cam = mIsZero(mLastCameraQuery.farPlane);
  166. Point3F world_pt;
  167. if (!bad_cam && unproject(screen_pt, &world_pt))
  168. {
  169. Point3F mouseVec = world_pt - cameraPoint;
  170. mouseVec.normalizeSafe();
  171. mMouse3DPos = cameraPoint;
  172. mMouse3DVec = mouseVec;
  173. F32 selectRange = arcaneFX::sTargetSelectionRange;
  174. Point3F mouseScaled = mouseVec*selectRange;
  175. Point3F rangeEnd = cameraPoint + mouseScaled;
  176. if (mode == arcaneFX::TARGETING_STANDARD)
  177. arcaneFX::rolloverRayCast(cameraPoint, rangeEnd, arcaneFX::sTargetSelectionMask);
  178. else if (mode == arcaneFX::TARGETING_FREE)
  179. arcaneFX::freeTargetingRayCast(cameraPoint, rangeEnd, arcaneFX::sFreeTargetSelectionMask);
  180. }
  181. }
  182. }
  183. void afxTSCtrl::onMouseEnter(const GuiEvent& evt)
  184. {
  185. //Con::printf("#### afxTSCtrl::onMouseEnter() ####");
  186. }
  187. void afxTSCtrl::onMouseDragged(const GuiEvent& evt)
  188. {
  189. //Con::printf("#### afxTSCtrl::onMouseDragged() ####");
  190. }
  191. void afxTSCtrl::onMouseLeave(const GuiEvent& evt)
  192. {
  193. //Con::printf("#### afxTSCtrl::onMouseLeave() ####");
  194. }
  195. bool afxTSCtrl::onMouseWheelUp(const GuiEvent& evt)
  196. {
  197. //Con::printf("#### afxTSCtrl::onMouseWheelUp() ####");
  198. Con::executef(this, "onMouseWheelUp");
  199. return true;
  200. }
  201. bool afxTSCtrl::onMouseWheelDown(const GuiEvent& evt)
  202. {
  203. //Con::printf("#### afxTSCtrl::onMouseWheelDown() ####");
  204. Con::executef(this, "onMouseWheelDown");
  205. return true;
  206. }
  207. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  208. void afxTSCtrl::setSpellBook(afxSpellBook* book)
  209. {
  210. if (book != spellbook)
  211. {
  212. spellbook = book;
  213. Con::executef(this, "onSpellbookChange", (spellbook) ? spellbook->getIdString() : "");
  214. }
  215. }
  216. void afxTSCtrl::clearTargetingMode()
  217. {
  218. targeting_mode.clear();
  219. pushTargetingMode(arcaneFX::TARGETING_OFF, arcaneFX::TARGET_CHECK_POLL);
  220. }
  221. void afxTSCtrl::pushTargetingMode(U8 mode, U8 check)
  222. {
  223. switch (mode)
  224. {
  225. case arcaneFX::TARGETING_OFF:
  226. case arcaneFX::TARGETING_STANDARD:
  227. case arcaneFX::TARGETING_FREE:
  228. break;
  229. default:
  230. Con::errorf("afxTSCtrl::setTargetingMode() -- unknown targeting mode [%d].", mode);
  231. return;
  232. }
  233. switch (check)
  234. {
  235. case arcaneFX::TARGET_CHECK_POLL:
  236. case arcaneFX::TARGET_CHECK_ON_MOUSE_MOVE:
  237. break;
  238. default:
  239. Con::errorf("afxTSCtrl::setTargetingMode() -- unknown targeting check method [%d].", check);
  240. return;
  241. }
  242. Targeting targeting = { mode, check };
  243. targeting_mode.push_back(targeting);
  244. }
  245. void afxTSCtrl::popTargetingMode()
  246. {
  247. if (targeting_mode.size() <= 1)
  248. return ;
  249. targeting_mode.pop_back();
  250. }
  251. U8 afxTSCtrl::getTargetingMode()
  252. {
  253. return (targeting_mode.size() > 0) ? targeting_mode.last().mode : arcaneFX::TARGETING_OFF;
  254. }
  255. U8 afxTSCtrl::getTargetingCheckMethod()
  256. {
  257. return (targeting_mode.size() > 0) ? targeting_mode.last().check : arcaneFX::TARGET_CHECK_POLL;
  258. }
  259. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  260. DefineEngineMethod(afxTSCtrl, setSpellBook, void, (afxSpellBook* spellbook),,
  261. "Associate a spellbook with an afxTSCtrl.\n\n"
  262. "@ingroup AFX")
  263. {
  264. object->setSpellBook(spellbook);
  265. }
  266. DefineEngineMethod(afxTSCtrl, pushTargetingMode, void, (U32 mode, U32 checkMethod), ((U32)arcaneFX::TARGETING_OFF, (U32)arcaneFX::TARGET_CHECK_POLL),
  267. "Push a new targeting-mode onto a statck of modes.\n\n"
  268. "@ingroup AFX")
  269. {
  270. object->pushTargetingMode((U8)mode, (U8)checkMethod);
  271. }
  272. DefineEngineMethod(afxTSCtrl, popTargetingMode, void, (),,
  273. "Pop the targeting-mode off a statck of modes.\n\n"
  274. "@ingroup AFX")
  275. {
  276. object->popTargetingMode();
  277. }
  278. DefineEngineMethod(afxTSCtrl, getTargetingMode, S32, (),,
  279. "Get the current targeting-mode.\n\n"
  280. "@ingroup AFX")
  281. {
  282. return object->getTargetingMode();
  283. }
  284. DefineEngineMethod(afxTSCtrl, getMouse3DVec, Point3F, (),,
  285. "Get the 3D direction vector for the mouse cursor.\n\n"
  286. "@ingroup AFX")
  287. {
  288. return object->getMouse3DVec();
  289. }
  290. DefineEngineMethod(afxTSCtrl, getMouse3DPos, Point3F, (),,
  291. "Get the 3D position of the mouse cursor.\n\n"
  292. "@ingroup AFX")
  293. {
  294. return object->getMouse3DPos();
  295. }
  296. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//