//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames // Copyright (C) 2015 Faust Logic, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // Some of the object selection code in this file is based on functionality described // in the following resource: // // Object Selection in Torque by Dave Myers // http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7335 // //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// #include "afx/arcaneFX.h" #include "console/engineAPI.h" #include "gui/core/guiCanvas.h" #include "T3D/gameBase/gameConnection.h" #include "T3D/gameFunctions.h" #include "afx/ui/afxTSCtrl.h" #include "afx/afxSpellBook.h" //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// IMPLEMENT_CONOBJECT(afxTSCtrl); ConsoleDocClass( afxTSCtrl, "@brief A customized variation of GameTSCtrl.\n\n" "@ingroup afxGUI\n" "@ingroup AFX\n" ); afxTSCtrl::afxTSCtrl() { mMouse3DVec.zero(); mMouse3DPos.zero(); mouse_dn_timestamp = 0; spellbook = NULL; clearTargetingMode(); } bool afxTSCtrl::processCameraQuery(CameraQuery *camq) { GameUpdateCameraFov(); return GameProcessCameraQuery(camq); } void afxTSCtrl::renderWorld(const RectI &updateRect) { GameRenderWorld(); } void afxTSCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent) { Parent::getCursor(cursor, showCursor, lastGuiEvent); GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn || !conn->getRolloverObj()) return; GuiCanvas *pRoot = getRoot(); if( !pRoot ) return; PlatformWindow* pWindow = pRoot->getPlatformWindow(); AssertFatal(pWindow != NULL, "GuiControl without owning platform window! This should not be possible."); PlatformCursorController* pController = pWindow->getCursorController(); AssertFatal(pController != NULL, "PlatformWindow without an owned CursorController!"); if(pRoot->mCursorChanged != PlatformCursorController::curHand) { // We've already changed the cursor, so set it back before we change it again. if(pRoot->mCursorChanged != -1) pController->popCursor(); // Now change the cursor shape pController->pushCursor(PlatformCursorController::curHand); pRoot->mCursorChanged = PlatformCursorController::curHand; } else if(pRoot->mCursorChanged != -1) { // Restore the cursor we changed pController->popCursor(); pRoot->mCursorChanged = -1; } } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// void afxTSCtrl::onMouseDown(const GuiEvent &evt) { //Con::printf("#### afxTSCtrl::onLeftMouseDown() ####"); // save a timestamp so we can measure how long the button is down mouse_dn_timestamp = Platform::getRealMilliseconds(); GuiCanvas* Canvas = getRoot(); // clear button down status because the ActionMap is going to capture // the mouse and the button up will never happen Canvas->clearMouseButtonDown(); // indicate that processing of event should continue (pass down to ActionMap) Canvas->setConsumeLastInputEvent(false); } void afxTSCtrl::onRightMouseDown(const GuiEvent& evt) { //Con::printf("#### afxTSCtrl::onRightMouseDown() ####"); GuiCanvas* Canvas = getRoot(); // clear right button down status because the ActionMap is going to capture // the mouse and the right button up will never happen Canvas->clearMouseRightButtonDown(); // indicate that processing of event should continue (pass down to ActionMap) Canvas->setConsumeLastInputEvent(false); } void afxTSCtrl::onMouseMove(const GuiEvent& evt) { AssertFatal(!targeting_mode.empty(), "Error, undefined targeting mode."); Targeting targeting = targeting_mode.last(); if (targeting.mode == arcaneFX::TARGETING_OFF || targeting.check != arcaneFX::TARGET_CHECK_ON_MOUSE_MOVE) return; performTargeting(evt.mousePoint, targeting.mode); } void afxTSCtrl::onRender(Point2I offset, const RectI &updateRect) { GameConnection* con = GameConnection::getConnectionToServer(); #if defined(BROKEN_DAMAGEFLASH_WHITEOUT_BLACKOUT) bool skipRender = (!con); #else bool skipRender = (!con || (con->getWhiteOut() >= 1.f) || (con->getDamageFlash() >= 1.f) || (con->getBlackOut() >= 1.f)); #endif if (!skipRender) Parent::onRender(offset, updateRect); GFX->setViewport(updateRect); } void afxTSCtrl::advanceTime(F32 dt) { AssertFatal(!targeting_mode.empty(), "Error, undefined targeting mode."); Targeting targeting = targeting_mode.last(); if (targeting.mode == arcaneFX::TARGETING_OFF || targeting.check != arcaneFX::TARGET_CHECK_POLL) return; GuiCanvas* Canvas = getRoot(); Point2I cursor_pos; if (Canvas && Canvas->getLastCursorPoint(cursor_pos)) { performTargeting(cursor_pos, targeting.mode); } }; void afxTSCtrl::performTargeting(const Point2I& mousePoint, U8 mode) { GuiCanvas* Canvas = getRoot(); if (mode != arcaneFX::TARGETING_FREE && !Canvas->isCursorON()) return; MatrixF cam_xfm; Point3F dummy_pt; if (GameGetCameraTransform(&cam_xfm, &dummy_pt)) { // get cam pos Point3F cameraPoint; cam_xfm.getColumn(3,&cameraPoint); // construct 3D screen point from mouse coords Point3F screen_pt((F32)mousePoint.x, (F32)mousePoint.y, 1.0f); // convert screen point to world point bool bad_cam = mIsZero(mLastCameraQuery.farPlane); Point3F world_pt; if (!bad_cam && unproject(screen_pt, &world_pt)) { Point3F mouseVec = world_pt - cameraPoint; mouseVec.normalizeSafe(); mMouse3DPos = cameraPoint; mMouse3DVec = mouseVec; F32 selectRange = arcaneFX::sTargetSelectionRange; Point3F mouseScaled = mouseVec*selectRange; Point3F rangeEnd = cameraPoint + mouseScaled; if (mode == arcaneFX::TARGETING_STANDARD) arcaneFX::rolloverRayCast(cameraPoint, rangeEnd, arcaneFX::sTargetSelectionMask); else if (mode == arcaneFX::TARGETING_FREE) arcaneFX::freeTargetingRayCast(cameraPoint, rangeEnd, arcaneFX::sFreeTargetSelectionMask); } } } void afxTSCtrl::onMouseEnter(const GuiEvent& evt) { //Con::printf("#### afxTSCtrl::onMouseEnter() ####"); } void afxTSCtrl::onMouseDragged(const GuiEvent& evt) { //Con::printf("#### afxTSCtrl::onMouseDragged() ####"); } void afxTSCtrl::onMouseLeave(const GuiEvent& evt) { //Con::printf("#### afxTSCtrl::onMouseLeave() ####"); } bool afxTSCtrl::onMouseWheelUp(const GuiEvent& evt) { //Con::printf("#### afxTSCtrl::onMouseWheelUp() ####"); Con::executef(this, "onMouseWheelUp"); return true; } bool afxTSCtrl::onMouseWheelDown(const GuiEvent& evt) { //Con::printf("#### afxTSCtrl::onMouseWheelDown() ####"); Con::executef(this, "onMouseWheelDown"); return true; } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// void afxTSCtrl::setSpellBook(afxSpellBook* book) { if (book != spellbook) { spellbook = book; Con::executef(this, "onSpellbookChange", (spellbook) ? spellbook->getIdString() : ""); } } void afxTSCtrl::clearTargetingMode() { targeting_mode.clear(); pushTargetingMode(arcaneFX::TARGETING_OFF, arcaneFX::TARGET_CHECK_POLL); } void afxTSCtrl::pushTargetingMode(U8 mode, U8 check) { switch (mode) { case arcaneFX::TARGETING_OFF: case arcaneFX::TARGETING_STANDARD: case arcaneFX::TARGETING_FREE: break; default: Con::errorf("afxTSCtrl::setTargetingMode() -- unknown targeting mode [%d].", mode); return; } switch (check) { case arcaneFX::TARGET_CHECK_POLL: case arcaneFX::TARGET_CHECK_ON_MOUSE_MOVE: break; default: Con::errorf("afxTSCtrl::setTargetingMode() -- unknown targeting check method [%d].", check); return; } Targeting targeting = { mode, check }; targeting_mode.push_back(targeting); } void afxTSCtrl::popTargetingMode() { if (targeting_mode.size() <= 1) return ; targeting_mode.pop_back(); } U8 afxTSCtrl::getTargetingMode() { return (targeting_mode.size() > 0) ? targeting_mode.last().mode : arcaneFX::TARGETING_OFF; } U8 afxTSCtrl::getTargetingCheckMethod() { return (targeting_mode.size() > 0) ? targeting_mode.last().check : arcaneFX::TARGET_CHECK_POLL; } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// DefineEngineMethod(afxTSCtrl, setSpellBook, void, (afxSpellBook* spellbook),, "Associate a spellbook with an afxTSCtrl.\n\n" "@ingroup AFX") { object->setSpellBook(spellbook); } DefineEngineMethod(afxTSCtrl, pushTargetingMode, void, (U32 mode, U32 checkMethod), ((U32)arcaneFX::TARGETING_OFF, (U32)arcaneFX::TARGET_CHECK_POLL), "Push a new targeting-mode onto a statck of modes.\n\n" "@ingroup AFX") { object->pushTargetingMode((U8)mode, (U8)checkMethod); } DefineEngineMethod(afxTSCtrl, popTargetingMode, void, (),, "Pop the targeting-mode off a statck of modes.\n\n" "@ingroup AFX") { object->popTargetingMode(); } DefineEngineMethod(afxTSCtrl, getTargetingMode, S32, (),, "Get the current targeting-mode.\n\n" "@ingroup AFX") { return object->getTargetingMode(); } DefineEngineMethod(afxTSCtrl, getMouse3DVec, Point3F, (),, "Get the 3D direction vector for the mouse cursor.\n\n" "@ingroup AFX") { return object->getMouse3DVec(); } DefineEngineMethod(afxTSCtrl, getMouse3DPos, Point3F, (),, "Get the 3D position of the mouse cursor.\n\n" "@ingroup AFX") { return object->getMouse3DPos(); } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//