00001
00033 #include "llviewerprecompiledheaders.h"
00034
00035 #include "llnetmap.h"
00036
00037 #include "indra_constants.h"
00038 #include "llui.h"
00039 #include "llmath.h"
00040 #include "llfocusmgr.h"
00041 #include "llglimmediate.h"
00042
00043 #include "llagent.h"
00044 #include "llcallingcard.h"
00045 #include "llcolorscheme.h"
00046 #include "llviewercontrol.h"
00047 #include "llfloaterworldmap.h"
00048 #include "llfloatermap.h"
00049 #include "llframetimer.h"
00050 #include "lltracker.h"
00051 #include "llmenugl.h"
00052 #include "llstatgraph.h"
00053 #include "llsurface.h"
00054 #include "lltextbox.h"
00055 #include "lluuid.h"
00056 #include "llviewercamera.h"
00057 #include "llviewerimage.h"
00058 #include "llviewerimagelist.h"
00059 #include "llviewermenu.h"
00060 #include "llviewerobjectlist.h"
00061 #include "llviewermenu.h"
00062 #include "llviewerparceloverlay.h"
00063 #include "llviewerregion.h"
00064 #include "llviewerwindow.h"
00065 #include "llvoavatar.h"
00066 #include "llworld.h"
00067 #include "llworldmapview.h"
00068 #include "llappviewer.h"
00069
00070 #include "llglheaders.h"
00071
00072 const F32 MAP_SCALE_MIN = 64;
00073 const F32 MAP_SCALE_MID = 172;
00074 const F32 MAP_SCALE_MAX = 512;
00075 const F32 MAP_SCALE_INCREMENT = 16;
00076
00077 const S32 TRACKING_RADIUS = 3;
00078
00079
00080 BOOL LLNetMap::sRotateMap = FALSE;
00081 LLNetMap* LLNetMap::sInstance = NULL;
00082
00083 LLNetMap::LLNetMap(
00084 const std::string& name,
00085 const LLRect& rect,
00086 const LLColor4& bg_color )
00087 :
00088 LLUICtrl(name, rect, FALSE, NULL, NULL), mBackgroundColor( bg_color ),
00089 mObjectMapTPM(1.f),
00090 mObjectMapPixels(255.f),
00091 mTargetPanX( 0.f ),
00092 mTargetPanY( 0.f ),
00093 mCurPanX( 0.f ),
00094 mCurPanY( 0.f ),
00095 mUpdateNow( FALSE )
00096 {
00097 mPixelsPerMeter = gMiniMapScale / REGION_WIDTH_METERS;
00098
00099 LLNetMap::sRotateMap = gSavedSettings.getBOOL( "MiniMapRotate" );
00100
00101
00102
00103
00104 mObjectImageCenterGlobal = gAgent.getCameraPositionGlobal();
00105
00106
00107 const S32 DIR_WIDTH = 10;
00108 const S32 DIR_HEIGHT = 10;
00109 LLRect major_dir_rect( 0, DIR_HEIGHT, DIR_WIDTH, 0 );
00110 const LLColor4 minor_color( 1.f, 1.f, 1.f, .7f );
00111 const LLRect minor_dir_rect( 0, DIR_HEIGHT, DIR_WIDTH * 2, 0 );
00112
00113
00114
00115
00116
00117 mTextBoxNorth = new LLTextBox( "N", major_dir_rect );
00118 mTextBoxNorth->setColor( minor_color );
00119 addChild( mTextBoxNorth );
00120
00121 mTextBoxEast = new LLTextBox( "E", major_dir_rect );
00122 mTextBoxEast->setColor( minor_color );
00123 addChild( mTextBoxEast );
00124
00125 major_dir_rect.mRight += 1 ;
00126 mTextBoxWest = new LLTextBox( "W", major_dir_rect );
00127 mTextBoxWest->setColor( minor_color );
00128 addChild( mTextBoxWest );
00129 major_dir_rect.mRight -= 1 ;
00130
00131 mTextBoxSouth = new LLTextBox( "S", major_dir_rect );
00132 mTextBoxSouth->setColor( minor_color );
00133 addChild( mTextBoxSouth );
00134
00135 mTextBoxSouthEast = new LLTextBox( "SE", minor_dir_rect );
00136 mTextBoxSouthEast->setColor( minor_color );
00137 addChild( mTextBoxSouthEast );
00138
00139 mTextBoxNorthEast = new LLTextBox( "NE", minor_dir_rect );
00140 mTextBoxNorthEast->setColor( minor_color );
00141 addChild( mTextBoxNorthEast );
00142
00143 mTextBoxSouthWest = new LLTextBox( "SW", minor_dir_rect );
00144 mTextBoxSouthWest->setColor( minor_color );
00145 addChild( mTextBoxSouthWest );
00146
00147 mTextBoxNorthWest = new LLTextBox( "NW", minor_dir_rect );
00148 mTextBoxNorthWest->setColor( minor_color );
00149 addChild( mTextBoxNorthWest );
00150
00151
00152 LLMenuGL* menu;
00153 menu = new LLMenuGL("popup");
00154 menu->setCanTearOff(FALSE);
00155 menu->append(new LLMenuItemCallGL("Zoom Close", handleZoomLevel,
00156 NULL, (void*)2) );
00157 menu->append(new LLMenuItemCallGL("Zoom Medium", handleZoomLevel,
00158 NULL, (void*)1) );
00159 menu->append(new LLMenuItemCallGL("Zoom Far", handleZoomLevel,
00160 NULL, (void*)0) );
00161 menu->appendSeparator();
00162 menu->append(new LLMenuItemCallGL("Stop Tracking", &LLTracker::stopTracking,
00163 &LLTracker::isTracking, NULL) );
00164 menu->setVisible(FALSE);
00165 addChild(menu);
00166 mPopupMenuHandle = menu->getHandle();
00167
00168 sInstance = this;
00169 }
00170
00171 LLNetMap::~LLNetMap()
00172 {
00173 sInstance = NULL;
00174 }
00175
00176 void LLNetMap::setScale( F32 scale )
00177 {
00178 gMiniMapScale = scale;
00179 if (gMiniMapScale == 0.f)
00180 {
00181 gMiniMapScale = 0.1f;
00182 }
00183
00184 if (mObjectImagep.notNull())
00185 {
00186 F32 half_width = (F32)(getRect().getWidth() / 2);
00187 F32 half_height = (F32)(getRect().getHeight() / 2);
00188 F32 radius = sqrt( half_width * half_width + half_height * half_height );
00189 F32 region_widths = (2.f*radius)/gMiniMapScale;
00190 F32 meters = region_widths * LLWorld::getInstance()->getRegionWidthInMeters();
00191 F32 num_pixels = (F32)mObjectImagep->getWidth();
00192 mObjectMapTPM = num_pixels/meters;
00193 mObjectMapPixels = 2.f*radius;
00194 }
00195
00196 mPixelsPerMeter = gMiniMapScale / REGION_WIDTH_METERS;
00197
00198 mUpdateNow = TRUE;
00199 }
00200
00201 void LLNetMap::translatePan( F32 delta_x, F32 delta_y )
00202 {
00203 mTargetPanX += delta_x;
00204 mTargetPanY += delta_y;
00205 }
00206
00207
00209
00210 void LLNetMap::draw()
00211 {
00212 static LLFrameTimer map_timer;
00213
00214 if (mObjectImagep.isNull())
00215 {
00216 createObjectImage();
00217 }
00218
00219 mCurPanX = lerp(mCurPanX, mTargetPanX, LLCriticalDamp::getInterpolant(0.1f));
00220 mCurPanY = lerp(mCurPanY, mTargetPanY, LLCriticalDamp::getInterpolant(0.1f));
00221
00222
00223 F32 rotation = 0;
00224
00225 {
00226 LLGLEnable scissor(GL_SCISSOR_TEST);
00227
00228 {
00229 LLGLSNoTexture no_texture;
00230 LLLocalClipRect clip(getLocalRect());
00231
00232 glMatrixMode(GL_MODELVIEW);
00233
00234
00235 gGL.color4fv( mBackgroundColor.mV );
00236 gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0);
00237 }
00238
00239
00240 S32 center_sw_left = getRect().getWidth() / 2 + llfloor(mCurPanX);
00241 S32 center_sw_bottom = getRect().getHeight() / 2 + llfloor(mCurPanY);
00242
00243 gGL.pushMatrix();
00244
00245 gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f);
00246
00247 if( LLNetMap::sRotateMap )
00248 {
00249
00250 rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
00251 glRotatef( rotation * RAD_TO_DEG, 0.f, 0.f, 1.f);
00252 }
00253
00254
00255 S32 region_width = llround(LLWorld::getInstance()->getRegionWidthInMeters());
00256
00257 for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->mActiveRegionList.begin();
00258 iter != LLWorld::getInstance()->mActiveRegionList.end(); ++iter)
00259 {
00260 LLViewerRegion* regionp = *iter;
00261
00262 LLVector3 origin_agent = regionp->getOriginAgent();
00263 LLVector3 rel_region_pos = origin_agent - gAgent.getCameraPositionAgent();
00264 F32 relative_x = (rel_region_pos.mV[0] / region_width) * gMiniMapScale;
00265 F32 relative_y = (rel_region_pos.mV[1] / region_width) * gMiniMapScale;
00266
00267
00268 F32 bottom = relative_y;
00269 F32 left = relative_x;
00270 F32 top = bottom + gMiniMapScale ;
00271 F32 right = left + gMiniMapScale ;
00272
00273 if (regionp == gAgent.getRegion())
00274 {
00275 gGL.color4f(1.f, 1.f, 1.f, 1.f);
00276 }
00277 else
00278 {
00279 gGL.color4f(0.8f, 0.8f, 0.8f, 1.f);
00280 }
00281
00282 if (!regionp->mAlive)
00283 {
00284 gGL.color4f(1.f, 0.5f, 0.5f, 1.f);
00285 }
00286
00287
00288
00289 LLViewerImage::bindTexture(regionp->getLand().getSTexture());
00290 gGL.begin(LLVertexBuffer::QUADS);
00291 gGL.texCoord2f(0.f, 1.f);
00292 gGL.vertex2f(left, top);
00293 gGL.texCoord2f(0.f, 0.f);
00294 gGL.vertex2f(left, bottom);
00295 gGL.texCoord2f(1.f, 0.f);
00296 gGL.vertex2f(right, bottom);
00297 gGL.texCoord2f(1.f, 1.f);
00298 gGL.vertex2f(right, top);
00299 gGL.end();
00300
00301
00302 glAlphaFunc(GL_GREATER, ABOVE_WATERLINE_ALPHA / 255.f );
00303 {
00304 if (regionp->getLand().getWaterTexture())
00305 {
00306 LLViewerImage::bindTexture(regionp->getLand().getWaterTexture());
00307 gGL.begin(LLVertexBuffer::QUADS);
00308 gGL.texCoord2f(0.f, 1.f);
00309 gGL.vertex2f(left, top);
00310 gGL.texCoord2f(0.f, 0.f);
00311 gGL.vertex2f(left, bottom);
00312 gGL.texCoord2f(1.f, 0.f);
00313 gGL.vertex2f(right, bottom);
00314 gGL.texCoord2f(1.f, 1.f);
00315 gGL.vertex2f(right, top);
00316 gGL.end();
00317 }
00318 }
00319 glAlphaFunc(GL_GREATER,0.01f);
00320 }
00321
00322
00323 LLVector3d old_center = mObjectImageCenterGlobal;
00324 LLVector3d new_center = gAgent.getCameraPositionGlobal();
00325
00326 new_center.mdV[0] = (5.f/mObjectMapTPM)*floor(0.2f*mObjectMapTPM*new_center.mdV[0]);
00327 new_center.mdV[1] = (5.f/mObjectMapTPM)*floor(0.2f*mObjectMapTPM*new_center.mdV[1]);
00328 new_center.mdV[2] = 0.f;
00329
00330 if (mUpdateNow || (map_timer.getElapsedTimeF32() > 0.5f))
00331 {
00332 mUpdateNow = FALSE;
00333 mObjectImageCenterGlobal = new_center;
00334
00335
00336
00337 U8 *default_texture = mObjectRawImagep->getData();
00338 memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );
00339
00340
00341 gObjectList.renderObjectsForMap(*this);
00342
00343 mObjectImagep->setSubImage(mObjectRawImagep, 0, 0, mObjectImagep->getWidth(), mObjectImagep->getHeight());
00344
00345 map_timer.reset();
00346 }
00347
00348 LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal);
00349 map_center_agent -= gAgent.getCameraPositionAgent();
00350 map_center_agent.mV[VX] *= gMiniMapScale/region_width;
00351 map_center_agent.mV[VY] *= gMiniMapScale/region_width;
00352
00353 LLViewerImage::bindTexture(mObjectImagep);
00354 F32 image_half_width = 0.5f*mObjectMapPixels;
00355 F32 image_half_height = 0.5f*mObjectMapPixels;
00356
00357 gGL.begin(LLVertexBuffer::QUADS);
00358 gGL.texCoord2f(0.f, 1.f);
00359 gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]);
00360 gGL.texCoord2f(0.f, 0.f);
00361 gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height);
00362 gGL.texCoord2f(1.f, 0.f);
00363 gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height);
00364 gGL.texCoord2f(1.f, 1.f);
00365 gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]);
00366 gGL.end();
00367
00368 gGL.popMatrix();
00369
00370 LLVector3d pos_global;
00371 LLVector3 pos_map;
00372
00373
00374 for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->mActiveRegionList.begin();
00375 iter != LLWorld::getInstance()->mActiveRegionList.end(); ++iter)
00376 {
00377 LLViewerRegion* regionp = *iter;
00378 const LLVector3d& origin_global = regionp->getOriginGlobal();
00379
00380 S32 count = regionp->mMapAvatars.count();
00381 S32 i;
00382 LLVector3 pos_local;
00383 U32 compact_local;
00384 U8 bits;
00385
00386
00387 for (i = 0; i < count; i++)
00388 {
00389 compact_local = regionp->mMapAvatars.get(i);
00390
00391 bits = compact_local & 0xFF;
00392 pos_local.mV[VZ] = F32(bits) * 4.f;
00393 compact_local >>= 8;
00394
00395 bits = compact_local & 0xFF;
00396 pos_local.mV[VY] = (F32)bits;
00397 compact_local >>= 8;
00398
00399 bits = compact_local & 0xFF;
00400 pos_local.mV[VX] = (F32)bits;
00401
00402 pos_global.setVec( pos_local );
00403 pos_global += origin_global;
00404
00405 pos_map = globalPosToView(pos_global);
00406
00407 BOOL show_as_friend = FALSE;
00408 if( i < regionp->mMapAvatarIDs.count())
00409 {
00410 show_as_friend = is_agent_friend(regionp->mMapAvatarIDs.get(i));
00411 }
00412 LLWorldMapView::drawAvatar(
00413 pos_map.mV[VX], pos_map.mV[VY],
00414 show_as_friend ? gFriendMapColor : gAvatarMapColor,
00415 pos_map.mV[VZ]);
00416 }
00417 }
00418
00419
00420 if (gAgent.getAutoPilot())
00421 {
00422 drawTracking( gAgent.getAutoPilotTargetGlobal(), gTrackColor );
00423 }
00424 else
00425 {
00426 LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
00427 if ( LLTracker::TRACKING_AVATAR == tracking_status )
00428 {
00429 drawTracking( LLAvatarTracker::instance().getGlobalPos(), gTrackColor );
00430 }
00431 else if ( LLTracker::TRACKING_LANDMARK == tracking_status
00432 || LLTracker::TRACKING_LOCATION == tracking_status )
00433 {
00434 drawTracking( LLTracker::getTrackedPositionGlobal(), gTrackColor );
00435 }
00436 }
00437
00438
00439 pos_global = gAgent.getPositionGlobal();
00440 pos_map = globalPosToView(pos_global);
00441 LLUIImagePtr you = LLWorldMapView::sAvatarYouSmallImage;
00442 you->draw(
00443 llround(pos_map.mV[VX]) - you->getWidth()/2,
00444 llround(pos_map.mV[VY]) - you->getHeight()/2);
00445
00446
00447 F32 meters_to_pixels = gMiniMapScale/ LLWorld::getInstance()->getRegionWidthInMeters();
00448
00449 F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect();
00450 F32 far_clip_meters = LLViewerCamera::getInstance()->getFar();
00451 F32 far_clip_pixels = far_clip_meters * meters_to_pixels;
00452
00453 F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 );
00454 F32 half_width_pixels = half_width_meters * meters_to_pixels;
00455
00456 F32 ctr_x = (F32)center_sw_left;
00457 F32 ctr_y = (F32)center_sw_bottom;
00458
00459
00460 LLGLSNoTexture no_texture;
00461
00462 if( LLNetMap::sRotateMap )
00463 {
00464 gGL.color4fv(gFrustumMapColor.mV);
00465
00466 gGL.begin( LLVertexBuffer::TRIANGLES );
00467 gGL.vertex2f( ctr_x, ctr_y );
00468 gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels );
00469 gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels );
00470 gGL.end();
00471 }
00472 else
00473 {
00474 gGL.color4fv(gRotatingFrustumMapColor.mV);
00475
00476
00477 gGL.pushMatrix();
00478 gGL.translatef( ctr_x, ctr_y, 0 );
00479 glRotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f);
00480 gGL.begin( LLVertexBuffer::TRIANGLES );
00481 gGL.vertex2f( 0, 0 );
00482 gGL.vertex2f( -half_width_pixels, far_clip_pixels );
00483 gGL.vertex2f( half_width_pixels, far_clip_pixels );
00484 gGL.end();
00485 gGL.popMatrix();
00486 }
00487 }
00488
00489
00490 setDirectionPos( mTextBoxEast, rotation );
00491 setDirectionPos( mTextBoxNorth, rotation + F_PI_BY_TWO );
00492 setDirectionPos( mTextBoxWest, rotation + F_PI );
00493 setDirectionPos( mTextBoxSouth, rotation + F_PI + F_PI_BY_TWO );
00494
00495 setDirectionPos( mTextBoxNorthEast, rotation + F_PI_BY_TWO / 2);
00496 setDirectionPos( mTextBoxNorthWest, rotation + F_PI_BY_TWO + F_PI_BY_TWO / 2);
00497 setDirectionPos( mTextBoxSouthWest, rotation + F_PI + F_PI_BY_TWO / 2);
00498 setDirectionPos( mTextBoxSouthEast, rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2);
00499
00500 LLUICtrl::draw();
00501 }
00502
00503 LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )
00504 {
00505 LLVector3d relative_pos_global = global_pos - gAgent.getCameraPositionGlobal();
00506 LLVector3 pos_local;
00507 pos_local.setVec(relative_pos_global);
00508
00509 pos_local.mV[VX] *= mPixelsPerMeter;
00510 pos_local.mV[VY] *= mPixelsPerMeter;
00511
00512
00513 if( LLNetMap::sRotateMap )
00514 {
00515 F32 radians = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
00516 LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
00517 pos_local.rotVec( rot );
00518 }
00519
00520 pos_local.mV[VX] += getRect().getWidth() / 2 + mCurPanX;
00521 pos_local.mV[VY] += getRect().getHeight() / 2 + mCurPanY;
00522
00523 return pos_local;
00524 }
00525
00526 void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,
00527 BOOL draw_arrow )
00528 {
00529 LLVector3 pos_local = globalPosToView( pos_global );
00530 if( (pos_local.mV[VX] < 0) ||
00531 (pos_local.mV[VY] < 0) ||
00532 (pos_local.mV[VX] >= getRect().getWidth()) ||
00533 (pos_local.mV[VY] >= getRect().getHeight()) )
00534 {
00535 if (draw_arrow)
00536 {
00537 S32 x = llround( pos_local.mV[VX] );
00538 S32 y = llround( pos_local.mV[VY] );
00539 LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10 );
00540 LLWorldMapView::drawTrackingArrow( getRect(), x, y, color );
00541 }
00542 }
00543 else
00544 {
00545 LLWorldMapView::drawTrackingDot(pos_local.mV[VX],
00546 pos_local.mV[VY],
00547 color,
00548 pos_local.mV[VZ]);
00549 }
00550 }
00551
00552 LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y )
00553 {
00554 x -= llround(getRect().getWidth() / 2 + mCurPanX);
00555 y -= llround(getRect().getHeight() / 2 + mCurPanY);
00556
00557 LLVector3 pos_local( (F32)x, (F32)y, 0 );
00558
00559 F32 radians = - atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
00560
00561 if( LLNetMap::sRotateMap )
00562 {
00563 LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
00564 pos_local.rotVec( rot );
00565 }
00566
00567 pos_local *= ( LLWorld::getInstance()->getRegionWidthInMeters() / gMiniMapScale );
00568
00569 LLVector3d pos_global;
00570 pos_global.setVec( pos_local );
00571 pos_global += gAgent.getCameraPositionGlobal();
00572
00573 return pos_global;
00574 }
00575
00576 BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
00577 {
00578
00579 setScale(llclamp(gMiniMapScale - clicks*MAP_SCALE_INCREMENT, MAP_SCALE_MIN, MAP_SCALE_MAX));
00580 return TRUE;
00581 }
00582
00583 BOOL LLNetMap::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen )
00584 {
00585 BOOL handled = FALSE;
00586 if (gDisconnected)
00587 {
00588 return FALSE;
00589 }
00590 LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) );
00591 if( region )
00592 {
00593 msg.assign( region->getName() );
00594
00595 #ifndef LL_RELEASE_FOR_DOWNLOAD
00596 char buffer[MAX_STRING];
00597 msg.append("\n");
00598 region->getHost().getHostName(buffer, MAX_STRING);
00599 msg.append(buffer);
00600 msg.append("\n");
00601 region->getHost().getString(buffer, MAX_STRING);
00602 msg.append(buffer);
00603 #endif
00604
00605
00606 msg.append("\n(Double-click to open Map)");
00607
00608 S32 SLOP = 4;
00609 localPointToScreen(
00610 x - SLOP, y - SLOP,
00611 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
00612 sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
00613 sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
00614 }
00615 handled = TRUE;
00616 return handled;
00617 }
00618
00619
00620 void LLNetMap::setDirectionPos( LLTextBox* text_box, F32 rotation )
00621 {
00622
00623
00624
00625
00626 F32 map_half_height = (F32)(getRect().getHeight() / 2);
00627 F32 map_half_width = (F32)(getRect().getWidth() / 2);
00628 F32 text_half_height = (F32)(text_box->getRect().getHeight() / 2);
00629 F32 text_half_width = (F32)(text_box->getRect().getWidth() / 2);
00630 F32 radius = llmin( map_half_height - text_half_height, map_half_width - text_half_width );
00631
00632
00633 radius -= 8.f;
00634
00635 text_box->setOrigin(
00636 llround(map_half_width - text_half_width + radius * cos( rotation )),
00637 llround(map_half_height - text_half_height + radius * sin( rotation )) );
00638 }
00639
00640 void LLNetMap::renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius_meters )
00641 {
00642 LLVector3 local_pos;
00643 local_pos.setVec( pos - mObjectImageCenterGlobal );
00644
00645 S32 diameter_pixels = llround(2 * radius_meters * mObjectMapTPM);
00646 renderPoint( local_pos, color, diameter_pixels );
00647 }
00648
00649
00650 void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
00651 S32 diameter, S32 relative_height)
00652 {
00653 if (diameter <= 0)
00654 {
00655 return;
00656 }
00657
00658 const S32 image_width = (S32)mObjectImagep->getWidth();
00659 const S32 image_height = (S32)mObjectImagep->getHeight();
00660
00661 S32 x_offset = llround(pos_local.mV[VX] * mObjectMapTPM + image_width / 2);
00662 S32 y_offset = llround(pos_local.mV[VY] * mObjectMapTPM + image_height / 2);
00663
00664 if ((x_offset < 0) || (x_offset >= image_width))
00665 {
00666 return;
00667 }
00668 if ((y_offset < 0) || (y_offset >= image_height))
00669 {
00670 return;
00671 }
00672
00673 U8 *datap = mObjectRawImagep->getData();
00674
00675 S32 neg_radius = diameter / 2;
00676 S32 pos_radius = diameter - neg_radius;
00677 S32 x, y;
00678
00679 if (relative_height > 0)
00680 {
00681
00682 S32 px, py;
00683
00684
00685 px = x_offset;
00686 for (y = -neg_radius; y < pos_radius; y++)
00687 {
00688 py = y_offset + y;
00689 if ((py < 0) || (py >= image_height))
00690 {
00691 continue;
00692 }
00693 S32 offset = px + py * image_width;
00694 ((U32*)datap)[offset] = color.mAll;
00695 }
00696
00697
00698 py = y_offset + pos_radius - 1;
00699 for (x = -neg_radius; x < pos_radius; x++)
00700 {
00701 px = x_offset + x;
00702 if ((px < 0) || (px >= image_width))
00703 {
00704 continue;
00705 }
00706 S32 offset = px + py * image_width;
00707 ((U32*)datap)[offset] = color.mAll;
00708 }
00709 }
00710 else
00711 {
00712
00713 for (x = -neg_radius; x < pos_radius; x++)
00714 {
00715 S32 p_x = x_offset + x;
00716 if ((p_x < 0) || (p_x >= image_width))
00717 {
00718 continue;
00719 }
00720
00721 for (y = -neg_radius; y < pos_radius; y++)
00722 {
00723 S32 p_y = y_offset + y;
00724 if ((p_y < 0) || (p_y >= image_height))
00725 {
00726 continue;
00727 }
00728 S32 offset = p_x + p_y * image_width;
00729 ((U32*)datap)[offset] = color.mAll;
00730 }
00731 }
00732 }
00733 }
00734
00735 void LLNetMap::createObjectImage()
00736 {
00737
00738 F32 half_width = (F32)(getRect().getWidth() / 2);
00739 F32 half_height = (F32)(getRect().getHeight() / 2);
00740 F32 radius = sqrt( half_width * half_width + half_height * half_height );
00741 S32 square_size = S32( 2 * radius );
00742
00743
00744 const S32 MIN_SIZE = 32;
00745 const S32 MAX_SIZE = 256;
00746 S32 img_size = MIN_SIZE;
00747 while( (img_size*2 < square_size ) && (img_size < MAX_SIZE) )
00748 {
00749 img_size <<= 1;
00750 }
00751
00752 if( mObjectImagep.isNull() ||
00753 (mObjectImagep->getWidth() != img_size) ||
00754 (mObjectImagep->getHeight() != img_size) )
00755 {
00756 mObjectRawImagep = new LLImageRaw(img_size, img_size, 4);
00757 U8* data = mObjectRawImagep->getData();
00758 memset( data, 0, img_size * img_size * 4 );
00759 mObjectImagep = new LLImageGL( mObjectRawImagep, FALSE);
00760 setScale(gMiniMapScale);
00761 }
00762 mUpdateNow = TRUE;
00763 }
00764
00765 BOOL LLNetMap::handleDoubleClick( S32 x, S32 y, MASK mask )
00766 {
00767 LLFloaterWorldMap::show(NULL, FALSE);
00768 return TRUE;
00769 }
00770
00771 BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
00772 {
00773 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
00774 if (menu)
00775 {
00776 menu->buildDrawLabels();
00777 menu->updateParent(LLMenuGL::sMenuContainer);
00778 LLMenuGL::showPopup(this, menu, x, y);
00779 }
00780 return TRUE;
00781 }
00782
00783
00784
00785 void LLNetMap::handleZoomLevel(void* which)
00786 {
00787 intptr_t level = (intptr_t)which;
00788
00789 switch(level)
00790 {
00791 case 0:
00792 LLNetMap::sInstance->setScale(MAP_SCALE_MIN);
00793 break;
00794 case 1:
00795 LLNetMap::sInstance->setScale(MAP_SCALE_MID);
00796 break;
00797 case 2:
00798 LLNetMap::sInstance->setScale(MAP_SCALE_MAX);
00799 break;
00800 default:
00801 break;
00802 }
00803 }