lltracker.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:22k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltracker.cpp
  3.  * @brief Container for objects user is tracking.
  4.  *
  5.  * $LicenseInfo:firstyear=2003&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2003-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. // library includes
  34. #include "llcoord.h"
  35. #include "lldarray.h"
  36. #include "llfontgl.h"
  37. #include "llgl.h"
  38. #include "llrender.h"
  39. #include "llinventory.h"
  40. #include "llpointer.h"
  41. #include "llstring.h"
  42. #include "lluuid.h"
  43. #include "v3math.h"
  44. #include "v3dmath.h"
  45. #include "v4color.h"
  46. // viewer includes
  47. #include "llappviewer.h"
  48. #include "lltracker.h"
  49. #include "llagent.h"
  50. #include "llcallingcard.h"
  51. #include "llfloaterworldmap.h"
  52. #include "llhudtext.h"
  53. #include "llhudview.h"
  54. #include "llinventorymodel.h"
  55. #include "llinventoryobserver.h"
  56. #include "lllandmarklist.h"
  57. #include "llsky.h"
  58. #include "llui.h"
  59. #include "llviewercamera.h"
  60. #include "llviewerinventory.h"
  61. #include "llworld.h"
  62. #include "llworldmapview.h"
  63. #include "llviewercontrol.h"
  64. const F32 DESTINATION_REACHED_RADIUS    = 3.0f;
  65. const F32 DESTINATION_VISITED_RADIUS    = 6.0f;
  66. // this last one is useful for when the landmark is
  67. // very close to agent when tracking is turned on
  68. const F32 DESTINATION_UNVISITED_RADIUS = 12.0f;
  69. const S32 ARROW_OFF_RADIUS_SQRD = 100;
  70. const S32 HUD_ARROW_SIZE = 32;
  71. // static
  72. LLTracker *LLTracker::sTrackerp = NULL;
  73. BOOL LLTracker::sCheesyBeacon = FALSE;
  74. LLTracker::LLTracker()
  75. : mTrackingStatus(TRACKING_NOTHING),
  76. mTrackingLocationType(LOCATION_NOTHING),
  77. mHUDArrowCenterX(0),
  78. mHUDArrowCenterY(0),
  79. mToolTip( "" ),
  80. mTrackedLandmarkName(""),
  81. mHasReachedLandmark(FALSE),
  82. mHasLandmarkPosition(FALSE),
  83. mLandmarkHasBeenVisited(FALSE),
  84. mTrackedLocationName( "" ),
  85. mIsTrackingLocation(FALSE),
  86. mHasReachedLocation(FALSE)
  87. { }
  88. LLTracker::~LLTracker()
  89. purgeBeaconText();
  90. }
  91. // static
  92. void LLTracker::stopTracking(void* userdata)
  93. {
  94. BOOL clear_ui = ((BOOL)(intptr_t)userdata);
  95. instance()->stopTrackingAll(clear_ui);
  96. }
  97. // static virtual
  98. void LLTracker::drawHUDArrow()
  99. {
  100. static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
  101. /* tracking autopilot destination has been disabled 
  102.    -- 2004.01.09, Leviathan
  103. // Draw dot for autopilot target
  104. if (gAgent.getAutoPilot())
  105. {
  106. instance()->drawMarker( gAgent.getAutoPilotTargetGlobal(), map_track_color );
  107. return;
  108. }
  109. */
  110. switch (getTrackingStatus())
  111. case TRACKING_AVATAR:
  112. // Tracked avatar
  113. if(LLAvatarTracker::instance().haveTrackingInfo())
  114. {
  115. instance()->drawMarker( LLAvatarTracker::instance().getGlobalPos(), map_track_color );
  116. break;
  117. case TRACKING_LANDMARK:
  118. instance()->drawMarker( getTrackedPositionGlobal(), map_track_color );
  119. break;
  120. case TRACKING_LOCATION:
  121. // HACK -- try to keep the location just above the terrain
  122. #if 0
  123. // UNHACKED by CRO - keep location where the location is
  124. instance()->mTrackedPositionGlobal.mdV[VZ] = 
  125. 0.9f * instance()->mTrackedPositionGlobal.mdV[VZ]
  126. + 0.1f * (LLWorld::getInstance()->resolveLandHeightGlobal(getTrackedPositionGlobal()) + 1.5f);
  127. #endif
  128. instance()->mTrackedPositionGlobal.mdV[VZ] = llclamp((F32)instance()->mTrackedPositionGlobal.mdV[VZ], LLWorld::getInstance()->resolveLandHeightGlobal(getTrackedPositionGlobal()) + 1.5f, (F32)instance()->getTrackedPositionGlobal().mdV[VZ]);
  129. instance()->drawMarker( getTrackedPositionGlobal(), map_track_color );
  130. break;
  131. default:
  132. break;
  133. }
  134. }
  135. // static 
  136. void LLTracker::render3D()
  137. {
  138. if (!gFloaterWorldMap)
  139. {
  140. return;
  141. }
  142. static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
  143. // Arbitary location beacon
  144. if( instance()->mIsTrackingLocation )
  145.   {
  146. if (!instance()->mBeaconText)
  147. {
  148. instance()->mBeaconText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
  149. instance()->mBeaconText->setDoFade(FALSE);
  150. }
  151. LLVector3d pos_global = instance()->mTrackedPositionGlobal;
  152. // (z-attenuation < 1) means compute "shorter" distance in z-axis,
  153. // so cancel tracking even if avatar is a little above or below.
  154. F32 dist = gFloaterWorldMap->getDistanceToDestination(pos_global, 0.5f);
  155. if (dist < DESTINATION_REACHED_RADIUS)
  156. {
  157. instance()->stopTrackingLocation();
  158. }
  159. else
  160. {
  161. renderBeacon( instance()->mTrackedPositionGlobal, map_track_color, 
  162.    instance()->mBeaconText, instance()->mTrackedLocationName );
  163. }
  164. }
  165. // Landmark beacon
  166. else if( !instance()->mTrackedLandmarkAssetID.isNull() )
  167. {
  168. if (!instance()->mBeaconText)
  169. {
  170. instance()->mBeaconText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
  171. instance()->mBeaconText->setDoFade(FALSE);
  172. }
  173. if (instance()->mHasLandmarkPosition)
  174. {
  175. F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->mTrackedPositionGlobal, 1.0f);
  176. if (   !instance()->mLandmarkHasBeenVisited
  177. && dist < DESTINATION_VISITED_RADIUS )
  178. {
  179. // its close enough ==> flag as visited
  180. instance()->setLandmarkVisited();
  181. }
  182. if (   !instance()->mHasReachedLandmark 
  183. && dist < DESTINATION_REACHED_RADIUS )
  184. {
  185. // its VERY CLOSE ==> automatically stop tracking
  186. instance()->stopTrackingLandmark();
  187. }
  188. else
  189. {
  190. if (    instance()->mHasReachedLandmark 
  191.  && dist > DESTINATION_UNVISITED_RADIUS )
  192. {
  193. // this is so that landmark beacons don't immediately 
  194. // disappear when they're created only a few meters 
  195. // away, yet disappear when the agent wanders away 
  196. // and back again
  197. instance()->mHasReachedLandmark = FALSE;
  198. }
  199. renderBeacon( instance()->mTrackedPositionGlobal, map_track_color, 
  200.   instance()->mBeaconText, instance()->mTrackedLandmarkName );
  201. }
  202. }
  203. else
  204. {
  205. // probably just finished downloading the asset
  206. instance()->cacheLandmarkPosition();
  207. }
  208. }
  209. else
  210. {
  211. // Avatar beacon
  212. LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
  213. if(av_tracker.haveTrackingInfo())
  214. {
  215. if (!instance()->mBeaconText)
  216. {
  217. instance()->mBeaconText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
  218. instance()->mBeaconText->setDoFade(FALSE);
  219. }
  220. F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->mTrackedPositionGlobal, 0.0f);
  221. if (dist < DESTINATION_REACHED_RADIUS)
  222. {
  223. instance()->stopTrackingAvatar();
  224. }
  225. else
  226. {
  227. renderBeacon( av_tracker.getGlobalPos(), map_track_color, 
  228.    instance()->mBeaconText, av_tracker.getName() );
  229. }
  230. }
  231. else
  232. {
  233. BOOL stop_tracking = FALSE;
  234. const LLUUID& avatar_id = av_tracker.getAvatarID();
  235. if(avatar_id.isNull())
  236. {
  237. stop_tracking = TRUE;
  238. }
  239. else 
  240. {
  241. const LLRelationship* buddy = av_tracker.getBuddyInfo(avatar_id);
  242. if(buddy && !buddy->isOnline() && !gAgent.isGodlike())
  243. {
  244. stop_tracking = TRUE;
  245. }
  246. if(!buddy && !gAgent.isGodlike())
  247. {
  248. stop_tracking = TRUE;
  249. }
  250. }
  251. if(stop_tracking)
  252. {
  253. instance()->stopTrackingAvatar();
  254. }
  255. }
  256. }
  257. }
  258. // static 
  259. void LLTracker::trackAvatar( const LLUUID& avatar_id, const std::string& name )
  260. {
  261. instance()->stopTrackingLandmark();
  262. instance()->stopTrackingLocation();
  263. LLAvatarTracker::instance().track( avatar_id, name );
  264. instance()->mTrackingStatus = TRACKING_AVATAR;
  265. instance()->mLabel = name;
  266. instance()->mToolTip = "";
  267. }
  268. // static 
  269. void LLTracker::trackLandmark( const LLUUID& asset_id, const LLUUID& item_id, const std::string& name)
  270. {
  271. instance()->stopTrackingAvatar();
  272. instance()->stopTrackingLocation();
  273.   instance()->mTrackedLandmarkAssetID = asset_id;
  274.   instance()->mTrackedLandmarkItemID = item_id;
  275.   instance()->mTrackedLandmarkName = name;
  276. instance()->cacheLandmarkPosition();
  277. instance()->mTrackingStatus = TRACKING_LANDMARK;
  278. instance()->mLabel = name;
  279. instance()->mToolTip = "";
  280. }
  281. // static 
  282. void LLTracker::trackLocation(const LLVector3d& pos_global, const std::string& full_name, const std::string& tooltip, ETrackingLocationType location_type)
  283. {
  284. instance()->stopTrackingAvatar();
  285. instance()->stopTrackingLandmark();
  286. instance()->mTrackedPositionGlobal = pos_global;
  287. instance()->mTrackedLocationName = full_name;
  288. instance()->mIsTrackingLocation = TRUE;
  289. instance()->mTrackingStatus = TRACKING_LOCATION;
  290. instance()->mTrackingLocationType = location_type;
  291. instance()->mLabel = full_name;
  292. instance()->mToolTip = tooltip;
  293. }
  294. // static 
  295. BOOL LLTracker::handleMouseDown(S32 x, S32 y)
  296. {
  297. BOOL eat_mouse_click = FALSE;
  298. // fortunately, we can always compute the tracking arrow center
  299. S32 dist_sqrd = (x - instance()->mHUDArrowCenterX) * (x - instance()->mHUDArrowCenterX) + 
  300. (y - instance()->mHUDArrowCenterY) * (y - instance()->mHUDArrowCenterY);
  301. if (dist_sqrd < ARROW_OFF_RADIUS_SQRD)
  302. {
  303. /* tracking autopilot destination has been disabled
  304.    -- 2004.01.09, Leviathan
  305. // turn off tracking
  306. if (gAgent.getAutoPilot())
  307. {
  308. gAgent.stopAutoPilot(TRUE); // TRUE because cancelled by user
  309. eat_mouse_click = TRUE;
  310. }
  311. */
  312. if (getTrackingStatus())
  313. {
  314. instance()->stopTrackingAll();
  315. eat_mouse_click = TRUE;
  316. }
  317. }
  318. return eat_mouse_click;
  319. }
  320. // static 
  321. LLVector3d LLTracker::getTrackedPositionGlobal()
  322. {
  323. LLVector3d pos_global;
  324. switch (getTrackingStatus())
  325. {
  326. case TRACKING_AVATAR:
  327. {
  328. LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
  329. if (av_tracker.haveTrackingInfo())
  330. {
  331. pos_global = av_tracker.getGlobalPos(); }
  332. break;
  333. }
  334. case TRACKING_LANDMARK:
  335. if( instance()->mHasLandmarkPosition )
  336. {
  337. pos_global = instance()->mTrackedPositionGlobal;
  338. }
  339. break;
  340. case TRACKING_LOCATION:
  341. pos_global = instance()->mTrackedPositionGlobal;
  342. break;
  343. default:
  344. break;
  345. }
  346. return pos_global;
  347. }
  348. // static
  349. BOOL LLTracker::hasLandmarkPosition()
  350. {
  351. if (!instance()->mHasLandmarkPosition)
  352. {
  353. // maybe we just received the landmark position info
  354. instance()->cacheLandmarkPosition();
  355. }
  356. return instance()->mHasLandmarkPosition;
  357. }
  358. // static
  359. const std::string& LLTracker::getTrackedLocationName()
  360. {
  361. return instance()->mTrackedLocationName;
  362. }
  363. F32 pulse_func(F32 t, F32 z)
  364. {
  365. if (!LLTracker::sCheesyBeacon)
  366. {
  367. return 0.f;
  368. }
  369. t *= F_PI;
  370. z -= t*64.f - 256.f;
  371. F32 a = cosf(z*F_PI/512.f)*10.0f;
  372. a = llmax(a, 9.9f);
  373. a -= 9.9f;
  374. a *= 10.f;
  375. return a;
  376. }
  377. void draw_shockwave(F32 center_z, F32 t, S32 steps, LLColor4 color)
  378. {
  379. if (!LLTracker::sCheesyBeacon)
  380. {
  381. return;
  382. }
  383. t *= 0.6284f/F_PI;
  384. t -= (F32) (S32) t;
  385. t = llmax(t, 0.5f);
  386. t -= 0.5f;
  387. t *= 2.0f;
  388. F32 radius = t*16536.f;
  389. // Inexact, but reasonably fast.
  390. F32 delta = F_TWO_PI / steps;
  391. F32 sin_delta = sin( delta );
  392. F32 cos_delta = cos( delta );
  393. F32 x = radius;
  394. F32 y = 0.f;
  395. LLColor4 ccol = LLColor4(1,1,1,(1.f-t)*0.25f);
  396. gGL.begin(LLRender::TRIANGLE_FAN);
  397. gGL.color4fv(ccol.mV);
  398. gGL.vertex3f(0.f, 0.f, center_z);
  399. // make sure circle is complete
  400. steps += 1;
  401. color.mV[3] = (1.f-t*t);
  402. gGL.color4fv(color.mV);
  403. while( steps-- )
  404. {
  405. // Successive rotations
  406. gGL.vertex3f( x, y, center_z );
  407. F32 x_new = x * cos_delta - y * sin_delta;
  408. y = x * sin_delta +  y * cos_delta;
  409. x = x_new;
  410. }
  411. gGL.end();
  412. }
  413. // static 
  414. void LLTracker::renderBeacon(LLVector3d pos_global, 
  415.  const LLColor4& color, 
  416.  LLHUDText* hud_textp, 
  417.  const std::string& label )
  418. {
  419. sCheesyBeacon = gSavedSettings.getBOOL("CheesyBeacon");
  420. LLVector3d to_vec = pos_global - gAgent.getCameraPositionGlobal();
  421. F32 dist = (F32)to_vec.magVec();
  422. F32 color_frac = 1.f;
  423. if (dist > 0.99f * LLViewerCamera::getInstance()->getFar())
  424. {
  425. color_frac = 0.4f;
  426. // pos_global = gAgent.getCameraPositionGlobal() + 0.99f*(LLViewerCamera::getInstance()->getFar()/dist)*to_vec;
  427. }
  428. else
  429. {
  430. color_frac = 1.f - 0.6f*(dist/LLViewerCamera::getInstance()->getFar());
  431. }
  432. LLColor4 fogged_color = color_frac * color + (1 - color_frac)*gSky.getFogColor();
  433. F32 FADE_DIST = 3.f;
  434. fogged_color.mV[3] = llmax(0.2f, llmin(0.5f,(dist-FADE_DIST)/FADE_DIST));
  435. LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(pos_global);
  436. LLGLSTracker gls_tracker; // default+ CULL_FACE + LIGHTING + GL_BLEND + GL_ALPHA_TEST
  437. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  438. LLGLDisable cull_face(GL_CULL_FACE);
  439. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
  440. glMatrixMode(GL_MODELVIEW);
  441. glPushMatrix();
  442. glTranslatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
  443. draw_shockwave(1024.f, gRenderStartTime.getElapsedTimeF32(), 32, fogged_color);
  444. gGL.color4fv(fogged_color.mV);
  445. const U32 BEACON_VERTS = 256;
  446. const F32 step = 1024.0f/BEACON_VERTS;
  447. LLVector3 x_axis = LLViewerCamera::getInstance()->getLeftAxis();
  448. F32 t = gRenderStartTime.getElapsedTimeF32();
  449. F32 dr = dist/LLViewerCamera::getInstance()->getFar();
  450. for (U32 i = 0; i < BEACON_VERTS; i++)
  451. {
  452. F32 x = x_axis.mV[0];
  453. F32 y = x_axis.mV[1];
  454. F32 z = i * step;
  455. F32 z_next = (i+1)*step;
  456. F32 a = pulse_func(t, z);
  457. F32 an = pulse_func(t, z_next);
  458. LLColor4 c_col = fogged_color + LLColor4(a,a,a,a);
  459. LLColor4 col_next = fogged_color + LLColor4(an,an,an,an);
  460. LLColor4 col_edge = fogged_color * LLColor4(a,a,a,0.0f);
  461. LLColor4 col_edge_next = fogged_color * LLColor4(an,an,an,0.0f);
  462. a *= 2.f;
  463. a += 1.0f+dr;
  464. an *= 2.f;
  465. an += 1.0f+dr;
  466. gGL.begin(LLRender::TRIANGLE_STRIP);
  467. gGL.color4fv(col_edge.mV);
  468. gGL.vertex3f(-x*a, -y*a, z);
  469. gGL.color4fv(col_edge_next.mV);
  470. gGL.vertex3f(-x*an, -y*an, z_next);
  471. gGL.color4fv(c_col.mV);
  472. gGL.vertex3f(0, 0, z);
  473. gGL.color4fv(col_next.mV);
  474. gGL.vertex3f(0, 0, z_next);
  475. gGL.color4fv(col_edge.mV);
  476. gGL.vertex3f(x*a,y*a,z);
  477. gGL.color4fv(col_edge_next.mV);
  478. gGL.vertex3f(x*an,y*an,z_next);
  479. gGL.end();
  480. }
  481. //gCylinder.render(1000);
  482. glPopMatrix();
  483. std::string text;
  484. text = llformat( "%.0f m", to_vec.magVec());
  485. LLWString wstr;
  486. wstr += utf8str_to_wstring(label);
  487. wstr += 'n';
  488. wstr += utf8str_to_wstring(text);
  489. hud_textp->setFont(LLFontGL::getFontSansSerif());
  490. hud_textp->setZCompare(FALSE);
  491. hud_textp->setColor(LLColor4(1.f, 1.f, 1.f, llmax(0.2f, llmin(1.f,(dist-FADE_DIST)/FADE_DIST))));
  492. hud_textp->setString(wstr);
  493. hud_textp->setVertAlignment(LLHUDText::ALIGN_VERT_CENTER);
  494. hud_textp->setPositionAgent(pos_agent);
  495. }
  496. void LLTracker::stopTrackingAll(BOOL clear_ui)
  497. {
  498. switch (mTrackingStatus)
  499. {
  500. case TRACKING_AVATAR :
  501. stopTrackingAvatar(clear_ui);
  502. break;
  503. case TRACKING_LANDMARK :
  504. stopTrackingLandmark(clear_ui);
  505. break;
  506. case TRACKING_LOCATION :
  507. stopTrackingLocation(clear_ui);
  508. break;
  509. default:
  510. mTrackingStatus = TRACKING_NOTHING;
  511. break;
  512. }
  513. }
  514. void LLTracker::stopTrackingAvatar(BOOL clear_ui)
  515. {
  516. LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
  517. if( !av_tracker.getAvatarID().isNull() )
  518. {
  519. av_tracker.untrack( av_tracker.getAvatarID() );
  520. }
  521. purgeBeaconText();
  522. gFloaterWorldMap->clearAvatarSelection(clear_ui);
  523. mTrackingStatus = TRACKING_NOTHING;
  524. }
  525. void LLTracker::stopTrackingLandmark(BOOL clear_ui)
  526. {
  527. purgeBeaconText();
  528. mTrackedLandmarkAssetID.setNull();
  529. mTrackedLandmarkItemID.setNull();
  530. mTrackedLandmarkName.assign("");
  531. mTrackedPositionGlobal.zeroVec();
  532. mHasLandmarkPosition = FALSE;
  533. mHasReachedLandmark = FALSE;
  534. mLandmarkHasBeenVisited = TRUE;
  535. gFloaterWorldMap->clearLandmarkSelection(clear_ui);
  536. mTrackingStatus = TRACKING_NOTHING;
  537. }
  538. void LLTracker::stopTrackingLocation(BOOL clear_ui)
  539. {
  540. purgeBeaconText();
  541. mTrackedLocationName.assign("");
  542. mIsTrackingLocation = FALSE;
  543. mTrackedPositionGlobal.zeroVec();
  544. gFloaterWorldMap->clearLocationSelection(clear_ui);
  545. mTrackingStatus = TRACKING_NOTHING;
  546. mTrackingLocationType = LOCATION_NOTHING;
  547. }
  548. void LLTracker::clearFocus()
  549. {
  550. instance()->mTrackingStatus = TRACKING_NOTHING;
  551. }
  552. void LLTracker::drawMarker(const LLVector3d& pos_global, const LLColor4& color)
  553. {
  554. // get position
  555. LLVector3 pos_local = gAgent.getPosAgentFromGlobal(pos_global);
  556. // check in frustum
  557. LLCoordGL screen;
  558. S32 x = 0;
  559. S32 y = 0;
  560. const BOOL CLAMP = TRUE;
  561. if (LLViewerCamera::getInstance()->projectPosAgentToScreen(pos_local, screen, CLAMP)
  562. || LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(pos_local, screen) )
  563. {
  564. gHUDView->screenPointToLocal(screen.mX, screen.mY, &x, &y);
  565. // the center of the rendered position of the arrow obeys 
  566. // the following rules:
  567. // (1) it lies on an ellipse centered on the target position 
  568. // (2) it lies on the line between the target and the window center
  569. // (3) right now the radii of the ellipse are fixed, but eventually
  570. //     they will be a function of the target text
  571. // 
  572. // from those rules we can compute the position of the 
  573. // lower left corner of the image
  574. LLRect rect = gHUDView->getRect();
  575. S32 x_center = lltrunc(0.5f * (F32)rect.getWidth());
  576. S32 y_center = lltrunc(0.5f * (F32)rect.getHeight());
  577. x = x - x_center; // x and y relative to center
  578. y = y - y_center;
  579. F32 dist = sqrt((F32)(x*x + y*y));
  580. S32 half_arrow_size = lltrunc(0.5f * HUD_ARROW_SIZE);
  581. if (dist > 0.f)
  582. {
  583. const F32 ARROW_ELLIPSE_RADIUS_X = 2 * HUD_ARROW_SIZE;
  584. const F32 ARROW_ELLIPSE_RADIUS_Y = HUD_ARROW_SIZE;
  585. // compute where the arrow should be
  586. F32 x_target = (F32)(x + x_center) - (ARROW_ELLIPSE_RADIUS_X * ((F32)x / dist) );
  587. F32 y_target = (F32)(y + y_center) - (ARROW_ELLIPSE_RADIUS_Y * ((F32)y / dist) );
  588. // keep the arrow within the window
  589. F32 x_clamped = llclamp( x_target, (F32)half_arrow_size, (F32)(rect.getWidth() - half_arrow_size));
  590. F32 y_clamped = llclamp( y_target, (F32)half_arrow_size, (F32)(rect.getHeight() - half_arrow_size));
  591. F32 slope = (F32)(y) / (F32)(x);
  592. F32 window_ratio = (F32)(rect.getHeight() - HUD_ARROW_SIZE) / (F32)(rect.getWidth() - HUD_ARROW_SIZE);
  593. // if the arrow has been clamped on one axis
  594. // then we need to compute the other axis
  595. if (llabs(slope) > window_ratio)
  596. {  
  597. if (y_clamped != (F32)y_target)
  598. {
  599. // clamp by y 
  600. x_clamped = (y_clamped - (F32)y_center) / slope + (F32)x_center;
  601. }
  602. }
  603. else if (x_clamped != (F32)x_target)
  604. {
  605. // clamp by x
  606. y_clamped = (x_clamped - (F32)x_center) * slope + (F32)y_center;
  607. }
  608. mHUDArrowCenterX = lltrunc(x_clamped);
  609. mHUDArrowCenterY = lltrunc(y_clamped);
  610. }
  611. else
  612. {
  613. // recycle the old values
  614. x = mHUDArrowCenterX - x_center;
  615. y = mHUDArrowCenterY - y_center;
  616. }
  617. F32 angle = atan2( (F32)y, (F32)x );
  618. gl_draw_scaled_rotated_image(mHUDArrowCenterX - half_arrow_size, 
  619.  mHUDArrowCenterY - half_arrow_size, 
  620.  HUD_ARROW_SIZE, HUD_ARROW_SIZE, 
  621.  RAD_TO_DEG * angle, 
  622.  LLWorldMapView::sTrackArrowImage->getImage(), 
  623.  color);
  624. }
  625. }
  626. void LLTracker::setLandmarkVisited()
  627. {
  628. // poke the inventory item
  629. if (!mTrackedLandmarkItemID.isNull())
  630. {
  631. LLInventoryItem* i = gInventory.getItem( mTrackedLandmarkItemID );
  632. LLViewerInventoryItem* item = (LLViewerInventoryItem*)i;
  633. if (   item 
  634. && !(item->getFlags()&LLInventoryItem::II_FLAGS_LANDMARK_VISITED))
  635. {
  636. U32 flags = item->getFlags();
  637. flags |= LLInventoryItem::II_FLAGS_LANDMARK_VISITED;
  638. item->setFlags(flags);
  639. LLMessageSystem* msg = gMessageSystem;
  640. msg->newMessage("ChangeInventoryItemFlags");
  641. msg->nextBlock("AgentData");
  642. msg->addUUID("AgentID", gAgent.getID());
  643. msg->addUUID("SessionID", gAgent.getSessionID());
  644. msg->nextBlock("InventoryData");
  645. msg->addUUID("ItemID", mTrackedLandmarkItemID);
  646. msg->addU32("Flags", flags);
  647. gAgent.sendReliableMessage();
  648. LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0);
  649. gInventory.accountForUpdate(up);
  650. // need to communicate that the icon needs to change...
  651. gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item->getUUID());
  652. gInventory.notifyObservers();
  653. }
  654. }
  655. }
  656. void LLTracker::cacheLandmarkPosition()
  657. {
  658. // the landmark asset download may have finished, in which case
  659. // we'll now be able to figure out where we're trying to go
  660. BOOL found_landmark = FALSE;
  661. if( mTrackedLandmarkAssetID == LLFloaterWorldMap::getHomeID())
  662. {
  663. LLVector3d pos_global;
  664. if ( gAgent.getHomePosGlobal( &mTrackedPositionGlobal ))
  665. {
  666. found_landmark = TRUE;
  667. }
  668. else
  669. {
  670. llwarns << "LLTracker couldn't find home pos" << llendl;
  671. mTrackedLandmarkAssetID.setNull();
  672. mTrackedLandmarkItemID.setNull();
  673. }
  674. }
  675. else
  676. {
  677. LLLandmark* landmark = gLandmarkList.getAsset(mTrackedLandmarkAssetID);
  678. if(landmark && landmark->getGlobalPos(mTrackedPositionGlobal))
  679. {
  680. found_landmark = TRUE;
  681. // cache the object's visitation status
  682. mLandmarkHasBeenVisited = FALSE;
  683. LLInventoryItem* item = gInventory.getItem(mTrackedLandmarkItemID);
  684. if (   item 
  685. && item->getFlags()&LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
  686. {
  687. mLandmarkHasBeenVisited = TRUE;
  688. }
  689. }
  690. }
  691. if ( found_landmark && gFloaterWorldMap )
  692. {
  693. mHasReachedLandmark = FALSE;
  694. F32 dist = gFloaterWorldMap->getDistanceToDestination(mTrackedPositionGlobal, 1.0f);
  695. if ( dist < DESTINATION_UNVISITED_RADIUS )
  696. {
  697. mHasReachedLandmark = TRUE;
  698. }
  699. mHasLandmarkPosition = TRUE;
  700. }
  701. mHasLandmarkPosition = found_landmark;
  702. }
  703. void LLTracker::purgeBeaconText()
  704. {
  705. if(!mBeaconText.isNull())
  706. {
  707. mBeaconText->markDead();
  708. mBeaconText = NULL;
  709. }
  710. }