llfloaterworldmap.cpp

Go to the documentation of this file.
00001 
00033 /*
00034  * Map of the entire world, with multiple background images,
00035  * avatar tracking, teleportation by double-click, etc.
00036  */
00037 
00038 #include "llviewerprecompiledheaders.h"
00039 
00040 #include "llfloaterworldmap.h"
00041 
00042 // Library includes
00043 #include "llfontgl.h"
00044 #include "llinventory.h"
00045 #include "lllineeditor.h"
00046 #include "message.h"
00047 
00048 // Viewer includes
00049 #include "llagent.h"
00050 #include "llviewerwindow.h"
00051 #include "llbutton.h"
00052 #include "llcallingcard.h"
00053 #include "llcolorscheme.h"
00054 #include "llcombobox.h"
00055 #include "llviewercontrol.h"
00056 #include "lldraghandle.h"
00057 #include "lleconomy.h"
00058 #include "llfirstuse.h"
00059 #include "llfocusmgr.h"
00060 #include "lliconctrl.h"
00061 #include "llinventorymodel.h"
00062 #include "llinventoryview.h"
00063 #include "lllandmarklist.h"
00064 #include "llnetmap.h"
00065 #include "llpreviewlandmark.h"
00066 #include "llradiogroup.h"
00067 #include "llregionhandle.h"
00068 #include "llresizehandle.h"
00069 #include "llresmgr.h"
00070 #include "llscrolllistctrl.h"
00071 #include "llsliderctrl.h"
00072 #include "llspinctrl.h"
00073 #include "llstatusbar.h"
00074 #include "lltabcontainer.h"
00075 #include "lltextbox.h"
00076 #include "lltracker.h"
00077 #include "llui.h"
00078 #include "lluiconstants.h"
00079 #include "llviewercamera.h"
00080 #include "llviewermenu.h"
00081 #include "llviewerregion.h"
00082 #include "llviewerstats.h"
00083 #include "llworldmap.h"
00084 #include "llworldmapview.h"
00085 #include "llurl.h"
00086 #include "llvieweruictrlfactory.h"
00087 #include "viewer.h"
00088 #include "llmapimagetype.h"
00089 #include "llweb.h"
00090 
00091 #include "llglheaders.h"
00092 
00093 //---------------------------------------------------------------------------
00094 // Constants
00095 //---------------------------------------------------------------------------
00096 static const F32 MAP_ZOOM_TIME = 0.2f;
00097 
00098 enum EPanDirection
00099 {
00100         PAN_UP,
00101         PAN_DOWN,
00102         PAN_LEFT,
00103         PAN_RIGHT
00104 };
00105 
00106 // Values in pixels per region
00107 static const F32 ZOOM_MIN = -8.f;       // initial value, updated by adjustZoomSlider
00108 static const F32 ZOOM_MAX = 0.f;
00109 static const F32 ZOOM_INC = 0.2f;
00110 
00111 static const F32 SIM_COORD_MIN   = 0.f;
00112 static const F32 SIM_COORD_MAX   = 255.f;
00113 static const F32 SIM_COORD_DEFAULT = 128.f;
00114 
00115 static const F64 MAX_FLY_DISTANCE = 363.f;  // Diagonal size of one sim.
00116 static const F64 MAX_FLY_DISTANCE_SQUARED = MAX_FLY_DISTANCE * MAX_FLY_DISTANCE;
00117 
00118 //---------------------------------------------------------------------------
00119 // Globals
00120 //---------------------------------------------------------------------------
00121 
00122 LLFloaterWorldMap* gFloaterWorldMap = NULL;
00123 
00124 class LLMapInventoryObserver : public LLInventoryObserver
00125 {
00126 public:
00127         LLMapInventoryObserver() {}
00128         virtual ~LLMapInventoryObserver() {}
00129         virtual void changed(U32 mask);
00130 };
00131   
00132 void LLMapInventoryObserver::changed(U32 mask)
00133 {
00134         // if there's a change we're interested in.
00135         if((mask & (LLInventoryObserver::CALLING_CARD | LLInventoryObserver::ADD |
00136                                 LLInventoryObserver::REMOVE)) != 0)
00137         {
00138                 gFloaterWorldMap->inventoryChanged();
00139         }
00140 }
00141 
00142 class LLMapFriendObserver : public LLFriendObserver
00143 {
00144 public:
00145         LLMapFriendObserver() {}
00146         virtual ~LLMapFriendObserver() {}
00147         virtual void changed(U32 mask);
00148 };
00149 
00150 void LLMapFriendObserver::changed(U32 mask)
00151 {
00152         // if there's a change we're interested in.
00153         if((mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE | LLFriendObserver::POWERS)) != 0)
00154         {
00155                 gFloaterWorldMap->friendsChanged();
00156         }
00157 }
00158 
00159 //---------------------------------------------------------------------------
00160 // Statics
00161 //---------------------------------------------------------------------------
00162 
00163 // Used as a pretend asset and inventory id to mean "landmark at my home location."
00164 const LLUUID LLFloaterWorldMap::sHomeID( "10000000-0000-0000-0000-000000000001" );
00165 
00166 //---------------------------------------------------------------------------
00167 // Construction and destruction
00168 //---------------------------------------------------------------------------
00169 
00170 
00171 LLFloaterWorldMap::LLFloaterWorldMap()
00172 :       LLFloater("worldmap", "FloaterWorldMapRect", "World Map",
00173                           TRUE,         // resize
00174                           410,          // min-width
00175                           520,          // min-height
00176                           FALSE,        // drag on left
00177                           TRUE,         // minimize
00178                           TRUE),        // close
00179         mInventory(NULL),
00180         mInventoryObserver(NULL),
00181         mFriendObserver(NULL),
00182         mCompletingRegionName(""),
00183         mWaitingForTracker(FALSE),
00184         mExactMatch(FALSE),
00185         mIsClosing(FALSE),
00186         mSetToUserPosition(TRUE),
00187         mTrackedLocation(0,0,0),
00188         mTrackedStatus(LLTracker::TRACKING_NOTHING)
00189 {
00190         LLCallbackMap::map_t factory_map;
00191         factory_map["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL);
00192         factory_map["terrain_mapview"] = LLCallbackMap(createWorldMapView, NULL);
00193         gUICtrlFactory->buildFloater(this, "floater_world_map.xml", &factory_map);
00194 }
00195 
00196 // static
00197 void* LLFloaterWorldMap::createWorldMapView(void* data)
00198 {
00199         return new LLWorldMapView("mapview", LLRect(0,300,400,0));
00200 }
00201 
00202 BOOL LLFloaterWorldMap::postBuild()
00203 {
00204         mTabs = LLUICtrlFactory::getTabContainerByName(this, "maptab");
00205         if (!mTabs) return FALSE;
00206 
00207         LLPanel *panel;
00208 
00209         panel = LLUICtrlFactory::getPanelByName(mTabs, "objects_mapview");
00210         if (panel)
00211         {
00212                 mTabs->setTabChangeCallback(panel, onCommitBackground);
00213                 mTabs->setTabUserData(panel, this);
00214         }
00215         panel = LLUICtrlFactory::getPanelByName(mTabs, "terrain_mapview");
00216         if (panel)
00217         {
00218                 mTabs->setTabChangeCallback(panel, onCommitBackground);
00219                 mTabs->setTabUserData(panel, this);
00220         }
00221 
00222         onCommitBackground((void*)this, false);
00223 
00224         childSetCommitCallback("friend combo", onAvatarComboCommit, this);
00225 
00226         LLComboBox *avatar_combo = LLUICtrlFactory::getComboBoxByName(this, "friend combo");
00227         if (avatar_combo)
00228         {
00229                 avatar_combo->selectFirstItem();
00230                 avatar_combo->setPrearrangeCallback( onAvatarComboPrearrange );
00231         }
00232 
00233         childSetAction("DoSearch", onLocationCommit, this);
00234 
00235         childSetFocusChangedCallback("location", updateSearchEnabled);
00236         childSetKeystrokeCallback("location", (void (*)(LLLineEditor*,void*))updateSearchEnabled, NULL);
00237         
00238         childSetCommitCallback("search_results", onCommitSearchResult, this);
00239         childSetDoubleClickCallback("search_results", onClickTeleportBtn);
00240         childSetCommitCallback("spin x", onCommitLocation, this);
00241         childSetCommitCallback("spin y", onCommitLocation, this);
00242         childSetCommitCallback("spin z", onCommitLocation, this);
00243 
00244         childSetCommitCallback("landmark combo", onLandmarkComboCommit, this);
00245 
00246         LLComboBox *landmark_combo = LLUICtrlFactory::getComboBoxByName(this, "landmark combo");
00247         if (landmark_combo)
00248         {
00249                 landmark_combo->selectFirstItem();
00250                 landmark_combo->setPrearrangeCallback( onLandmarkComboPrearrange );
00251         }
00252 
00253         childSetAction("Go Home", onGoHome, this);
00254 
00255         childSetAction("Teleport", onClickTeleportBtn, this);
00256 
00257         childSetAction("Show Destination", onShowTargetBtn, this);
00258         childSetAction("Show My Location", onShowAgentBtn, this);
00259         childSetAction("Clear", onClearBtn, this);
00260         childSetAction("copy_slurl", onCopySLURL, this);
00261 
00262         mCurZoomVal = log(gMapScale)/log(2.f);
00263         childSetValue("zoom slider", gMapScale);
00264 
00265         setDefaultBtn(NULL);
00266 
00267         if ( gAgent.isTeen() )
00268         {
00269                 // Hide Mature Events controls
00270                 childHide("events_mature_icon");
00271                 childHide("events_mature_label");
00272                 childHide("event_mature_chk");
00273         }
00274 
00275         mZoomTimer.stop();
00276 
00277         return TRUE;
00278 }
00279 
00280 // virtual
00281 LLFloaterWorldMap::~LLFloaterWorldMap()
00282 {
00283         // All cleaned up by LLView destructor
00284         mTabs = NULL;
00285 
00286         // Inventory deletes all observers on shutdown
00287         mInventory = NULL;
00288         mInventoryObserver = NULL;
00289 
00290         // avatar tracker will delete this for us.
00291         mFriendObserver = NULL;
00292 }
00293 
00294 
00295 // virtual
00296 void LLFloaterWorldMap::onClose(bool app_quitting)
00297 {
00298         setVisible(FALSE);
00299 }
00300 
00301 // static
00302 void LLFloaterWorldMap::show(void*, BOOL center_on_target)
00303 {
00304         BOOL was_visible = gFloaterWorldMap->getVisible();
00305 
00306         gFloaterWorldMap->mIsClosing = FALSE;
00307         gFloaterWorldMap->open();               /* Flawfinder: ignore */
00308 
00309         LLWorldMapView* map_panel;
00310         map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel();
00311         map_panel->clearLastClick();
00312 
00313         if (!was_visible)
00314         {
00315                 // reset pan on show, so it centers on you again
00316                 if (!center_on_target)
00317                 {
00318                         LLWorldMapView::setPan(0, 0, TRUE);
00319                 }
00320                 map_panel->updateVisibleBlocks();
00321 
00322                 // Reload the agent positions when we show the window
00323                 gWorldMap->eraseItems();
00324 
00325                 // Reload any maps that may have changed
00326                 gWorldMap->clearSimFlags();
00327 
00328                 const S32 panel_num = gFloaterWorldMap->mTabs->getCurrentPanelIndex();
00329                 const bool request_from_sim = true;
00330                 gWorldMap->setCurrentLayer(panel_num, request_from_sim);
00331 
00332                 // We may already have a bounding box for the regions of the world,
00333                 // so use that to adjust the view.
00334                 gFloaterWorldMap->adjustZoomSliderBounds();
00335 
00336                 // Could be first show
00337                 LLFirstUse::useMap();
00338 
00339                 // Start speculative download of landmarks
00340                 LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
00341                 gInventory.startBackgroundFetch(landmark_folder_id);
00342 
00343                 gFloaterWorldMap->childSetFocus("location", TRUE);
00344                 gFocusMgr.triggerFocusFlash();
00345 
00346                 gFloaterWorldMap->buildAvatarIDList();
00347                 gFloaterWorldMap->buildLandmarkIDLists();
00348 
00349                 // If nothing is being tracked, set flag so the user position will be found
00350                 gFloaterWorldMap->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
00351         }
00352         
00353         if (center_on_target)
00354         {
00355                 gFloaterWorldMap->centerOnTarget(FALSE);
00356         }
00357 }
00358 
00359 
00360 
00361 // static
00362 void LLFloaterWorldMap::reloadIcons(void*)
00363 {
00364         gWorldMap->eraseItems();
00365 
00366         gWorldMap->sendMapLayerRequest();
00367 }
00368 
00369 
00370 // static
00371 void LLFloaterWorldMap::toggle(void*)
00372 {
00373         BOOL visible = gFloaterWorldMap->getVisible();
00374 
00375         if (!visible)
00376         {
00377                 show(NULL, FALSE);
00378         }
00379         else
00380         {
00381                 gFloaterWorldMap->mIsClosing = TRUE;
00382                 gFloaterWorldMap->close();
00383         }
00384 }
00385 
00386 
00387 // static
00388 void LLFloaterWorldMap::hide(void*)
00389 {
00390         gFloaterWorldMap->mIsClosing = TRUE;
00391         gFloaterWorldMap->close();
00392 }
00393 
00394 
00395 // virtual
00396 void LLFloaterWorldMap::setVisible( BOOL visible )
00397 {
00398         LLFloater::setVisible( visible );
00399 
00400         gSavedSettings.setBOOL( "ShowWorldMap", visible );
00401 
00402         if( !visible )
00403         {
00404                 // While we're not visible, discard the overlay images we're using
00405                 if (gWorldMap)
00406                 {
00407                         gWorldMap->clearImageRefs();
00408                 }
00409         }
00410 }
00411 
00412 
00413 // virtual
00414 BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask)
00415 {
00416         BOOL handled;
00417         handled = LLFloater::handleHover(x, y, mask);
00418         return handled;
00419 }
00420 
00421 BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
00422 {
00423         if (getVisible() && !isMinimized() && isFrontmost())
00424         {
00425                 F32 slider_value = (F32)childGetValue("zoom slider").asReal();
00426                 slider_value += ((F32)clicks * -0.3333f);
00427                 childSetValue("zoom slider", LLSD(slider_value));
00428                 return TRUE;
00429         }
00430         return FALSE;
00431 }
00432 
00433 
00434 // virtual
00435 void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent )
00436 {
00437         LLFloater::reshape( width, height, called_from_parent );
00438 
00439         // Might have changed size of world display area
00440         // JC: Technically, this is correct, but it makes the slider "pop"
00441         // if you resize the window, then draw the slider.  Just leaving it
00442         // the way it was when you opened the window seems better.
00443         // adjustZoomSliderBounds();
00444 }
00445 
00446 
00447 // virtual
00448 void LLFloaterWorldMap::draw()
00449 {
00450         if( !getVisible() )
00451         {
00452                 return;
00453         }
00454 
00455         // On orientation island, users don't have a home location yet, so don't
00456         // let them teleport "home".  It dumps them in an often-crowed welcome
00457         // area (infohub) and they get confused. JC
00458         LLViewerRegion* regionp = gAgent.getRegion();
00459         bool agent_on_prelude = (regionp && regionp->isPrelude());
00460         bool enable_go_home = gAgent.isGodlike() || !agent_on_prelude;
00461         childSetEnabled("Go Home", enable_go_home);
00462 
00463         updateLocation();
00464         
00465         LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); 
00466         if (LLTracker::TRACKING_AVATAR == tracking_status)
00467         {
00468                 childSetColor("avatar_icon", gTrackColor);
00469         }
00470         else
00471         {
00472                 childSetColor("avatar_icon", gDisabledTrackColor);
00473         }
00474 
00475         if (LLTracker::TRACKING_LANDMARK == tracking_status)
00476         {
00477                 childSetColor("landmark_icon", gTrackColor);
00478         }
00479         else
00480         {
00481                 childSetColor("landmark_icon", gDisabledTrackColor);
00482         }
00483 
00484         if (LLTracker::TRACKING_LOCATION == tracking_status)
00485         {
00486                 childSetColor("location_icon", gTrackColor);
00487         }
00488         else
00489         {
00490                 if (mCompletingRegionName != "")
00491                 {
00492                         F64 seconds = LLTimer::getElapsedSeconds();
00493                         double value = fmod(seconds, 2);
00494                         value = 0.5 + 0.5*cos(value * 3.14159f);
00495                         LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0);
00496                         childSetColor("location_icon", loading_color);
00497                 }
00498                 else
00499                 {
00500                         childSetColor("location_icon", gDisabledTrackColor);
00501                 }
00502         }
00503 
00504         // check for completion of tracking data
00505         if (mWaitingForTracker)
00506         {
00507                 centerOnTarget(TRUE);
00508         }
00509 
00510         childSetEnabled("Teleport", (BOOL)tracking_status);
00511 //      childSetEnabled("Clear", (BOOL)tracking_status);
00512         childSetEnabled("Show Destination", (BOOL)tracking_status || gWorldMap->mIsTrackingUnknownLocation);
00513         childSetEnabled("copy_slurl", (mSLURL.size() > 0) );
00514 
00515         setMouseOpaque(TRUE);
00516         mDragHandle->setMouseOpaque(TRUE);
00517 
00518         //RN: snaps to zoom value because interpolation caused jitter in the text rendering
00519         if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)childGetValue("zoom slider").asReal())
00520         {
00521                 mZoomTimer.start();
00522         }
00523         F32 interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME;
00524         if (interp > 1.f)
00525         {
00526                 interp = 1.f;
00527                 mZoomTimer.stop();
00528         }
00529         mCurZoomVal = lerp(mCurZoomVal, (F32)childGetValue("zoom slider").asReal(), interp);
00530         F32 map_scale = 256.f*pow(2.f, mCurZoomVal);
00531         LLWorldMapView::setScale( map_scale );
00532         
00533         LLFloater::draw();
00534 }
00535 
00536 
00537 //-------------------------------------------------------------------------
00538 // Internal utility functions
00539 //-------------------------------------------------------------------------
00540 
00541 
00542 void LLFloaterWorldMap::trackAvatar( const LLUUID& avatar_id, const LLString& name )
00543 {
00544         LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo");
00545         if (!iface) return;
00546 
00547         buildAvatarIDList();
00548         if(iface->setCurrentByID(avatar_id) || gAgent.isGodlike())
00549         {
00550                 // *HACK: Adjust Z values automatically for liaisons & gods so
00551                 // they swoop down when they click on the map. Requested
00552                 // convenience.
00553                 if(gAgent.isGodlike())
00554                 {
00555                         childSetValue("spin z", LLSD(200.f));
00556                 }
00557                 // Don't re-request info if we already have it or we won't have it in time to teleport
00558                 if (mTrackedStatus != LLTracker::TRACKING_AVATAR || name != mTrackedAvatarName)
00559                 {
00560                         mTrackedStatus = LLTracker::TRACKING_AVATAR;
00561                         mTrackedAvatarName = name;
00562                         LLTracker::trackAvatar(avatar_id, name);
00563                 }
00564         }
00565         else
00566         {
00567                 LLTracker::stopTracking(NULL);
00568         }
00569         setDefaultBtn("Teleport");
00570 }
00571 
00572 void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
00573 {
00574         LLCtrlSelectionInterface *iface = childGetSelectionInterface("landmark combo");
00575         if (!iface) return;
00576 
00577         buildLandmarkIDLists();
00578         BOOL found = FALSE;
00579         S32 idx;
00580         for (idx = 0; idx < mLandmarkItemIDList.count(); idx++)
00581         {
00582                 if ( mLandmarkItemIDList.get(idx) == landmark_item_id)
00583                 {
00584                         found = TRUE;
00585                         break;
00586                 }
00587         }
00588 
00589         if (found && iface->setCurrentByID( landmark_item_id ) ) 
00590         {
00591                 LLUUID asset_id = mLandmarkAssetIDList.get( idx );
00592                 LLString name;
00593                 LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(this, "landmark combo");
00594                 if (combo) name = combo->getSimple();
00595                 mTrackedStatus = LLTracker::TRACKING_LANDMARK;
00596                 LLTracker::trackLandmark(mLandmarkAssetIDList.get( idx ),       // assetID
00597                                                                 mLandmarkItemIDList.get( idx ), // itemID
00598                                                                 name);                  // name
00599 
00600                 if( asset_id != sHomeID )
00601                 {
00602                         // start the download process
00603                         gLandmarkList.getAsset( asset_id);
00604                 }
00605 
00606                 // We have to download both region info and landmark data, so set busy. JC
00607 //              getWindow()->incBusyCount();
00608         }
00609         else
00610         {
00611                 LLTracker::stopTracking(NULL);
00612         }
00613         setDefaultBtn("Teleport");
00614 }
00615 
00616 
00617 void LLFloaterWorldMap::trackEvent(const LLItemInfo &event_info)
00618 {
00619         mTrackedStatus = LLTracker::TRACKING_LOCATION;
00620         LLTracker::trackLocation(event_info.mPosGlobal, event_info.mName, event_info.mToolTip, LLTracker::LOCATION_EVENT);
00621         setDefaultBtn("Teleport");
00622 }
00623 
00624 void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item)
00625 {
00626         mTrackedStatus = LLTracker::TRACKING_LOCATION;
00627         LLTracker::trackLocation(item.mPosGlobal, item.mName, item.mToolTip, LLTracker::LOCATION_ITEM);
00628         setDefaultBtn("Teleport");
00629 }
00630 
00631 void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
00632 {
00633         LLSimInfo* sim_info = gWorldMap->simInfoFromPosGlobal(pos_global);
00634         if (!sim_info)
00635         {
00636                 gWorldMap->mIsTrackingUnknownLocation = TRUE;
00637                 gWorldMap->mInvalidLocation = FALSE;
00638                 gWorldMap->mUnknownLocation = pos_global;
00639                 LLTracker::stopTracking(NULL);
00640                 S32 world_x = S32(pos_global.mdV[0] / 256);
00641                 S32 world_y = S32(pos_global.mdV[1] / 256);
00642                 gWorldMap->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
00643                 setDefaultBtn("");
00644                 return;
00645         }
00646         if (sim_info->mAccess == SIM_ACCESS_DOWN)
00647         {
00648                 // Down sim. Show the blue circle of death!
00649                 gWorldMap->mIsTrackingUnknownLocation = TRUE;
00650                 gWorldMap->mUnknownLocation = pos_global;
00651                 gWorldMap->mInvalidLocation = TRUE;
00652                 LLTracker::stopTracking(NULL);
00653                 setDefaultBtn("");
00654                 return;
00655         }
00656 
00657         LLString sim_name;
00658         gWorldMap->simNameFromPosGlobal( pos_global, sim_name );
00659         F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
00660         F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
00661         LLString full_name = llformat("%s (%d, %d, %d)", 
00662                                                                   sim_name.c_str(), 
00663                                                                   llround(region_x), 
00664                                                                   llround(region_y),
00665                                                                   llround((F32)pos_global.mdV[VZ]));
00666 
00667         LLString tooltip("");
00668         mTrackedStatus = LLTracker::TRACKING_LOCATION;
00669         LLTracker::trackLocation(pos_global, full_name, tooltip);
00670         gWorldMap->mIsTrackingUnknownLocation = FALSE;
00671         gWorldMap->mIsTrackingDoubleClick = FALSE;
00672         gWorldMap->mIsTrackingCommit = FALSE;
00673 
00674         setDefaultBtn("Teleport");
00675 }
00676 
00677 void LLFloaterWorldMap::updateLocation()
00678 {
00679         bool gotSimName;
00680 
00681         LLTracker::ETrackingStatus status = LLTracker::getTrackingStatus();
00682 
00683         // These values may get updated by a message, so need to check them every frame
00684         // The fields may be changed by the user, so only update them if the data changes
00685         LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
00686         if (pos_global.isExactlyZero())
00687         {
00688                 LLVector3d agentPos = gAgent.getPositionGlobal();
00689 
00690                 // Set to avatar's current postion if nothing is selected
00691                 if ( status == LLTracker::TRACKING_NOTHING && mSetToUserPosition )
00692                 {
00693                         // Make sure we know where we are before setting the current user position
00694                         LLString agent_sim_name;
00695                         gotSimName = gWorldMap->simNameFromPosGlobal( agentPos, agent_sim_name );
00696                         if ( gotSimName )
00697                         {
00698                                 mSetToUserPosition = FALSE;
00699 
00700                                 // Fill out the location field
00701                                 childSetValue("location", agent_sim_name);
00702 
00703                                 // Figure out where user is
00704                                 LLVector3d agentPos = gAgent.getPositionGlobal();
00705 
00706                                 S32 agent_x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) );
00707                                 S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
00708                                 S32 agent_z = llround( (F32)agentPos.mdV[VZ] );
00709 
00710                                 childSetValue("spin x", LLSD(agent_x) );
00711                                 childSetValue("spin y", LLSD(agent_y) );
00712                                 childSetValue("spin z", LLSD(agent_z) );
00713 
00714                                 // Set the current SLURL
00715                                 mSLURL = LLWeb::escapeURL( llformat("http://slurl.com/secondlife/%s/%d/%d/%d", 
00716                                                                 agent_sim_name.c_str(), agent_x, agent_y, agent_z) );
00717                         }
00718                 }
00719 
00720                 return; // invalid location
00721         }
00722         LLString sim_name;
00723         gotSimName = gWorldMap->simNameFromPosGlobal( pos_global, sim_name );
00724         if ((status != LLTracker::TRACKING_NOTHING) &&
00725                 (status != mTrackedStatus || pos_global != mTrackedLocation || sim_name != mTrackedSimName))
00726         {
00727                 mTrackedStatus = status;
00728                 mTrackedLocation = pos_global;
00729                 mTrackedSimName = sim_name;
00730                 
00731                 if (status == LLTracker::TRACKING_AVATAR)
00732                 {
00733                         // *HACK: Adjust Z values automatically for liaisons &
00734                         // gods so they swoop down when they click on the
00735                         // map. Requested convenience.
00736                         if(gAgent.isGodlike())
00737                         {
00738                                 pos_global[2] = 200;
00739                         }
00740                 }
00741 
00742                 childSetValue("location", sim_name);
00743                 
00744                 F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
00745                 F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
00746                 childSetValue("spin x", LLSD(region_x) );
00747                 childSetValue("spin y", LLSD(region_y) );
00748                 childSetValue("spin z", LLSD((F32)pos_global.mdV[VZ]) );
00749 
00750                 // simNameFromPosGlobal can fail, so don't give the user an invalid SLURL
00751                 if ( gotSimName )
00752                 {
00753                         mSLURL = LLWeb::escapeURL(llformat("http://slurl.com/secondlife/%s/%d/%d/%d", 
00754                                                                                 sim_name.c_str(), llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ])));
00755                 }
00756                 else
00757                 {       // Empty SLURL will disable the "Copy SLURL to clipboard" button
00758                         mSLURL = "";
00759                 }
00760         }
00761 }
00762 
00763 void LLFloaterWorldMap::trackURL(const LLString& region_name, S32 x_coord, S32 y_coord, S32 z_coord)
00764 {
00765         LLSimInfo* sim_info = gWorldMap->simInfoFromName(region_name);
00766         z_coord = llclamp(z_coord, 0, 1000);
00767         if (sim_info)
00768         {
00769                 LLVector3 local_pos;
00770                 local_pos.mV[VX] = (F32)x_coord;
00771                 local_pos.mV[VY] = (F32)y_coord;
00772                 local_pos.mV[VZ] = (F32)z_coord;
00773                 LLVector3d global_pos = sim_info->getGlobalPos(local_pos);
00774                 trackLocation(global_pos);
00775                 setDefaultBtn("Teleport");
00776         }
00777         else
00778         {
00779                 // fill in UI based on URL
00780                 gFloaterWorldMap->childSetValue("location", region_name);
00781                 childSetValue("spin x", LLSD((F32)x_coord));
00782                 childSetValue("spin y", LLSD((F32)y_coord));
00783                 childSetValue("spin z", LLSD((F32)z_coord));
00784 
00785                 // pass sim name to combo box
00786                 gFloaterWorldMap->mCompletingRegionName = region_name;
00787                 gWorldMap->sendNamedRegionRequest(region_name);
00788                 LLString::toLower(gFloaterWorldMap->mCompletingRegionName);
00789                 gWorldMap->mIsTrackingCommit = TRUE;
00790         }
00791 }
00792 
00793 void LLFloaterWorldMap::observeInventory(LLInventoryModel* model)
00794 {
00795         if(mInventory)
00796         {
00797                 mInventory->removeObserver(mInventoryObserver);
00798                 delete mInventoryObserver;
00799                 mInventory = NULL;
00800                 mInventoryObserver = NULL;
00801         }
00802         if(model)
00803         {
00804                 mInventory = model;
00805                 mInventoryObserver = new LLMapInventoryObserver;
00806                 // Inventory deletes all observers on shutdown
00807                 mInventory->addObserver(mInventoryObserver);
00808                 inventoryChanged();
00809         }
00810 }
00811 
00812 void LLFloaterWorldMap::inventoryChanged()
00813 {
00814         if(!LLTracker::getTrackedLandmarkItemID().isNull())
00815         {
00816                 LLUUID item_id = LLTracker::getTrackedLandmarkItemID();
00817                 buildLandmarkIDLists();
00818                 trackLandmark(item_id);
00819         }
00820 }
00821 
00822 void LLFloaterWorldMap::observeFriends()
00823 {
00824         if(!mFriendObserver)
00825         {
00826                 mFriendObserver = new LLMapFriendObserver;
00827                 LLAvatarTracker::instance().addObserver(mFriendObserver);
00828                 friendsChanged();
00829         }
00830 }
00831 
00832 void LLFloaterWorldMap::friendsChanged()
00833 {
00834         LLAvatarTracker& t = LLAvatarTracker::instance();
00835         const LLUUID& avatar_id = t.getAvatarID();
00836         buildAvatarIDList();
00837         if(avatar_id.notNull())
00838         {
00839                 LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo");
00840                 if(!iface || !iface->setCurrentByID(avatar_id) || 
00841                         !t.getBuddyInfo(avatar_id)->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION) || gAgent.isGodlike())
00842                 {
00843                         LLTracker::stopTracking(NULL);
00844                 }
00845         }
00846 }
00847 
00848 // No longer really builds a list.  Instead, just updates mAvatarCombo.
00849 void LLFloaterWorldMap::buildAvatarIDList()
00850 {
00851         LLCtrlListInterface *list = childGetListInterface("friend combo");
00852         if (!list) return;
00853 
00854     // Delete all but the "None" entry
00855         S32 list_size = list->getItemCount();
00856         while (list_size > 1)
00857         {
00858                 list->selectNthItem(1);
00859                 list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
00860                 --list_size;
00861         }
00862 
00863         LLSD default_column;
00864         default_column["name"] = "friend name";
00865         default_column["label"] = "Friend Name";
00866         default_column["width"] = 500;
00867         list->addColumn(default_column);
00868 
00869         // Get all of the calling cards for avatar that are currently online
00870         LLCollectMappableBuddies collector;
00871         LLAvatarTracker::instance().applyFunctor(collector);
00872         LLCollectMappableBuddies::buddy_map_t::iterator it;
00873         LLCollectMappableBuddies::buddy_map_t::iterator end;
00874         it = collector.mMappable.begin();
00875         end = collector.mMappable.end();
00876         for( ; it != end; ++it)
00877         {
00878                 list->addSimpleElement((*it).first, ADD_BOTTOM, (*it).second);
00879         }
00880 
00881         list->setCurrentByID( LLAvatarTracker::instance().getAvatarID() );
00882         list->selectFirstItem();
00883 }
00884 
00885 
00886 void LLFloaterWorldMap::buildLandmarkIDLists()
00887 {
00888         LLCtrlListInterface *list = childGetListInterface("landmark combo");
00889         if (!list) return;
00890 
00891     // Delete all but the "None" entry
00892         S32 list_size = list->getItemCount();
00893         while (list_size > 1)
00894         {
00895                 list->selectNthItem(1);
00896                 list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
00897                 --list_size;
00898         }
00899 
00900         mLandmarkItemIDList.reset();
00901         mLandmarkAssetIDList.reset();
00902 
00903         // Get all of the current landmarks
00904         mLandmarkAssetIDList.put( LLUUID::null );
00905         mLandmarkItemIDList.put( LLUUID::null );
00906 
00907         mLandmarkAssetIDList.put( sHomeID );
00908         mLandmarkItemIDList.put( sHomeID );
00909 
00910         LLInventoryModel::cat_array_t cats;
00911         LLInventoryModel::item_array_t items;
00912         LLIsType is_landmark(LLAssetType::AT_LANDMARK);
00913         gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
00914                                                                         cats,
00915                                                                         items,
00916                                                                         LLInventoryModel::EXCLUDE_TRASH,
00917                                                                         is_landmark);
00918         std::sort(items.begin(), items.end(), LLViewerInventoryItem::comparePointers());
00919         
00920         S32 count = items.count();
00921         for(S32 i = 0; i < count; ++i)
00922         {
00923                 LLInventoryItem* item = items.get(i);
00924 
00925                 list->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID());
00926 
00927                 mLandmarkAssetIDList.put( item->getAssetUUID() );
00928                 mLandmarkItemIDList.put( item->getUUID() );
00929         }
00930         list->sortByColumn("landmark name", TRUE);
00931         list->selectFirstItem();
00932 }
00933 
00934 
00935 F32 LLFloaterWorldMap::getDistanceToDestination(const LLVector3d &destination, 
00936                                                                                                 F32 z_attenuation) const
00937 {
00938         LLVector3d delta = destination - gAgent.getPositionGlobal();
00939         // by attenuating the z-component we effectively 
00940         // give more weight to the x-y plane
00941         delta.mdV[VZ] *= z_attenuation;
00942         F32 distance = (F32)delta.magVec();
00943         return distance;
00944 }
00945 
00946 
00947 void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui)
00948 {
00949         LLCtrlListInterface *list = childGetListInterface("search_results");
00950         if (list)
00951         {
00952                 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00953         }
00954         if (!childHasKeyboardFocus("spin x"))
00955         {
00956                 childSetValue("spin x", SIM_COORD_DEFAULT);
00957         }
00958         if (!childHasKeyboardFocus("spin y"))
00959         {
00960                 childSetValue("spin y", SIM_COORD_DEFAULT);
00961         }
00962         if (!childHasKeyboardFocus("spin z"))
00963         {
00964                 childSetValue("spin z", 0);
00965         }
00966         gWorldMap->mIsTrackingCommit = FALSE;
00967         mCompletingRegionName = "";
00968         mExactMatch = FALSE;
00969 }
00970 
00971 
00972 void LLFloaterWorldMap::clearLandmarkSelection(BOOL clear_ui)
00973 {
00974         if (clear_ui || !childHasKeyboardFocus("landmark combo"))
00975         {
00976                 LLCtrlListInterface *list = childGetListInterface("landmark combo");
00977                 if (list)
00978                 {
00979                         list->selectByValue( "None" );
00980                 }
00981         }
00982 }
00983 
00984 
00985 void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui)
00986 {
00987         if (clear_ui || !childHasKeyboardFocus("friend combo"))
00988         {
00989                 mTrackedStatus = LLTracker::TRACKING_NOTHING;
00990                 LLCtrlListInterface *list = childGetListInterface("friend combo");
00991                 if (list)
00992                 {
00993                         list->selectByValue( "None" );
00994                 }
00995         }
00996 }
00997 
00998 
00999 // Adjust the maximally zoomed out limit of the zoom slider so you
01000 // can see the whole world, plus a little.
01001 void LLFloaterWorldMap::adjustZoomSliderBounds()
01002 {
01003         // World size in regions
01004         S32 world_width_regions  = gWorldMap->getWorldWidth() / REGION_WIDTH_UNITS;
01005         S32 world_height_regions = gWorldMap->getWorldHeight() / REGION_WIDTH_UNITS;
01006 
01007         // Pad the world size a little bit, so we have a nice border on
01008         // the edge
01009         world_width_regions++;
01010         world_height_regions++;
01011 
01012         // Find how much space we have to display the world
01013         LLWorldMapView* map_panel;
01014         map_panel = (LLWorldMapView*)mTabs->getCurrentPanel();
01015         LLRect view_rect = map_panel->getRect();
01016 
01017         // View size in pixels
01018         S32 view_width = view_rect.getWidth();
01019         S32 view_height = view_rect.getHeight();
01020 
01021         // Pixels per region to display entire width/height
01022         F32 width_pixels_per_region = (F32) view_width / (F32) world_width_regions;
01023         F32 height_pixels_per_region = (F32) view_height / (F32) world_height_regions;
01024 
01025         F32 pixels_per_region = llmin(width_pixels_per_region,
01026                                                                   height_pixels_per_region);
01027 
01028         // Round pixels per region to an even number of slider increments
01029         S32 slider_units = llfloor(pixels_per_region / 0.2f);
01030         pixels_per_region = slider_units * 0.2f;
01031 
01032         // Make sure the zoom slider can be moved at least a little bit.
01033         // Likewise, less than the increment pixels per region is just silly.
01034         pixels_per_region = llclamp(pixels_per_region, 1.f, (F32)(pow(2.f, ZOOM_MAX) * 128.f));
01035 
01036         F32 min_power = log(pixels_per_region/256.f)/log(2.f);
01037         childSetMinValue("zoom slider", min_power);
01038 }
01039 
01040 
01041 //-------------------------------------------------------------------------
01042 // User interface widget callbacks
01043 //-------------------------------------------------------------------------
01044 
01045 // static
01046 void LLFloaterWorldMap::onPanBtn( void* userdata )
01047 {
01048         if( !gFloaterWorldMap ) return;
01049 
01050         EPanDirection direction = (EPanDirection)(intptr_t)userdata;
01051 
01052         S32 pan_x = 0;
01053         S32 pan_y = 0;
01054         switch( direction )
01055         {
01056         case PAN_UP:    pan_y = -1;     break;
01057         case PAN_DOWN:  pan_y = 1;      break;
01058         case PAN_LEFT:  pan_x = 1;      break;
01059         case PAN_RIGHT: pan_x = -1;     break;
01060         default:                llassert(0);    return;
01061         }
01062 
01063         LLWorldMapView* map_panel;
01064         map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel();
01065         map_panel->translatePan( pan_x, pan_y );
01066 }
01067 
01068 // static
01069 void LLFloaterWorldMap::onGoHome(void*)
01070 {
01071         gAgent.teleportHome();
01072         gFloaterWorldMap->close();
01073 }
01074 
01075 
01076 // static 
01077 void LLFloaterWorldMap::onLandmarkComboPrearrange( LLUICtrl* ctrl, void* userdata )
01078 {
01079         LLFloaterWorldMap* self = gFloaterWorldMap;
01080         if( !self || self->mIsClosing )
01081         {
01082                 return;
01083         }
01084 
01085         LLCtrlListInterface *list = self->childGetListInterface("landmark combo");
01086         if (!list) return;
01087 
01088         LLUUID current_choice = list->getCurrentID();
01089 
01090         gFloaterWorldMap->buildLandmarkIDLists();
01091 
01092         if( current_choice.isNull() || !list->setCurrentByID( current_choice ) )
01093         {
01094                 LLTracker::stopTracking(NULL);
01095         }
01096 
01097 }
01098 
01099 // static 
01100 void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata )
01101 {
01102         LLFloaterWorldMap* self = gFloaterWorldMap;
01103 
01104         if( !self || self->mIsClosing )
01105         {
01106                 return;
01107         }
01108 
01109         LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("landmark combo");
01110         if (!list) return;
01111 
01112         LLUUID asset_id;
01113         LLUUID item_id = list->getCurrentID();
01114 
01115         LLTracker::stopTracking(NULL);
01116 
01117         //RN: stopTracking() clears current combobox selection, need to reassert it here
01118         list->setCurrentByID(item_id);
01119 
01120         if( item_id.isNull() )
01121         {
01122         }
01123         else if( item_id == sHomeID )
01124         {
01125                 asset_id = sHomeID;
01126         }
01127         else
01128         {
01129                 LLInventoryItem* item = gInventory.getItem( item_id );
01130                 if( item )
01131                 {
01132                         asset_id = item->getAssetUUID();
01133                 }
01134                 else
01135                 {
01136                         // Something went wrong, so revert to a safe value.
01137                         item_id.setNull();
01138                 }
01139         }
01140         
01141         self->trackLandmark( item_id);
01142         onShowTargetBtn(self);
01143 
01144         // Reset to user postion if nothing is tracked
01145         self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
01146 }
01147 
01148 // static 
01149 void LLFloaterWorldMap::onAvatarComboPrearrange( LLUICtrl* ctrl, void* userdata )
01150 {
01151         LLFloaterWorldMap* self = gFloaterWorldMap;
01152         if( !self || self->mIsClosing )
01153         {
01154                 return;
01155         }
01156 
01157         LLCtrlListInterface *list = self->childGetListInterface("friend combo");
01158         if (!list) return;
01159 
01160         LLUUID current_choice;
01161 
01162         if( LLAvatarTracker::instance().haveTrackingInfo() )
01163         {
01164                 current_choice = LLAvatarTracker::instance().getAvatarID();
01165         }
01166 
01167         self->buildAvatarIDList();
01168 
01169         if( !list->setCurrentByID( current_choice ) || current_choice.isNull() )
01170         {
01171                 LLTracker::stopTracking(NULL);
01172         }
01173 }
01174 
01175 
01176 // static 
01177 void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata )
01178 {
01179         LLFloaterWorldMap* self = gFloaterWorldMap;
01180         if( !self || self->mIsClosing )
01181         {
01182                 return;
01183         }
01184 
01185         LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("friend combo");
01186         if (!list) return;
01187 
01188         const LLUUID& new_avatar_id = list->getCurrentID();
01189         if (new_avatar_id.notNull())
01190         {
01191                 LLString name;
01192                 LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(gFloaterWorldMap, "friend combo");
01193                 if (combo) name = combo->getSimple();
01194                 self->trackAvatar(new_avatar_id, name);
01195                 onShowTargetBtn(self);
01196         }
01197         else
01198         {       // Reset to user postion if nothing is tracked
01199                 self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
01200         }
01201 }
01202 
01203 // static 
01204 void LLFloaterWorldMap::updateSearchEnabled( LLUICtrl* ctrl, void* userdata )
01205 {
01206         LLFloaterWorldMap *self = gFloaterWorldMap;
01207         if (self->childHasKeyboardFocus("location") && 
01208                 self->childGetValue("location").asString().length() > 0)
01209         {
01210                 self->setDefaultBtn("DoSearch");
01211         }
01212         else
01213         {
01214                 self->setDefaultBtn(NULL);
01215         }
01216 }
01217 
01218 // static 
01219 void LLFloaterWorldMap::onLocationCommit( void* userdata )
01220 {
01221         LLFloaterWorldMap *self = gFloaterWorldMap;
01222         if( !self || self->mIsClosing )
01223         {
01224                 return;
01225         }
01226 
01227         self->clearLocationSelection(FALSE);
01228         self->mCompletingRegionName = "";
01229         self->mLastRegionName = "";
01230 
01231         LLString str = self->childGetValue("location").asString();
01232 
01233         // Trim any leading and trailing spaces in the search target
01234         LLString saved_str = str;
01235         LLString::trim( str );
01236         if ( str != saved_str )
01237         {       // Set the value in the UI if any spaces were removed
01238                 self->childSetValue("location", str);
01239         }
01240 
01241         LLString::toLower(str);
01242         gFloaterWorldMap->mCompletingRegionName = str;
01243         gWorldMap->mIsTrackingCommit = TRUE;
01244         self->mExactMatch = FALSE;
01245         if (str.length() >= 3)
01246         {
01247                 gWorldMap->sendNamedRegionRequest(str);
01248         }
01249         else
01250         {
01251                 str += "#";
01252                 gWorldMap->sendNamedRegionRequest(str);
01253         }
01254 }
01255 
01256 
01257 // static
01258 void LLFloaterWorldMap::onClearBtn(void* data)
01259 {
01260         LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
01261         self->mTrackedStatus = LLTracker::TRACKING_NOTHING;
01262         LLTracker::stopTracking((void *)(intptr_t)TRUE);
01263         gWorldMap->mIsTrackingUnknownLocation = FALSE;
01264         self->mSLURL = "";                              // Clear the SLURL since it's invalid
01265         self->mSetToUserPosition = TRUE;        // Revert back to the current user position
01266 }
01267 
01268 // static
01269 void LLFloaterWorldMap::onFlyBtn(void* data)
01270 {
01271         LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
01272         self->fly();
01273 }
01274 
01275 void LLFloaterWorldMap::onShowTargetBtn(void* data)
01276 {
01277         LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
01278         self->centerOnTarget(TRUE);
01279 }
01280 
01281 void LLFloaterWorldMap::onShowAgentBtn(void* data)
01282 {
01283         LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate
01284 
01285         // Set flag so user's location will be displayed if not tracking anything else
01286         LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
01287         self->mSetToUserPosition = TRUE;        
01288 }
01289 
01290 // static
01291 void LLFloaterWorldMap::onClickTeleportBtn(void* data)
01292 {
01293         LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
01294         self->teleport();
01295 }
01296 
01297 // static
01298 void LLFloaterWorldMap::onCopySLURL(void* data)
01299 {
01300         LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
01301         gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(self->mSLURL));
01302         
01303         LLString::format_map_t args;
01304         args["[SLURL]"] = self->mSLURL;
01305 
01306         LLAlertDialog::showXml("CopySLURL", args);
01307 }
01308 
01309 void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data)
01310 {
01311         LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
01312         if(!self) return;
01313         self->childSetEnabled("event_mature_chk", self->childGetValue("event_chk"));
01314 }
01315 
01316 // protected
01317 void LLFloaterWorldMap::centerOnTarget(BOOL animate)
01318 {
01319         LLVector3d pos_global;
01320         if(LLTracker::getTrackingStatus() != LLTracker::TRACKING_NOTHING)
01321         {
01322                 LLVector3d tracked_position = LLTracker::getTrackedPositionGlobal();
01323                 //RN: tracker doesn't allow us to query completion, so we check for a tracking position of
01324                 // absolute zero, and keep trying in the draw loop
01325                 if (tracked_position.isExactlyZero())
01326                 {
01327                         mWaitingForTracker = TRUE;
01328                         return;
01329                 }
01330                 else
01331                 {
01332                         // We've got the position finally, so we're no longer busy. JC
01333 //                      getWindow()->decBusyCount();
01334                         pos_global = LLTracker::getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal();
01335                 }
01336         }
01337         else if(gWorldMap->mIsTrackingUnknownLocation)
01338         {
01339                 pos_global = gWorldMap->mUnknownLocation - gAgent.getCameraPositionGlobal();;
01340         }
01341         else
01342         {
01343                 // default behavior = center on agent
01344                 pos_global.clearVec();
01345         }
01346 
01347         LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sPixelsPerMeter)), 
01348                                                         -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sPixelsPerMeter)),
01349                                                         !animate);
01350         mWaitingForTracker = FALSE;
01351 }
01352 
01353 // protected
01354 void LLFloaterWorldMap::fly()
01355 {
01356         LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
01357 
01358         // Start the autopilot and close the floater, 
01359         // so we can see where we're flying
01360         if (!pos_global.isExactlyZero())
01361         {
01362                 gAgent.startAutoPilotGlobal( pos_global );
01363                 close();
01364         }
01365         else
01366         {
01367                 make_ui_sound("UISndInvalidOp");
01368         }
01369 }
01370 
01371 
01372 // protected
01373 void LLFloaterWorldMap::teleport()
01374 {
01375         BOOL teleport_home = FALSE;
01376         LLVector3d pos_global;
01377         LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
01378 
01379         LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
01380         if (LLTracker::TRACKING_AVATAR == tracking_status
01381                 && av_tracker.haveTrackingInfo() )
01382         {
01383                 pos_global = av_tracker.getGlobalPos();
01384                 pos_global.mdV[VZ] = childGetValue("spin z");
01385         }
01386         else if ( LLTracker::TRACKING_LANDMARK == tracking_status)
01387         {
01388                 if( LLTracker::getTrackedLandmarkAssetID() == sHomeID )
01389                 {
01390                         teleport_home = TRUE;
01391                 }
01392                 else
01393                 {
01394                         LLLandmark* landmark = gLandmarkList.getAsset( LLTracker::getTrackedLandmarkAssetID() );
01395                         LLUUID region_id;
01396                         if(landmark
01397                            && !landmark->getGlobalPos(pos_global)
01398                            && landmark->getRegionID(region_id))
01399                         {
01400                                 LLLandmark::requestRegionHandle(
01401                                         gMessageSystem,
01402                                         gAgent.getRegionHost(),
01403                                         region_id,
01404                                         NULL);
01405                         }
01406                 }
01407         }
01408         else if ( LLTracker::TRACKING_LOCATION == tracking_status)
01409         {
01410                 pos_global = LLTracker::getTrackedPositionGlobal();
01411         }
01412         else
01413         {
01414                 make_ui_sound("UISndInvalidOp");
01415         }
01416 
01417         // Do the teleport, which will also close the floater
01418         if (teleport_home)
01419         {
01420                 gAgent.teleportHome();
01421         }
01422         else if (!pos_global.isExactlyZero())
01423         {
01424                 if(LLTracker::TRACKING_LANDMARK == tracking_status)
01425                 {
01426                         gAgent.teleportViaLandmark(LLTracker::getTrackedLandmarkAssetID());
01427                 }
01428                 else
01429                 {
01430                         gAgent.teleportViaLocation( pos_global );
01431                 }
01432         }
01433 }
01434 
01435 // static
01436 void LLFloaterWorldMap::onGoToLandmarkDialog( S32 option, void* userdata )
01437 {
01438         LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
01439         switch( option )
01440         {
01441         case 0:
01442                 self->teleportToLandmark();
01443                 break;
01444         case 1:
01445                 self->flyToLandmark();
01446                 break;
01447         default:
01448                 // nothing
01449                 break;
01450         }
01451 }
01452 
01453 void LLFloaterWorldMap::flyToLandmark()
01454 {
01455         LLVector3d destination_pos_global;
01456         if( !LLTracker::getTrackedLandmarkAssetID().isNull() )
01457         {
01458                 if (LLTracker::hasLandmarkPosition())
01459                 {
01460                         gAgent.startAutoPilotGlobal( LLTracker::getTrackedPositionGlobal() );
01461                 }
01462         }
01463 }
01464 
01465 void LLFloaterWorldMap::teleportToLandmark()
01466 {
01467         BOOL has_destination = FALSE;
01468         LLUUID destination_id; // Null means "home"
01469 
01470         if( LLTracker::getTrackedLandmarkAssetID() == sHomeID )
01471         {
01472                 has_destination = TRUE;
01473         }
01474         else
01475         {
01476                 LLLandmark* landmark = gLandmarkList.getAsset( LLTracker::getTrackedLandmarkAssetID() );
01477                 LLVector3d global_pos;
01478                 if(landmark && landmark->getGlobalPos(global_pos))
01479                 {
01480                         destination_id = LLTracker::getTrackedLandmarkAssetID();
01481                         has_destination = TRUE;
01482                 }
01483                 else if(landmark)
01484                 {
01485                         // pop up an anonymous request request.
01486                         LLUUID region_id;
01487                         if(landmark->getRegionID(region_id))
01488                         {
01489                                 LLLandmark::requestRegionHandle(
01490                                         gMessageSystem,
01491                                         gAgent.getRegionHost(),
01492                                         region_id,
01493                                         NULL);
01494                         }
01495                 }
01496         }
01497 
01498         if( has_destination )
01499         {
01500                 gAgent.teleportViaLandmark( destination_id );
01501         }
01502 }
01503 
01504 
01505 void LLFloaterWorldMap::teleportToAvatar()
01506 {
01507         LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
01508         if(av_tracker.haveTrackingInfo())
01509         {
01510                 LLVector3d pos_global = av_tracker.getGlobalPos();
01511                 gAgent.teleportViaLocation( pos_global );
01512         }
01513 }
01514 
01515 
01516 void LLFloaterWorldMap::flyToAvatar()
01517 {
01518         if( LLAvatarTracker::instance().haveTrackingInfo() )
01519         {
01520                 gAgent.startAutoPilotGlobal( LLAvatarTracker::instance().getGlobalPos() );
01521         }
01522 }
01523 
01524 // static
01525 void LLFloaterWorldMap::onCommitBackground(void* userdata, bool from_click)
01526 {
01527         LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
01528 
01529         // Find my index
01530         S32 index = self->mTabs->getCurrentPanelIndex();
01531 
01532         if (gWorldMap)
01533         {
01534                 gWorldMap->setCurrentLayer(index);
01535         }
01536 }
01537 
01538 void LLFloaterWorldMap::updateSims(bool found_null_sim)
01539 {
01540         if (mCompletingRegionName == "")
01541         {
01542                 return;
01543         }
01544 
01545         LLCtrlListInterface *list = childGetListInterface("search_results");
01546         if (!list) return;
01547         list->operateOnAll(LLCtrlListInterface::OP_DELETE);
01548 
01549         LLSD selected_value = list->getSimpleSelectedValue();
01550 
01551         S32 name_length = mCompletingRegionName.length();
01552 
01553         BOOL match_found = FALSE;
01554         S32 num_results = 0;
01555         std::map<U64, LLSimInfo*>::const_iterator it;
01556         for (it = gWorldMap->mSimInfoMap.begin(); it != gWorldMap->mSimInfoMap.end(); ++it)
01557         {
01558                 LLSimInfo* info = (*it).second;
01559                 LLString sim_name = info->mName;
01560                 LLString sim_name_lower = sim_name;
01561                 LLString::toLower(sim_name_lower);
01562 
01563                 if (sim_name_lower.substr(0, name_length) == mCompletingRegionName)
01564                 {
01565                         if (gWorldMap->mIsTrackingCommit)
01566                         {
01567                                 if (sim_name_lower == mCompletingRegionName)
01568                                 {
01569                                         selected_value = sim_name;
01570                                         match_found = TRUE;
01571                                 }
01572                         }
01573 
01574                         LLSD value;
01575                         value["id"] = sim_name;
01576                         value["columns"][0]["column"] = "sim_name";
01577                         value["columns"][0]["value"] = sim_name;
01578                         list->addElement(value);
01579                         num_results++;
01580                 }
01581         }
01582         
01583         list->selectByValue(selected_value);
01584 
01585         if (found_null_sim)
01586         {
01587                 mCompletingRegionName = "";
01588         }
01589 
01590         if (match_found)
01591         {
01592                 mExactMatch = TRUE;
01593                 childSetFocus("search_results");
01594                 onCommitSearchResult(NULL, this);
01595         }
01596         else if (!mExactMatch && num_results > 0)
01597         {
01598                 list->selectFirstItem(); // select first item by default
01599                 childSetFocus("search_results");
01600                 onCommitSearchResult(NULL, this);
01601         }
01602         else
01603         {
01604                 list->addSimpleElement("None found.");
01605                 list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
01606         }
01607 }
01608 
01609 // static
01610 void LLFloaterWorldMap::onCommitLocation(LLUICtrl* ctrl, void* userdata)
01611 {
01612         LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
01613         LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
01614         if ( LLTracker::TRACKING_LOCATION == tracking_status)
01615         {
01616                 LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
01617                 F64 local_x = self->childGetValue("spin x");
01618                 F64 local_y = self->childGetValue("spin y");
01619                 F64 local_z = self->childGetValue("spin z");
01620                 pos_global.mdV[VX] += -fmod(pos_global.mdV[VX], 256.0) + local_x;
01621                 pos_global.mdV[VY] += -fmod(pos_global.mdV[VY], 256.0) + local_y;
01622                 pos_global.mdV[VZ] = local_z;
01623                 self->trackLocation(pos_global);
01624         }
01625 }
01626 
01627 // static
01628 void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata)
01629 {
01630         LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
01631 
01632         LLCtrlListInterface *list = self->childGetListInterface("search_results");
01633         if (!list) return;
01634 
01635         LLSD selected_value = list->getSimpleSelectedValue();
01636         LLString sim_name = selected_value.asString();
01637         if (sim_name.empty())
01638         {
01639                 return;
01640         }
01641         LLString::toLower(sim_name);
01642 
01643         std::map<U64, LLSimInfo*>::const_iterator it;
01644         for (it = gWorldMap->mSimInfoMap.begin(); it != gWorldMap->mSimInfoMap.end(); ++it)
01645         {
01646                 LLSimInfo* info = (*it).second;
01647                 LLString info_sim_name = info->mName;
01648                 LLString::toLower(info_sim_name);
01649 
01650                 if (sim_name == info_sim_name)
01651                 {
01652                         LLVector3d pos_global = from_region_handle( info->mHandle );
01653                         F64 local_x = self->childGetValue("spin x");
01654                         F64 local_y = self->childGetValue("spin y");
01655                         F64 local_z = self->childGetValue("spin z");
01656                         pos_global.mdV[VX] += local_x;
01657                         pos_global.mdV[VY] += local_y;
01658                         pos_global.mdV[VZ] = local_z;
01659 
01660                         self->childSetValue("location", sim_name);
01661                         self->trackLocation(pos_global);
01662                         self->setDefaultBtn("Teleport");
01663                         break;
01664                 }
01665         }
01666 
01667         onShowTargetBtn(self);
01668 }

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