llnetmap.cpp

Go to the documentation of this file.
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"             // clampf()
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"             // shared draw code
00068 #include "viewer.h"                             // Only for constants!
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 //static
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         // Surface texture is dynamically generated/updated.
00102 //      createObjectImage();
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         // Right-click menu
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                         // Hack!  Sometimes world hasn't been initialized at this point.
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         // Prepare a scissor region
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                         // Draw background rectangle
00259                         glColor4fv( mBackgroundColor.mV );
00260                         gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0);
00261                 }
00262 
00263                 // region 0,0 is in the middle
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                         // rotate subsequent draws to agent rotation
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                 // figure out where agent is
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                         // Find x and y position relative to camera's center.
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                         // background region rectangle
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                         // Draw using texture.
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                         // Draw water
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                         // Center moved enough.
00360                         // Create the base texture.
00361                         U8 *default_texture = mObjectRawImagep->getData();
00362                         memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );
00363 
00364                         // Draw buildings
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                 // Draw avatars
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                         // TODO: it'd be very cool to draw these in sorted order from lowest Z to highest.
00410                         // just be careful to sort the avatar IDs along with the positions. -MG
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                 // Draw dot for autopilot target
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                 // Draw dot for self avatar position
00463                 //drawTracking( gAgent.getPosGlobalFromAgent(gAgent.getFrameAgent().getCenter()), gSelfMapColor );
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                 // Draw frustum
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                         // If we don't rotate the map, we have to rotate the frustum.
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         // Rotation of 0 means that North is up
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);  // convert to floats from doubles
00533 
00534         pos_local.mV[VX] *= mPixelsPerMeter;
00535         pos_local.mV[VY] *= mPixelsPerMeter;
00536         // leave Z component in meters
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         // note that clicks are reversed from what you'd think
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];                /*Flawfinder: ignore*/
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                         // *TODO: put this under the control of XUI so it can be
00632                         // translated.
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         // Rotation is in radians.
00651         // Rotation of 0 means x = 1, y = 0 on the unit circle.
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         // Inset by a little to account for position display.
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                 // ...point above agent
00710                 S32 px, py;
00711 
00712                 // vertical line
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                 // top line
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                 // ...point level with agent
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         // Find the size of the side of a square that surrounds the circle that surrounds mRect.
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         // Find the least power of two >= the minimum size.
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 // static
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 }

Generated on Thu Jul 1 06:08:55 2010 for Second Life Viewer by  doxygen 1.4.7