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