PageRenderTime 62ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/lltoolpie.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1890 lines | 1462 code | 254 blank | 174 comment | 332 complexity | c63fa80013735e49cdd879fedf6fb607 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lltoolpie.cpp
  3. * @brief LLToolPie class implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "lltoolpie.h"
  28. #include "indra_constants.h"
  29. #include "llclickaction.h"
  30. #include "llparcel.h"
  31. #include "llagent.h"
  32. #include "llagentcamera.h"
  33. #include "llavatarnamecache.h"
  34. #include "llfocusmgr.h"
  35. #include "llfirstuse.h"
  36. #include "llfloaterland.h"
  37. #include "llfloaterreg.h"
  38. #include "llfloaterscriptdebug.h"
  39. #include "lltooltip.h"
  40. #include "llhudeffecttrail.h"
  41. #include "llhudmanager.h"
  42. #include "llkeyboard.h"
  43. #include "llmediaentry.h"
  44. #include "llmenugl.h"
  45. #include "llmutelist.h"
  46. #include "llresmgr.h" // getMonetaryString
  47. #include "llselectmgr.h"
  48. #include "lltoolfocus.h"
  49. #include "lltoolgrab.h"
  50. #include "lltoolmgr.h"
  51. #include "lltoolselect.h"
  52. #include "lltrans.h"
  53. #include "llviewercamera.h"
  54. #include "llviewerparcelmedia.h"
  55. #include "llviewercontrol.h"
  56. #include "llviewermenu.h"
  57. #include "llviewerobjectlist.h"
  58. #include "llviewerobject.h"
  59. #include "llviewerparcelmgr.h"
  60. #include "llviewerwindow.h"
  61. #include "llviewermedia.h"
  62. #include "llvoavatarself.h"
  63. #include "llviewermediafocus.h"
  64. #include "llworld.h"
  65. #include "llui.h"
  66. #include "llweb.h"
  67. #include "pipeline.h" // setHighlightObject
  68. extern BOOL gDebugClicks;
  69. static void handle_click_action_play();
  70. static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp);
  71. static ECursorType cursor_from_parcel_media(U8 click_action);
  72. LLToolPie::LLToolPie()
  73. : LLTool(std::string("Pie")),
  74. mMouseButtonDown( false ),
  75. mMouseOutsideSlop( false ),
  76. mMouseSteerX(-1),
  77. mMouseSteerY(-1),
  78. mBlockClickToWalk(false),
  79. mClickAction(0),
  80. mClickActionBuyEnabled( gSavedSettings.getBOOL("ClickActionBuyEnabled") ),
  81. mClickActionPayEnabled( gSavedSettings.getBOOL("ClickActionPayEnabled") )
  82. {
  83. }
  84. BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
  85. {
  86. BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
  87. // This override DISABLES the keyboard focus reset that LLTool::handleAnyMouseClick adds.
  88. // LLToolPie will do the right thing in its pick callback.
  89. return result;
  90. }
  91. BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
  92. {
  93. mMouseOutsideSlop = FALSE;
  94. mMouseDownX = x;
  95. mMouseDownY = y;
  96. //left mouse down always picks transparent
  97. mPick = gViewerWindow->pickImmediate(x, y, TRUE);
  98. mPick.mKeyMask = mask;
  99. mMouseButtonDown = true;
  100. handleLeftClickPick();
  101. return TRUE;
  102. }
  103. // Spawn context menus on right mouse down so you can drag over and select
  104. // an item.
  105. BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
  106. {
  107. // don't pick transparent so users can't "pay" transparent objects
  108. mPick = gViewerWindow->pickImmediate(x, y, FALSE);
  109. mPick.mKeyMask = mask;
  110. // claim not handled so UI focus stays same
  111. handleRightClickPick();
  112. return FALSE;
  113. }
  114. BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
  115. {
  116. LLToolMgr::getInstance()->clearTransientTool();
  117. return LLTool::handleRightMouseUp(x, y, mask);
  118. }
  119. BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks)
  120. {
  121. return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
  122. }
  123. // True if you selected an object.
  124. BOOL LLToolPie::handleLeftClickPick()
  125. {
  126. S32 x = mPick.mMousePt.mX;
  127. S32 y = mPick.mMousePt.mY;
  128. MASK mask = mPick.mKeyMask;
  129. if (mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL)
  130. {
  131. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel();
  132. if (parcel)
  133. {
  134. LLViewerParcelMgr::getInstance()->selectCollisionParcel();
  135. if (parcel->getParcelFlag(PF_USE_PASS_LIST)
  136. && !LLViewerParcelMgr::getInstance()->isCollisionBanned())
  137. {
  138. // if selling passes, just buy one
  139. void* deselect_when_done = (void*)TRUE;
  140. LLPanelLandGeneral::onClickBuyPass(deselect_when_done);
  141. }
  142. else
  143. {
  144. // not selling passes, get info
  145. LLFloaterReg::showInstance("about_land");
  146. }
  147. }
  148. gFocusMgr.setKeyboardFocus(NULL);
  149. return LLTool::handleMouseDown(x, y, mask);
  150. }
  151. // didn't click in any UI object, so must have clicked in the world
  152. LLViewerObject *object = mPick.getObject();
  153. LLViewerObject *parent = NULL;
  154. if (mPick.mPickType != LLPickInfo::PICK_LAND)
  155. {
  156. LLViewerParcelMgr::getInstance()->deselectLand();
  157. }
  158. if (object)
  159. {
  160. parent = object->getRootEdit();
  161. }
  162. if (handleMediaClick(mPick))
  163. {
  164. return TRUE;
  165. }
  166. // If it's a left-click, and we have a special action, do it.
  167. if (useClickAction(mask, object, parent))
  168. {
  169. mClickAction = 0;
  170. if (object && object->getClickAction())
  171. {
  172. mClickAction = object->getClickAction();
  173. }
  174. else if (parent && parent->getClickAction())
  175. {
  176. mClickAction = parent->getClickAction();
  177. }
  178. switch(mClickAction)
  179. {
  180. case CLICK_ACTION_TOUCH:
  181. // touch behavior down below...
  182. break;
  183. case CLICK_ACTION_SIT:
  184. {
  185. if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // agent not already sitting
  186. {
  187. handle_object_sit_or_stand();
  188. // put focus in world when sitting on an object
  189. gFocusMgr.setKeyboardFocus(NULL);
  190. return TRUE;
  191. } // else nothing (fall through to touch)
  192. }
  193. case CLICK_ACTION_PAY:
  194. if ( mClickActionPayEnabled )
  195. {
  196. if ((object && object->flagTakesMoney())
  197. || (parent && parent->flagTakesMoney()))
  198. {
  199. // pay event goes to object actually clicked on
  200. mClickActionObject = object;
  201. mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
  202. if (LLSelectMgr::getInstance()->selectGetAllValid())
  203. {
  204. // call this right away, since we have all the info we need to continue the action
  205. selectionPropertiesReceived();
  206. }
  207. return TRUE;
  208. }
  209. }
  210. break;
  211. case CLICK_ACTION_BUY:
  212. if ( mClickActionBuyEnabled )
  213. {
  214. mClickActionObject = parent;
  215. mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
  216. if (LLSelectMgr::getInstance()->selectGetAllValid())
  217. {
  218. // call this right away, since we have all the info we need to continue the action
  219. selectionPropertiesReceived();
  220. }
  221. return TRUE;
  222. }
  223. break;
  224. case CLICK_ACTION_OPEN:
  225. if (parent && parent->allowOpen())
  226. {
  227. mClickActionObject = parent;
  228. mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
  229. if (LLSelectMgr::getInstance()->selectGetAllValid())
  230. {
  231. // call this right away, since we have all the info we need to continue the action
  232. selectionPropertiesReceived();
  233. }
  234. }
  235. return TRUE;
  236. case CLICK_ACTION_PLAY:
  237. handle_click_action_play();
  238. return TRUE;
  239. case CLICK_ACTION_OPEN_MEDIA:
  240. // mClickActionObject = object;
  241. handle_click_action_open_media(object);
  242. return TRUE;
  243. case CLICK_ACTION_ZOOM:
  244. {
  245. const F32 PADDING_FACTOR = 2.f;
  246. LLViewerObject* object = gObjectList.findObject(mPick.mObjectID);
  247. if (object)
  248. {
  249. gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
  250. LLBBox bbox = object->getBoundingBoxAgent() ;
  251. F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
  252. F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
  253. LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
  254. obj_to_cam.normVec();
  255. LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
  256. gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance),
  257. object_center_global,
  258. mPick.mObjectID );
  259. }
  260. }
  261. return TRUE;
  262. default:
  263. // nothing
  264. break;
  265. }
  266. }
  267. // put focus back "in world"
  268. if (gFocusMgr.getKeyboardFocus())
  269. {
  270. // don't click to walk on attempt to give focus to world
  271. mBlockClickToWalk = true;
  272. gFocusMgr.setKeyboardFocus(NULL);
  273. }
  274. BOOL touchable = (object && object->flagHandleTouch())
  275. || (parent && parent->flagHandleTouch());
  276. // Switch to grab tool if physical or triggerable
  277. if (object &&
  278. !object->isAvatar() &&
  279. ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable)
  280. )
  281. {
  282. gGrabTransientTool = this;
  283. mMouseButtonDown = false;
  284. LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() );
  285. return LLToolGrab::getInstance()->handleObjectHit( mPick );
  286. }
  287. LLHUDIcon* last_hit_hud_icon = mPick.mHUDIcon;
  288. if (!object && last_hit_hud_icon && last_hit_hud_icon->getSourceObject())
  289. {
  290. LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID());
  291. }
  292. // If left-click never selects or spawns a menu
  293. // Eat the event.
  294. if (!gSavedSettings.getBOOL("LeftClickShowMenu"))
  295. {
  296. // mouse already released
  297. if (!mMouseButtonDown)
  298. {
  299. return true;
  300. }
  301. while( object && object->isAttachment() && !object->flagHandleTouch())
  302. {
  303. // don't pick avatar through hud attachment
  304. if (object->isHUDAttachment())
  305. {
  306. break;
  307. }
  308. object = (LLViewerObject*)object->getParent();
  309. }
  310. if (object && object == gAgentAvatarp && !gSavedSettings.getBOOL("ClickToWalk"))
  311. {
  312. // we left clicked on avatar, switch to focus mode
  313. mMouseButtonDown = false;
  314. LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance());
  315. gViewerWindow->hideCursor();
  316. LLToolCamera::getInstance()->setMouseCapture(TRUE);
  317. LLToolCamera::getInstance()->pickCallback(mPick);
  318. gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
  319. return TRUE;
  320. }
  321. //////////
  322. // // Could be first left-click on nothing
  323. // LLFirstUse::useLeftClickNoHit();
  324. /////////
  325. // Eat the event
  326. return LLTool::handleMouseDown(x, y, mask);
  327. }
  328. if (gAgent.leftButtonGrabbed())
  329. {
  330. // if the left button is grabbed, don't put up the pie menu
  331. return LLTool::handleMouseDown(x, y, mask);
  332. }
  333. // Can't ignore children here.
  334. LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
  335. // Spawn pie menu
  336. LLTool::handleRightMouseDown(x, y, mask);
  337. return TRUE;
  338. }
  339. BOOL LLToolPie::useClickAction(MASK mask,
  340. LLViewerObject* object,
  341. LLViewerObject* parent)
  342. {
  343. return mask == MASK_NONE
  344. && object
  345. && !object->isAttachment()
  346. && LLPrimitive::isPrimitive(object->getPCode())
  347. && (object->getClickAction()
  348. || parent->getClickAction());
  349. }
  350. U8 final_click_action(LLViewerObject* obj)
  351. {
  352. if (!obj) return CLICK_ACTION_NONE;
  353. if (obj->isAttachment()) return CLICK_ACTION_NONE;
  354. U8 click_action = CLICK_ACTION_TOUCH;
  355. LLViewerObject* parent = obj->getRootEdit();
  356. if (obj->getClickAction()
  357. || (parent && parent->getClickAction()))
  358. {
  359. if (obj->getClickAction())
  360. {
  361. click_action = obj->getClickAction();
  362. }
  363. else if (parent && parent->getClickAction())
  364. {
  365. click_action = parent->getClickAction();
  366. }
  367. }
  368. return click_action;
  369. }
  370. ECursorType LLToolPie::cursorFromObject(LLViewerObject* object)
  371. {
  372. LLViewerObject* parent = NULL;
  373. if (object)
  374. {
  375. parent = object->getRootEdit();
  376. }
  377. U8 click_action = final_click_action(object);
  378. ECursorType cursor = UI_CURSOR_ARROW;
  379. switch(click_action)
  380. {
  381. case CLICK_ACTION_SIT:
  382. {
  383. if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // not already sitting?
  384. {
  385. cursor = UI_CURSOR_TOOLSIT;
  386. }
  387. }
  388. break;
  389. case CLICK_ACTION_BUY:
  390. if ( mClickActionBuyEnabled )
  391. {
  392. cursor = UI_CURSOR_TOOLBUY;
  393. }
  394. break;
  395. case CLICK_ACTION_OPEN:
  396. // Open always opens the parent.
  397. if (parent && parent->allowOpen())
  398. {
  399. cursor = UI_CURSOR_TOOLOPEN;
  400. }
  401. break;
  402. case CLICK_ACTION_PAY:
  403. if ( mClickActionPayEnabled )
  404. {
  405. if ((object && object->flagTakesMoney())
  406. || (parent && parent->flagTakesMoney()))
  407. {
  408. cursor = UI_CURSOR_TOOLBUY;
  409. }
  410. }
  411. break;
  412. case CLICK_ACTION_ZOOM:
  413. cursor = UI_CURSOR_TOOLZOOMIN;
  414. break;
  415. case CLICK_ACTION_PLAY:
  416. case CLICK_ACTION_OPEN_MEDIA:
  417. cursor = cursor_from_parcel_media(click_action);
  418. break;
  419. default:
  420. break;
  421. }
  422. return cursor;
  423. }
  424. void LLToolPie::resetSelection()
  425. {
  426. mLeftClickSelection = NULL;
  427. mClickActionObject = NULL;
  428. mClickAction = 0;
  429. }
  430. void LLToolPie::walkToClickedLocation()
  431. {
  432. if(mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
  433. mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
  434. mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
  435. mAutoPilotDestination->setPixelSize(5);
  436. mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
  437. mAutoPilotDestination->setDuration(3.f);
  438. handle_go_to();
  439. }
  440. // When we get object properties after left-clicking on an object
  441. // with left-click = buy, if it's the same object, do the buy.
  442. // static
  443. void LLToolPie::selectionPropertiesReceived()
  444. {
  445. // Make sure all data has been received.
  446. // This function will be called repeatedly as the data comes in.
  447. if (!LLSelectMgr::getInstance()->selectGetAllValid())
  448. {
  449. return;
  450. }
  451. LLObjectSelection* selection = LLToolPie::getInstance()->getLeftClickSelection();
  452. if (selection)
  453. {
  454. LLViewerObject* selected_object = selection->getPrimaryObject();
  455. // since we don't currently have a way to lock a selection, it could have changed
  456. // after we initially clicked on the object
  457. if (selected_object == LLToolPie::getInstance()->getClickActionObject())
  458. {
  459. U8 click_action = LLToolPie::getInstance()->getClickAction();
  460. switch (click_action)
  461. {
  462. case CLICK_ACTION_BUY:
  463. if ( LLToolPie::getInstance()->mClickActionBuyEnabled )
  464. {
  465. handle_buy();
  466. }
  467. break;
  468. case CLICK_ACTION_PAY:
  469. if ( LLToolPie::getInstance()->mClickActionPayEnabled )
  470. {
  471. handle_give_money_dialog();
  472. }
  473. break;
  474. case CLICK_ACTION_OPEN:
  475. LLFloaterReg::showInstance("openobject");
  476. break;
  477. default:
  478. break;
  479. }
  480. }
  481. }
  482. LLToolPie::getInstance()->resetSelection();
  483. }
  484. BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
  485. {
  486. mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
  487. LLViewerObject *parent = NULL;
  488. LLViewerObject *object = mHoverPick.getObject();
  489. if (object)
  490. {
  491. parent = object->getRootEdit();
  492. }
  493. // Show screen-space highlight glow effect
  494. bool show_highlight = false;
  495. if (handleMediaHover(mHoverPick))
  496. {
  497. // *NOTE: If you think the hover glow conflicts with the media outline, you
  498. // could disable it here.
  499. show_highlight = true;
  500. // cursor set by media object
  501. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
  502. }
  503. else if (!mMouseOutsideSlop
  504. && mMouseButtonDown
  505. && gSavedSettings.getBOOL("ClickToWalk"))
  506. {
  507. S32 delta_x = x - mMouseDownX;
  508. S32 delta_y = y - mMouseDownY;
  509. S32 threshold = gSavedSettings.getS32("DragAndDropDistanceThreshold");
  510. if (delta_x * delta_x + delta_y * delta_y > threshold * threshold)
  511. {
  512. startCameraSteering();
  513. steerCameraWithMouse(x, y);
  514. gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
  515. }
  516. else
  517. {
  518. gViewerWindow->setCursor(UI_CURSOR_ARROW);
  519. }
  520. }
  521. else if (inCameraSteerMode())
  522. {
  523. steerCameraWithMouse(x, y);
  524. gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
  525. }
  526. else
  527. {
  528. // perform a separate pick that detects transparent objects since they respond to 1-click actions
  529. LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE);
  530. LLViewerObject* click_action_object = click_action_pick.getObject();
  531. if (click_action_object && useClickAction(mask, click_action_object, click_action_object->getRootEdit()))
  532. {
  533. show_highlight = true;
  534. ECursorType cursor = cursorFromObject(click_action_object);
  535. gViewerWindow->setCursor(cursor);
  536. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
  537. }
  538. else if ((object && !object->isAvatar() && object->usePhysics())
  539. || (parent && !parent->isAvatar() && parent->usePhysics()))
  540. {
  541. show_highlight = true;
  542. gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
  543. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
  544. }
  545. else if ( (object && object->flagHandleTouch())
  546. || (parent && parent->flagHandleTouch()))
  547. {
  548. show_highlight = true;
  549. gViewerWindow->setCursor(UI_CURSOR_HAND);
  550. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
  551. }
  552. else
  553. {
  554. gViewerWindow->setCursor(UI_CURSOR_ARROW);
  555. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
  556. }
  557. }
  558. if(!object)
  559. {
  560. LLViewerMediaFocus::getInstance()->clearHover();
  561. }
  562. static LLCachedControl<bool> enable_highlight(
  563. gSavedSettings, "RenderHoverGlowEnable", false);
  564. LLDrawable* drawable = NULL;
  565. if (enable_highlight && show_highlight && object)
  566. {
  567. drawable = object->mDrawable;
  568. }
  569. gPipeline.setHighlightObject(drawable);
  570. return TRUE;
  571. }
  572. BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
  573. {
  574. LLViewerObject* obj = mPick.getObject();
  575. U8 click_action = final_click_action(obj);
  576. // let media have first pass at click
  577. if (handleMediaMouseUp() || LLViewerMediaFocus::getInstance()->getFocus())
  578. {
  579. mBlockClickToWalk = true;
  580. }
  581. stopCameraSteering();
  582. mMouseButtonDown = false;
  583. if (click_action == CLICK_ACTION_NONE // not doing 1-click action
  584. && gSavedSettings.getBOOL("ClickToWalk") // click to walk enabled
  585. && !gAgent.getFlying() // don't auto-navigate while flying until that works
  586. && gAgentAvatarp
  587. && !gAgentAvatarp->isSitting()
  588. && !mBlockClickToWalk // another behavior hasn't cancelled click to walk
  589. && !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
  590. && (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
  591. || mPick.mObjectID.notNull())) // or on an object
  592. {
  593. // handle special cases of steering picks
  594. LLViewerObject* avatar_object = mPick.getObject();
  595. // get pointer to avatar
  596. while (avatar_object && !avatar_object->isAvatar())
  597. {
  598. avatar_object = (LLViewerObject*)avatar_object->getParent();
  599. }
  600. if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
  601. {
  602. const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
  603. // pretend we picked some point a bit in front of avatar
  604. mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
  605. }
  606. gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
  607. walkToClickedLocation();
  608. LLFirstUse::notMoving(false);
  609. return TRUE;
  610. }
  611. gViewerWindow->setCursor(UI_CURSOR_ARROW);
  612. if (hasMouseCapture())
  613. {
  614. setMouseCapture(FALSE);
  615. }
  616. LLToolMgr::getInstance()->clearTransientTool();
  617. gAgentCamera.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on
  618. mBlockClickToWalk = false;
  619. return LLTool::handleMouseUp(x, y, mask);
  620. }
  621. void LLToolPie::stopClickToWalk()
  622. {
  623. mPick.mPosGlobal = gAgent.getPositionGlobal();
  624. handle_go_to();
  625. if(mAutoPilotDestination)
  626. {
  627. mAutoPilotDestination->markDead();
  628. }
  629. }
  630. BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
  631. {
  632. if (gDebugClicks)
  633. {
  634. llinfos << "LLToolPie handleDoubleClick (becoming mouseDown)" << llendl;
  635. }
  636. if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
  637. {
  638. if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
  639. (mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
  640. {
  641. walkToClickedLocation();
  642. return TRUE;
  643. }
  644. }
  645. else if (gSavedSettings.getBOOL("DoubleClickTeleport"))
  646. {
  647. LLViewerObject* objp = mPick.getObject();
  648. LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
  649. bool is_in_world = mPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
  650. bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND;
  651. bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero();
  652. bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
  653. bool has_click_action = final_click_action(objp);
  654. if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
  655. {
  656. LLVector3d pos = mPick.mPosGlobal;
  657. pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
  658. gAgent.teleportViaLocationLookAt(pos);
  659. return TRUE;
  660. }
  661. }
  662. return FALSE;
  663. }
  664. static bool needs_tooltip(LLSelectNode* nodep)
  665. {
  666. if (!nodep)
  667. return false;
  668. LLViewerObject* object = nodep->getObject();
  669. LLViewerObject *parent = (LLViewerObject *)object->getParent();
  670. if (object->flagHandleTouch()
  671. || (parent && parent->flagHandleTouch())
  672. || object->flagTakesMoney()
  673. || (parent && parent->flagTakesMoney())
  674. || object->flagAllowInventoryAdd()
  675. )
  676. {
  677. return true;
  678. }
  679. U8 click_action = final_click_action(object);
  680. if (click_action != 0)
  681. {
  682. return true;
  683. }
  684. if (nodep->mValid)
  685. {
  686. bool anyone_copy = anyone_copy_selection(nodep);
  687. bool for_sale = for_sale_selection(nodep);
  688. if (anyone_copy || for_sale)
  689. {
  690. return true;
  691. }
  692. }
  693. return false;
  694. }
  695. BOOL LLToolPie::handleTooltipLand(std::string line, std::string tooltip_msg)
  696. {
  697. LLViewerParcelMgr::getInstance()->setHoverParcel( mHoverPick.mPosGlobal );
  698. //
  699. // Do not show hover for land unless prefs are set to allow it.
  700. //
  701. if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return TRUE;
  702. // Didn't hit an object, but since we have a land point we
  703. // must be hovering over land.
  704. LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel();
  705. LLUUID owner;
  706. S32 width = 0;
  707. S32 height = 0;
  708. if ( hover_parcel )
  709. {
  710. owner = hover_parcel->getOwnerID();
  711. width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth());
  712. height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight());
  713. }
  714. // Line: "Land"
  715. line.clear();
  716. line.append(LLTrans::getString("TooltipLand"));
  717. if (hover_parcel)
  718. {
  719. line.append(hover_parcel->getName());
  720. }
  721. tooltip_msg.append(line);
  722. tooltip_msg.push_back('\n');
  723. // Line: "Owner: James Linden"
  724. line.clear();
  725. line.append(LLTrans::getString("TooltipOwner") + " ");
  726. if ( hover_parcel )
  727. {
  728. std::string name;
  729. if (LLUUID::null == owner)
  730. {
  731. line.append(LLTrans::getString("TooltipPublic"));
  732. }
  733. else if (hover_parcel->getIsGroupOwned())
  734. {
  735. if (gCacheName->getGroupName(owner, name))
  736. {
  737. line.append(name);
  738. line.append(LLTrans::getString("TooltipIsGroup"));
  739. }
  740. else
  741. {
  742. line.append(LLTrans::getString("RetrievingData"));
  743. }
  744. }
  745. else if(gCacheName->getFullName(owner, name))
  746. {
  747. line.append(name);
  748. }
  749. else
  750. {
  751. line.append(LLTrans::getString("RetrievingData"));
  752. }
  753. }
  754. else
  755. {
  756. line.append(LLTrans::getString("RetrievingData"));
  757. }
  758. tooltip_msg.append(line);
  759. tooltip_msg.push_back('\n');
  760. // Line: "no fly, not safe, no build"
  761. // Don't display properties for your land. This is just
  762. // confusing, because you can do anything on your own land.
  763. if ( hover_parcel && owner != gAgent.getID() )
  764. {
  765. S32 words = 0;
  766. line.clear();
  767. // JC - Keep this in the same order as the checkboxes
  768. // on the land info panel
  769. if ( !hover_parcel->getAllowModify() )
  770. {
  771. if ( hover_parcel->getAllowGroupModify() )
  772. {
  773. line.append(LLTrans::getString("TooltipFlagGroupBuild"));
  774. }
  775. else
  776. {
  777. line.append(LLTrans::getString("TooltipFlagNoBuild"));
  778. }
  779. words++;
  780. }
  781. if ( !hover_parcel->getAllowTerraform() )
  782. {
  783. if (words) line.append(", ");
  784. line.append(LLTrans::getString("TooltipFlagNoEdit"));
  785. words++;
  786. }
  787. if ( hover_parcel->getAllowDamage() )
  788. {
  789. if (words) line.append(", ");
  790. line.append(LLTrans::getString("TooltipFlagNotSafe"));
  791. words++;
  792. }
  793. // Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04
  794. if ( !hover_parcel->getAllowFly() )
  795. {
  796. if (words) line.append(", ");
  797. line.append(LLTrans::getString("TooltipFlagNoFly"));
  798. words++;
  799. }
  800. if ( !hover_parcel->getAllowOtherScripts() )
  801. {
  802. if (words) line.append(", ");
  803. if ( hover_parcel->getAllowGroupScripts() )
  804. {
  805. line.append(LLTrans::getString("TooltipFlagGroupScripts"));
  806. }
  807. else
  808. {
  809. line.append(LLTrans::getString("TooltipFlagNoScripts"));
  810. }
  811. words++;
  812. }
  813. if (words)
  814. {
  815. tooltip_msg.append(line);
  816. tooltip_msg.push_back('\n');
  817. }
  818. }
  819. if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE))
  820. {
  821. LLStringUtil::format_map_t args;
  822. S32 price = hover_parcel->getSalePrice();
  823. args["[AMOUNT]"] = LLResMgr::getInstance()->getMonetaryString(price);
  824. line = LLTrans::getString("TooltipForSaleL$", args);
  825. tooltip_msg.append(line);
  826. tooltip_msg.push_back('\n');
  827. }
  828. // trim last newlines
  829. if (!tooltip_msg.empty())
  830. {
  831. tooltip_msg.erase(tooltip_msg.size() - 1);
  832. LLToolTipMgr::instance().show(tooltip_msg);
  833. }
  834. return TRUE;
  835. }
  836. BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg)
  837. {
  838. if ( hover_object->isHUDAttachment() )
  839. {
  840. // no hover tips for HUD elements, since they can obscure
  841. // what the HUD is displaying
  842. return TRUE;
  843. }
  844. if ( hover_object->isAttachment() )
  845. {
  846. // get root of attachment then parent, which is avatar
  847. LLViewerObject* root_edit = hover_object->getRootEdit();
  848. if (!root_edit)
  849. {
  850. // Strange parenting issue, don't show any text
  851. return TRUE;
  852. }
  853. hover_object = (LLViewerObject*)root_edit->getParent();
  854. if (!hover_object)
  855. {
  856. // another strange parenting issue, bail out
  857. return TRUE;
  858. }
  859. }
  860. line.clear();
  861. if (hover_object->isAvatar())
  862. {
  863. // only show tooltip if same inspector not already open
  864. LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_avatar");
  865. if (!existing_inspector
  866. || !existing_inspector->getVisible()
  867. || existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID())
  868. {
  869. // IDEVO: try to get display name + username
  870. std::string final_name;
  871. std::string full_name;
  872. if (!gCacheName->getFullName(hover_object->getID(), full_name))
  873. {
  874. LLNameValue* firstname = hover_object->getNVPair("FirstName");
  875. LLNameValue* lastname = hover_object->getNVPair("LastName");
  876. if (firstname && lastname)
  877. {
  878. full_name = LLCacheName::buildFullName(
  879. firstname->getString(), lastname->getString());
  880. }
  881. else
  882. {
  883. full_name = LLTrans::getString("TooltipPerson");
  884. }
  885. }
  886. LLAvatarName av_name;
  887. if (LLAvatarNameCache::useDisplayNames() &&
  888. LLAvatarNameCache::get(hover_object->getID(), &av_name))
  889. {
  890. final_name = av_name.getCompleteName();
  891. }
  892. else
  893. {
  894. final_name = full_name;
  895. }
  896. // *HACK: We may select this object, so pretend it was clicked
  897. mPick = mHoverPick;
  898. LLInspector::Params p;
  899. p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
  900. p.message(final_name);
  901. p.image.name("Inspector_I");
  902. p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
  903. p.visible_time_near(6.f);
  904. p.visible_time_far(3.f);
  905. p.delay_time(gSavedSettings.getF32("AvatarInspectorTooltipDelay"));
  906. p.wrap(false);
  907. LLToolTipMgr::instance().show(p);
  908. }
  909. }
  910. else
  911. {
  912. //
  913. // We have hit a regular object (not an avatar or attachment)
  914. //
  915. //
  916. // Default prefs will suppress display unless the object is interactive
  917. //
  918. bool show_all_object_tips =
  919. (bool)gSavedSettings.getBOOL("ShowAllObjectHoverTip");
  920. LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();
  921. // only show tooltip if same inspector not already open
  922. LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_object");
  923. if (nodep &&
  924. (!existing_inspector
  925. || !existing_inspector->getVisible()
  926. || existing_inspector->getKey()["object_id"].asUUID() != hover_object->getID()))
  927. {
  928. // Add price to tooltip for items on sale
  929. bool for_sale = for_sale_selection(nodep);
  930. if(for_sale)
  931. {
  932. LLStringUtil::format_map_t args;
  933. S32 price = nodep->mSaleInfo.getSalePrice();
  934. args["[AMOUNT]"] = LLResMgr::getInstance()->getMonetaryString(price);
  935. tooltip_msg.append(LLTrans::getString("TooltipPrice", args) );
  936. }
  937. if (nodep->mName.empty())
  938. {
  939. tooltip_msg.append(LLTrans::getString("TooltipNoName"));
  940. }
  941. else
  942. {
  943. tooltip_msg.append( nodep->mName );
  944. }
  945. bool has_media = false;
  946. bool is_time_based_media = false;
  947. bool is_web_based_media = false;
  948. bool is_media_playing = false;
  949. bool is_media_displaying = false;
  950. // Does this face have media?
  951. const LLTextureEntry* tep = hover_object->getTE(mHoverPick.mObjectFace);
  952. if(tep)
  953. {
  954. has_media = tep->hasMedia();
  955. const LLMediaEntry* mep = has_media ? tep->getMediaData() : NULL;
  956. if (mep)
  957. {
  958. viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
  959. LLPluginClassMedia* media_plugin = NULL;
  960. if (media_impl.notNull() && (media_impl->hasMedia()))
  961. {
  962. is_media_displaying = true;
  963. //LLStringUtil::format_map_t args;
  964. media_plugin = media_impl->getMediaPlugin();
  965. if(media_plugin)
  966. {
  967. if(media_plugin->pluginSupportsMediaTime())
  968. {
  969. is_time_based_media = true;
  970. is_web_based_media = false;
  971. //args["[CurrentURL]"] = media_impl->getMediaURL();
  972. is_media_playing = media_impl->isMediaPlaying();
  973. }
  974. else
  975. {
  976. is_time_based_media = false;
  977. is_web_based_media = true;
  978. //args["[CurrentURL]"] = media_plugin->getLocation();
  979. }
  980. //tooltip_msg.append(LLTrans::getString("CurrentURL", args));
  981. }
  982. }
  983. }
  984. }
  985. // Avoid showing tip over media that's displaying unless it's for sale
  986. // also check the primary node since sometimes it can have an action even though
  987. // the root node doesn't
  988. bool needs_tip = (!is_media_displaying ||
  989. for_sale) &&
  990. (has_media ||
  991. needs_tooltip(nodep) ||
  992. needs_tooltip(LLSelectMgr::getInstance()->getPrimaryHoverNode()));
  993. if (show_all_object_tips || needs_tip)
  994. {
  995. // We may select this object, so pretend it was clicked
  996. mPick = mHoverPick;
  997. LLInspector::Params p;
  998. p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
  999. p.message(tooltip_msg);
  1000. p.image.name("Inspector_I");
  1001. p.click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace));
  1002. p.time_based_media(is_time_based_media);
  1003. p.web_based_media(is_web_based_media);
  1004. p.media_playing(is_media_playing);
  1005. p.click_playmedia_callback(boost::bind(playCurrentMedia, mHoverPick));
  1006. p.click_homepage_callback(boost::bind(VisitHomePage, mHoverPick));
  1007. p.visible_time_near(6.f);
  1008. p.visible_time_far(3.f);
  1009. p.delay_time(gSavedSettings.getF32("ObjectInspectorTooltipDelay"));
  1010. p.wrap(false);
  1011. LLToolTipMgr::instance().show(p);
  1012. }
  1013. }
  1014. }
  1015. return TRUE;
  1016. }
  1017. BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
  1018. {
  1019. if (!LLUI::sSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE;
  1020. if (!mHoverPick.isValid()) return TRUE;
  1021. LLViewerObject* hover_object = mHoverPick.getObject();
  1022. // update hover object and hover parcel
  1023. LLSelectMgr::getInstance()->setHoverObject(hover_object, mHoverPick.mObjectFace);
  1024. std::string tooltip_msg;
  1025. std::string line;
  1026. if ( hover_object )
  1027. {
  1028. handleTooltipObject(hover_object, line, tooltip_msg );
  1029. }
  1030. else if (mHoverPick.mPickType == LLPickInfo::PICK_LAND)
  1031. {
  1032. handleTooltipLand(line, tooltip_msg);
  1033. }
  1034. return TRUE;
  1035. }
  1036. static void show_inspector(const char* inspector, const char* param, const LLUUID& source_id)
  1037. {
  1038. LLSD params;
  1039. params[param] = source_id;
  1040. if (LLToolTipMgr::instance().toolTipVisible())
  1041. {
  1042. LLRect rect = LLToolTipMgr::instance().getToolTipRect();
  1043. params["pos"]["x"] = rect.mLeft;
  1044. params["pos"]["y"] = rect.mTop;
  1045. }
  1046. LLFloaterReg::showInstance(inspector, params);
  1047. }
  1048. static void show_inspector(const char* inspector, LLSD& params)
  1049. {
  1050. if (LLToolTipMgr::instance().toolTipVisible())
  1051. {
  1052. LLRect rect = LLToolTipMgr::instance().getToolTipRect();
  1053. params["pos"]["x"] = rect.mLeft;
  1054. params["pos"]["y"] = rect.mTop;
  1055. }
  1056. LLFloaterReg::showInstance(inspector, params);
  1057. }
  1058. // static
  1059. void LLToolPie::showAvatarInspector(const LLUUID& avatar_id)
  1060. {
  1061. show_inspector("inspect_avatar", "avatar_id", avatar_id);
  1062. }
  1063. // static
  1064. void LLToolPie::showObjectInspector(const LLUUID& object_id)
  1065. {
  1066. show_inspector("inspect_object", "object_id", object_id);
  1067. }
  1068. // static
  1069. void LLToolPie::showObjectInspector(const LLUUID& object_id, const S32& object_face)
  1070. {
  1071. LLSD params;
  1072. params["object_id"] = object_id;
  1073. params["object_face"] = object_face;
  1074. show_inspector("inspect_object", params);
  1075. }
  1076. // static
  1077. void LLToolPie::playCurrentMedia(const LLPickInfo& info)
  1078. {
  1079. //FIXME: how do we handle object in different parcel than us?
  1080. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  1081. if (!parcel) return;
  1082. LLPointer<LLViewerObject> objectp = info.getObject();
  1083. // Early out cases. Must clear media hover.
  1084. // did not hit an object or did not hit a valid face
  1085. if ( objectp.isNull() ||
  1086. info.mObjectFace < 0 ||
  1087. info.mObjectFace >= objectp->getNumTEs() )
  1088. {
  1089. return;
  1090. }
  1091. // Does this face have media?
  1092. const LLTextureEntry* tep = objectp->getTE(info.mObjectFace);
  1093. if (!tep)
  1094. return;
  1095. const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
  1096. if(!mep)
  1097. return;
  1098. //TODO: Can you Use it?
  1099. LLPluginClassMedia* media_plugin = NULL;
  1100. viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
  1101. if(media_impl.notNull() && media_impl->hasMedia())
  1102. {
  1103. media_plugin = media_impl->getMediaPlugin();
  1104. if (media_plugin && media_plugin->pluginSupportsMediaTime())
  1105. {
  1106. if(media_impl->isMediaPlaying())
  1107. {
  1108. media_impl->pause();
  1109. }
  1110. else
  1111. {
  1112. media_impl->play();
  1113. }
  1114. }
  1115. }
  1116. }
  1117. // static
  1118. void LLToolPie::VisitHomePage(const LLPickInfo& info)
  1119. {
  1120. //FIXME: how do we handle object in different parcel than us?
  1121. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  1122. if (!parcel) return;
  1123. LLPointer<LLViewerObject> objectp = info.getObject();
  1124. // Early out cases. Must clear media hover.
  1125. // did not hit an object or did not hit a valid face
  1126. if ( objectp.isNull() ||
  1127. info.mObjectFace < 0 ||
  1128. info.mObjectFace >= objectp->getNumTEs() )
  1129. {
  1130. return;
  1131. }
  1132. // Does this face have media?
  1133. const LLTextureEntry* tep = objectp->getTE(info.mObjectFace);
  1134. if (!tep)
  1135. return;
  1136. const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
  1137. if(!mep)
  1138. return;
  1139. //TODO: Can you Use it?
  1140. LLPluginClassMedia* media_plugin = NULL;
  1141. viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
  1142. if(media_impl.notNull() && media_impl->hasMedia())
  1143. {
  1144. media_plugin = media_impl->getMediaPlugin();
  1145. if (media_plugin && !(media_plugin->pluginSupportsMediaTime()))
  1146. {
  1147. media_impl->navigateHome();
  1148. }
  1149. }
  1150. }
  1151. void LLToolPie::handleSelect()
  1152. {
  1153. // tool is reselected when app gets focus, etc.
  1154. mBlockClickToWalk = true;
  1155. }
  1156. void LLToolPie::handleDeselect()
  1157. {
  1158. if( hasMouseCapture() )
  1159. {
  1160. setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly
  1161. }
  1162. // remove temporary selection for pie menu
  1163. LLSelectMgr::getInstance()->setHoverObject(NULL);
  1164. LLSelectMgr::getInstance()->validateSelection();
  1165. }
  1166. LLTool* LLToolPie::getOverrideTool(MASK mask)
  1167. {
  1168. if (gSavedSettings.getBOOL("EnableGrab"))
  1169. {
  1170. if (mask == MASK_CONTROL)
  1171. {
  1172. return LLToolGrab::getInstance();
  1173. }
  1174. else if (mask == (MASK_CONTROL | MASK_SHIFT))
  1175. {
  1176. return LLToolGrab::getInstance();
  1177. }
  1178. }
  1179. return LLTool::getOverrideTool(mask);
  1180. }
  1181. void LLToolPie::stopEditing()
  1182. {
  1183. if( hasMouseCapture() )
  1184. {
  1185. setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly
  1186. }
  1187. }
  1188. void LLToolPie::onMouseCaptureLost()
  1189. {
  1190. stopCameraSteering();
  1191. mMouseButtonDown = false;
  1192. handleMediaMouseUp();
  1193. }
  1194. void LLToolPie::stopCameraSteering()
  1195. {
  1196. mMouseOutsideSlop = false;
  1197. }
  1198. bool LLToolPie::inCameraSteerMode()
  1199. {
  1200. return mMouseButtonDown && mMouseOutsideSlop && gSavedSettings.getBOOL("ClickToWalk");
  1201. }
  1202. // true if x,y outside small box around start_x,start_y
  1203. BOOL LLToolPie::outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y)
  1204. {
  1205. S32 dx = x - start_x;
  1206. S32 dy = y - start_y;
  1207. return (dx <= -2 || 2 <= dx || dy <= -2 || 2 <= dy);
  1208. }
  1209. void LLToolPie::render()
  1210. {
  1211. return;
  1212. }
  1213. static void handle_click_action_play()
  1214. {
  1215. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  1216. if (!parcel) return;
  1217. LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus();
  1218. switch(status)
  1219. {
  1220. case LLViewerMediaImpl::MEDIA_PLAYING:
  1221. LLViewerParcelMedia::pause();
  1222. break;
  1223. case LLViewerMediaImpl::MEDIA_PAUSED:
  1224. LLViewerParcelMedia::start();
  1225. break;
  1226. default:
  1227. LLViewerParcelMedia::play(parcel);
  1228. break;
  1229. }
  1230. }
  1231. bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
  1232. {
  1233. //FIXME: how do we handle object in different parcel than us?
  1234. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  1235. LLPointer<LLViewerObject> objectp = pick.getObject();
  1236. if (!parcel ||
  1237. objectp.isNull() ||
  1238. pick.mObjectFace < 0 ||
  1239. pick.mObjectFace >= objectp->getNumTEs())
  1240. {
  1241. LLViewerMediaFocus::getInstance()->clearFocus();
  1242. return false;
  1243. }
  1244. // Does this face have media?
  1245. const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
  1246. if(!tep)
  1247. return false;
  1248. LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
  1249. if(!mep)
  1250. return false;
  1251. viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
  1252. if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
  1253. {
  1254. if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
  1255. {
  1256. // It's okay to give this a null impl
  1257. LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
  1258. }
  1259. else
  1260. {
  1261. // Make sure keyboard focus is set to the media focus object.
  1262. gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
  1263. LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
  1264. media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
  1265. mMediaMouseCaptureID = mep->getMediaID();
  1266. setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
  1267. }
  1268. return true;
  1269. }
  1270. LLViewerMediaFocus::getInstance()->clearFocus();
  1271. return false;
  1272. }
  1273. bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
  1274. {
  1275. //FIXME: how do we handle object in different parcel than us?
  1276. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  1277. if (!parcel) return false;
  1278. LLPointer<LLViewerObject> objectp = pick.getObject();
  1279. // Early out cases. Must clear media hover.
  1280. // did not hit an object or did not hit a valid face
  1281. if ( objectp.isNull() ||
  1282. pick.mObjectFace < 0 ||
  1283. pick.mObjectFace >= objectp->getNumTEs() )
  1284. {
  1285. LLViewerMediaFocus::getInstance()->clearHover();
  1286. return false;
  1287. }
  1288. // Does this face have media?
  1289. const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
  1290. if(!tep)
  1291. return false;
  1292. const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
  1293. if (mep
  1294. && gSavedSettings.getBOOL("MediaOnAPrimUI"))
  1295. {
  1296. viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
  1297. if(media_impl.notNull())
  1298. {
  1299. // Update media hover object
  1300. if (!LLViewerMediaFocus::getInstance()->isHoveringOverFace(objectp, pick.mObjectFace))
  1301. {
  1302. LLViewerMediaFocus::getInstance()->setHoverFace(objectp, pick.mObjectFace, media_impl, pick.mNormal);
  1303. }
  1304. // If this is the focused media face, send mouse move events.
  1305. if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace))
  1306. {
  1307. media_impl->mouseMove(pick.mUVCoords, gKeyboard->currentMask(TRUE));
  1308. gViewerWindow->setCursor(media_impl->getLastSetCursor());
  1309. }
  1310. else
  1311. {
  1312. // This is not the focused face -- set the default cursor.
  1313. gViewerWindow->setCursor(UI_CURSOR_ARROW);
  1314. }
  1315. return true;
  1316. }
  1317. }
  1318. // In all other cases, clear media hover.
  1319. LLViewerMediaFocus::getInstance()->clearHover();
  1320. return false;
  1321. }
  1322. bool LLToolPie::handleMediaMouseUp()
  1323. {
  1324. bool result = false;
  1325. if(mMediaMouseCaptureID.notNull())
  1326. {
  1327. // Face media needs to know the mouse went up.
  1328. viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mMediaMouseCaptureID);
  1329. if(media_impl)
  1330. {
  1331. // This will send a mouseUp event to the plugin using the last known mouse coordinate (from a mouseDown or mouseMove), which is what we want.
  1332. media_impl->onMouseCaptureLost();
  1333. }
  1334. mMediaMouseCaptureID.setNull();
  1335. result = true;
  1336. }
  1337. return result;
  1338. }
  1339. static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp)
  1340. {
  1341. //FIXME: how do we handle object in different parcel than us?
  1342. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  1343. if (!parcel) return;
  1344. // did we hit an object?
  1345. if (objectp.isNull()) return;
  1346. // did we hit a valid face on the object?
  1347. S32 face = LLToolPie::getInstance()->getPick().mObjectFace;
  1348. if( face < 0 || face >= objectp->getNumTEs() ) return;
  1349. // is media playing on this face?
  1350. if (LLViewerMedia::getMediaImplFromTextureID(objectp->getTE(face)->getID()) != NULL)
  1351. {
  1352. handle_click_action_play();
  1353. return;
  1354. }
  1355. std::string media_url = std::string ( parcel->getMediaURL () );
  1356. std::string media_type = std::string ( parcel->getMediaType() );
  1357. LLStringUtil::trim(media_url);
  1358. LLWeb::loadURL(media_url);
  1359. }
  1360. static ECursorType cursor_from_parcel_media(U8 click_action)
  1361. {
  1362. // HACK: This is directly referencing an impl name. BAD!
  1363. // This can be removed when we have a truly generic media browser that only
  1364. // builds an impl based on the type of url it is passed.
  1365. //FIXME: how do we handle object in different parcel than us?
  1366. ECursorType open_cursor = UI_CURSOR_ARROW;
  1367. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  1368. if (!parcel) return open_cursor;
  1369. std::string media_url = std::string ( parcel->getMediaURL () );
  1370. std::string media_type = std::string ( parcel->getMediaType() );
  1371. LLStringUtil::trim(media_url);
  1372. open_cursor = UI_CURSOR_TOOLMEDIAOPEN;
  1373. LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus();
  1374. switch(status)
  1375. {
  1376. case LLViewerMediaImpl::MEDIA_PLAYING:
  1377. return click_action == CLICK_ACTION_PLAY ? UI_CURSOR_TOOLPAUSE : open_cursor;
  1378. default:
  1379. return UI_CURSOR_TOOLPLAY;
  1380. }
  1381. }
  1382. // True if we handled the event.
  1383. BOOL LLToolPie::handleRightClickPick()
  1384. {
  1385. S32 x = mPick.mMousePt.mX;
  1386. S32 y = mPick.mMousePt.mY;
  1387. MASK mask = mPick.mKeyMask;
  1388. if (mPick.mPickType != LLPickInfo::PICK_LAND)
  1389. {
  1390. LLViewerParcelMgr::getInstance()->deselectLand();
  1391. }
  1392. // didn't click in any UI object, so must have clicked in the world
  1393. LLViewerObject *object = mPick.getObject();
  1394. LLViewerObject *parent = NULL;
  1395. if(object)
  1396. parent = object->getRootEdit();
  1397. // Can't ignore children here.
  1398. LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
  1399. // Spawn pie menu
  1400. if (mPick.mPickType == LLPickInfo::PICK_LAND)
  1401. {
  1402. LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal );
  1403. gMenuHolder->setParcelSelection(selection);
  1404. gMenuLand->show(x, y);
  1405. showVisualContextMenuEffect();
  1406. }
  1407. else if (mPick.mObjectID == gAgent.getID() )
  1408. {
  1409. if(!gMenuAvatarSelf)
  1410. {
  1411. //either at very early startup stage or at late quitting stage,
  1412. //this event is ignored.
  1413. return TRUE ;
  1414. }
  1415. gMenuAvatarSelf->show(x, y);
  1416. }
  1417. else if (object)
  1418. {
  1419. gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection());
  1420. bool is_other_attachment = (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner());
  1421. if (object->isAvatar()
  1422. || is_other_attachment)
  1423. {
  1424. // Find the attachment's avatar
  1425. while( object && object->isAttachment())
  1426. {
  1427. object = (LLViewerObject*)object->getParent();
  1428. llassert(object);
  1429. }
  1430. if (!object)
  1431. {
  1432. return TRUE; // unexpected, but escape
  1433. }
  1434. // Object is an avatar, so check for mute by id.
  1435. LLVOAvatar* avatar = (LLVOAvatar*)object;
  1436. std::string name = avatar->getFullname();
  1437. std::string mute_msg;
  1438. if (LLMuteList::getInstance()->isMuted(avatar->getID(), avatar->getFullname()))
  1439. {
  1440. mute_msg = LLTrans::getString("UnmuteAvatar");
  1441. }
  1442. else
  1443. {
  1444. mute_msg = LLTrans::getString("MuteAvatar");
  1445. }
  1446. if (is_other_attachment)
  1447. {
  1448. gMenuAttachmentOther->getChild<LLUICtrl>("Avatar Mute")->setValue(mute_msg);
  1449. gMenuAttachmentOther->show(x, y);
  1450. }
  1451. else
  1452. {
  1453. gMenuAvatarOther->getChild<LLUICtrl>("Avatar Mute")->setValue(mute_msg);
  1454. gMenuAvatarOther->show(x, y);
  1455. }
  1456. }
  1457. else if (object->isAttachment())
  1458. {
  1459. gMenuAttachmentSelf->show(x, y);
  1460. }
  1461. else
  1462. {
  1463. // BUG: What about chatting child objects?
  1464. std::string name;
  1465. LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
  1466. if (node)
  1467. {
  1468. name = node->mName;
  1469. }
  1470. std::string mute_msg;
  1471. if (LLMuteList::getInstance()->isMuted(object->getID(), name))
  1472. {
  1473. mute_msg = LLTrans::getString("UnmuteObject");
  1474. }
  1475. else
  1476. {
  1477. mute_msg = LLTrans::getString("MuteObject2");
  1478. }
  1479. gMenuHolder->getChild<LLUICtrl>("Object Mute")->setValue(mute_msg);
  1480. gMenuObject->show(x, y);
  1481. showVisualContextMenuEffect();
  1482. }
  1483. }
  1484. LLTool::handleRightMouseDown(x, y, mask);
  1485. // We handled the event.
  1486. return TRUE;
  1487. }
  1488. void LLToolPie::showVisualContextMenuEffect()
  1489. {
  1490. // VEFFECT: ShowPie
  1491. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
  1492. effectp->setPositionGlobal(mPick.mPosGlobal);
  1493. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1494. effectp->setDuration(0.25f);
  1495. }
  1496. typedef enum e_near_far
  1497. {
  1498. NEAR_INTERSECTION,
  1499. FAR_INTERSECTION
  1500. } ENearFar;
  1501. bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius, e_near_far near_far, LLVector3& intersection_pt)
  1502. {
  1503. // do ray/sphere intersection by solving quadratic equation
  1504. LLVector3 sphere_to_ray_start_vec = ray_pt - sphere_center;
  1505. F32 B = 2.f * ray_dir * sphere_to_ray_start_vec;
  1506. F32 C = sphere_to_ray_start_vec.lengthSquared() - (sphere_radius * sphere_radius);
  1507. F32 discriminant = B*B - 4.f*C;
  1508. if (discriminant >= 0.f)
  1509. { // intersection detected, now find closest one
  1510. F32 t0 = (-B - sqrtf(discriminant)) / 2.f;
  1511. if (t0 > 0.f && near_far == NEAR_INTERSECTION)
  1512. {
  1513. intersection_pt = ray_pt + ray_dir * t0;
  1514. }
  1515. else
  1516. {
  1517. F32 t1 = (-B + sqrtf(discriminant)) / 2.f;
  1518. intersection_pt = ray_pt + ray_dir * t1;
  1519. }
  1520. return true;
  1521. }
  1522. else
  1523. { // no intersection
  1524. return false;
  1525. }
  1526. }
  1527. void LLToolPie::startCameraSteering()
  1528. {
  1529. LLFirstUse::notMoving(false);
  1530. mMouseOutsideSlop = true;
  1531. mBlockClickToWalk = true;
  1532. if (gAgentCamera.getFocusOnAvatar())
  1533. {
  1534. mSteerPick = mPick;
  1535. // handle special cases of steering picks
  1536. LLViewerObject* avatar_object = mSteerPick.getObject();
  1537. // get pointer to avatar
  1538. while (avatar_object && !avatar_object->isAvatar())
  1539. {
  1540. avatar_object = (LLViewerObject*)avatar_object->getParent();
  1541. }
  1542. // if clicking on own avatar...
  1543. if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
  1544. {
  1545. // ...project pick point a few meters in front of avatar
  1546. mSteerPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * 3.0;
  1547. }
  1548. if (!mSteerPick.isValid())
  1549. {
  1550. mSteerPick.mPosGlobal = gAgent.getPosGlobalFromAgent(
  1551. LLViewerCamera::instance().getOrigin() + gViewerWindow->mouseDirectionGlobal(mSteerPick.mMousePt.mX, mSteerPick.mMousePt.mY) * 100.f);
  1552. }
  1553. setMouseCapture(TRUE);
  1554. mMouseSteerX = mMouseDownX;
  1555. mMouseSteerY = mMouseDownY;
  1556. const LLVector3 camera_to_rotation_center = gAgent.getFrameAgent().getOrigin() - LLViewerCamera::instance().getOrigin();
  1557. const LLVector3 rotation_center_to_pick = gAgent.getPosAgentFromGlobal(mSteerPick.mPosGlobal) - gAgent.getFrameAgent().getOrigin();
  1558. mClockwise = camera_to_rotation_center * rotation_center_to_pick < 0.f;
  1559. if (mMouseSteerGrabPoint) { mMouseSteerGrabPoint->markDead(); }
  1560. mMouseSteerGrabPoint = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
  1561. mMouseSteerGrabPoint->setPositionGlobal(mSteerPick.mPosGlobal);
  1562. mMouseSteerGrabPoint->setColor(LLColor4U(170, 210, 190));
  1563. mMouseSteerGrabPoint->setPixelSize(5);
  1564. mMouseSteerGrabPoint->setDuration(2.f);
  1565. }
  1566. }
  1567. void LLToolPie::steerCameraWithMouse(S32 x, S32 y)
  1568. {
  1569. const LLViewerCamera& camera = LLViewerCamera::instance();
  1570. const LLCoordFrame& rotation_frame = gAgent.getFrameAgent();
  1571. const LLVector3 pick_pos = gAgent.getPosAgentFromGlobal(mSteerPick.mPosGlobal);
  1572. const LLVector3 pick_rotation_center = rotation_frame.getOrigin() + parallel_component(pick_pos - rotation_frame.getOrigin(), rotation_frame.getUpAxis());
  1573. const F32 MIN_ROTATION_RADIUS_FRACTION = 0.2f;
  1574. const F32 min_rotation_radius = MIN_ROTATION_RADIUS_FRACTION * dist_vec(pick_rotation_center, camera.getOrigin());;
  1575. const F32 pick_distance_from_rotation_center = llclamp(dist_vec(pick_pos, pick_rotation_center), min_rotation_radius, F32_MAX);
  1576. const LLVector3 camera_to_rotation_center = pick_rotation_center - camera.getOrigin();
  1577. const LLVector3 adjusted_camera_pos = LLViewerCamera::instance().getOrigin() + projected_vec(camera_to_rotation_center, rotation_frame.getUpAxis());
  1578. const F32 camera_distance_from_rotation_center = dist_vec(adjusted_camera_pos, pick_rotation_center);
  1579. LLVector3 mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(x, y), rotation_frame.getUpAxis());
  1580. mouse_ray.normalize();
  1581. LLVector3 old_mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(mMouseSteerX, mMouseSteerY), rotation_frame.getUpAxis());
  1582. old_mouse_ray.normalize();
  1583. F32 yaw_angle;
  1584. F32 old_yaw_angle;
  1585. LLVector3 mouse_on_sphere;
  1586. LLVector3 old_mouse_on_sphere;
  1587. if (intersect_ray_with_sphere(
  1588. adjusted_camera_pos,
  1589. mouse_ray,
  1590. pick_rotation_center,
  1591. pick_distance_from_rotation_center,
  1592. FAR_INTERSECTION,
  1593. mouse_on_sphere))
  1594. {
  1595. LLVector3 mouse_sphere_offset = mouse_on_sphere - pick_rotation_center;
  1596. yaw_angle = atan2f(mouse_sphere_offset * rotation_frame.getLeftAxis(), mouse_sphere_offset * rotation_frame.getAtAxis());
  1597. }
  1598. else
  1599. {
  1600. yaw_angle = F_PI_BY_TWO + asinf(pick_distance_from_rotation_center / camera_distance_from_rotation_center);
  1601. if (mouse_ray * rotation_frame.getLeftAxis() < 0.f)
  1602. {
  1603. yaw_angle *= -1.f;
  1604. }
  1605. }
  1606. if (intersect_ray_with_sphere(
  1607. adjusted_camera_pos,
  1608. old_mouse_ray,
  1609. pick_rotation_center,
  1610. pick_distance_from_rotation_center,
  1611. FAR_INTERSECTION,
  1612. old_mouse_on_sphere))
  1613. {
  1614. LLVector3 mouse_sphere_offset = old_mouse_on_sphere - pick_rotation_center;
  1615. old_yaw_angle = atan2f(mouse_sphere_offset * rotation_frame.getLeftAxis(), mouse_sphere_offset * rotation_frame.getAtAxis());
  1616. }
  1617. else
  1618. {
  1619. old_yaw_angle = F_PI_BY_TWO + asinf(pick_distance_from_rotation_center / camera_distance_from_rotation_center);
  1620. if (mouse_ray * rotation_frame.getLeftAxis() < 0.f)
  1621. {
  1622. old_yaw_angle *= -1.f;
  1623. }
  1624. }
  1625. const F32 delta_angle = yaw_angle - old_yaw_angle;
  1626. if (mClockwise)
  1627. {
  1628. gAgent.yaw(delta_angle);
  1629. }
  1630. else
  1631. {
  1632. gAgent.yaw(-delta_angle);
  1633. }
  1634. mMouseSteerX = x;
  1635. mMouseSteerY = y;
  1636. }