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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llnetmap.cpp
  3.  * @author James Cook
  4.  * @brief Display of surrounding regions, objects, and agents. 
  5.  *
  6.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  7.  * 
  8.  * Copyright (c) 2001-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #include "llviewerprecompiledheaders.h"
  34. #include "llnetmap.h"
  35. // Library includes (should move below)
  36. #include "indra_constants.h"
  37. #include "llmath.h"
  38. #include "llfloaterreg.h"
  39. #include "llfocusmgr.h"
  40. #include "lllocalcliprect.h"
  41. #include "llrender.h"
  42. #include "llui.h"
  43. #include "lltooltip.h"
  44. #include "llglheaders.h"
  45. // Viewer includes
  46. #include "llagent.h"
  47. #include "llappviewer.h" // for gDisconnected
  48. #include "llcallingcard.h" // LLAvatarTracker
  49. #include "lltracker.h"
  50. #include "llsurface.h"
  51. #include "llviewercamera.h"
  52. #include "llviewercontrol.h"
  53. #include "llviewertexture.h"
  54. #include "llviewertexturelist.h"
  55. #include "llviewermenu.h"
  56. #include "llviewerobjectlist.h"
  57. #include "llviewerregion.h"
  58. #include "llworld.h"
  59. #include "llworldmapview.h" // shared draw code
  60. static LLDefaultChildRegistry::Register<LLNetMap> r1("net_map");
  61. const F32 LLNetMap::MAP_SCALE_MIN = 32;
  62. const F32 LLNetMap::MAP_SCALE_MID = 1024;
  63. const F32 LLNetMap::MAP_SCALE_MAX = 4096;
  64. const F32 MAP_SCALE_INCREMENT = 16;
  65. const F32 MAP_SCALE_ZOOM_FACTOR = 1.04f; // Zoom in factor per click of scroll wheel (4%)
  66. const F32 MIN_DOT_RADIUS = 3.5f;
  67. const F32 DOT_SCALE = 0.75f;
  68. const F32 MIN_PICK_SCALE = 2.f;
  69. LLNetMap::LLNetMap (const Params & p)
  70. : LLUICtrl (p),
  71. mBackgroundColor (p.bg_color()),
  72. mScale( MAP_SCALE_MID ),
  73. mPixelsPerMeter( MAP_SCALE_MID / REGION_WIDTH_METERS ),
  74. mObjectMapTPM(0.f),
  75. mObjectMapPixels(0.f),
  76. mTargetPanX(0.f),
  77. mTargetPanY(0.f),
  78. mCurPanX(0.f),
  79. mCurPanY(0.f),
  80. mUpdateNow(FALSE),
  81. mObjectImageCenterGlobal( gAgent.getCameraPositionGlobal() ),
  82. mObjectRawImagep(),
  83. mObjectImagep(),
  84. mClosestAgentToCursor(),
  85. mClosestAgentAtLastRightClick(),
  86. mToolTipMsg()
  87. {
  88. mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
  89. }
  90. LLNetMap::~LLNetMap()
  91. {
  92. }
  93. void LLNetMap::setScale( F32 scale )
  94. {
  95. mScale = llclamp(scale, 0.1f, 16.f*1024.f); // [reasonably small , unreasonably large]
  96. if (mObjectImagep.notNull())
  97. {
  98. F32 width = (F32)(getRect().getWidth());
  99. F32 height = (F32)(getRect().getHeight());
  100. F32 diameter = sqrt(width * width + height * height);
  101. F32 region_widths = diameter / mScale;
  102. F32 meters = region_widths * LLWorld::getInstance()->getRegionWidthInMeters();
  103. F32 num_pixels = (F32)mObjectImagep->getWidth();
  104. mObjectMapTPM = num_pixels / meters;
  105. mObjectMapPixels = diameter;
  106. }
  107. mPixelsPerMeter = mScale / REGION_WIDTH_METERS;
  108. mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
  109. mUpdateNow = TRUE;
  110. }
  111. void LLNetMap::translatePan( F32 delta_x, F32 delta_y )
  112. {
  113. mTargetPanX += delta_x;
  114. mTargetPanY += delta_y;
  115. }
  116. ///////////////////////////////////////////////////////////////////////////////////
  117. void LLNetMap::draw()
  118. {
  119.   static LLFrameTimer map_timer;
  120. static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white);
  121. static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white);
  122. static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
  123. static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white);
  124. static LLUIColor map_frustum_color = LLUIColorTable::instance().getColor("MapFrustumColor", LLColor4::white);
  125. static LLUIColor map_frustum_rotating_color = LLUIColorTable::instance().getColor("MapFrustumRotatingColor", LLColor4::white);
  126. if (mObjectImagep.isNull())
  127. {
  128. createObjectImage();
  129. }
  130. mCurPanX = lerp(mCurPanX, mTargetPanX, LLCriticalDamp::getInterpolant(0.1f));
  131. mCurPanY = lerp(mCurPanY, mTargetPanY, LLCriticalDamp::getInterpolant(0.1f));
  132. // Prepare a scissor region
  133. F32 rotation = 0;
  134. {
  135. LLLocalClipRect clip(getLocalRect());
  136. {
  137. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  138. glMatrixMode(GL_MODELVIEW);
  139. // Draw background rectangle
  140. LLColor4 background_color = mBackgroundColor.get();
  141. gGL.color4fv( background_color.mV );
  142. gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0);
  143. }
  144. // region 0,0 is in the middle
  145. S32 center_sw_left = getRect().getWidth() / 2 + llfloor(mCurPanX);
  146. S32 center_sw_bottom = getRect().getHeight() / 2 + llfloor(mCurPanY);
  147. gGL.pushMatrix();
  148. gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f);
  149. static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
  150. if( rotate_map )
  151. {
  152. // rotate subsequent draws to agent rotation
  153. rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
  154. glRotatef( rotation * RAD_TO_DEG, 0.f, 0.f, 1.f);
  155. }
  156. // figure out where agent is
  157. S32 region_width = llround(LLWorld::getInstance()->getRegionWidthInMeters());
  158. for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
  159.  iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
  160. {
  161. LLViewerRegion* regionp = *iter;
  162. // Find x and y position relative to camera's center.
  163. LLVector3 origin_agent = regionp->getOriginAgent();
  164. LLVector3 rel_region_pos = origin_agent - gAgent.getCameraPositionAgent();
  165. F32 relative_x = (rel_region_pos.mV[0] / region_width) * mScale;
  166. F32 relative_y = (rel_region_pos.mV[1] / region_width) * mScale;
  167. // background region rectangle
  168. F32 bottom = relative_y;
  169. F32 left = relative_x;
  170. F32 top = bottom + mScale ;
  171. F32 right = left + mScale ;
  172. if (regionp == gAgent.getRegion())
  173. {
  174. gGL.color4f(1.f, 1.f, 1.f, 1.f);
  175. }
  176. else
  177. {
  178. gGL.color4f(0.8f, 0.8f, 0.8f, 1.f);
  179. }
  180. if (!regionp->isAlive())
  181. {
  182. gGL.color4f(1.f, 0.5f, 0.5f, 1.f);
  183. }
  184. // Draw using texture.
  185. gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture());
  186. gGL.begin(LLRender::QUADS);
  187. gGL.texCoord2f(0.f, 1.f);
  188. gGL.vertex2f(left, top);
  189. gGL.texCoord2f(0.f, 0.f);
  190. gGL.vertex2f(left, bottom);
  191. gGL.texCoord2f(1.f, 0.f);
  192. gGL.vertex2f(right, bottom);
  193. gGL.texCoord2f(1.f, 1.f);
  194. gGL.vertex2f(right, top);
  195. gGL.end();
  196. // Draw water
  197. gGL.setAlphaRejectSettings(LLRender::CF_GREATER, ABOVE_WATERLINE_ALPHA / 255.f);
  198. {
  199. if (regionp->getLand().getWaterTexture())
  200. {
  201. gGL.getTexUnit(0)->bind(regionp->getLand().getWaterTexture());
  202. gGL.begin(LLRender::QUADS);
  203. gGL.texCoord2f(0.f, 1.f);
  204. gGL.vertex2f(left, top);
  205. gGL.texCoord2f(0.f, 0.f);
  206. gGL.vertex2f(left, bottom);
  207. gGL.texCoord2f(1.f, 0.f);
  208. gGL.vertex2f(right, bottom);
  209. gGL.texCoord2f(1.f, 1.f);
  210. gGL.vertex2f(right, top);
  211. gGL.end();
  212. }
  213. }
  214. gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
  215. }
  216. LLVector3d old_center = mObjectImageCenterGlobal;
  217. LLVector3d new_center = gAgent.getCameraPositionGlobal();
  218. new_center.mdV[0] = (5.f/mObjectMapTPM)*floor(0.2f*mObjectMapTPM*new_center.mdV[0]);
  219. new_center.mdV[1] = (5.f/mObjectMapTPM)*floor(0.2f*mObjectMapTPM*new_center.mdV[1]);
  220. new_center.mdV[2] = 0.f;
  221. if (mUpdateNow || (map_timer.getElapsedTimeF32() > 0.5f))
  222. {
  223. mUpdateNow = FALSE;
  224. mObjectImageCenterGlobal = new_center;
  225. // Center moved enough.
  226. // Create the base texture.
  227. U8 *default_texture = mObjectRawImagep->getData();
  228. memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );
  229. // Draw buildings
  230. gObjectList.renderObjectsForMap(*this);
  231. mObjectImagep->setSubImage(mObjectRawImagep, 0, 0, mObjectImagep->getWidth(), mObjectImagep->getHeight());
  232. map_timer.reset();
  233. }
  234. LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal);
  235. map_center_agent -= gAgent.getCameraPositionAgent();
  236. map_center_agent.mV[VX] *= mScale/region_width;
  237. map_center_agent.mV[VY] *= mScale/region_width;
  238. gGL.getTexUnit(0)->bind(mObjectImagep);
  239. F32 image_half_width = 0.5f*mObjectMapPixels;
  240. F32 image_half_height = 0.5f*mObjectMapPixels;
  241. gGL.begin(LLRender::QUADS);
  242. gGL.texCoord2f(0.f, 1.f);
  243. gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]);
  244. gGL.texCoord2f(0.f, 0.f);
  245. gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height);
  246. gGL.texCoord2f(1.f, 0.f);
  247. gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height);
  248. gGL.texCoord2f(1.f, 1.f);
  249. gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]);
  250. gGL.end();
  251. gGL.popMatrix();
  252. LLVector3d pos_global;
  253. LLVector3 pos_map;
  254. // Mouse pointer in local coordinates
  255. S32 local_mouse_x;
  256. S32 local_mouse_y;
  257. //localMouse(&local_mouse_x, &local_mouse_y);
  258. LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
  259. mClosestAgentToCursor.setNull();
  260. F32 closest_dist = F32_MAX;
  261. F32 min_pick_dist = mDotRadius * MIN_PICK_SCALE; 
  262. // Draw avatars
  263. for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
  264.  iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
  265. {
  266. LLViewerRegion* regionp = *iter;
  267. const LLVector3d& origin_global = regionp->getOriginGlobal();
  268. S32 count = regionp->mMapAvatars.count();
  269. S32 i;
  270. LLVector3 pos_local;
  271. U32 compact_local;
  272. U8 bits;
  273. // TODO: it'd be very cool to draw these in sorted order from lowest Z to highest.
  274. // just be careful to sort the avatar IDs along with the positions. -MG
  275. for (i = 0; i < count; i++)
  276. {
  277. compact_local = regionp->mMapAvatars.get(i);
  278. bits = compact_local & 0xFF;
  279. pos_local.mV[VZ] = F32(bits) * 4.f;
  280. compact_local >>= 8;
  281. bits = compact_local & 0xFF;
  282. pos_local.mV[VY] = (F32)bits;
  283. compact_local >>= 8;
  284. bits = compact_local & 0xFF;
  285. pos_local.mV[VX] = (F32)bits;
  286. pos_global.setVec( pos_local );
  287. pos_global += origin_global;
  288. pos_map = globalPosToView(pos_global);
  289. BOOL show_as_friend = FALSE;
  290. if( i < regionp->mMapAvatarIDs.count())
  291. {
  292. show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(regionp->mMapAvatarIDs.get(i)) != NULL);
  293. }
  294. LLWorldMapView::drawAvatar(
  295. pos_map.mV[VX], pos_map.mV[VY], 
  296. show_as_friend ? map_avatar_friend_color : map_avatar_color, 
  297. pos_map.mV[VZ], mDotRadius);
  298. F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y));
  299. if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist)
  300. {
  301. closest_dist = dist_to_cursor;
  302. mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i);
  303. }
  304. }
  305. }
  306. // Draw dot for autopilot target
  307. if (gAgent.getAutoPilot())
  308. {
  309. drawTracking( gAgent.getAutoPilotTargetGlobal(), map_track_color );
  310. }
  311. else
  312. {
  313. LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
  314. if (  LLTracker::TRACKING_AVATAR == tracking_status )
  315. {
  316. drawTracking( LLAvatarTracker::instance().getGlobalPos(), map_track_color );
  317. else if ( LLTracker::TRACKING_LANDMARK == tracking_status 
  318. || LLTracker::TRACKING_LOCATION == tracking_status )
  319. {
  320. drawTracking( LLTracker::getTrackedPositionGlobal(), map_track_color );
  321. }
  322. }
  323. // Draw dot for self avatar position
  324. pos_global = gAgent.getPositionGlobal();
  325. pos_map = globalPosToView(pos_global);
  326. LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage;
  327. S32 dot_width = llround(mDotRadius * 2.f);
  328. you->draw(llround(pos_map.mV[VX] - mDotRadius),
  329.   llround(pos_map.mV[VY] - mDotRadius),
  330.   dot_width,
  331.   dot_width);
  332. // Draw frustum
  333. F32 meters_to_pixels = mScale/ LLWorld::getInstance()->getRegionWidthInMeters();
  334. F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect();
  335. F32 far_clip_meters = LLViewerCamera::getInstance()->getFar();
  336. F32 far_clip_pixels = far_clip_meters * meters_to_pixels;
  337. F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 );
  338. F32 half_width_pixels = half_width_meters * meters_to_pixels;
  339. F32 ctr_x = (F32)center_sw_left;
  340. F32 ctr_y = (F32)center_sw_bottom;
  341. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  342. if( rotate_map )
  343. {
  344. gGL.color4fv((map_frustum_color()).mV);
  345. gGL.begin( LLRender::TRIANGLES  );
  346. gGL.vertex2f( ctr_x, ctr_y );
  347. gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels );
  348. gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels );
  349. gGL.end();
  350. }
  351. else
  352. {
  353. gGL.color4fv((map_frustum_rotating_color()).mV);
  354. // If we don't rotate the map, we have to rotate the frustum.
  355. gGL.pushMatrix();
  356. gGL.translatef( ctr_x, ctr_y, 0 );
  357. glRotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f);
  358. gGL.begin( LLRender::TRIANGLES  );
  359. gGL.vertex2f( 0, 0 );
  360. gGL.vertex2f( -half_width_pixels, far_clip_pixels );
  361. gGL.vertex2f(  half_width_pixels, far_clip_pixels );
  362. gGL.end();
  363. gGL.popMatrix();
  364. }
  365. }
  366. LLUICtrl::draw();
  367. }
  368. void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent)
  369. {
  370. LLUICtrl::reshape(width, height, called_from_parent);
  371. createObjectImage();
  372. }
  373. LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )
  374. {
  375. LLVector3d relative_pos_global = global_pos - gAgent.getCameraPositionGlobal();
  376. LLVector3 pos_local;
  377. pos_local.setVec(relative_pos_global);  // convert to floats from doubles
  378. pos_local.mV[VX] *= mPixelsPerMeter;
  379. pos_local.mV[VY] *= mPixelsPerMeter;
  380. // leave Z component in meters
  381. static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
  382. if( rotate_map )
  383. {
  384. F32 radians = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
  385. LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
  386. pos_local.rotVec( rot );
  387. }
  388. pos_local.mV[VX] += getRect().getWidth() / 2 + mCurPanX;
  389. pos_local.mV[VY] += getRect().getHeight() / 2 + mCurPanY;
  390. return pos_local;
  391. }
  392. void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color, 
  393. BOOL draw_arrow )
  394. {
  395. LLVector3 pos_local = globalPosToView( pos_global );
  396. if( (pos_local.mV[VX] < 0) ||
  397. (pos_local.mV[VY] < 0) ||
  398. (pos_local.mV[VX] >= getRect().getWidth()) ||
  399. (pos_local.mV[VY] >= getRect().getHeight()) )
  400. {
  401. if (draw_arrow)
  402. {
  403. S32 x = llround( pos_local.mV[VX] );
  404. S32 y = llround( pos_local.mV[VY] );
  405. LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10 );
  406. LLWorldMapView::drawTrackingArrow( getRect(), x, y, color );
  407. }
  408. }
  409. else
  410. {
  411. LLWorldMapView::drawTrackingDot(pos_local.mV[VX], 
  412. pos_local.mV[VY], 
  413. color,
  414. pos_local.mV[VZ]);
  415. }
  416. }
  417. LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y )
  418. {
  419. x -= llround(getRect().getWidth() / 2 + mCurPanX);
  420. y -= llround(getRect().getHeight() / 2 + mCurPanY);
  421. LLVector3 pos_local( (F32)x, (F32)y, 0 );
  422. F32 radians = - atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
  423. static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
  424. if( rotate_map )
  425. {
  426. LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
  427. pos_local.rotVec( rot );
  428. }
  429. pos_local *= ( LLWorld::getInstance()->getRegionWidthInMeters() / mScale );
  430. LLVector3d pos_global;
  431. pos_global.setVec( pos_local );
  432. pos_global += gAgent.getCameraPositionGlobal();
  433. return pos_global;
  434. }
  435. BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
  436. {
  437. // note that clicks are reversed from what you'd think: i.e. > 0  means zoom out, < 0 means zoom in
  438. F32 scale = mScale;
  439.         
  440. scale *= pow(MAP_SCALE_ZOOM_FACTOR, -clicks);
  441. setScale(llclamp(scale, MAP_SCALE_MIN, MAP_SCALE_MAX));
  442. return TRUE;
  443. }
  444. BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
  445. {
  446. if (gDisconnected)
  447. {
  448. return FALSE;
  449. }
  450. // mToolTipMsg = "[AGENT][REGION](Double-click to open Map)"
  451. LLStringUtil::format_map_t args;
  452. std::string fullname;
  453. if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname))
  454. {
  455. args["[AGENT]"] = fullname + "n";
  456. }
  457. else
  458. {
  459. args["[AGENT]"] = "";
  460. }
  461. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) );
  462. if( region )
  463. {
  464. args["[REGION]"] = region->getName() + "n";
  465. }
  466. else
  467. {
  468. args["[REGION]"] = "";
  469. }
  470. std::string msg = mToolTipMsg;
  471. LLStringUtil::format(msg, args);
  472. LLRect sticky_rect;
  473. // set sticky_rect
  474. if (region)
  475. {
  476. S32 SLOP = 4;
  477. localPointToScreen( 
  478. x - SLOP, y - SLOP, 
  479. &(sticky_rect.mLeft), &(sticky_rect.mBottom) );
  480. sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP;
  481. sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP;
  482. }
  483. LLToolTipMgr::instance().show(LLToolTip::Params()
  484. .message(msg)
  485. .sticky_rect(sticky_rect));
  486. return TRUE;
  487. }
  488. void LLNetMap::renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius_meters )
  489. {
  490. LLVector3 local_pos;
  491. local_pos.setVec( pos - mObjectImageCenterGlobal );
  492. S32 diameter_pixels = llround(2 * radius_meters * mObjectMapTPM);
  493. renderPoint( local_pos, color, diameter_pixels );
  494. }
  495. void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color, 
  496.    S32 diameter, S32 relative_height)
  497. {
  498. if (diameter <= 0)
  499. {
  500. return;
  501. }
  502. const S32 image_width = (S32)mObjectImagep->getWidth();
  503. const S32 image_height = (S32)mObjectImagep->getHeight();
  504. S32 x_offset = llround(pos_local.mV[VX] * mObjectMapTPM + image_width / 2);
  505. S32 y_offset = llround(pos_local.mV[VY] * mObjectMapTPM + image_height / 2);
  506. if ((x_offset < 0) || (x_offset >= image_width))
  507. {
  508. return;
  509. }
  510. if ((y_offset < 0) || (y_offset >= image_height))
  511. {
  512. return;
  513. }
  514. U8 *datap = mObjectRawImagep->getData();
  515. S32 neg_radius = diameter / 2;
  516. S32 pos_radius = diameter - neg_radius;
  517. S32 x, y;
  518. if (relative_height > 0)
  519. {
  520. // ...point above agent
  521. S32 px, py;
  522. // vertical line
  523. px = x_offset;
  524. for (y = -neg_radius; y < pos_radius; y++)
  525. {
  526. py = y_offset + y;
  527. if ((py < 0) || (py >= image_height))
  528. {
  529. continue;
  530. }
  531. S32 offset = px + py * image_width;
  532. ((U32*)datap)[offset] = color.mAll;
  533. }
  534. // top line
  535. py = y_offset + pos_radius - 1;
  536. for (x = -neg_radius; x < pos_radius; x++)
  537. {
  538. px = x_offset + x;
  539. if ((px < 0) || (px >= image_width))
  540. {
  541. continue;
  542. }
  543. S32 offset = px + py * image_width;
  544. ((U32*)datap)[offset] = color.mAll;
  545. }
  546. }
  547. else
  548. {
  549. // ...point level with agent
  550. for (x = -neg_radius; x < pos_radius; x++)
  551. {
  552. S32 p_x = x_offset + x;
  553. if ((p_x < 0) || (p_x >= image_width))
  554. {
  555. continue;
  556. }
  557. for (y = -neg_radius; y < pos_radius; y++)
  558. {
  559. S32 p_y = y_offset + y;
  560. if ((p_y < 0) || (p_y >= image_height))
  561. {
  562. continue;
  563. }
  564. S32 offset = p_x + p_y * image_width;
  565. ((U32*)datap)[offset] = color.mAll;
  566. }
  567. }
  568. }
  569. }
  570. void LLNetMap::createObjectImage()
  571. {
  572. // Find the size of the side of a square that surrounds the circle that surrounds getRect().
  573. // ... which is, the diagonal of the rect.
  574. F32 width = (F32)getRect().getWidth();
  575. F32 height = (F32)getRect().getHeight();
  576. S32 square_size = llround( sqrt(width*width + height*height) );
  577. // Find the least power of two >= the minimum size.
  578. const S32 MIN_SIZE = 64;
  579. const S32 MAX_SIZE = 256;
  580. S32 img_size = MIN_SIZE;
  581. while( (img_size*2 < square_size ) && (img_size < MAX_SIZE) )
  582. {
  583. img_size <<= 1;
  584. }
  585. if( mObjectImagep.isNull() ||
  586. (mObjectImagep->getWidth() != img_size) ||
  587. (mObjectImagep->getHeight() != img_size) )
  588. {
  589. mObjectRawImagep = new LLImageRaw(img_size, img_size, 4);
  590. U8* data = mObjectRawImagep->getData();
  591. memset( data, 0, img_size * img_size * 4 );
  592. mObjectImagep = LLViewerTextureManager::getLocalTexture( mObjectRawImagep.get(), FALSE);
  593. }
  594. setScale(mScale);
  595. mUpdateNow = TRUE;
  596. }