diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e46a05a59..dcdf7c673 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -542,6 +542,7 @@ set(viewer_SOURCE_FILES llwlparamset.cpp llworld.cpp llworldmap.cpp + llworldmapmessage.cpp llworldmipmap.cpp llworldmapview.cpp llxmlrpctransaction.cpp @@ -1050,6 +1051,7 @@ set(viewer_HEADER_FILES llwlparamset.h llworld.h llworldmap.h + llworldmapmessage.h llworldmipmap.h llworldmapview.h llxmlrpctransaction.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 2b6e85eeb..5180856ed 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -77,6 +77,7 @@ #include "llvoavatarself.h" #include "llworld.h" #include "llworldmap.h" +#include "llworldmapmessage.h" //Misc non-standard includes #include "llurldispatcher.h" @@ -3688,7 +3689,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) (F32)(pos_global.mdV[VY] - region_origin.mdV[VY]), (F32)(pos_global.mdV[VZ])); pos_local += offset; - teleportRequest(info->getHandle(), pos_local); + teleportRequest(handle, pos_local); } else if(regionp && teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY]))) @@ -3737,10 +3738,6 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) mbTeleportKeepsLookAt = true; gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction U64 region_handle = to_region_handle(pos_global); - LLSimInfo* simInfo = LLWorldMap::instance().simInfoFromHandle(region_handle); - if(simInfo) - region_handle = simInfo->getHandle(); - LLVector3 pos_local = (LLVector3)(pos_global - from_region_handle(region_handle)); teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); } @@ -4180,7 +4177,7 @@ void LLAgent::showLureDestination(const std::string fromname, const int global_x { U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); - LLWorldMap::getInstance()->sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); //Will call onFoundLureDestination on response + LLWorldMapMessage::getInstance()->sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); //Will call onFoundLureDestination on response } } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f23d46e9b..7bf666e42 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -504,7 +504,7 @@ static void settings_to_globals() gAllowIdleAFK = gSavedSettings.getBOOL("AllowIdleAFK"); gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); - LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); + LLWorldMapView::sMapScale = llmax(.1f,gSavedSettings.getF32("MapScale")); LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips"); } diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index d541a93e5..c24c146f3 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -70,6 +70,7 @@ #include "llviewerregion.h" #include "llviewerstats.h" #include "llworldmap.h" +#include "llworldmapmessage.h" #include "llworldmapview.h" #include "lluictrlfactory.h" #include "llappviewer.h" @@ -88,6 +89,21 @@ //--------------------------------------------------------------------------- static const F32 MAP_ZOOM_TIME = 0.2f; +// Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed +// width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across +// sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit. +// Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window. +static const S32 MAX_VISIBLE_REGIONS = 512; + +// It would be more logical to have this inside the method where it is used but to compile under gcc this +// struct has to be here. +struct SortRegionNames +{ + inline bool operator ()(std::pair const& _left, std::pair const& _right) + { + return(LLStringUtil::compareInsensitive(_left.second->getName(), _right.second->getName()) < 0); + } +}; enum EPanDirection { PAN_UP, @@ -97,17 +113,10 @@ enum EPanDirection }; // Values in pixels per region -static const F32 ZOOM_MIN = -8.f; // initial value, updated by adjustZoomSlider -static const F32 ZOOM_MAX = 0.f; -static const F32 ZOOM_INC = 0.2f; +static const F32 ZOOM_MAX = 128.f; -static const F32 SIM_COORD_MIN = 0.f; -static const F32 SIM_COORD_MAX = 255.f; static const F32 SIM_COORD_DEFAULT = 128.f; -static const F64 MAX_FLY_DISTANCE = 363.f; // Diagonal size of one sim. -static const F64 MAX_FLY_DISTANCE_SQUARED = MAX_FLY_DISTANCE * MAX_FLY_DISTANCE; - //--------------------------------------------------------------------------- // Globals //--------------------------------------------------------------------------- @@ -166,13 +175,16 @@ LLFloaterWorldMap::LLFloaterWorldMap() mInventory(NULL), mInventoryObserver(NULL), mFriendObserver(NULL), - mCompletingRegionName(""), + mCompletingRegionName(), + mCompletingRegionPos(), mWaitingForTracker(FALSE), - mExactMatch(FALSE), mIsClosing(FALSE), mSetToUserPosition(TRUE), mTrackedLocation(0,0,0), - mTrackedStatus(LLTracker::TRACKING_NOTHING) + mTrackedStatus(LLTracker::TRACKING_NOTHING), + mListFriendCombo(NULL), + mListLandmarkCombo(NULL), + mListSearchResults(NULL) { LLCallbackMap::map_t factory_map; factory_map["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL); @@ -197,54 +209,58 @@ BOOL LLFloaterWorldMap::postBuild() mPanel = getChild("objects_mapview"); - childSetCommitCallback("friend combo", onAvatarComboCommit, this); - LLComboBox *avatar_combo = getChild("friend combo"); - if (avatar_combo) - { - avatar_combo->selectFirstItem(); - avatar_combo->setPrearrangeCallback( onAvatarComboPrearrange ); - avatar_combo->setTextEntryCallback( onComboTextEntry ); - } - - childSetAction("DoSearch", onLocationCommit, this); - + avatar_combo->selectFirstItem(); + avatar_combo->setPrearrangeCallback( onAvatarComboPrearrange ); + avatar_combo->setTextEntryCallback( onComboTextEntry ); + mListFriendCombo = dynamic_cast(avatar_combo); + LLLineEditor *location_editor = getChild("location"); location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1)); location_editor->setKeystrokeCallback( onSearchTextEntry ); - childSetCommitCallback("search_results", onCommitSearchResult, this); - childSetDoubleClickCallback("search_results", onClickTeleportBtn); - childSetCommitCallback("spin x", onCommitLocation, this); - childSetCommitCallback("spin y", onCommitLocation, this); - childSetCommitCallback("spin z", onCommitLocation, this); + LLScrollListCtrl* search_results = getChild("search_results"); + search_results->setDoubleClickCallback(&LLFloaterWorldMap::onClickTeleportBtn_static); + search_results->setCallbackUserData(this); + mListSearchResults = dynamic_cast(search_results); + + - childSetCommitCallback("landmark combo", onLandmarkComboCommit, this); LLComboBox *landmark_combo = getChild( "landmark combo"); - if (landmark_combo) - { - landmark_combo->selectFirstItem(); - landmark_combo->setPrearrangeCallback( onLandmarkComboPrearrange ); - landmark_combo->setTextEntryCallback( onComboTextEntry ); - } - childSetAction("Go Home", onGoHome, this); + landmark_combo->selectFirstItem(); + landmark_combo->setPrearrangeCallback( onLandmarkComboPrearrange ); + landmark_combo->setTextEntryCallback( onComboTextEntry ); + mListLandmarkCombo = dynamic_cast(landmark_combo); + + avatar_combo->setCommitCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboCommit,this) ); + + search_results->setCommitCallback( boost::bind(&LLFloaterWorldMap::onCommitSearchResult,this) ); + + landmark_combo->setCommitCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit,this) ); + + getChild("spin x")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCoordinatesCommit,this) ); + getChild("spin y")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCoordinatesCommit,this) ); + getChild("spin z")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCoordinatesCommit,this) ); + + getChild("DoSearch")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onLocationCommit,this) ); + getChild("Go Home")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onGoHome,this) ); + getChild("Teleport")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onClickTeleportBtn,this) ); + getChild("Show Destination")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onShowTargetBtn,this) ); + getChild("Show My Location")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onShowAgentBtn,this) ); + getChild("Clear")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onClearBtn,this) ); + getChild("copy_slurl")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCopySLURL,this) ); - childSetAction("Teleport", onClickTeleportBtn, this); - - childSetAction("Show Destination", onShowTargetBtn, this); - childSetAction("Show My Location", onShowAgentBtn, this); - childSetAction("Clear", onClearBtn, this); - childSetAction("copy_slurl", onCopySLURL, this); - - mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f); - childSetValue("zoom slider", LLWorldMapView::sMapScale); + mCurZoomVal = log(LLWorldMapView::sMapScale/256.f)/log(2.f); + childSetValue("zoom slider", mCurZoomVal); setDefaultBtn(NULL); mZoomTimer.stop(); - + + onChangeMaturity(); + return TRUE; } @@ -253,13 +269,15 @@ LLFloaterWorldMap::~LLFloaterWorldMap() { // All cleaned up by LLView destructor mPanel = NULL; - + // Inventory deletes all observers on shutdown mInventory = NULL; mInventoryObserver = NULL; - + // avatar tracker will delete this for us. mFriendObserver = NULL; + + gFloaterWorldMap = NULL; } @@ -297,14 +315,8 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) } map_panel->updateVisibleBlocks(); - // Reload the agent positions when we show the window - LLWorldMap::getInstance()->eraseItems(); - - // Reload any maps that may have changed - LLWorldMap::getInstance()->clearSimFlags(); - - const bool request_from_sim = true; - LLWorldMap::getInstance()->setCurrentLayer(0, request_from_sim); + // Reload items as they may have changed + LLWorldMap::getInstance()->reloadItems(); // We may already have a bounding box for the regions of the world, // so use that to adjust the view. @@ -338,9 +350,7 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) // static void LLFloaterWorldMap::reloadIcons(void*) { - LLWorldMap::getInstance()->eraseItems(); - - LLWorldMap::getInstance()->sendMapLayerRequest(); + LLWorldMap::getInstance()->reloadItems(); } @@ -396,9 +406,7 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks) { if (!isMinimized() && isFrontmost()) { - LLRect area; - childGetRect("search_results", area); - if(!area.pointInRect(x, y)) + if(mPanel->pointInView(x, y)) { F32 slider_value = (F32)childGetValue("zoom slider").asReal(); slider_value += ((F32)clicks * -0.3333f); @@ -427,20 +435,6 @@ void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent // virtual void LLFloaterWorldMap::draw() { - // Hide/Show Mature Events controls - childSetVisible("events_mature_icon", gAgent.canAccessMature()); - childSetVisible("events_mature_label", gAgent.canAccessMature()); - childSetVisible("event_mature_chk", gAgent.canAccessMature()); - - childSetVisible("events_adult_icon", gAgent.canAccessMature()); - childSetVisible("events_adult_label", gAgent.canAccessMature()); - childSetVisible("event_adult_chk", gAgent.canAccessMature()); - bool adult_enabled = gAgent.canAccessAdult(); - if (!adult_enabled) - { - childSetValue("event_adult_chk", FALSE); - } - childSetEnabled("event_adult_chk", adult_enabled); // On orientation island, users don't have a home location yet, so don't // let them teleport "home". It dumps them in an often-crowed welcome @@ -481,7 +475,7 @@ void LLFloaterWorldMap::draw() { F64 seconds = LLTimer::getElapsedSeconds(); double value = fmod(seconds, 2); - value = 0.5 + 0.5*cos(value * 3.14159f); + value = 0.5 + 0.5*cos(value * F_PI); LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0); childSetColor("location_icon", loading_color); } @@ -499,36 +493,30 @@ void LLFloaterWorldMap::draw() childSetEnabled("Teleport", (BOOL)tracking_status); // childSetEnabled("Clear", (BOOL)tracking_status); - childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->mIsTrackingUnknownLocation); + childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->isTracking()); childSetEnabled("copy_slurl", (mSLURL.size() > 0) ); setMouseOpaque(TRUE); getDragHandle()->setMouseOpaque(TRUE); - + //RN: snaps to zoom value because interpolation caused jitter in the text rendering - F32 interp = 1.f; - if (!mZoomTimer.getStarted()) + if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild("zoom slider")->getValue().asReal()) { - mCurZoomValInterpolationStart = mCurZoomVal; - if (mCurZoomVal < (F32)childGetValue("zoom slider").asReal()) - { - mZoomTimer.start(); - } + mZoomTimer.start(); } - if (mZoomTimer.getStarted()) - { - interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME; - } - if (interp >= 1.f) + F32 interp = mZoomTimer.getStarted() ? mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME : 1.f; + if (interp > 1.f) { interp = 1.f; mZoomTimer.stop(); } - // Interpolate between mCurZoomValInterpolationStart and "zoom slider". - mCurZoomVal = lerp(mCurZoomValInterpolationStart, (F32)childGetValue("zoom slider").asReal(), interp); + mCurZoomVal = lerp(mCurZoomVal, (F32)getChild("zoom slider")->getValue().asReal(), interp); F32 map_scale = 256.f*pow(2.f, mCurZoomVal); LLWorldMapView::setScale( map_scale ); + onChangeMaturity(); + + LLFloater::draw(); } @@ -632,32 +620,37 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); if (!sim_info) { - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE; - LLWorldMap::getInstance()->mInvalidLocation = FALSE; - LLWorldMap::getInstance()->mUnknownLocation = pos_global; + // We haven't found a region for that point yet, leave the tracking to the world map + LLWorldMap::getInstance()->setTracking(pos_global); LLTracker::stopTracking(NULL); S32 world_x = S32(pos_global.mdV[0] / 256); S32 world_y = S32(pos_global.mdV[1] / 256); - LLWorldMap::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true); + LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true); setDefaultBtn(""); + + // clicked on a non-region - turn off coord display + enableTeleportCoordsDisplay( false ); + return; } if (sim_info->isDown()) { - // Down sim. Show the blue circle of death! - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE; - LLWorldMap::getInstance()->mUnknownLocation = pos_global; - LLWorldMap::getInstance()->mInvalidLocation = TRUE; + // Down region. Show the blue circle of death! + // i.e. let the world map that this and tell it it's invalid + LLWorldMap::getInstance()->setTracking(pos_global); + LLWorldMap::getInstance()->setTrackingInvalid(); LLTracker::stopTracking(NULL); setDefaultBtn(""); + + // clicked on a down region - turn off coord display + enableTeleportCoordsDisplay( false ); + return; } - + std::string sim_name = sim_info->getName(); - U32 locX, locY; - from_region_handle(sim_info->getHandle(), &locX, &locY); - F32 region_x = pos_global.mdV[VX] - locX; - F32 region_y = pos_global.mdV[VY] - locY; + F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); + F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); std::string full_name = llformat("%s (%d, %d, %d)", // sim_name.c_str(), // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-04 (RLVa-1.0.0a) @@ -670,13 +663,43 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) std::string tooltip(""); mTrackedStatus = LLTracker::TRACKING_LOCATION; LLTracker::trackLocation(pos_global, full_name, tooltip); - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE; - LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; - + LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking + + LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal(); + updateTeleportCoordsDisplay( coord_pos ); + + // we have a valid region - turn on coord display + enableTeleportCoordsDisplay( true ); + setDefaultBtn("Teleport"); } + +// enable/disable teleport destination coordinates +void LLFloaterWorldMap::enableTeleportCoordsDisplay( bool enabled ) +{ + childSetEnabled("spin x", enabled ); + childSetEnabled("spin y", enabled ); + childSetEnabled("spin z", enabled ); +} + +// update display of teleport destination coordinates - pos is in global coordinates +void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos ) +{ + // if we're going to update their value, we should also enable them + enableTeleportCoordsDisplay( true ); + + // convert global specified position to a local one + F32 region_local_x = (F32)fmod( pos.mdV[VX], (F64)REGION_WIDTH_METERS ); + F32 region_local_y = (F32)fmod( pos.mdV[VY], (F64)REGION_WIDTH_METERS ); + F32 region_local_z = (F32)llclamp( pos.mdV[VZ], 0.0, (F64)REGION_HEIGHT_METERS ); + + // write in the values + childSetValue("spin x", region_local_x ); + childSetValue("spin y", region_local_y ); + childSetValue("spin z", region_local_z ); + } + void LLFloaterWorldMap::updateLocation() { bool gotSimName; @@ -703,19 +726,16 @@ void LLFloaterWorldMap::updateLocation() // Fill out the location field childSetValue("location", agent_sim_name); + // update the coordinate display with location of avatar in region + updateTeleportCoordsDisplay( agentPos ); + + S32 x = llround( (F32)fmod( (F32)agentPos[VX], (F32)REGION_WIDTH_METERS ) ); + S32 y = llround( (F32)fmod( (F32)agentPos[VY], (F32)REGION_WIDTH_METERS ) ); + S32 z = llround( (F32)agentPos[VZ] ); + // Figure out where user is - LLVector3d agentPos = gAgent.getPositionGlobal(); - - S32 agent_x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) ); - S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) ); - S32 agent_z = llround( (F32)agentPos.mdV[VZ] ); - - childSetValue("spin x", LLSD(agent_x) ); - childSetValue("spin y", LLSD(agent_y) ); - childSetValue("spin z", LLSD(agent_z) ); - // Set the current SLURL - mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z); + mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, x, y, z); // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) @@ -751,16 +771,18 @@ void LLFloaterWorldMap::updateLocation() childSetValue("location", sim_name); - F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); - F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); - childSetValue("spin x", LLSD(region_x) ); - childSetValue("spin y", LLSD(region_y) ); - childSetValue("spin z", LLSD((F32)pos_global.mdV[VZ]) ); - + // refresh coordinate display to reflect where user clicked. + LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal(); + updateTeleportCoordsDisplay( coord_pos ); + // simNameFromPosGlobal can fail, so don't give the user an invalid SLURL if ( gotSimName ) { - mSLURL = LLURLDispatcher::buildSLURL(sim_name, llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ])); + LLVector3d agentPos = gAgent.getPositionGlobal(); + S32 x = llround( (F32)fmod( (F32)agentPos[VX], (F32)REGION_WIDTH_METERS ) ); + S32 y = llround( (F32)fmod( (F32)agentPos[VY], (F32)REGION_WIDTH_METERS ) ); + S32 z = llround( (F32)agentPos[VZ] ); + mSLURL = LLURLDispatcher::buildSLURL(sim_name, x, y, z); } else { // Empty SLURL will disable the "Copy SLURL to clipboard" button @@ -795,15 +817,17 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3 { // fill in UI based on URL gFloaterWorldMap->childSetValue("location", region_name); - childSetValue("spin x", LLSD((F32)x_coord)); - childSetValue("spin y", LLSD((F32)y_coord)); - childSetValue("spin z", LLSD((F32)z_coord)); + + // Save local coords to highlight position after region global + // position is returned. + gFloaterWorldMap->mCompletingRegionPos.set( + (F32)x_coord, (F32)y_coord, (F32)z_coord); // pass sim name to combo box gFloaterWorldMap->mCompletingRegionName = region_name; - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name); + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name); LLStringUtil::toLower(gFloaterWorldMap->mCompletingRegionName); - LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; + LLWorldMap::getInstance()->setTrackingCommit(); } } @@ -868,9 +892,9 @@ void LLFloaterWorldMap::friendsChanged() // No longer really builds a list. Instead, just updates mAvatarCombo. void LLFloaterWorldMap::buildAvatarIDList() { - LLCtrlListInterface *list = childGetListInterface("friend combo"); + LLCtrlListInterface *list = mListFriendCombo; if (!list) return; - + // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) @@ -904,12 +928,9 @@ void LLFloaterWorldMap::buildAvatarIDList() void LLFloaterWorldMap::buildLandmarkIDLists() { - LLCtrlListInterface *list = childGetListInterface("landmark combo"); - if (!list) - { - return; - } - + LLCtrlListInterface *list = mListLandmarkCombo; + if (!list) return; + // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) @@ -969,7 +990,7 @@ F32 LLFloaterWorldMap::getDistanceToDestination(const LLVector3d &destination, void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) { - LLCtrlListInterface *list = childGetListInterface("search_results"); + LLCtrlListInterface *list = mListSearchResults; if (list) { list->operateOnAll(LLCtrlListInterface::OP_DELETE); @@ -986,9 +1007,9 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) { childSetValue("spin z", 0); } - LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; + //Singu Note: Don't do this. It basically 'eats' the first click onto void space if the previous tracked target was a valid sim. + //LLWorldMap::getInstance()->cancelTracking(); mCompletingRegionName = ""; - mExactMatch = FALSE; } @@ -996,7 +1017,7 @@ void LLFloaterWorldMap::clearLandmarkSelection(BOOL clear_ui) { if (clear_ui || !childHasKeyboardFocus("landmark combo")) { - LLCtrlListInterface *list = childGetListInterface("landmark combo"); + LLCtrlListInterface *list = mListLandmarkCombo; if (list) { list->selectByValue( "None" ); @@ -1010,7 +1031,7 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui) if (clear_ui || !childHasKeyboardFocus("friend combo")) { mTrackedStatus = LLTracker::TRACKING_NOTHING; - LLCtrlListInterface *list = childGetListInterface("friend combo"); + LLCtrlListInterface *list = mListFriendCombo; if (list) { list->selectByValue( "None" ); @@ -1023,22 +1044,22 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui) // can see the whole world, plus a little. void LLFloaterWorldMap::adjustZoomSliderBounds() { - // World size in regions - S32 world_width_regions = LLWorldMap::getInstance()->getWorldWidth() / REGION_WIDTH_UNITS; - S32 world_height_regions = LLWorldMap::getInstance()->getWorldHeight() / REGION_WIDTH_UNITS; - - // Pad the world size a little bit, so we have a nice border on - // the edge - world_width_regions++; - world_height_regions++; - + // Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed + // width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across + // sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit. + // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window. + S32 world_width_regions = MAX_VISIBLE_REGIONS; + S32 world_height_regions = MAX_VISIBLE_REGIONS; + // Find how much space we have to display the world - LLRect view_rect = mPanel->getRect(); - + LLWorldMapView* map_panel; + map_panel = (LLWorldMapView*)mPanel; + LLRect view_rect = map_panel->getRect(); + // View size in pixels S32 view_width = view_rect.getWidth(); S32 view_height = view_rect.getHeight(); - + // Pixels per region to display entire width/height F32 width_pixels_per_region = (F32) view_width / (F32) world_width_regions; F32 height_pixels_per_region = (F32) view_height / (F32) world_height_regions; @@ -1052,9 +1073,10 @@ void LLFloaterWorldMap::adjustZoomSliderBounds() // Make sure the zoom slider can be moved at least a little bit. // Likewise, less than the increment pixels per region is just silly. - pixels_per_region = llclamp(pixels_per_region, 1.f, (F32)(pow(2.f, ZOOM_MAX) * 128.f)); - + pixels_per_region = llclamp(pixels_per_region, 1.f, ZOOM_MAX); + F32 min_power = log(pixels_per_region/256.f)/log(2.f); + childSetMinValue("zoom slider", min_power); } @@ -1063,34 +1085,10 @@ void LLFloaterWorldMap::adjustZoomSliderBounds() // User interface widget callbacks //------------------------------------------------------------------------- -// static -void LLFloaterWorldMap::onPanBtn( void* userdata ) -{ - if( !gFloaterWorldMap ) return; - - EPanDirection direction = (EPanDirection)(intptr_t)userdata; - - S32 pan_x = 0; - S32 pan_y = 0; - switch( direction ) - { - case PAN_UP: pan_y = -1; break; - case PAN_DOWN: pan_y = 1; break; - case PAN_LEFT: pan_x = 1; break; - case PAN_RIGHT: pan_x = -1; break; - default: llassert(0); return; - } - - LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; - map_panel->translatePan( pan_x, pan_y ); -} - -// static -void LLFloaterWorldMap::onGoHome(void*) +void LLFloaterWorldMap::onGoHome() { gAgent.teleportHome(); - gFloaterWorldMap->close(); + close(); } @@ -1122,7 +1120,7 @@ void LLFloaterWorldMap::onComboTextEntry( LLLineEditor* ctrl, void* userdata ) // Reset the tracking whenever we start typing into any of the search fields, // so that hitting does an auto-complete versus teleporting us to the // previously selected landmark/friend. - LLTracker::clearFocus(); + LLTracker::stopTracking(NULL); } // static @@ -1133,16 +1131,14 @@ void LLFloaterWorldMap::onSearchTextEntry( LLLineEditor* ctrl, void* userdata ) } // static -void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) +void LLFloaterWorldMap::onLandmarkComboCommit() { - LLFloaterWorldMap* self = gFloaterWorldMap; - - if( !self || self->mIsClosing ) + if( mIsClosing ) { return; } - - LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("landmark combo"); + + LLCtrlListInterface *list = mListLandmarkCombo; if (!list) return; LLUUID asset_id; @@ -1174,11 +1170,11 @@ void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) } } - self->trackLandmark( item_id); - onShowTargetBtn(self); - + trackLandmark( item_id); + onShowTargetBtn(); + // Reset to user postion if nothing is tracked - self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); + mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } // static @@ -1208,31 +1204,28 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( LLUICtrl* ctrl, void* userdata } } - -// static -void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata ) +void LLFloaterWorldMap::onAvatarComboCommit() { - LLFloaterWorldMap* self = gFloaterWorldMap; - if( !self || self->mIsClosing ) + if( mIsClosing ) { return; } - - LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("friend combo"); + + LLCtrlListInterface *list = mListFriendCombo; if (!list) return; - + const LLUUID& new_avatar_id = list->getCurrentID(); if (new_avatar_id.notNull()) { std::string name; - LLComboBox* combo = gFloaterWorldMap->getChild("friend combo"); + LLComboBox* combo = getChild("friend combo"); if (combo) name = combo->getSimple(); - self->trackAvatar(new_avatar_id, name); - onShowTargetBtn(self); + trackAvatar(new_avatar_id, name); + onShowTargetBtn(); } else { // Reset to user postion if nothing is tracked - self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); + mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } } @@ -1254,105 +1247,99 @@ void LLFloaterWorldMap::updateSearchEnabled() } } -// static -void LLFloaterWorldMap::onLocationCommit( void* userdata ) +void LLFloaterWorldMap::onLocationCommit() { - LLFloaterWorldMap *self = gFloaterWorldMap; - if( !self || self->mIsClosing ) + if( mIsClosing ) { return; } + + clearLocationSelection(FALSE); + mCompletingRegionName = ""; + mLastRegionName = ""; - self->clearLocationSelection(FALSE); - self->mCompletingRegionName = ""; - self->mLastRegionName = ""; - - std::string str = self->childGetValue("location").asString(); + std::string str = childGetValue("location").asString(); // Trim any leading and trailing spaces in the search target std::string saved_str = str; LLStringUtil::trim( str ); if ( str != saved_str ) { // Set the value in the UI if any spaces were removed - self->childSetValue("location", str); + childSetValue("location", str); + } + + // Don't try completing empty name (STORM-1427). + if (str.empty()) + { + return; } LLStringUtil::toLower(str); - gFloaterWorldMap->mCompletingRegionName = str; - LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; - self->mExactMatch = FALSE; + mCompletingRegionName = str; + LLWorldMap::getInstance()->setTrackingCommit(); if (str.length() >= 3) { - LLWorldMap::getInstance()->sendNamedRegionRequest(str); + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str); } else { str += "#"; - LLWorldMap::getInstance()->sendNamedRegionRequest(str); + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str); } } - -// static -void LLFloaterWorldMap::onClearBtn(void* data) +void LLFloaterWorldMap::onCoordinatesCommit() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->mTrackedStatus = LLTracker::TRACKING_NOTHING; + if( mIsClosing ) + { + return; + } + + S32 x_coord = (S32)childGetValue("spin x").asReal(); + S32 y_coord = (S32)childGetValue("spin y").asReal(); + S32 z_coord = (S32)childGetValue("spin z").asReal(); + + const std::string region_name = childGetValue("location").asString(); + + trackURL( region_name, x_coord, y_coord, z_coord ); +} + +void LLFloaterWorldMap::onClearBtn() +{ + mTrackedStatus = LLTracker::TRACKING_NOTHING; LLTracker::stopTracking((void *)(intptr_t)TRUE); - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - self->mSLURL = ""; // Clear the SLURL since it's invalid - self->mSetToUserPosition = TRUE; // Revert back to the current user position + LLWorldMap::getInstance()->cancelTracking(); + mSLURL = ""; // Clear the SLURL since it's invalid + mSetToUserPosition = TRUE; // Revert back to the current user position } -// static -void LLFloaterWorldMap::onFlyBtn(void* data) +void LLFloaterWorldMap::onShowTargetBtn() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->fly(); + centerOnTarget(TRUE); } -void LLFloaterWorldMap::onShowTargetBtn(void* data) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->centerOnTarget(TRUE); -} - -void LLFloaterWorldMap::onShowAgentBtn(void* data) +void LLFloaterWorldMap::onShowAgentBtn() { LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate - // Set flag so user's location will be displayed if not tracking anything else - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->mSetToUserPosition = TRUE; + mSetToUserPosition = TRUE; } -// static -void LLFloaterWorldMap::onClickTeleportBtn(void* data) +void LLFloaterWorldMap::onClickTeleportBtn() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->teleport(); + teleport(); } -// static -void LLFloaterWorldMap::onCopySLURL(void* data) +void LLFloaterWorldMap::onCopySLURL() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(self->mSLURL)); + getWindow()->copyTextToClipboard(utf8str_to_wstring(mSLURL)); LLSD args; - args["SLURL"] = self->mSLURL; + args["SLURL"] = mSLURL; LLNotificationsUtil::add("CopySLURL", args); } -void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - if(!self) return; - self->childSetEnabled("event_mature_chk", self->childGetValue("event_chk")); - self->childSetEnabled("event_adult_chk", self->childGetValue("event_chk")); -} - // protected void LLFloaterWorldMap::centerOnTarget(BOOL animate) { @@ -1374,9 +1361,12 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) pos_global = LLTracker::getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal(); } } - else if(LLWorldMap::getInstance()->mIsTrackingUnknownLocation) + else if(LLWorldMap::getInstance()->isTracking()) { - pos_global = LLWorldMap::getInstance()->mUnknownLocation - gAgentCamera.getCameraPositionGlobal();; + pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();; + + + } else { @@ -1472,24 +1462,6 @@ void LLFloaterWorldMap::teleport() } } -// static -void LLFloaterWorldMap::onGoToLandmarkDialog( S32 option, void* userdata ) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; - switch( option ) - { - case 0: - self->teleportToLandmark(); - break; - case 1: - self->flyToLandmark(); - break; - default: - // nothing - break; - } -} - void LLFloaterWorldMap::flyToLandmark() { LLVector3d destination_pos_global; @@ -1570,59 +1542,57 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) LLScrollListCtrl *list = getChild("search_results"); list->operateOnAll(LLCtrlListInterface::OP_DELETE); - - LLSD selected_value = list->getSelectedValue(); - + S32 name_length = mCompletingRegionName.length(); + + LLSD match; - BOOL match_found = FALSE; S32 num_results = 0; - std::map::const_iterator it; - for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + + std::vector > sim_info_vec(LLWorldMap::getInstance()->getRegionMap().begin(), LLWorldMap::getInstance()->getRegionMap().end()); + std::sort(sim_info_vec.begin(), sim_info_vec.end(), SortRegionNames()); + + for (std::vector >::const_iterator it = sim_info_vec.begin(); it != sim_info_vec.end(); ++it) { - LLSimInfo* info = (*it).second; - std::string sim_name = info->getName(); - std::string sim_name_lower = sim_name; + LLSimInfo* info = it->second; + std::string sim_name_lower = info->getName(); LLStringUtil::toLower(sim_name_lower); if (sim_name_lower.substr(0, name_length) == mCompletingRegionName) { - if (LLWorldMap::getInstance()->mIsTrackingCommit) + if (sim_name_lower == mCompletingRegionName) { - if (sim_name_lower == mCompletingRegionName) - { - selected_value = sim_name; - match_found = TRUE; - } + match = info->getName(); } LLSD value; - value["id"] = sim_name; + value["id"] = info->getName(); value["columns"][0]["column"] = "sim_name"; - value["columns"][0]["value"] = sim_name; + value["columns"][0]["value"] = info->getName(); list->addElement(value); num_results++; } } - list->selectByValue(selected_value); - - if (found_null_sim) + if (found_null_sim || match.isDefined()) { mCompletingRegionName = ""; } - - if (match_found) + + if (num_results > 0) { - mExactMatch = TRUE; + // if match found, highlight it and go + if (!match.isUndefined()) + { + list->selectByValue(match); + } + // else select first found item + else + { + list->selectFirstItem(); + } childSetFocus("search_results"); - onCommitSearchResult(NULL, this); - } - else if (!mExactMatch && num_results > 0) - { - list->selectFirstItem(); // select first item by default - childSetFocus("search_results"); - onCommitSearchResult(NULL, this); + onCommitSearchResult(); } else { @@ -1632,32 +1602,12 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) } } -// static -void LLFloaterWorldMap::onCommitLocation(LLUICtrl* ctrl, void* userdata) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; - LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); - if ( LLTracker::TRACKING_LOCATION == tracking_status) - { - LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - F64 local_x = self->childGetValue("spin x"); - F64 local_y = self->childGetValue("spin y"); - F64 local_z = self->childGetValue("spin z"); - pos_global.mdV[VX] += -fmod(pos_global.mdV[VX], 256.0) + local_x; - pos_global.mdV[VY] += -fmod(pos_global.mdV[VY], 256.0) + local_y; - pos_global.mdV[VZ] = local_z; - self->trackLocation(pos_global); - } -} -// static -void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata) +void LLFloaterWorldMap::onCommitSearchResult() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; - - LLCtrlListInterface *list = self->childGetListInterface("search_results"); + LLCtrlListInterface *list = mListSearchResults; if (!list) return; - + LLSD selected_value = list->getSelectedValue(); std::string sim_name = selected_value.asString(); if (sim_name.empty()) @@ -1674,19 +1624,52 @@ void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata) if (info->isName(sim_name)) { LLVector3d pos_global = info->getGlobalOrigin(); - F64 local_x = self->childGetValue("spin x"); - F64 local_y = self->childGetValue("spin y"); - F64 local_z = self->childGetValue("spin z"); - pos_global.mdV[VX] += local_x; - pos_global.mdV[VY] += local_y; - pos_global.mdV[VZ] = local_z; + + const F64 SIM_COORD_DEFAULT = 128.0; + LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f); + + // Did this value come from a trackURL() request? + if (!mCompletingRegionPos.isExactlyZero()) + { + pos_local = mCompletingRegionPos; + mCompletingRegionPos.clear(); + } + pos_global.mdV[VX] += (F64)pos_local.mV[VX]; + pos_global.mdV[VY] += (F64)pos_local.mV[VY]; + pos_global.mdV[VZ] = (F64)pos_local.mV[VZ]; - self->childSetValue("location", sim_name); - self->trackLocation(pos_global); - self->setDefaultBtn("Teleport"); + childSetValue("location", sim_name); + trackLocation(pos_global); + setDefaultBtn("Teleport"); break; } } - onShowTargetBtn(self); + onShowTargetBtn(); +} + +void LLFloaterWorldMap::onChangeMaturity() +{ + bool can_access_mature = gAgent.canAccessMature(); + bool can_access_adult = gAgent.canAccessAdult(); + + childSetVisible("events_mature_icon", can_access_mature); + childSetVisible("events_mature_label", can_access_mature); + childSetVisible("event_mature_chk", can_access_mature); + + childSetVisible("events_adult_icon", can_access_adult); + childSetVisible("events_adult_label", can_access_adult); + childSetVisible("event_adult_chk", can_access_adult); + + // disable mature / adult events. + if (!can_access_mature) + { + static LLCachedControl show_mature("MapShowMatureEvents",false); + show_mature = false; + } + if (!can_access_adult) + { + static LLCachedControl show_adult("MapShowAdultEvents",false); + show_adult = false; + } } diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 80cc25abd..b7f00e1df 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -111,29 +111,26 @@ public: // teleport to the tracked item, if there is one void teleport(); + void onChangeMaturity(); -protected: - static void onPanBtn( void* userdata ); - - static void onGoHome(void* data); +protected: + void onGoHome(); static void onLandmarkComboPrearrange( LLUICtrl* ctrl, void* data ); - static void onLandmarkComboCommit( LLUICtrl* ctrl, void* data ); + void onLandmarkComboCommit(); static void onAvatarComboPrearrange( LLUICtrl* ctrl, void* data ); - static void onAvatarComboCommit( LLUICtrl* ctrl, void* data ); + void onAvatarComboCommit(); static void onComboTextEntry( LLLineEditor* ctrl, void* data ); static void onSearchTextEntry( LLLineEditor* ctrl, void* data ); - static void onClearBtn(void*); - static void onFlyBtn(void*); - static void onClickTeleportBtn(void*); - static void onShowTargetBtn(void*); - static void onShowAgentBtn(void*); - static void onCopySLURL(void*); - - static void onCheckEvents(LLUICtrl* ctrl, void*); + void onClearBtn(); + void onClickTeleportBtn(); + static void onClickTeleportBtn_static(void* data) {((LLFloaterWorldMap*)data)->onClickTeleportBtn();}; + void onShowTargetBtn(); + void onShowAgentBtn(); + void onCopySLURL(); void centerOnTarget(BOOL animate); void updateLocation(); @@ -142,7 +139,6 @@ protected: void fly(); void buildLandmarkIDLists(); - static void onGoToLandmarkDialog(S32 option,void* userdata); void flyToLandmark(); void teleportToLandmark(); void setLandmarkVisited(); @@ -152,24 +148,28 @@ protected: void teleportToAvatar(); void updateSearchEnabled(); - void onLocationFocusChanged( LLFocusableElement* focus ); - static void onLocationCommit( void* userdata ); - static void onCommitLocation( LLUICtrl* ctrl, void* userdata ); - static void onCommitSearchResult( LLUICtrl* ctrl, void* userdata ); + void onLocationFocusChanged( LLFocusableElement* ctrl ); + void onLocationCommit(); + void onCoordinatesCommit(); + void onCommitSearchResult(); void cacheLandmarkPosition(); -protected: - LLPanel* mPanel; // Panel displaying the map +private: + LLPanel* mPanel; // Panel displaying the map // Sets sMapScale, in pixels per region F32 mCurZoomVal; - F32 mCurZoomValInterpolationStart; // Used during mZoomTimer interpolation. LLFrameTimer mZoomTimer; + // update display of teleport destination coordinates - pos is in global coordinates + void updateTeleportCoordsDisplay( const LLVector3d& pos ); + + // enable/disable teleport destination coordinates + void enableTeleportCoordsDisplay( bool enabled ); + LLDynamicArray mLandmarkAssetIDList; LLDynamicArray mLandmarkItemIDList; - BOOL mHasLandmarkPosition; static const LLUUID sHomeID; @@ -178,9 +178,12 @@ protected: LLFriendObserver* mFriendObserver; std::string mCompletingRegionName; + // Local position from trackURL() request, used to select final + // position once region lookup complete. + LLVector3 mCompletingRegionPos; + std::string mLastRegionName; BOOL mWaitingForTracker; - BOOL mExactMatch; BOOL mIsClosing; BOOL mSetToUserPosition; @@ -190,6 +193,10 @@ protected: std::string mTrackedSimName; std::string mTrackedAvatarName; std::string mSLURL; + + LLCtrlListInterface * mListFriendCombo; + LLCtrlListInterface * mListLandmarkCombo; + LLCtrlListInterface * mListSearchResults; }; extern LLFloaterWorldMap* gFloaterWorldMap; diff --git a/indra/newview/llmapresponders.cpp b/indra/newview/llmapresponders.cpp index cf0769bce..eaae3e450 100644 --- a/indra/newview/llmapresponders.cpp +++ b/indra/newview/llmapresponders.cpp @@ -38,6 +38,8 @@ #include "llviewertexturelist.h" #include "llworldmap.h" #include "llagent.h" +#include "llworldmapmessage.h" +#include "llsdserialize.h" //virtual void LLMapLayerResponder::result(const LLSD& result) @@ -45,22 +47,19 @@ void LLMapLayerResponder::result(const LLSD& result) llinfos << "LLMapLayerResponder::result from capabilities" << llendl; S32 agent_flags = result["AgentData"]["Flags"]; - - if (agent_flags != LLWorldMap::getInstance()->mCurrentMap) + U32 layer = flagsToLayer(agent_flags); + + if (layer != SIM_LAYER_COMPOSITE) { llwarns << "Invalid or out of date map image type returned!" << llendl; return; } LLUUID image_id; - //U32 left, right, top, bottom; - LLWorldMap::getInstance()->mMapLayers[agent_flags].clear(); - - bool use_web_map_tiles = LLWorldMap::useWebMapTiles(); + LLWorldMap::getInstance()->mMapLayers.clear(); LLSD::array_const_iterator iter; - BOOL adjust = FALSE; for(iter = result["LayerData"].beginArray(); iter != result["LayerData"].endArray(); ++iter) { const LLSD& layer_data = *iter; @@ -74,146 +73,12 @@ void LLMapLayerResponder::result(const LLSD& result) new_layer.LayerExtents.mTop = layer_data["Top"]; new_layer.LayerImageID = layer_data["ImageID"]; -// if (use_web_map_tiles) -// { -// new_layer.LayerImage = LLWorldMap::loadObjectsTile((U32)new_layer.LayerExtents.mLeft, (U32)new_layer.LayerExtents.mBottom); // no good... Maybe using of level 2 and higher web maps ? -// } -// else -// { - new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID); -// } + new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID); + gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); - F32 x_meters = F32(new_layer.LayerExtents.mLeft*REGION_WIDTH_UNITS); - F32 y_meters = F32(new_layer.LayerExtents.mBottom*REGION_WIDTH_UNITS); - adjust = LLWorldMap::getInstance()->extendAABB(U32(x_meters), U32(y_meters), - U32(x_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getWidth()), - U32(y_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getHeight())) || adjust; - - LLWorldMap::getInstance()->mMapLayers[agent_flags].push_back(new_layer); + LLWorldMap::getInstance()->mMapLayers.push_back(new_layer); } - - LLWorldMap::getInstance()->mMapLoaded[agent_flags] = TRUE; - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); - - /* - U32 agent_flags; - msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - - if (agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) - { - llwarns << "Invalid map image type returned! " << agent_flags << llendl; - return; - } - */ - - bool found_null_sim = false; - - adjust = FALSE; - if (result.has("MapBlocks")) - { - const LLSD& map_blocks = result["MapBlocks"]; - for (iter = map_blocks.beginArray(); iter != map_blocks.endArray(); ++iter) - { - const LLSD& map_block = *iter; - - S32 x_regions = map_block["X"]; - S32 y_regions = map_block["Y"]; - S32 x_size = map_block["SizeX"]; - S32 y_size = map_block["SizeY"]; - std::string name = map_block["Name"]; - S32 access = map_block["Access"]; - S32 region_flags = map_block["RegionFlags"]; - S32 water_height = map_block["WaterHeight"]; - LLUUID image_id = map_block["MapImageID"]; - - U32 x_meters = x_regions * REGION_WIDTH_UNITS; - U32 y_meters = y_regions * REGION_WIDTH_UNITS; - - if (access == 255) - { - // This region doesn't exist - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) - { - // We were tracking this location, but it doesn't exist - LLWorldMap::getInstance()->mInvalidLocation = TRUE; - } - - found_null_sim = true; - } - else - { - adjust = LLWorldMap::getInstance()->extendAABB(x_meters, - y_meters, - x_meters+REGION_WIDTH_UNITS, - y_meters+REGION_WIDTH_UNITS) || adjust; - U64 handle = to_region_handle(x_meters, y_meters); - - // llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl; - - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if (siminfo == NULL) - { - siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); - } - - siminfo->setName( name ); - siminfo->setAccess( access ); /*Flawfinder: ignore*/ - siminfo->setRegionFlags( region_flags ); - siminfo->setWaterHeight( (F32) water_height ); - siminfo->setMapImageID( image_id, agent_flags ); - siminfo->setSize((U16)x_size, (U16)y_size); - if (use_web_map_tiles) - { - siminfo->mCurrentImage = LLWorldMap::loadObjectsTile((U32)x_regions, (U32)y_regions); - } - else - { - siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap]); - } - siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); - gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); - - if (siminfo->mMapImageID[2].notNull()) - { - siminfo->mOverlayImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[2]); - } - else - { - siminfo->mOverlayImage = NULL; - } - - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) - { - if (siminfo->isDown()) - { - // We were tracking this location, but it doesn't exist - LLWorldMap::getInstance()->mInvalidLocation = true; - } - else - { - // We were tracking this location, and it does exist - bool is_tracking_dbl = LLWorldMap::getInstance()->mIsTrackingDoubleClick == TRUE; - gFloaterWorldMap->trackLocation(LLWorldMap::getInstance()->mUnknownLocation); - if (is_tracking_dbl) - { - LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - gAgent.teleportViaLocation( pos_global ); - } - } - } - } - } - } - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); - gFloaterWorldMap->updateSims(found_null_sim); + LLWorldMap::getInstance()->mMapLoaded = true; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 2b6ded3fd..bdae27c97 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -190,6 +190,7 @@ #include "llwind.h" #include "llworld.h" #include "llworldmap.h" +#include "llworldmapmessage.h" #include "llxfermanager.h" #include "pipeline.h" #include "llappviewer.h" @@ -3392,8 +3393,8 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply); - msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply); - msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply); + msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); + msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply); msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h index 285036527..c727c29d5 100644 --- a/indra/newview/lltracker.h +++ b/indra/newview/lltracker.h @@ -81,7 +81,7 @@ public: // these are static so that they can be used a callbacks static ETrackingStatus getTrackingStatus() { return instance()->mTrackingStatus; } static ETrackingLocationType getTrackedLocationType() { return instance()->mTrackingLocationType; } - static BOOL isTracking(void*) { return (BOOL) instance()->mTrackingStatus; } + static BOOL isTracking(void*) { return instance()->mTrackingStatus != TRACKING_NOTHING; } static void stopTracking(void*); static void clearFocus(); diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 1144c5827..a9971abbd 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -45,6 +45,7 @@ #include "llurlsimstring.h" #include "llweb.h" #include "llworldmap.h" +#include "llworldmapmessage.h" // library includes #include "llsd.h" @@ -243,7 +244,7 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous url_displayp->setName(region_name); // Request a region handle by name - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, LLURLDispatcherImpl::regionNameCallback, url, false); // don't teleport @@ -282,7 +283,7 @@ void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::strin LLVector3d global_pos = from_region_handle(region_handle) + LLVector3d(local_pos); U64 new_region_handle = to_region_handle(global_pos); - LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, + LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, LLURLDispatcherImpl::regionHandleCallback, url, teleport); } @@ -401,7 +402,7 @@ public: { url += tokens[i].asString() + "/"; } - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, LLURLDispatcherImpl::regionHandleCallback, url, true); // teleport diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 0c0b12075..569451ab0 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3596,7 +3596,6 @@ void set_god_level(U8 god_level) // God mode changes region visibility LLWorldMap::getInstance()->reset(); - LLWorldMap::getInstance()->setCurrentLayer(0); // inventory in items may change in god mode gObjectList.dirtyAllObjectInventory(); diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 7672cca2f..dda570ea8 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -47,46 +47,79 @@ #include "llviewertexturelist.h" #include "llviewerregion.h" #include "llregionflags.h" - #include "hippogridmanager.h" -bool LLWorldMap::sGotMapURL = false; -const F32 AGENTS_UPDATE_TIMER = 60.0; // Seconds between 2 agent requests for a region -const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes +#include "llworldmapmessage.h" +#include "hippogridmanager.h" + +bool LLWorldMap::sGotMapURL = false; +// Timers to temporise database requests +const F32 AGENTS_UPDATE_TIMER = 60.0; // Seconds between 2 agent requests for a region +const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // Seconds before we consider re-requesting item data for the grid + +//--------------------------------------------------------------------------- +// LLItemInfo +//--------------------------------------------------------------------------- -// For DEV-17507, do lazy image loading in llworldmapview.cpp instead, -// limiting requests to currently visible regions and minimizing the -// number of textures being requested simultaneously. -// -// Uncomment IMMEDIATE_IMAGE_LOAD to restore the old behavior -// -//#define IMMEDIATE_IMAGE_LOAD LLItemInfo::LLItemInfo(F32 global_x, F32 global_y, const std::string& name, - LLUUID id, - S32 extra, S32 extra2) + LLUUID id) : mName(name), mToolTip(""), mPosGlobal(global_x, global_y, 40.0), mID(id), - mSelected(FALSE), - mExtra(extra), - mExtra2(extra2) + mCount(1) +// mSelected(false) +// mColor() { - mRegionHandle = to_region_handle(mPosGlobal); } +//--------------------------------------------------------------------------- +// LLSimInfo +//--------------------------------------------------------------------------- + LLSimInfo::LLSimInfo(U64 handle) : mHandle(handle), mName(), mAgentsUpdateTime(0), - mShowAgentLocations(FALSE), mAccess(0x0), mRegionFlags(0x0), - mWaterHeight(0.f), - mAlpha(-1.f) + mFirstAgentRequest(true), + mSizeX(REGION_WIDTH_UNITS), + mSizeY(REGION_WIDTH_UNITS), + mAlpha(0.f) { } +void LLSimInfo::setLandForSaleImage (LLUUID image_id) +{ + mMapImageID[SIM_LAYER_OVERLAY] = image_id; + // Fetch the image + if (mMapImageID[SIM_LAYER_OVERLAY].notNull()) + { + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + else + { + mLayerImage[SIM_LAYER_OVERLAY] = NULL; + } +} + +LLPointer LLSimInfo::getLandForSaleImage () +{ + if (mLayerImage[SIM_LAYER_OVERLAY].isNull() && mMapImageID[SIM_LAYER_OVERLAY].notNull()) + { + // Fetch the image if it hasn't been done yet (unlikely but...) + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + if (!mLayerImage[SIM_LAYER_OVERLAY].isNull()) + { + // Boost the fetch level when we try to access that image + mLayerImage[SIM_LAYER_OVERLAY]->setBoostLevel(LLViewerTexture::BOOST_MAP); + } + return mLayerImage[SIM_LAYER_OVERLAY]; +} LLVector3d LLSimInfo::getGlobalPos(const LLVector3& local_pos) const { @@ -109,18 +142,31 @@ LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const void LLSimInfo::clearImage() { - if (!mOverlayImage.isNull()) + for(U32 layer = SIM_LAYER_BEGIN; layer < SIM_LAYER_COUNT;++layer) { - mOverlayImage->setBoostLevel(0); - mOverlayImage = NULL; + if(!mLayerImage[layer].isNull()) + { + mLayerImage[layer]->setBoostLevel(0); + mLayerImage[layer]=NULL; + } } } -void LLSimInfo::dropImagePriority() +void LLSimInfo::dropImagePriority(sim_layer_type layer/* = SIM_LAYER_COUNT*/) { - if (!mOverlayImage.isNull()) + if(layer == SIM_LAYER_COUNT) { - mOverlayImage->setBoostLevel(0); + for(U32 layer = SIM_LAYER_BEGIN; layer < SIM_LAYER_COUNT;++layer) + { + if(!mLayerImage[layer].isNull()) + { + mLayerImage[layer]->setBoostLevel(0); + } + } + } + else if(layer < SIM_LAYER_COUNT && layer >= SIM_LAYER_BEGIN && !mLayerImage[layer].isNull()) + { + mLayerImage[layer]->setBoostLevel(0); } } @@ -129,116 +175,154 @@ void LLSimInfo::updateAgentCount(F64 time) { if ((time - mAgentsUpdateTime > AGENTS_UPDATE_TIMER) || mFirstAgentRequest) { - LLWorldMap::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, mHandle); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, mHandle); mAgentsUpdateTime = time; mFirstAgentRequest = false; } } + +// Get the total agents count +const S32 LLSimInfo::getAgentCount() const +{ + S32 total_agent_count = 0; + for (LLSimInfo::item_info_list_t::const_iterator it = mAgentLocations.begin(); it != mAgentLocations.end(); ++it) + { + total_agent_count += it->getCount(); + } + return total_agent_count; +} + bool LLSimInfo::isName(const std::string& name) const { return (LLStringUtil::compareInsensitive(name, mName) == 0); } +void LLSimInfo::dump() const +{ + U32 x_pos, y_pos; + from_region_handle(mHandle, &x_pos, &y_pos); + + LL_INFOS("World Map") << x_pos << "," << y_pos + << " " << mName + << " " << (S32)mAccess + << " " << std::hex << mRegionFlags << std::dec + << " " << mSizeX << "x" << mSizeY +// << " " << mWaterHeight + << LL_ENDL; +} + +void LLSimInfo::clearItems() +{ + mTelehubs.clear(); + mInfohubs.clear(); + mPGEvents.clear(); + mMatureEvents.clear(); + mAdultEvents.clear(); + mLandForSale.clear(); + mLandForSaleAdult.clear(); +// We persist the agent count though as it is updated on a frequent basis +// mAgentLocations.clear(); +} + +void LLSimInfo::insertAgentLocation(const LLItemInfo& item) +{ + std::string name = item.getName(); + + // Find the last item in the list with a different name and erase them + item_info_list_t::iterator lastiter; + for (lastiter = mAgentLocations.begin(); lastiter != mAgentLocations.end(); ++lastiter) + { + LLItemInfo& info = *lastiter; + if (info.isName(name)) + { + break; + } + } + if (lastiter != mAgentLocations.begin()) + { + mAgentLocations.erase(mAgentLocations.begin(), lastiter); + } + + // Now append the new location + mAgentLocations.push_back(item); +} + //--------------------------------------------------------------------------- // World Map //--------------------------------------------------------------------------- LLWorldMap::LLWorldMap() : - mIsTrackingUnknownLocation( FALSE ), - mInvalidLocation( FALSE ), - mIsTrackingDoubleClick( FALSE ), - mIsTrackingCommit( FALSE ), - mUnknownLocation( 0, 0, 0 ), - mRequestLandForSale(true), - mCurrentMap(0), - mMinX(U32_MAX), - mMaxX(U32_MIN), - mMinY(U32_MAX), - mMaxY(U32_MIN), - mNeighborMap(NULL), - mTelehubCoverageMap(NULL), - mNeighborMapWidth(0), - mNeighborMapHeight(0), - mSLURLRegionName(), - mSLURLRegionHandle(0), - mSLURL(), - mSLURLCallback(0), - mSLURLTeleport(false) + mIsTrackingLocation( false ), + mIsTrackingFound( false ), + mIsInvalidLocation( false ), + mIsTrackingDoubleClick( false ), + mIsTrackingCommit( false ), + mTrackingLocation( 0, 0, 0 ), + mFirstRequest(true), + mMapLoaded(false) { - for (S32 map=0; map LLWorldMap::LLWorldMap()" << LL_ENDL; + /*for (U32 map=SIM_LAYER_BEGIN; map LLWorldMap::~LLWorldMap()" << LL_ENDL; reset(); - for (S32 map=0; map REQUEST_ITEMS_TIMER) + bool clear = false; + if ((mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER) || mFirstRequest || force) { mRequestTimer.reset(); - mTelehubs.clear(); - mInfohubs.clear(); - mPGEvents.clear(); - mMatureEvents.clear(); - mAdultEvents.clear(); - mLandForSale.clear(); + LLSimInfo* sim_info = NULL; + for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + { + sim_info = it->second; + if (sim_info) + { + sim_info->clearItems(); + } + } + clear = true; + mFirstRequest = false; } -// mAgentLocationsMap.clear(); // persists -// mNumAgents.clear(); // persists + return clear; } - void LLWorldMap::clearImageRefs() { // We clear the reference to the images we're holding. @@ -252,11 +336,6 @@ void LLWorldMap::clearImageRefs() sim_info = it->second; if(sim_info) { - if (sim_info->mCurrentImage) - { - sim_info->mCurrentImage->setBoostLevel(0); - sim_info->mCurrentImage = NULL; - } sim_info->clearImage(); } } @@ -265,12 +344,13 @@ void LLWorldMap::clearImageRefs() // Doesn't clear the already-loaded sim infos, just re-requests them void LLWorldMap::clearSimFlags() { - for (S32 map=0; map::const_iterator it; - for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + sim_info_map_t::iterator it = mSimInfoMap.find(handle); + if (it != mSimInfoMap.end()) { - const U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - if(handle == findhandle) - { - return info; - } - U32 x = 0, y = 0; - from_region_handle(findhandle, &x, &y); - U32 checkRegionX, checkRegionY; - from_region_handle(handle, &checkRegionX, &checkRegionY); - - if(x >= checkRegionX && x < (checkRegionX + info->getSizeX()) && - y >= checkRegionY && y < (checkRegionY + info->getSizeY())) - { - return info; - } + return it->second; } return NULL; } @@ -358,256 +423,75 @@ bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string return (sim_info != NULL); } -void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) -{ - //TODO: we only have 1 layer -SG - mCurrentMap = layer; - if (!mMapLoaded[layer] || request_layer) - { - sendMapLayerRequest(); - } - - if (mTelehubs.size() == 0 || - mInfohubs.size() == 0) - { - // Request for telehubs - sendItemRequest(MAP_ITEM_TELEHUB); - } - - if (mPGEvents.size() == 0) - { - // Request for events - sendItemRequest(MAP_ITEM_PG_EVENT); - } - - if (mMatureEvents.size() == 0) - { - // Request for events (mature) - sendItemRequest(MAP_ITEM_MATURE_EVENT); - } - - if (mAdultEvents.size() == 0) - { - // Request for events (adult) - sendItemRequest(MAP_ITEM_ADULT_EVENT); - } - - if (mLandForSale.size() == 0) - { - // Request for Land For Sale - sendItemRequest(MAP_ITEM_LAND_FOR_SALE); - } - - if (mLandForSaleAdult.size() == 0) - { - // Request for Land For Sale - sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT); - } - - clearImageRefs(); - clearSimFlags(); -} - -void LLWorldMap::sendItemRequest(U32 type, U64 handle) -{ - LLMessageSystem* msg = gMessageSystem; - S32 layer = mCurrentMap; - - msg->newMessageFast(_PREHASH_MapItemRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, layer); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - - msg->nextBlockFast(_PREHASH_RequestData); - msg->addU32Fast(_PREHASH_ItemType, type); - msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim - - gAgent.sendReliableMessage(); -} - // public void LLWorldMap::sendMapLayerRequest() { if (!gAgent.getRegion()) return; - LLSD body; - body["Flags"] = mCurrentMap; std::string url = gAgent.getRegion()->getCapability( gAgent.isGodlike() ? "MapLayerGod" : "MapLayer"); + U32 flags = layerToFlags((sim_layer_type)SIM_LAYER_COMPOSITE); if (!url.empty()) { - llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl; + LLSD body; + body["Flags"] = (LLSD::Integer)flags; + //llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl; LLHTTPClient::post(url, body, new LLMapLayerResponder()); } else { - llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl; + //llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl; LLMessageSystem* msg = gMessageSystem; - S32 layer = mCurrentMap; // Request for layer msg->newMessageFast(_PREHASH_MapLayerRequest); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, layer); + msg->addU32Fast(_PREHASH_Flags, flags); msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim gAgent.sendReliableMessage(); - - if (mRequestLandForSale) - { - msg->newMessageFast(_PREHASH_MapLayerRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, 2); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - gAgent.sendReliableMessage(); - } } } -// public -void LLWorldMap::sendNamedRegionRequest(std::string region_name) -{ - LLMessageSystem* msg = gMessageSystem; - S32 layer = mCurrentMap; - // Request for layer - msg->newMessageFast(_PREHASH_MapNameRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, layer); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - msg->nextBlockFast(_PREHASH_NameData); - msg->addStringFast(_PREHASH_Name, region_name); - gAgent.sendReliableMessage(); -} -// public -void LLWorldMap::sendNamedRegionRequest(std::string region_name, - url_callback_t callback, - const std::string& callback_url, - bool teleport) // immediately teleport when result returned -{ - mSLURLRegionName = region_name; - mSLURLRegionHandle = 0; - mSLURL = callback_url; - mSLURLCallback = callback; - mSLURLTeleport = teleport; - - sendNamedRegionRequest(region_name); -} - -void LLWorldMap::sendHandleRegionRequest(U64 region_handle, - url_callback_t callback, - const std::string& callback_url, - bool teleport) // immediately teleport when result returned -{ - mSLURLRegionName.clear(); - mSLURLRegionHandle = region_handle; - mSLURL = callback_url; - mSLURLCallback = callback; - mSLURLTeleport = teleport; - - U32 global_x; - U32 global_y; - from_region_handle(region_handle, &global_x, &global_y); - U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); - U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); - - sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); -} - -// public -void LLWorldMap::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) -{ - S32 layer = mCurrentMap; - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MapBlockRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - U32 flags = layer; - flags |= (return_nonexistent ? 0x10000 : 0); - msg->addU32Fast(_PREHASH_Flags, flags); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - msg->nextBlockFast(_PREHASH_PositionData); - msg->addU16Fast(_PREHASH_MinX, min_x); - msg->addU16Fast(_PREHASH_MinY, min_y); - msg->addU16Fast(_PREHASH_MaxX, max_x); - msg->addU16Fast(_PREHASH_MaxY, max_y); - gAgent.sendReliableMessage(); - - if (mRequestLandForSale) - { - msg->newMessageFast(_PREHASH_MapBlockRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, 2); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - msg->nextBlockFast(_PREHASH_PositionData); - msg->addU16Fast(_PREHASH_MinX, min_x); - msg->addU16Fast(_PREHASH_MinY, min_y); - msg->addU16Fast(_PREHASH_MaxX, max_x); - msg->addU16Fast(_PREHASH_MaxY, max_y); - gAgent.sendReliableMessage(); - } -} // public static void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) { - llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl; + //llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl; U32 agent_flags; msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - if (agent_flags != (U32)LLWorldMap::getInstance()->mCurrentMap) + U32 layer = flagsToLayer(agent_flags); + if (layer != SIM_LAYER_COMPOSITE) { llwarns << "Invalid or out of date map image type returned!" << llendl; return; } LLUUID image_id; - //U32 left, right, top, bottom; S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_LayerData); - LLWorldMap::getInstance()->mMapLayers[agent_flags].clear(); + LLWorldMap::getInstance()->mMapLayers.clear(); -// bool use_web_map_tiles = useWebMapTiles(); - BOOL adjust = FALSE; for (S32 block=0; blockgetUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block); - + U32 left, right, top, bottom; msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block); msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Right, right, block); msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block); msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block); -// if (use_web_map_tiles) -// { -// new_layer.LayerImage = loadObjectsTile(left, bottom); // no good... Maybe using of level 2 and higher web maps ? -// } -// else -// { - new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); -// } + new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -617,269 +501,148 @@ void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) new_layer.LayerExtents.mBottom = bottom; new_layer.LayerExtents.mTop = top; - F32 x_meters = F32(left*REGION_WIDTH_UNITS); - F32 y_meters = F32(bottom*REGION_WIDTH_UNITS); - adjust = LLWorldMap::getInstance()->extendAABB(U32(x_meters), U32(y_meters), - U32(x_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getWidth()), - U32(y_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getHeight())) || adjust; - - LLWorldMap::getInstance()->mMapLayers[agent_flags].push_back(new_layer); + LLWorldMap::getInstance()->mMapLayers.push_back(new_layer); } - LLWorldMap::getInstance()->mMapLoaded[agent_flags] = TRUE; - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); + LLWorldMap::getInstance()->mMapLoaded = true; } // public static bool LLWorldMap::useWebMapTiles() { - return gSavedSettings.getBOOL("UseWebMapTiles") && - (( gHippoGridManager->getConnectedGrid()->isSecondLife() || sGotMapURL) && LLWorldMap::getInstance()->mCurrentMap == 0); + static const LLCachedControl use_web_map_tiles("UseWebMapTiles",false); + return use_web_map_tiles && + (( gHippoGridManager->getConnectedGrid()->isSecondLife() || sGotMapURL)); } -// public static -LLPointer LLWorldMap::loadObjectsTile(U32 grid_x, U32 grid_y) +void LLWorldMap::reloadItems(bool force) { - // Get the grid coordinates - std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", 1, grid_x, grid_y); - - LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl,TRUE,LLViewerTexture::BOOST_MAP,LLViewerTexture::LOD_TEXTURE); - img->setBoostLevel(LLViewerTexture::BOOST_MAP); - - // Return the smart pointer - return img; -} - -// public static -void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) -{ - U32 agent_flags; - msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - - if ((S32)agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) + //LL_INFOS("World Map") << "LLWorldMap::reloadItems()" << LL_ENDL; + if (clearItems(force)) { - llwarns << "Invalid map image type returned! " << agent_flags << llendl; - return; + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_TELEHUB); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_PG_EVENT); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_MATURE_EVENT); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_ADULT_EVENT); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE); } - - S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data); - - bool found_null_sim = false; - -#ifdef IMMEDIATE_IMAGE_LOAD - bool use_web_map_tiles = useWebMapTiles(); -#endif - BOOL adjust = FALSE; - for (S32 block=0; blockgetU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block); - msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block); - msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); - msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, block); - msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block); - msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block); - msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block); - if(msg->getNumberOfBlocksFast(_PREHASH_Size) > 0) + if(!mMapLoaded || force) + sendMapLayerRequest(); + } +} + + +// static public +// Insert a region in the region map +// returns true if region inserted, false otherwise +bool LLWorldMap::insertRegion(U32 x_world, U32 y_world, U32 x_size, U32 y_size, U32 agent_flags, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags) +{ + // This region doesn't exist + if (accesscode == 255) + { + // Checks if the track point is in it and invalidates it if it is + if (LLWorldMap::getInstance()->isTrackingInRectangle( x_world, y_world, x_world + REGION_WIDTH_UNITS, y_world + REGION_WIDTH_UNITS)) { - msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeX, x_size, block); - msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeY, y_size, block); + LLWorldMap::getInstance()->setTrackingInvalid(); } - if(x_size == 0 || (x_size % 16) != 0|| (y_size % 16) != 0) + // return failure to insert + return false; + } + else + { + U64 handle = to_region_handle(x_world, y_world); + //LL_INFOS("World Map") << "Map sim : " << name << ", ID : " << image_id.getString() << LL_ENDL; + // Insert the region in the region map of the world map + // Loading the LLSimInfo object with what we got and insert it in the map + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if (siminfo == NULL) { - x_size = 256; - y_size = 256; + siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); } - U32 x_meters = x_regions * REGION_WIDTH_UNITS; - U32 y_meters = y_regions * REGION_WIDTH_UNITS; + siminfo->setName( name ); + siminfo->setAccess( accesscode ); + siminfo->setRegionFlags( region_flags ); + //siminfo->setWaterHeight((F32) water_height); + U32 layer = flagsToLayer(agent_flags); + if (layer == SIM_LAYER_OVERLAY) + siminfo->setLandForSaleImage(image_id); + else if(layer < SIM_LAYER_COUNT) + siminfo->setMapImageID( image_id, layer ); + siminfo->setSize( x_size, y_size ); - U64 handle = to_region_handle(x_meters, y_meters); - - if (accesscode == 255) + // Handle the location tracking (for teleport, UI feedback and info display) + if (LLWorldMap::getInstance()->isTrackingInRectangle( x_world, y_world, x_world + REGION_WIDTH_UNITS, y_world + REGION_WIDTH_UNITS)) { - // This region doesn't exist - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) + if (siminfo->isDown()) { - // We were tracking this location, but it doesn't exist - LLWorldMap::getInstance()->mInvalidLocation = TRUE; - } - - found_null_sim = true; - } - else - { - adjust = LLWorldMap::getInstance()->extendAABB(x_meters, - y_meters, - x_meters+REGION_WIDTH_UNITS, - y_meters+REGION_WIDTH_UNITS) || adjust; - //LL_INFOS("World Map") << "Map sim : " << name << ", ID : " << image_id.getString() << LL_ENDL; - // Insert the region in the region map of the world map - // Loading the LLSimInfo object with what we got and insert it in the map - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if (siminfo == NULL) - { - siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); - } - - siminfo->setName( name ); - siminfo->setAccess( accesscode ); - siminfo->setRegionFlags( region_flags ); - siminfo->setWaterHeight((F32) water_height); - siminfo->setMapImageID( image_id, agent_flags ); - siminfo->setSize( x_size, y_size ); - -#ifdef IMMEDIATE_IMAGE_LOAD - if (use_web_map_tiles) - { - siminfo->mCurrentImage = loadObjectsTile((U32)x_regions, (U32)y_regions); + // We were tracking this location, but it's no available + LLWorldMap::getInstance()->setTrackingInvalid(); } else { - siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); + // We were tracking this location, and it does exist and is available + LLWorldMap::getInstance()->setTrackingValid(); } - gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); - siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); -#endif + } + // return insert region success + return true; + } +} + +// static public +// Insert an item in the relevant region map +// returns true if item inserted, false otherwise +bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 type, S32 extra, S32 extra2) +{ + // Create an item record for the received object + LLItemInfo new_item((F32)x_world, (F32)y_world, name, uuid); + + // Compute a region handle based on the objects coordinates + LLVector3d pos((F32)x_world, (F32)y_world, 40.0); + U64 handle = to_region_handle(pos); + + // Get the region record for that handle or NULL if we haven't browsed it yet + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if (siminfo == NULL) + { + siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); + } + + //LL_INFOS("World Map") << "Process item : type = " << type << LL_ENDL; + switch (type) + { + case MAP_ITEM_TELEHUB: // telehubs + { + /* Merov: we are not using the hub color anymore for display so commenting that out + // Telehub color + U32 X = x_world / REGION_WIDTH_UNITS; + U32 Y = y_world / REGION_WIDTH_UNITS; + F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f; + F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f; + F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f; + F32 add_amt = (X % 2) ? 0.15f : -0.15f; + add_amt += (Y % 2) ? -0.15f : 0.15f; + LLColor4 color(red + add_amt, green + add_amt, blue + add_amt); + new_item.setColor(color); + */ - if (siminfo->mMapImageID[2].notNull()) + // extra2 specifies whether this is an infohub or a telehub. + if (extra2) { -#ifdef IMMEDIATE_IMAGE_LOAD - siminfo->mOverlayImage = LLViewerTextureManager::getFetchedTextureURL(siminfo->mMapImageID[2]); -#endif + siminfo->insertInfoHub(new_item); } else { - siminfo->mOverlayImage = NULL; - } - - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) - { - if (siminfo->isDown()) - { - // We were tracking this location, but it doesn't exist - LLWorldMap::getInstance()->mInvalidLocation = true; - } - else - { - // We were tracking this location, and it does exist - bool is_tracking_dbl = LLWorldMap::getInstance()->mIsTrackingDoubleClick == TRUE; - gFloaterWorldMap->trackLocation(LLWorldMap::getInstance()->mUnknownLocation); - if (is_tracking_dbl) - { - LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - gAgent.teleportViaLocation( pos_global ); - } - } + siminfo->insertTeleHub(new_item); } + break; } - - if(LLWorldMap::getInstance()->mSLURLCallback != NULL) - { - // Server returns definitive capitalization, SLURL might not have that. - if ((LLStringUtil::compareInsensitive(LLWorldMap::getInstance()->mSLURLRegionName, name)==0) - || (LLWorldMap::getInstance()->mSLURLRegionHandle == handle)) - { - url_callback_t callback = LLWorldMap::getInstance()->mSLURLCallback; - - LLWorldMap::getInstance()->mSLURLCallback = NULL; - LLWorldMap::getInstance()->mSLURLRegionName.clear(); - LLWorldMap::getInstance()->mSLURLRegionHandle = 0; - - callback(handle, LLWorldMap::getInstance()->mSLURL, image_id, LLWorldMap::getInstance()->mSLURLTeleport); - } - } - if( gAgent.mPendingLure && - (U16)(gAgent.mPendingLure->mPosGlobal.mdV[0] / REGION_WIDTH_UNITS) == x_regions && - (U16)(gAgent.mPendingLure->mPosGlobal.mdV[1] / REGION_WIDTH_UNITS) == y_regions ) - { - gAgent.onFoundLureDestination(); - } - } - - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); - gFloaterWorldMap->updateSims(found_null_sim); -} - -// public static -void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) -{ - U32 type; - msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type); - - S32 num_blocks = msg->getNumberOfBlocks("Data"); - - for (S32 block=0; blockgetU32Fast(_PREHASH_Data, _PREHASH_X, X, block); - msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block); - msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block); - msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block); - msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block); - - F32 world_x = (F32)X; - X /= REGION_WIDTH_UNITS; - F32 world_y = (F32)Y; - Y /= REGION_WIDTH_UNITS; - - LLItemInfo new_item(world_x, world_y, name, uuid, extra, extra2); - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(new_item.getRegionHandle()); - - switch (type) - { - case MAP_ITEM_TELEHUB: // telehubs - { - // Telehub color, store in extra as 4 U8's - U8 *color = (U8 *)&new_item.mExtra; - - F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f; - F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f; - F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f; - F32 add_amt = (X % 2) ? 0.15f : -0.15f; - add_amt += (Y % 2) ? -0.15f : 0.15f; - color[0] = U8((red + add_amt) * 255); - color[1] = U8((green + add_amt) * 255); - color[2] = U8((blue + add_amt) * 255); - color[3] = 255; - - // extra2 specifies whether this is an infohub or a telehub. - if (extra2) - { - LLWorldMap::getInstance()->mInfohubs.push_back(new_item); - } - else - { - LLWorldMap::getInstance()->mTelehubs.push_back(new_item); - } - - break; - } - case MAP_ITEM_PG_EVENT: // events - case MAP_ITEM_MATURE_EVENT: - case MAP_ITEM_ADULT_EVENT: + case MAP_ITEM_PG_EVENT: // events + case MAP_ITEM_MATURE_EVENT: + case MAP_ITEM_ADULT_EVENT: { struct tm* timep; // Convert to Pacific, based on server's opinion of whether @@ -894,252 +657,64 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) timep->tm_min, (timep->tm_hour < 12 ? "AM" : "PM") ) ); - // HACK: store Z in extra2 - new_item.setElevation((F64)extra2); - if (type == MAP_ITEM_PG_EVENT) - { - LLWorldMap::getInstance()->mPGEvents.push_back(new_item); - } - else if (type == MAP_ITEM_MATURE_EVENT) - { - LLWorldMap::getInstance()->mMatureEvents.push_back(new_item); - } - else if (type == MAP_ITEM_ADULT_EVENT) - { - LLWorldMap::getInstance()->mAdultEvents.push_back(new_item); - } - - break; - } - case MAP_ITEM_LAND_FOR_SALE: // land for sale - case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale + // HACK: store Z in extra2 + new_item.setElevation((F64)extra2); + if (type == MAP_ITEM_PG_EVENT) { - new_item.setTooltip(llformat("%d sq. m. %s%d", new_item.mExtra, - gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), - new_item.mExtra2)); - if (type == MAP_ITEM_LAND_FOR_SALE) - { - LLWorldMap::getInstance()->mLandForSale.push_back(new_item); - } - else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT) - { - LLWorldMap::getInstance()->mLandForSaleAdult.push_back(new_item); + siminfo->insertPGEvent(new_item); + } + else if (type == MAP_ITEM_MATURE_EVENT) + { + siminfo->insertMatureEvent(new_item); + } + else if (type == MAP_ITEM_ADULT_EVENT) + { + siminfo->insertAdultEvent(new_item); + } + break; + } + case MAP_ITEM_LAND_FOR_SALE: // land for sale + case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale + { + new_item.setTooltip(llformat("%d sq. m. %s%d", extra, + gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), + extra2)); + if (type == MAP_ITEM_LAND_FOR_SALE) + { + siminfo->insertLandForSale(new_item); + } + else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT) + { + siminfo->insertLandForSaleAdult(new_item); } break; } case MAP_ITEM_CLASSIFIED: // classifieds { - //DEPRECATED: no longer used - break; - } - case MAP_ITEM_AGENT_LOCATIONS: // agent locations - { - if (!siminfo) - { - llinfos << "siminfo missing for " << new_item.getGlobalPosition().mdV[0] << ", " << new_item.getGlobalPosition().mdV[1] << llendl; - break; - } -// llinfos << "New Location " << new_item.mName << llendl; - - item_info_list_t& agentcounts = LLWorldMap::getInstance()->mAgentLocationsMap[new_item.getRegionHandle()]; - - // Find the last item in the list with a different name and erase them - item_info_list_t::iterator lastiter; - for (lastiter = agentcounts.begin(); lastiter!=agentcounts.end(); ++lastiter) - { - const LLItemInfo& info = *lastiter; - if (info.isName(new_item.getName())) - { - break; - } - } - if (lastiter != agentcounts.begin()) - { - agentcounts.erase(agentcounts.begin(), lastiter); - } - // Now append the new location - if (new_item.mExtra > 0) - { - agentcounts.push_back(new_item); - } - break; - } - default: - break; - }; - } -} - -void LLWorldMap::dump() -{ - for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) - { - U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - - llinfos << x_pos << "," << y_pos - << " " << info->getName() - << " " << (S32)info->getAccess() - << " " << std::hex << info->getRegionFlags() << std::dec - << " " << info->getWaterHeight() - //<< " " << info->mTelehubName - //<< " " << info->mTelehubPosition - << llendl; - - if (info->mCurrentImage) - { - llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel() - << " fullwidth " << info->mCurrentImage->getWidth(0) - << " fullheight " << info->mCurrentImage->getHeight(0) - << " maxvirt " << info->mCurrentImage->getMaxVirtualSize() - << " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel() - << llendl; + //DEPRECATED: no longer used + break; } - } -} - - -BOOL LLWorldMap::extendAABB(U32 min_x, U32 min_y, U32 max_x, U32 max_y) -{ - BOOL rv = FALSE; - if (min_x < mMinX) - { - rv = TRUE; - mMinX = min_x; - } - if (min_y < mMinY) - { - rv = TRUE; - mMinY = min_y; - } - if (max_x > mMaxX) - { - rv = TRUE; - mMaxX = max_x; - } - if (max_y > mMaxY) - { - rv = TRUE; - mMaxY = max_y; - } - lldebugs << "World map aabb: (" << mMinX << ", " << mMinY << "), (" - << mMaxX << ", " << mMaxY << ")" << llendl; - return rv; -} - - -U32 LLWorldMap::getWorldWidth() const -{ - return mMaxX - mMinX; -} - - -U32 LLWorldMap::getWorldHeight() const -{ - return mMaxY - mMinY; -} - -BOOL LLWorldMap::coveredByTelehub(LLSimInfo* infop) -{ - /*if (!mTelehubCoverageMap) - { - return FALSE; - } - U32 x_pos, y_pos; - from_region_handle(infop->mHandle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - - S32 index = x_pos - (mMinX / REGION_WIDTH_UNITS - 1) + (mNeighborMapWidth * (y_pos - (mMinY / REGION_WIDTH_UNITS - 1))); - return mTelehubCoverageMap[index] != 0; */ - return FALSE; -} - -void LLWorldMap::updateTelehubCoverage() -{ - /*S32 neighbor_width = getWorldWidth() / REGION_WIDTH_UNITS + 2; - S32 neighbor_height = getWorldHeight() / REGION_WIDTH_UNITS + 2; - if (neighbor_width > mNeighborMapWidth || neighbor_height > mNeighborMapHeight) - { - mNeighborMapWidth = neighbor_width; - mNeighborMapHeight = neighbor_height; - delete mNeighborMap; - delete mTelehubCoverageMap; - - mNeighborMap = new U8[mNeighborMapWidth * mNeighborMapHeight]; - mTelehubCoverageMap = new U8[mNeighborMapWidth * mNeighborMapHeight]; - } - - memset(mNeighborMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8)); - memset(mTelehubCoverageMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8)); - - // leave 1 sim border - S32 min_x = (mMinX / REGION_WIDTH_UNITS) - 1; - S32 min_y = (mMinY / REGION_WIDTH_UNITS) - 1; - - std::map::const_iterator it; - for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) - { - U64 handle = (*it).first; - //LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - x_pos -= min_x; - y_pos -= min_y; - - S32 index = x_pos + (mNeighborMapWidth * y_pos); - mNeighborMap[index - 1]++; - mNeighborMap[index + 1]++; - mNeighborMap[index - mNeighborMapWidth]++; - mNeighborMap[index + mNeighborMapWidth]++; - } - - for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) - { - U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - x_pos -= min_x; - y_pos -= min_y; - - S32 index = x_pos + (mNeighborMapWidth * y_pos); - - if (!info->mTelehubName.empty() && mNeighborMap[index]) + case MAP_ITEM_AGENT_LOCATIONS: // agent locations { - S32 x_start = llmax(0, S32(x_pos - 5)); - S32 x_span = llmin(mNeighborMapWidth - 1, (S32)(x_pos + 5)) - x_start + 1; - S32 y_start = llmax(0, (S32)y_pos - 5); - S32 y_end = llmin(mNeighborMapHeight - 1, (S32)(y_pos + 5)); - for (S32 y_index = y_start; y_index <= y_end; y_index++) +// LL_INFOS("World Map") << "New Location " << new_item.mName << LL_ENDL; + if (extra > 0) { - memset(&mTelehubCoverageMap[x_start + y_index * mNeighborMapWidth], 0xff, sizeof(U8) * x_span); + new_item.setCount(extra); + siminfo->insertAgentLocation(new_item); } + break; } + default: + break; } + return true; +} - for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) - { - U64 handle = (*it).first; - //LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - - S32 index = x_pos - min_x + (mNeighborMapWidth * (y_pos - min_y)); - mTelehubCoverageMap[index] *= mNeighborMap[index]; - }*/ +bool LLWorldMap::isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1) +{ + if (!mIsTrackingLocation) + return false; + return ((mTrackingLocation[0] >= x0) && (mTrackingLocation[0] < x1) && (mTrackingLocation[1] >= y0) && (mTrackingLocation[1] < y1)); } // Drop priority of all images being fetched by the map @@ -1155,19 +730,85 @@ void LLWorldMap::dropImagePriorities() } } -LLPointer LLSimInfo::getLandForSaleImage () +// Load all regions in a given rectangle (in region grid coordinates, i.e. world / 256 meters) +void LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1) { - if (mOverlayImage.isNull() && mMapImageID[2].notNull()) + // Convert those boundaries to the corresponding (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) block coordinates + U32 global_x0 = x0 / MAP_BLOCK_SIZE; + U32 global_x1 = x1 / MAP_BLOCK_SIZE; + U32 global_y0 = y0 / MAP_BLOCK_SIZE; + U32 global_y1 = y1 / MAP_BLOCK_SIZE; + + //Singu note: There's a bunch of extra logic here, as opensim grids support sim coordinates that extend beyond the range + // used on the official grid. We basically just extend what LL had here by nesting the mMapBlockLoaded array in a 'dynamic' grid, + // essentially making that array a 'block' itself. An std::map was used to conserve memory, as we selectively only allocate desired + // blocks, and although lookups aren't blazingly fast with that container, it isn't likeley to accumulate very many entries. + + //MapBlockRequest uses U16 for coordinate components. + // In order not to exceed U16_MAX values, MAP_BLOCK_RES*MAP_BLOCK_SIZE*(i or j) can't exceed U16_MAX(65535) + U32 max_range = (U16_MAX+1)/MAP_BLOCK_RES/MAP_BLOCK_SIZE - 1; + + //Desired coordinate ranges in our 'dynamic' grid of 512x512 grids of 4x4 sim blocks. + U32 map_block_x0 = global_x0 / MAP_BLOCK_RES; + U32 map_block_x1 = llmin(global_x1 / MAP_BLOCK_RES, max_range); + U32 map_block_y0 = global_y0 / MAP_BLOCK_RES; + U32 map_block_y1 = llmin(global_y1 / MAP_BLOCK_RES, max_range); + + const bool layer_start = useWebMapTiles() ? SIM_LAYER_OVERLAY : SIM_LAYER_BEGIN; + for (U32 i = map_block_x0; i <= map_block_x1; ++i) { - // Fetch the image if it hasn't been done yet (unlikely but...) - mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID[2], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); - mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); - } - if (!mOverlayImage.isNull()) + for (U32 j = map_block_y0; j <= map_block_y1; ++j) { - // Boost the fetch level when we try to access that image - mOverlayImage->setBoostLevel(LLViewerTexture::BOOST_MAP); + + //Desired coordinate ranges in our 512x512 grids of 4x4 sim blocks. + x0 = global_x0 - i * MAP_BLOCK_RES; + x1 = llmin(global_x1 - i * (U32)MAP_BLOCK_RES, (U32)MAP_BLOCK_RES-1); + y0 = global_y0 - j * MAP_BLOCK_RES; + y1 = llmin(global_y1 - j * (U32)MAP_BLOCK_RES, (U32)MAP_BLOCK_RES-1); + + for(U32 layer = layer_start;layer &block = mMapBlockMap[layer][(i << 16) | j]; + if(block.empty()) + { + //New block. Allocate the array and set all entries to false. (seen as mMapBlockLoaded in v3) + block.resize(MAP_BLOCK_RES*MAP_BLOCK_RES,false); + } + + // Load the region info those blocks + for (S32 block_x = llmax(x0, 0); block_x <= llmin(x1, MAP_BLOCK_RES-1); ++block_x) + { + for (S32 block_y = llmax(y0, 0); block_y <= llmin(y1, MAP_BLOCK_RES-1); ++block_y) + { + S32 offset = block_x | (block_y * MAP_BLOCK_RES); + // if(!mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset]) + if (!block[offset]) + { + U16 min_x = (block_x + i * MAP_BLOCK_RES) * MAP_BLOCK_SIZE; + U16 max_x = min_x + MAP_BLOCK_SIZE - 1; + U16 min_y = (block_y + j * MAP_BLOCK_RES) * MAP_BLOCK_SIZE; + U32 max_y = min_y + MAP_BLOCK_SIZE - 1; + + //LL_INFOS("World Map") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL; + LLWorldMapMessage::getInstance()->sendMapBlockRequest(min_x, min_y, max_x, max_y, false, layerToFlags((sim_layer_type)layer)); + block[offset] = true; + } + } + } + } + } } - return mOverlayImage; } +void LLWorldMap::dump() +{ + LL_INFOS("World Map") << "LLWorldMap::dump()" << LL_ENDL; + for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + { + LLSimInfo* info = it->second; + if (info) + { + info->dump(); + } + } +} diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index c9e6be37e..c34dc0f21 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -51,39 +51,80 @@ class LLMessageSystem; - +// Description of objects like hubs, events, land for sale, people and more (TBD). +// Note: we don't store a "type" in there so we need to store instances of this class in +// well known objects (i.e. list of objects which type is "well known"). class LLItemInfo { public: - LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id, S32 extra = 0, S32 extra2 = 0); + LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id); // Setters void setTooltip(const std::string& tooltip) { mToolTip = tooltip; } void setElevation(F64 z) { mPosGlobal.mdV[VZ] = z; } + void setCount(S32 count) { mCount = count; } +// void setSelected(bool selected) { mSelected = selected; } +// void setColor(LLColor4 color) { mColor = color; } + // Accessors const LLVector3d& getGlobalPosition() const { return mPosGlobal; } const std::string& getName() const { return mName; } const std::string& getToolTip() const { return mToolTip; } const LLUUID& getUUID() const { return mID; } - U64 getRegionHandle() const { return mRegionHandle; } + S32 getCount() const { return mCount; } + + U64 getRegionHandle() const { return to_region_handle(mPosGlobal); } // Build the handle on the fly + bool isName(const std::string& name) const { return (mName == name); } // True if name same as item's name +// bool isSelected() const { return mSelected; } + private: - std::string mName; - std::string mToolTip; - LLVector3d mPosGlobal; - LLUUID mID; - U64 mRegionHandle; -public: //public for now.. non-standard. - BOOL mSelected; - S32 mExtra; - S32 mExtra2; + std::string mName; // Name of the individual item + std::string mToolTip; // Tooltip : typically, something to be displayed to the user when selecting this item + LLVector3d mPosGlobal; // Global world position + LLUUID mID; // UUID of the item + S32 mCount; // Number of elements in item (e.g. people count) + // Currently not used but might prove useful one day so we comment out +// bool mSelected; // Selected or not: updated by the viewer UI, not the simulator or asset DB +// LLColor4 mColor; // Color of the item }; -#define MAP_SIM_IMAGE_TYPES 3 -// 0 - Prim -// 1 - Terrain Only -// 2 - Overlay: Land For Sale +//Layer types that we intend to support. +enum sim_layer_type +{ + SIM_LAYER_BEGIN, + SIM_LAYER_COMPOSITE=0, //Legacy terrain+prim texture provided in MapBlockReply message. + SIM_LAYER_OVERLAY, //The land-for-sale overlay texture provided in MapBlockReply message. + SIM_LAYER_COUNT +}; +//The MapBlockRequest message 'layerflags' don't match the order of the sim_layer_type, so a few +//simple inline functions have been provided to convert between sim_layer_type and layerflag. +inline U32 layerToFlags(sim_layer_type layer) +{ + static U32 flags[SIM_LAYER_COUNT] = {0,2}; + return flags[layer]; +} +inline U32 flagsToLayer(U32 flags) +{ + //We only want the low two bytes, so mask out the rest. + if((flags & 0xFFFF) == 0) + return SIM_LAYER_COMPOSITE; + else if((flags & 0xFFFF) == 2) + return SIM_LAYER_OVERLAY; + else + return U32_MAX; +} + +// Info per region +// Such records are stored in a global map hold by the LLWorldMap and indexed by region handles. +// To avoid creating too many of them, they are requested in "blocks" corresponding to areas covered by the screen. +// Unfortunately, when the screen covers the whole world (zoomed out), that can translate in requesting info for +// every sim on the grid... Not good... +// To avoid this, the code implements a cut-off threshold for overlay graphics and, therefore, all LLSimInfo. +// In other words, when zooming out too much, we simply stop requesting LLSimInfo and +// LLItemInfo and just display the map tiles. +// As they are stored in different structures (LLSimInfo and LLWorldMipmap), this strategy is now workable. class LLSimInfo { public: @@ -96,17 +137,17 @@ public: LLVector3 getLocalPos(LLVector3d global_pos) const; void clearImage(); // Clears the reference to the Land for sale image for that region - void dropImagePriority(); // Drops the boost level of the Land for sale image for that region - LLPointer getLandForSaleImage(); // Get the overlay image, fetch it if necessary + void dropImagePriority(sim_layer_type layer = SIM_LAYER_COUNT); // Drops the boost level of the Land for sale image for that region void updateAgentCount(F64 time); // Send an item request for agent count on that region if time's up + // Setters void setName(std::string& name) { mName = name; } - void setSize(U16 sizeX, U16 sizeY) { mSizeX = sizeX; mSizeY = sizeY; } - void setAccess (U8 accesscode) { mAccess = accesscode; } + void setAccess (U32 accesscode) { mAccess = accesscode; } void setRegionFlags (U32 region_flags) { mRegionFlags = region_flags; } - void setWaterHeight (F32 water_height) { mWaterHeight = water_height; } + void setSize(U16 sizeX, U16 sizeY) { mSizeX = sizeX; mSizeY = sizeY; } void setAlpha(F32 alpha) { mAlpha = alpha; } + void setLandForSaleImage (LLUUID image_id); void setMapImageID (const LLUUID& id, const U8 &layer) { mMapImageID[layer] = id; } // Accessors @@ -115,43 +156,73 @@ public: const U32 getRegionFlags() const { return mRegionFlags; } const std::string getAccessString() const { return LLViewerRegion::accessToString((U8)mAccess); } const U8 getAccess() const { return mAccess; } + const S32 getAgentCount() const; // Compute the total agents count + LLPointer getLandForSaleImage(); // Get the overlay image, fetch it if necessary - const F32 getWaterHeight() const { return mWaterHeight; } const F32 getAlpha() const { return mAlpha; } - const U64 getHandle() const { return mHandle; } const U16 getSizeX() const { return mSizeX; } const U16 getSizeY() const { return mSizeY; } bool isName(const std::string& name) const; bool isDown() { return (mAccess == SIM_ACCESS_DOWN); } bool isPG() { return (mAccess <= SIM_ACCESS_PG); } bool isAdult() { return (mAccess == SIM_ACCESS_ADULT); } + + // Debug only + void dump() const; // Print the region info to the standard output + + // Items lists handling + typedef std::vector item_info_list_t; + void clearItems(); + + void insertTeleHub(const LLItemInfo& item) { mTelehubs.push_back(item); } + void insertInfoHub(const LLItemInfo& item) { mInfohubs.push_back(item); } + void insertPGEvent(const LLItemInfo& item) { mPGEvents.push_back(item); } + void insertMatureEvent(const LLItemInfo& item) { mMatureEvents.push_back(item); } + void insertAdultEvent(const LLItemInfo& item) { mAdultEvents.push_back(item); } + void insertLandForSale(const LLItemInfo& item) { mLandForSale.push_back(item); } + void insertLandForSaleAdult(const LLItemInfo& item) { mLandForSaleAdult.push_back(item); } + void insertAgentLocation(const LLItemInfo& item); + + const LLSimInfo::item_info_list_t& getTeleHub() const { return mTelehubs; } + const LLSimInfo::item_info_list_t& getInfoHub() const { return mInfohubs; } + const LLSimInfo::item_info_list_t& getPGEvent() const { return mPGEvents; } + const LLSimInfo::item_info_list_t& getMatureEvent() const { return mMatureEvents; } + const LLSimInfo::item_info_list_t& getAdultEvent() const { return mAdultEvents; } + const LLSimInfo::item_info_list_t& getLandForSale() const { return mLandForSale; } + const LLSimInfo::item_info_list_t& getLandForSaleAdult() const { return mLandForSaleAdult; } + const LLSimInfo::item_info_list_t& getAgentLocation() const { return mAgentLocations; } + private: U64 mHandle; std::string mName; F64 mAgentsUpdateTime; // Time stamp giving the last time the agents information was requested for that region bool mFirstAgentRequest; // Init agent request flag - U8 mAccess; + + U32 mAccess; // Down/up and maturity rating of the region U32 mRegionFlags; - F32 mWaterHeight; U16 mSizeX; U16 mSizeY; F32 mAlpha; public: - BOOL mShowAgentLocations; // are agents visible? - - // Image ID for the current overlay mode. - LLUUID mMapImageID[MAP_SIM_IMAGE_TYPES]; - - // Hold a reference to the currently displayed image. - LLPointer mCurrentImage; - LLPointer mOverlayImage; + // Handling the "land for sale / land for auction" overlay image + LLUUID mMapImageID[SIM_LAYER_COUNT]; // Image ID of the overlay image + LLPointer mLayerImage[SIM_LAYER_COUNT]; + + // Items for this region + // Those are data received through item requests (as opposed to block requests for the rest of the data) + item_info_list_t mTelehubs; // List of tele hubs in the region + item_info_list_t mInfohubs; // List of info hubs in the region + item_info_list_t mPGEvents; // List of PG events in the region + item_info_list_t mMatureEvents; // List of Mature events in the region + item_info_list_t mAdultEvents; // List of Adult events in the region (AO) + item_info_list_t mLandForSale; // List of Land for sales in the region + item_info_list_t mLandForSaleAdult; // List of Adult Land for sales in the region (AO) + item_info_list_t mAgentLocations; // List of agents in the region }; -#define MAP_BLOCK_RES 256 - struct LLWorldMapLayer { BOOL LayerDefined; @@ -162,6 +233,11 @@ struct LLWorldMapLayer LLWorldMapLayer() : LayerDefined(FALSE) { } }; +// We request region data on the world by "blocks" of (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) regions +// This is to reduce the number of requests to the asset DB and get things in big "blocks" +const S32 MAP_MAX_SIZE = 2048; +const S32 MAP_BLOCK_SIZE = 4; +const S32 MAP_BLOCK_RES = (MAP_MAX_SIZE / MAP_BLOCK_SIZE); class LLWorldMap : public LLSingleton { @@ -175,135 +251,103 @@ public: // clears the list void reset(); - // clear the visible items - void eraseItems(); - - // Removes references to cached images - void clearImageRefs(); - - // Clears the flags indicating that we've received sim infos - // Causes a re-request of the sim info without erasing extisting info - void clearSimFlags(); - - // Drops the priority of the images being fetched - void dropImagePriorities(); + void clearImageRefs(); // Clears the image references + void dropImagePriorities(); // Drops the priority of the images being fetched + void reloadItems(bool force = false); // Reload the items (people, hub, etc...) // Region Map access typedef std::map sim_info_map_t; const LLWorldMap::sim_info_map_t& getRegionMap() const { return mSimInfoMap; } - // Returns simulator information, or NULL if out of range + void updateRegions(S32 x0, S32 y0, S32 x1, S32 y1); // Requests region info for a rectangle of regions (in grid coordinates) + + // Insert a region and items in the map global instance + // Note: x_world and y_world in world coordinates (meters) + static bool insertRegion(U32 x_world, U32 y_world, U32 x_size, U32 y_size, U32 agent_flags, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags); + static bool insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 type, S32 extra, S32 extra2); + + // Get info on sims (region) : note that those methods only search the range of loaded sims (the one that are being browsed) + // *not* the entire world. So a NULL return does not mean a down or unexisting region, just an out of range region. LLSimInfo* simInfoFromHandle(const U64 handle); - - // Returns simulator information, or NULL if out of range LLSimInfo* simInfoFromPosGlobal(const LLVector3d& pos_global); - - // Returns simulator information for named sim, or NULL if non-existent LLSimInfo* simInfoFromName(const std::string& sim_name); // Gets simulator name for a global position, returns true if it was found bool simNameFromPosGlobal(const LLVector3d& pos_global, std::string& outSimName ); - - // Sets the current layer - void setCurrentLayer(S32 layer, bool request_layer = false); - - void sendMapLayerRequest(); - void sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent = false); - void sendNamedRegionRequest(std::string region_name); - void sendNamedRegionRequest(std::string region_name, - url_callback_t callback, - const std::string& callback_url, - bool teleport); - void sendHandleRegionRequest(U64 region_handle, - url_callback_t callback, - const std::string& callback_url, - bool teleport); - void sendItemRequest(U32 type, U64 handle = 0); - - static void processMapLayerReply(LLMessageSystem*, void**); - static void processMapBlockReply(LLMessageSystem*, void**); - static void processMapItemReply(LLMessageSystem*, void**); - + static void gotMapServerURL(bool flag) { sGotMapURL = flag; } static bool useWebMapTiles(); - static LLPointer loadObjectsTile(U32 grid_x, U32 grid_y); void dump(); - // Extend the bounding box of the list of simulators. Returns true - // if the extents changed. - BOOL extendAABB(U32 x_min, U32 y_min, U32 x_max, U32 y_max); + // Track handling + void cancelTracking() { mIsTrackingLocation = false; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = false; } - // build coverage maps for telehub region visualization - void updateTelehubCoverage(); - BOOL coveredByTelehub(LLSimInfo* infop); + void setTracking(const LLVector3d& loc) { mIsTrackingLocation = true; mTrackingLocation = loc; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = false;} + void setTrackingInvalid() { mIsTrackingFound = true; mIsInvalidLocation = true; } + void setTrackingValid() { mIsTrackingFound = true; mIsInvalidLocation = false; } + void setTrackingDoubleClick() { mIsTrackingDoubleClick = true; } + void setTrackingCommit() { mIsTrackingCommit = true; } + + bool isTracking() { return mIsTrackingLocation; } + bool isTrackingValidLocation() { return mIsTrackingFound && !mIsInvalidLocation; } + bool isTrackingInvalidLocation() { return mIsTrackingFound && mIsInvalidLocation; } + bool isTrackingDoubleClick() { return mIsTrackingDoubleClick; } + bool isTrackingCommit() { return mIsTrackingCommit; } + bool isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1); + + LLVector3d getTrackedPositionGlobal() const { return mTrackingLocation; } + + std::vector::iterator getMapLayerBegin() { return mMapLayers.begin(); } + std::vector::iterator getMapLayerEnd() { return mMapLayers.end(); } + std::map >::const_iterator findMapBlock(U32 layer, U32 x, U32 y) const + { return LLWorldMap::instance().mMapBlockMap[layer].find((x<<16)|y); } + std::map >::const_iterator getMapBlockEnd(U32 layer) const + { return LLWorldMap::instance().mMapBlockMap[layer].end(); } - // Bounds of the world, in meters - U32 getWorldWidth() const; - U32 getWorldHeight() const; - // World Mipmap delegation: currently used when drawing the mipmap void equalizeBoostLevels(); LLPointer getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true) { return mWorldMipmap.getObjectsTile(grid_x, grid_y, level, load); } + static void processMapLayerReply(LLMessageSystem*, void**); private: bool clearItems(bool force = false); // Clears the item lists + void clearSimFlags(); // Clears the block flags indicating that we've already requested region infos // Create a region record corresponding to the handle, insert it in the region map and returns a pointer LLSimInfo* createSimInfoFromHandle(const U64 handle); - + // Map from region-handle to simulator info sim_info_map_t mSimInfoMap; -public: + // Request legacy background layers. + void sendMapLayerRequest(); - BOOL mIsTrackingUnknownLocation, mInvalidLocation, mIsTrackingDoubleClick, mIsTrackingCommit; - LLVector3d mUnknownLocation; - - bool mRequestLandForSale; - - typedef std::vector item_info_list_t; - item_info_list_t mTelehubs; - item_info_list_t mInfohubs; - item_info_list_t mPGEvents; - item_info_list_t mMatureEvents; - item_info_list_t mAdultEvents; - item_info_list_t mLandForSale; - item_info_list_t mLandForSaleAdult; - - std::map mNumAgents; - - typedef std::map agent_list_map_t; - agent_list_map_t mAgentLocationsMap; - - std::vector mMapLayers[MAP_SIM_IMAGE_TYPES]; - BOOL mMapLoaded[MAP_SIM_IMAGE_TYPES]; - BOOL * mMapBlockLoaded[MAP_SIM_IMAGE_TYPES]; - S32 mCurrentMap; - - // AABB of the list of simulators - U32 mMinX; - U32 mMaxX; - U32 mMinY; - U32 mMaxY; - - U8* mNeighborMap; - U8* mTelehubCoverageMap; - S32 mNeighborMapWidth; - S32 mNeighborMapHeight; + std::vector mMapLayers; + bool mMapLoaded; private: LLWorldMipmap mWorldMipmap; + // The World is divided in "blocks" of (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) regions that get requested at once. + // This boolean table avoids "blocks" to be requested multiple times. + // Issue: Not sure this scheme is foolproof though as I've seen + // cases where a block is never retrieved and, because of this boolean being set, never re-requested + //bool * mMapBlockLoaded[MAP_SIM_IMAGE_TYPES]; // Telling us if the block of regions has been requested or not + std::map > mMapBlockMap[SIM_LAYER_COUNT]; + + // Track location data : used while there's nothing tracked yet by LLTracker + bool mIsTrackingLocation; // True when we're tracking a point + bool mIsTrackingFound; // True when the tracking position has been found, valid or not + bool mIsInvalidLocation; // The region is down or the location does not correspond to an existing region + bool mIsTrackingDoubleClick; // User double clicked to set the location (i.e. teleport when found please...) + bool mIsTrackingCommit; // User used the search or landmark fields to set the location + LLVector3d mTrackingLocation; // World global position being tracked + + // General grid items request timing flags (used for events,hubs and land for sale) LLTimer mRequestTimer; - - // search for named region for url processing - std::string mSLURLRegionName; - U64 mSLURLRegionHandle; - std::string mSLURL; - url_callback_t mSLURLCallback; - bool mSLURLTeleport; - + bool mFirstRequest; + static bool sGotMapURL; }; diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp new file mode 100644 index 000000000..b25a3db75 --- /dev/null +++ b/indra/newview/llworldmapmessage.cpp @@ -0,0 +1,301 @@ +/** + * @file llworldmapmessage.cpp + * @brief Handling of the messages to the DB made by and for the world map. + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llworldmapmessage.h" +#include "message.h" + +#include "llworldmap.h" +#include "llagent.h" +#include "llfloaterworldmap.h" + +const U32 LAYER_FLAG = 2; + +//--------------------------------------------------------------------------- +// World Map Message Handling +//--------------------------------------------------------------------------- + +LLWorldMapMessage::LLWorldMapMessage() : + mSLURLRegionName(), + mSLURLRegionHandle(0), + mSLURL(), + mSLURLCallback(0), + mSLURLTeleport(false) +{ +} + +LLWorldMapMessage::~LLWorldMapMessage() +{ +} + +void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) +{ + //LL_INFOS("World Map") << "Send item request : type = " << type << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_MapItemRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_Flags, LAYER_FLAG); + msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim + msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim + + msg->nextBlockFast(_PREHASH_RequestData); + msg->addU32Fast(_PREHASH_ItemType, type); + msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim + + gAgent.sendReliableMessage(); +} + +void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name) +{ + //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + + // Request for layer + msg->newMessageFast(_PREHASH_MapNameRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_Flags, LAYER_FLAG); + msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim + msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim + msg->nextBlockFast(_PREHASH_NameData); + msg->addStringFast(_PREHASH_Name, region_name); + gAgent.sendReliableMessage(); +} + +void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name, + url_callback_t callback, + const std::string& callback_url, + bool teleport) // immediately teleport when result returned +{ + //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + mSLURLRegionName = region_name; + mSLURLRegionHandle = 0; + mSLURL = callback_url; + mSLURLCallback = callback; + mSLURLTeleport = teleport; + + sendNamedRegionRequest(region_name); +} + +void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle, + url_callback_t callback, + const std::string& callback_url, + bool teleport) // immediately teleport when result returned +{ + //LL_INFOS("World Map") << "LLWorldMap::sendHandleRegionRequest()" << LL_ENDL; + mSLURLRegionName.clear(); + mSLURLRegionHandle = region_handle; + mSLURL = callback_url; + mSLURLCallback = callback; + mSLURLTeleport = teleport; + + U32 global_x; + U32 global_y; + from_region_handle(region_handle, &global_x, &global_y); + U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); + U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); + + sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true, LAYER_FLAG); +} + +// public +void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent, S32 layer) +{ + //LL_INFOS("World Map") << "LLWorldMap::sendMapBlockRequest()" << ", min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << "), nonexistent = " << return_nonexistent << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MapBlockRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + U32 flags = layer; + flags |= (return_nonexistent ? 0x10000 : 0); + msg->addU32Fast(_PREHASH_Flags, flags); + msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim + msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim + msg->nextBlockFast(_PREHASH_PositionData); + msg->addU16Fast(_PREHASH_MinX, min_x); + msg->addU16Fast(_PREHASH_MinY, min_y); + msg->addU16Fast(_PREHASH_MaxX, max_x); + msg->addU16Fast(_PREHASH_MaxY, max_y); + gAgent.sendReliableMessage(); +} + +// public static +void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) +{ + U32 agent_flags; + msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); + + U32 layer = flagsToLayer(agent_flags); + if (layer >= SIM_LAYER_COUNT) + { + llwarns << "Invalid map image type returned! layer = " << agent_flags << llendl; + return; + } + + S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data); + //LL_INFOS("World Map") << "LLWorldMap::processMapBlockReply(), num_blocks = " << num_blocks << LL_ENDL; + + bool found_null_sim = false; + + for (S32 block=0; blockgetU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block); + msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block); + msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); + msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, block); + msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block); +// msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block); +// msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block); + msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block); + if(msg->getNumberOfBlocksFast(_PREHASH_Size) > 0) + { + msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeX, x_size, block); + msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeY, y_size, block); + } + if(x_size == 0 || (x_size % 16) != 0|| (y_size % 16) != 0) + { + x_size = 256; + y_size = 256; + } + + U32 x_world = (U32)(x_regions) * REGION_WIDTH_UNITS; + U32 y_world = (U32)(y_regions) * REGION_WIDTH_UNITS; + + // name shouldn't be empty, see EXT-4568 + //llassert(!name.empty()); + + //Opensim bug. BlockRequest can return sims without names, with an accesscode that isn't 255. + // skip if this has happened. + if(name.empty() && accesscode != 255) + continue; + + // Insert that region in the world map, if failure, flag it as a "null_sim" + if (!(LLWorldMap::getInstance()->insertRegion(x_world, y_world, x_size, y_size, agent_flags, name, image_id, (U32)accesscode, region_flags))) + { + found_null_sim = true; + } + + // If we hit a valid tracking location, do what needs to be done app level wise + if (LLWorldMap::getInstance()->isTrackingValidLocation()) + { + LLVector3d pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal(); + if (LLWorldMap::getInstance()->isTrackingDoubleClick()) + { + // Teleport if the user double clicked + gAgent.teleportViaLocation(pos_global); + } + // Update the "real" tracker information + gFloaterWorldMap->trackLocation(pos_global); + } + + // Handle the SLURL callback if any + url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; + if(callback != NULL) + { + U64 handle = to_region_handle(x_world, y_world); + // Check if we reached the requested region + if ((LLStringUtil::compareInsensitive(LLWorldMapMessage::getInstance()->mSLURLRegionName, name)==0) + || (LLWorldMapMessage::getInstance()->mSLURLRegionHandle == handle)) + { + LLWorldMapMessage::getInstance()->mSLURLCallback = NULL; + LLWorldMapMessage::getInstance()->mSLURLRegionName.clear(); + LLWorldMapMessage::getInstance()->mSLURLRegionHandle = 0; + + callback(handle, LLWorldMapMessage::getInstance()->mSLURL, image_id, LLWorldMapMessage::getInstance()->mSLURLTeleport); + } + } + if( gAgent.mPendingLure && + (U16)(gAgent.mPendingLure->mPosGlobal.mdV[0] / REGION_WIDTH_UNITS) == x_regions && + (U16)(gAgent.mPendingLure->mPosGlobal.mdV[1] / REGION_WIDTH_UNITS) == y_regions ) + { + gAgent.onFoundLureDestination(); + } + } + // Tell the UI to update itself + gFloaterWorldMap->updateSims(found_null_sim); +} + +// public static +void LLWorldMapMessage::processMapItemReply(LLMessageSystem* msg, void**) +{ + //LL_INFOS("World Map") << "LLWorldMap::processMapItemReply()" << LL_ENDL; + U32 type; + msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type); + + S32 num_blocks = msg->getNumberOfBlocks("Data"); + + for (S32 block=0; blockgetU32Fast(_PREHASH_Data, _PREHASH_X, X, block); + msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block); + msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); + msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block); + msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block); + msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block); + + LLWorldMap::getInstance()->insertItem(X, Y, name, uuid, type, extra, extra2); + } +} +void LLWorldMapMessage::handleSLURL(std::string& name, U32 x_world, U32 y_world, LLUUID image_id) +{ + // Handle the SLURL callback if any + url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; + if(callback != NULL) + { + U64 handle = to_region_handle(x_world, y_world); + // Check if we reached the requested region + if ((LLStringUtil::compareInsensitive(LLWorldMapMessage::getInstance()->mSLURLRegionName, name)==0) + || (LLWorldMapMessage::getInstance()->mSLURLRegionHandle == handle)) + { + LLWorldMapMessage::getInstance()->mSLURLCallback = NULL; + LLWorldMapMessage::getInstance()->mSLURLRegionName.clear(); + LLWorldMapMessage::getInstance()->mSLURLRegionHandle = 0; + + callback(handle, LLWorldMapMessage::getInstance()->mSLURL, image_id, LLWorldMapMessage::getInstance()->mSLURLTeleport); + } + } +} + diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h new file mode 100644 index 000000000..bd4bd7545 --- /dev/null +++ b/indra/newview/llworldmapmessage.h @@ -0,0 +1,79 @@ +/** + * @file llworldmapmessage.h + * @brief Handling of the messages to the DB made by and for the world map. + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLWORLDMAPMESSAGE_H +#define LL_LLWORLDMAPMESSAGE_H + +// Handling of messages (send and process) as well as SLURL callback if necessary +class LLMessageSystem; + +class LLWorldMapMessage : public LLSingleton +{ +public: + typedef boost::function + url_callback_t; + + LLWorldMapMessage(); + ~LLWorldMapMessage(); + + // Process incoming answers to map stuff requests + static void processMapBlockReply(LLMessageSystem*, void**); + static void processMapItemReply(LLMessageSystem*, void**); + + // Request data for all regions in a rectangular area. Coordinates in grids (i.e. meters / 256). + void sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent, S32 layer = 2); + + // Various methods to request LLSimInfo data to the simulator and asset DB + void sendNamedRegionRequest(std::string region_name); + void sendNamedRegionRequest(std::string region_name, + url_callback_t callback, + const std::string& callback_url, + bool teleport); + void sendHandleRegionRequest(U64 region_handle, + url_callback_t callback, + const std::string& callback_url, + bool teleport); + + // Request item data for regions + // Note: the handle works *only* when requesting agent count (type = MAP_ITEM_AGENT_LOCATIONS). In that case, + // the request will actually be transitting through the spaceserver (all that is done on the sim). + // All other values of type do create a global grid request to the asset DB. So no need to try to get, say, + // the events for one particular region. For such a request, the handle is ignored. + void sendItemRequest(U32 type, U64 handle = 0); + + void handleSLURL(std::string& name, U32 x_world, U32 y_world, LLUUID image_id); + +private: + // Search for region (by name or handle) for SLURL processing and teleport + // None of this relies explicitly on the LLWorldMap instance so better handle it here + std::string mSLURLRegionName; + U64 mSLURLRegionHandle; + std::string mSLURL; + url_callback_t mSLURLCallback; + bool mSLURLTeleport; +}; + +#endif // LL_LLWORLDMAPMESSAGE_H diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index bdd3b6054..038b4ae33 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -109,8 +109,6 @@ LLUIImagePtr LLWorldMapView::sClassifiedsImage = NULL; LLUIImagePtr LLWorldMapView::sForSaleImage = NULL; LLUIImagePtr LLWorldMapView::sForSaleAdultImage = NULL; -F32 LLWorldMapView::sThresholdA = 48.f; -F32 LLWorldMapView::sThresholdB = 96.f; F32 LLWorldMapView::sPanX = 0.f; F32 LLWorldMapView::sPanY = 0.f; F32 LLWorldMapView::sTargetPanX = 0.f; @@ -124,11 +122,18 @@ F32 CONE_SIZE = 0.6f; std::map LLWorldMapView::sStringsMap; -const int SIM_NULL_MAP_SCALE=4; // width in pixels, where we start drawing "null" sims +F32 DRAW_TEXT_THRESHOLD = 96.f; + const int SIM_MAP_AGENT_SCALE=8; // width in pixels, where we start drawing agents -const int SIM_MAP_SCALE=4; // width in pixels, where we start drawing sim tiles +const int SIM_DATA_SCALE=12; // width in pixels where we start requesting sim info const int SIM_LANDFORSALE_SCALE=32; +const int SIM_COMPOSITE_SCALE=2; // width in pixels, where we start drawing sim tiles. (legacy tiling method) +const int SIM_FETCH_SCALE=SIM_DATA_SCALE; // width in pixels, where we start requesting sim tile textures. (legacy tiling method) + +// When on, draw an outline for each mipmap tile gotten from S3 +#define DEBUG_DRAW_TILE 0 + void LLWorldMapView::initClass() { @@ -241,6 +246,7 @@ LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) LLWorldMapView::~LLWorldMapView() { + //LL_INFOS("World Map") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL; cleanupTextures(); } @@ -254,6 +260,10 @@ void LLWorldMapView::cleanupTextures() // static void LLWorldMapView::setScale( F32 scale ) { + if(!LLWorldMap::useWebMapTiles()) //adjust the scale range if drawing legacy tiles to avoid drawing a bajillion 1x1 tiles. + { + scale = SIM_COMPOSITE_SCALE + scale*((256.f-SIM_COMPOSITE_SCALE)/256.f); + } if (scale != sMapScale) { F32 old_scale = sMapScale; @@ -306,7 +316,7 @@ void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap ) BOOL is_agent_in_region(LLViewerRegion* region, LLSimInfo* info) { - return ((region && info) && (info->isName(region->getName()))); + return (region && info && info->isName(region->getName())); } @@ -348,15 +358,25 @@ void LLWorldMapView::draw() gGL.setColorMask(true, true); gGL.setSceneBlendType(LLRender::BT_ALPHA); - if(gHippoGridManager->getConnectedGrid()->isSecondLife()) + static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); + if(LLWorldMap::useWebMapTiles()) drawMipmap(width, height); else - drawTiles(width, height); - LLFontGL* font = LLFontGL::getFontSansSerifSmall(); + drawLegacyBackgroundLayers(width, height); - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.setColorMask(true, true); + //Singu Note: This is done before drawing the transparent offline overlay. drawMipmap doesn't actually + // fill every possible block on the minimap. Every space must be filled for the offline overlay to look correct. + // Draw background rectangle + LLGLSUIDefault gls_ui; + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); + gGL.blendFunc(LLRender::BF_ONE_MINUS_DEST_ALPHA, LLRender::BF_DEST_ALPHA); + gGL.color4fv( mBackgroundColor.mV ); + gl_rect_2d(0, height, width, 0); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + } // Draw the region name in the lower left corner for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); @@ -364,7 +384,7 @@ void LLWorldMapView::draw() { U64 handle = it->first; LLSimInfo* info = it->second; - + LLVector3d origin_global = from_region_handle(handle); // Find x and y position relative to camera's center. @@ -376,27 +396,104 @@ void LLWorldMapView::draw() // When the view isn't panned, 0,0 = center of rectangle F32 bottom = sPanY + half_height + relative_y; F32 left = sPanX + half_width + relative_x; - //F32 top = bottom + sMapScale ; - //F32 right = left + sMapScale ; + F32 top = bottom + sMapScale * ((F32)info->getSizeY() / REGION_WIDTH_METERS); + F32 right = left + sMapScale * ((F32)info->getSizeX() / REGION_WIDTH_METERS); + + // Discard if region is outside the screen rectangle (not visible on screen) + if ((top < 0.f) || (bottom > height) || + (right < 0.f) || (left > width) ) + { + // Drop the "land for sale" fetching priority since it's outside the view rectangle + info->dropImagePriority(); + continue; + } + + // This list is used by other methods to know which regions are indeed displayed on screen + + mVisibleRegions.push_back(handle); - info->mShowAgentLocations = (sMapScale >= SIM_MAP_AGENT_SCALE); - mVisibleRegions.push_back(handle); // Update the agent count for that region if we're not too zoomed out already if (sMapScale >= SIM_MAP_AGENT_SCALE) { info->updateAgentCount(current_time); } - std::string mesg; - if (sMapScale < sThresholdA) + F32 alpha = !LLWorldMap::useWebMapTiles() ? drawLegacySimTile(*info,left,top,right,bottom) : 1.f; + + if (info->isDown()) { + // Draw a transparent red square over down sims + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); + gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.begin(LLRender::QUADS); + gGL.vertex2f(left, top); + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, bottom); + gGL.vertex2f(right, top); + gGL.end(); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); } - else if (sMapScale < sThresholdB) + // As part of the AO project, we no longer want to draw access indicators; + // it's too complicated to get all the rules straight and will only + // cause confusion. + /********************** + else if (!info->isPG() && gAgent.isTeen()) { - // mesg = llformat( info->mAgents); + // If this is a mature region, and you are not, draw a line across it + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color3f(1.f, 0.f, 0.f); + gGL.begin(LLRender::LINES); + gGL.vertex2f(left, top); + gGL.vertex2f(right, bottom); + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, top); + gGL.end(); + } + **********************/ + else if (map_show_land_for_sale && (sMapScale >= SIM_LANDFORSALE_SCALE)) + { + // Draw the overlay image "Land for Sale / Land for Auction" + LLViewerFetchedTexture* overlayimage = info->getLandForSaleImage(); + if (overlayimage) + { + // Inform the fetch mechanism of the size we need + S32 draw_size = llround(sMapScale); + overlayimage->setKnownDrawSize( llround(draw_size * LLUI::sGLScaleFactor.mV[VX] * ((F32)info->getSizeX() / REGION_WIDTH_METERS)), + llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)info->getSizeY() / REGION_WIDTH_METERS))); + // Draw something whenever we have enough info + if (overlayimage->hasGLTexture() && !overlayimage->isMissingAsset() && overlayimage->getID() != IMG_DEFAULT) + { + gGL.getTexUnit(0)->bind(overlayimage); + gGL.color4f(1.f, 1.f, 1.f, alpha); + gGL.begin(LLRender::QUADS); + gGL.texCoord2f(0.f, 1.f); + gGL.vertex3f(left, top, -0.5f); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex3f(left, bottom, -0.5f); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3f(right, bottom, -0.5f); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex3f(right, top, -0.5f); + gGL.end(); + } + } } else { + // If we're not displaying the "land for sale", drop fetching priority of both. + info->dropImagePriority(SIM_LAYER_OVERLAY); + } + + // Draw the region name in the lower left corner + if (sMapScale >= DRAW_TEXT_THRESHOLD) + { + LLFontGL* font = LLFontGL::getFontSansSerifSmall(); + std::string mesg; + //mesg = llformat("%d / %s (%s)", // info->mAgents, // info->mName.c_str(), @@ -404,14 +501,18 @@ void LLWorldMapView::draw() // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-04 (RLVa-1.0.0a) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) { - mesg = RlvStrings::getString(RLV_STRING_HIDDEN); + if(!info->getName().empty()) + mesg = RlvStrings::getString(RLV_STRING_HIDDEN); } // [/RLVa:KB] else if (info->isDown()) { - mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); + if(info->getName().empty()) + mesg = llformat( "(%s)", sStringsMap["offline"].c_str()); + else + mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); } - else + else if(!info->getName().empty()) // Online sims should have names... { mesg = info->getName(); U8 access = info->getAccess(); @@ -434,91 +535,151 @@ void LLWorldMapView::draw() break; } } - } - - if (!mesg.empty()) - { - font->renderUTF8( - mesg, 0, - llfloor(left + 3), - llfloor(bottom + 2), - LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); - - // If map texture is still loading, - // display "Loading" placeholder text. - /*if ((simimage != NULL) && - simimage->getDiscardLevel() != 1 && - simimage->getDiscardLevel() != 0) + if (!mesg.empty()) { font->renderUTF8( - sStringsMap["loading"], 0, - llfloor(left + 18), - llfloor(top - 25), - LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); - }*/ + mesg, 0, + llfloor(left + 3), llfloor(bottom + 2), + LLColor4::white, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); + } } + } - } - - - // Draw background rectangle - LLGLSUIDefault gls_ui; + static const LLCachedControl map_show_requests("MapShowRequests", false); + if(map_show_requests) { + const F32 map_to_pixels = MAP_MAX_SIZE*sMapScale; + const F32 block_to_pixels = MAP_BLOCK_SIZE*sMapScale; + const F32 padding = .25f*sMapScale; + + //In sim coords. + const F32 centerX = -sPanX/sMapScale + camera_global.mdV[VX]/REGION_WIDTH_METERS; + const F32 centerY = -sPanY/sMapScale + camera_global.mdV[VY]/REGION_WIDTH_METERS; + const F32 bottom = centerY - half_height/sMapScale ; + const F32 left = centerX - half_width/sMapScale ; + const F32 top = centerY + half_height/sMapScale ; + const F32 right = centerX + half_width/sMapScale ; + + const U32 max_range = (U16_MAX+1)/MAP_BLOCK_RES/MAP_BLOCK_SIZE - 1; + const U32 map_block_x0 = (U32)(llmax(left,0.f) / MAP_MAX_SIZE); + const U32 map_block_x1 = llclamp(U32(right / MAP_MAX_SIZE), U32(0), max_range); + const U32 map_block_y0 = (U32)(llmax(bottom,0.f) / MAP_MAX_SIZE); + const U32 map_block_y1 = llclamp(U32(top / MAP_MAX_SIZE), U32(0), max_range); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); - gGL.blendFunc(LLRender::BF_ONE_MINUS_DEST_ALPHA, LLRender::BF_DEST_ALPHA); - gGL.color4fv( mBackgroundColor.mV ); - gl_rect_2d(0, height, width, 0); + + for(U32 i = map_block_x0; i <= map_block_x1; ++i) + { + const F32 base_left = i*map_to_pixels-left*sMapScale; + const F32 base_right = base_left + map_to_pixels; + if( base_right <= 0.f) + continue; + if( base_left >= width) + break; + for (U32 j = map_block_y0; j <= map_block_y1; ++j) + { + const F32 base_bottom = j*map_to_pixels-bottom*sMapScale; + const F32 base_top = base_bottom + map_to_pixels; + if( base_top <= 0.f) + continue; + if( base_bottom >= height) + break; + + std::map >::const_iterator it = LLWorldMap::getInstance()->findMapBlock(SIM_LAYER_OVERLAY,i,j); + + if(it != LLWorldMap::getInstance()->getMapBlockEnd(SIM_LAYER_OVERLAY)) + gGL.color4f(0.5f, 0.0f, 0.0f, 0.4f); + else + gGL.color4f(0.2f, .2f, 0.2f, 0.4f); + gGL.begin(LLRender::QUADS); + gGL.vertex2f(base_left+padding, base_top-padding); + gGL.vertex2f(base_left+padding, base_bottom+padding); + gGL.vertex2f(base_right-padding, base_bottom+padding); + gGL.vertex2f(base_right-padding, base_top-padding); + gGL.end(); + if(it != LLWorldMap::getInstance()->getMapBlockEnd(SIM_LAYER_OVERLAY)) + { + for(U32 x=0;x= width) + break; + for(U32 y=0;y= height) + break; + if(it->second[x | (y * MAP_BLOCK_RES)]) + gGL.color4f(0.0f, 0.5f, 0.0f, 0.4f); + else + gGL.color4f(0.4f, 0.0f, 0.0f, 0.4f); + gGL.begin(LLRender::QUADS); + gGL.vertex2f(block_left+padding, block_top-padding); + gGL.vertex2f(block_left+padding, block_bottom+padding); + gGL.vertex2f(block_right-padding, block_bottom+padding); + gGL.vertex2f(block_right-padding, block_top-padding); + gGL.end(); + + for(U32 sim_x=0;sim_x map_show_infohubs("MapShowInfohubs"); - if (map_show_infohubs) //(sMapScale >= sThresholdB) - { - drawGenericItems(LLWorldMap::getInstance()->mInfohubs, sInfohubImage); - } - - // Telehubs static const LLCachedControl map_show_telehubs("MapShowTelehubs"); - if (map_show_telehubs) //(sMapScale >= sThresholdB) + static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); + static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); + if(sMapScale >= DRAW_TEXT_THRESHOLD && (map_show_infohubs || + map_show_telehubs || + map_show_land_for_sale || + map_show_mature_events || + map_show_adult_events)) { - drawGenericItems(LLWorldMap::getInstance()->mTelehubs, sTelehubImage); + drawItems(); } - // Home Sweet Home + // Draw the Home location (always) LLVector3d home; if (gAgent.getHomePosGlobal(&home)) { drawImage(home, sHomeImage); } - static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); - if (map_show_land_for_sale) - { - drawGenericItems(LLWorldMap::getInstance()->mLandForSale, sForSaleImage); - // for 1.23, we're showing normal land and adult land in the same UI; you don't - // get a choice about which ones you want. If you're currently asking for adult - // content and land you'll get the adult land. - if (gAgent.canAccessAdult()) - { - drawGenericItems(LLWorldMap::getInstance()->mLandForSaleAdult, sForSaleAdultImage); - } - } - - drawEvents(); - - // Now draw your avatar after all that other stuff. + // Draw the current agent after all that other stuff. LLVector3d pos_global = gAgent.getPositionGlobal(); drawImage(pos_global, sAvatarYouImage); @@ -539,7 +700,7 @@ void LLWorldMapView::draw() // Draw icons for the avatars in each region. // Drawn after your avatar so you can see nearby people. static const LLCachedControl map_show_people("MapShowPeople"); - if (map_show_people) + if (map_show_people && sMapScale >= SIM_MAP_AGENT_SCALE) { drawAgents(); } @@ -561,23 +722,33 @@ void LLWorldMapView::draw() drawTracking( pos_global, gTrackColor, TRUE, LLTracker::getLabel(), LLTracker::getToolTip() ); } } - else if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation) + else if (LLWorldMap::getInstance()->isTracking()) { - if (LLWorldMap::getInstance()->mInvalidLocation) + if (LLWorldMap::getInstance()->isTrackingInvalidLocation()) { - // We know this location to be invalid + // We know this location to be invalid, draw a blue circle LLColor4 loading_color(0.0, 0.5, 1.0, 1.0); - drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Invalid Location", ""); + drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, LLTrans::getString("InvalidLocation"), ""); } else { + // We don't know yet what that location is, draw a throbing blue circle double value = fmod(current_time, 2); - value = 0.5 + 0.5*cos(value * 3.14159f); + value = 0.5 + 0.5*cos(value * F_PI); LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0); - drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Loading...", ""); + drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, LLTrans::getString("LoadingData"), ""); } } // #endif used to be here + + //Provide some feedback, because nothing will load if zoomed far out on the map when using legacy sim drawing. + if(!LLWorldMap::useWebMapTiles() && (sMapScale < SIM_FETCH_SCALE || sMapScale < SIM_DATA_SCALE)) + { + LLFontGL::getFontSansSerifSmall()->renderUTF8("(Zoom to resume loading)", 0, + width-2, LLFontGL::getFontSansSerifSmall()->getLineHeight()*1.5f, + LLColor4::white, + LLFontGL::RIGHT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); + } // turn off the scissor LLGLDisable no_scissor(GL_SCISSOR_TEST); @@ -598,63 +769,50 @@ void LLWorldMapView::setVisible(BOOL visible) LLPanel::setVisible(visible); if (!visible) { - for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++) - { - for (U32 layer_idx=0; layer_idxmMapLayers[map].size(); ++layer_idx) - { - if (LLWorldMap::getInstance()->mMapLayers[map][layer_idx].LayerDefined) - { - LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[map][layer_idx]; - layer->LayerImage->setBoostLevel(0); - } - } - } - for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); - it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + std::vector::iterator begin = LLWorldMap::getInstance()->getMapLayerBegin(); + std::vector::iterator end = LLWorldMap::getInstance()->getMapLayerEnd(); + for(std::vector::iterator it = begin; it != end; ++it) { - LLSimInfo* info = (*it).second; - if (info->mCurrentImage.notNull()) + if (it->LayerDefined) { - info->mCurrentImage->setBoostLevel(0); - } - if (info->mOverlayImage.notNull()) - { - info->mOverlayImage->setBoostLevel(0); + it->LayerImage->setBoostLevel(0); } } + // Drop the download of tiles and images priority to nil if we hide the map + LLWorldMap::getInstance()->dropImagePriorities(); } } -void LLWorldMapView::drawTiles(S32 width, S32 height) { +void LLWorldMapView::drawLegacyBackgroundLayers(S32 width, S32 height) { const F32 half_width = F32(width) / 2.0f; const F32 half_height = F32(height) / 2.0f; - F32 layer_alpha = 1.f; LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - // Draw one image per layer - for (U32 layer_idx=0; layer_idxmMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx) + std::vector::const_iterator begin = LLWorldMap::getInstance()->getMapLayerBegin(); + std::vector::const_iterator end = LLWorldMap::getInstance()->getMapLayerEnd(); + for (std::vector::const_iterator it = begin; it != end; ++it) { - if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined) + if (!it->LayerDefined) { continue; } - LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx]; - LLViewerTexture *current_image = layer->LayerImage; + const LLWorldMapLayer& layer = *it; + LLViewerTexture *current_image = layer.LayerImage; - if (current_image->isMissingAsset()) + if (!current_image || current_image->isMissingAsset() || current_image->getID() == IMG_DEFAULT) { continue; // better to draw nothing than the missing asset image } - LLVector3d origin_global((F64)layer->LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer->LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f); + LLVector3d origin_global((F64)layer.LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer.LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f); // Find x and y position relative to camera's center. LLVector3d rel_region_pos = origin_global - camera_global; F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale; F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; - F32 pix_width = sMapScale*(layer->LayerExtents.getWidth() + 1); - F32 pix_height = sMapScale*(layer->LayerExtents.getHeight() + 1); + F32 pix_width = sMapScale*(layer.LayerExtents.getWidth() + 1); + F32 pix_height = sMapScale*(layer.LayerExtents.getHeight() + 1); // When the view isn't panned, 0,0 = center of rectangle F32 bottom = sPanY + half_height + relative_y; @@ -674,11 +832,11 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { continue; } - current_image->setBoostLevel(LLViewerTexture::BOOST_MAP_VISIBLE); + current_image->setBoostLevel(LLViewerTexture::BOOST_MAP); current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY])); - if (!current_image->hasGLTexture()) + if (!current_image->hasGLTexture()) //Still loading. { continue; // better to draw nothing than the default image } @@ -690,10 +848,8 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { gGL.getTexUnit(0)->bind(current_image); // Draw map image into RGB - //gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gGL.setColorMask(true, false); - gGL.color4f(1.f, 1.f, 1.f, layer_alpha); - + gGL.color4f(1.f, 1.f, 1.f, 1.f); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.0f, 1.0f); gGL.vertex3f(left, top, -1.0f); @@ -704,7 +860,6 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { gGL.texCoord2f(1.0f, 1.0f); gGL.vertex3f(right, top, -1.0f); gGL.end(); - // draw an alpha of 1 where the sims are visible gGL.setColorMask(false, true); gGL.color4f(1.f, 1.f, 1.f, 1.f); @@ -719,455 +874,78 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { gGL.texCoord2f(1.0f, 1.0f); gGL.vertex2f(right, top); gGL.end(); + + gGL.setColorMask(true, true); } +} - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.setColorMask(true, true); - - F32 sim_alpha = 1.f; - - // Draw one image per region, centered on the camera position. +F32 LLWorldMapView::drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S32 right, S32 bottom) +{ + const F32 ALPHA_CUTOFF = 0.001f; const S32 MAX_SIMULTANEOUS_TEX = 100; const S32 MAX_REQUEST_PER_TICK = 5; const S32 MIN_REQUEST_PER_TICK = 1; S32 textures_requested_this_tick = 0; + LLViewerFetchedTexture* simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE]; - bool use_web_map_tiles = LLWorldMap::useWebMapTiles(); - - for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); - it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + const bool sim_visible = sMapScale >= SIM_COMPOSITE_SCALE; + const bool sim_fetchable = sMapScale >= SIM_FETCH_SCALE; + + if(sim_fetchable) { - U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - - LLViewerTexture* simimage = info->mCurrentImage; - LLViewerTexture* overlayimage = info->mOverlayImage; - - if (sMapScale < SIM_MAP_SCALE) - { - if (simimage != NULL) simimage->setBoostLevel(0); - if (overlayimage != NULL) overlayimage->setBoostLevel(0); - continue; - } - - LLVector3d origin_global = from_region_handle(handle); - LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - - // Find x and y position relative to camera's center. - LLVector3d rel_region_pos = origin_global - camera_global; - F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale; - F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; - - // When the view isn't panned, 0,0 = center of rectangle - F32 bottom = sPanY + half_height + relative_y; - F32 left = sPanX + half_width + relative_x; - F32 top = bottom + sMapScale * ((F32)info->getSizeY() / 256.f); - F32 right = left + sMapScale * ((F32)info->getSizeX() / 256.f); - - // Switch to world map texture (if available for this region) if either: - // 1. Tiles are zoomed out small enough, or - // 2. Sim's texture has not been loaded yet - F32 map_scale_cutoff = SIM_MAP_SCALE; -#if 0 // This is always false, as REGION_FLAGS_NULL_LAYER doesn't exist anymore - if ((info->getRegionFlags() & REGION_FLAGS_NULL_LAYER) > 0) - { - map_scale_cutoff = SIM_NULL_MAP_SCALE; - } -#endif - - bool sim_visible = - (sMapScale >= map_scale_cutoff) && - (simimage != NULL) && - (simimage->hasGLTexture()); - - if (sim_visible) - { - // Fade in - if (info->getAlpha() < 0.0f) - info->setAlpha( 1.f ); // don't fade initially - else - info->setAlpha(lerp(info->getAlpha(), 1.f, LLCriticalDamp::getInterpolant(0.15f))); - } - else - { - // Fade out - if (info->getAlpha() < 0.0f) - info->setAlpha( 0.f ); // don't fade initially - else - info->setAlpha(lerp(info->getAlpha(), 0.f, LLCriticalDamp::getInterpolant(0.15f))); - } - - // discard regions that are outside the rectangle - // and discard small regions - if (top < 0.f || - bottom > height || - right < 0.f || - left > width ) - { - if (simimage != NULL) simimage->setBoostLevel(0); - if (overlayimage != NULL) overlayimage->setBoostLevel(0); - continue; - } - - if (info->mCurrentImage.isNull()) + if (!simimage && sim_info.mMapImageID[SIM_LAYER_COMPOSITE].notNull() && sim_info.mMapImageID[SIM_LAYER_COMPOSITE] != IMG_DEFAULT) { if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) || ((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) && (textures_requested_this_tick < MAX_REQUEST_PER_TICK))) { textures_requested_this_tick++; - if (use_web_map_tiles && info->getSizeX() == REGION_WIDTH_UNITS && - info->getSizeY() == REGION_WIDTH_UNITS) - { - LLVector3d region_pos = info->getGlobalOrigin(); - info->mCurrentImage = LLWorldMap::loadObjectsTile((U32)(region_pos.mdV[VX] / REGION_WIDTH_UNITS), (U32)(region_pos.mdV[VY] / REGION_WIDTH_UNITS)); - } - else - { - info->mCurrentImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE); - } - info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); - simimage = info->mCurrentImage; - gGL.getTexUnit(0)->bind(simimage); - } - } - if (info->mOverlayImage.isNull() && info->mMapImageID[2].notNull()) - { - if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) || - ((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) && - (textures_requested_this_tick < MAX_REQUEST_PER_TICK))) - { - textures_requested_this_tick++; - info->mOverlayImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[2], MIPMAP_TRUE); - info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); - overlayimage = info->mOverlayImage; - gGL.getTexUnit(0)->bind(overlayimage); + simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE] = LLViewerTextureManager::getFetchedTexture(sim_info.mMapImageID[SIM_LAYER_COMPOSITE], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + simimage->setAddressMode(LLTexUnit::TAM_CLAMP); } } + } - // Bias the priority escalation for images nearer - LLVector3d center_global = origin_global; - center_global.mdV[VX] += 128.0; - center_global.mdV[VY] += 128.0; + const bool sim_drawable = simimage && !simimage->isMissingAsset() && simimage->getID() != IMG_DEFAULT; + const bool sim_fetching = sim_drawable && !simimage->hasGLTexture(); + const F32 fade_target = sim_visible ? 1.f : 0.f; + //Logic is a bit confusing here. Basically, we want to fade out on zoom-out, and fade in on either zoom-in OR texture has finished fetching. + //However, we instantly hide the tile if the texture is invalid or hasn't loaded. The tile never would have been visible before this, anyhow. + if (!sim_drawable || sim_fetching) + sim_info.setAlpha( 0.f ); + else if (llabs(sim_info.getAlpha() - fade_target) > ALPHA_CUTOFF) //This gives us a nice fade when a visible sims texture finishes loading, or visiblity has changed. + sim_info.setAlpha(lerp(sim_info.getAlpha(), fade_target, LLCriticalDamp::getInterpolant(0.15f))); + F32 alpha = sim_info.getAlpha(); + + //call setKnownDrawSize if image is still loading, or its actually being drawn. + if(sim_fetching || alpha >= ALPHA_CUTOFF) + { S32 draw_size = llround(sMapScale); - if (simimage != NULL) + simimage->setKnownDrawSize( llround(draw_size * LLUI::sGLScaleFactor.mV[VX] * ((F32)sim_info.getSizeX() / REGION_WIDTH_METERS)), + llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)sim_info.getSizeY() / REGION_WIDTH_METERS))); + simimage->setBoostLevel(LLViewerTexture::BOOST_MAP); + if(alpha >= ALPHA_CUTOFF) { - simimage->setBoostLevel(LLViewerTexture::BOOST_MAP); - simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX] * ((F32)info->getSizeX() / REGION_WIDTH_UNITS)), - llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)info->getSizeY() / REGION_WIDTH_UNITS))); - } - - if (overlayimage != NULL) - { - overlayimage->setBoostLevel(LLViewerTexture::BOOST_MAP); - overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX] * ((F32)info->getSizeX() / REGION_WIDTH_UNITS)), - llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)info->getSizeY() / REGION_WIDTH_UNITS))); - } - -// LLTextureView::addDebugImage(simimage); - - if (sim_visible && info->getAlpha() > 0.001f) - { - // Draw using the texture. If we don't clamp we get artifact at - // the edge. - LLGLSUIDefault gls_ui; - if (simimage != NULL) - gGL.getTexUnit(0)->bind(simimage); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - F32 alpha = sim_alpha * info->getAlpha(); - gGL.color4f(1.f, 1.0f, 1.0f, alpha); - + gGL.getTexUnit(0)->bind(simimage); + gGL.color4f(1.f, 1.f, 1.f, alpha); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); - gGL.vertex3f(left, top, 0.f); + gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(left, bottom, 0.f); + gGL.vertex2f(left, bottom); gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, 0.f); + gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); - gGL.vertex3f(right, top, 0.f); - gGL.end(); - - static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); - if (map_show_land_for_sale && overlayimage && overlayimage->hasGLTexture()) - { - gGL.getTexUnit(0)->bind(overlayimage); - gGL.color4f(1.f, 1.f, 1.f, alpha); - gGL.begin(LLRender::QUADS); - gGL.texCoord2f(0.f, 1.f); - gGL.vertex3f(left, top, -0.5f); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(left, bottom, -0.5f); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, -0.5f); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex3f(right, top, -0.5f); - gGL.end(); - } - - if (true /*V3: REGION_FLAGS_NULL_LAYER doesn't exist... (info->getRegionFlags() & REGION_FLAGS_NULL_LAYER) == 0*/) - { - // draw an alpha of 1 where the sims are visible (except NULL sims) - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.setColorMask(false, true); - gGL.color4f(1.f, 1.f, 1.f, 1.f); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::QUADS); - gGL.vertex2f(left, top); - gGL.vertex2f(left, bottom); - gGL.vertex2f(right, bottom); - gGL.vertex2f(right, top); - gGL.end(); - - gGL.setColorMask(true, true); - } - } - - if (info->isDown()) - { - // Draw a transparent red square over down sims - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); - gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::QUADS); - gGL.vertex2f(left, top); - gGL.vertex2f(left, bottom); - gGL.vertex2f(right, bottom); gGL.vertex2f(right, top); gGL.end(); } - - // As part of the AO project, we no longer want to draw access indicators; - // it's too complicated to get all the rules straight and will only - // cause confusion. - /********************** - // If this is mature, and you are not, draw a line across it - if (info->mAccess != SIM_ACCESS_DOWN - && info->mAccess > SIM_ACCESS_PG - && gAgent.isTeen()) - { - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color3f(1.f, 0.f, 0.f); - gGL.begin(LLRender::LINES); - gGL.vertex2f(left, top); - gGL.vertex2f(right, bottom); - gGL.vertex2f(left, bottom); - gGL.vertex2f(right, top); - gGL.end(); - } - **********************/ } -} - -void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image) -{ - LLWorldMap::item_info_list_t::const_iterator e; - for (e = items.begin(); e != items.end(); ++e) + else //Either the texture is invalid or view has zoomed out far enough and the sim has fully faded away. { - drawGenericItem(*e, image); + sim_info.dropImagePriority(SIM_LAYER_COMPOSITE); } -} - -void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image) -{ - drawImage(item.getGlobalPosition(), image); -} - - -void LLWorldMapView::drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color) -{ - LLVector3 pos_map = globalPosToView( global_pos ); - image->draw(llround(pos_map.mV[VX] - image->getWidth() /2.f), - llround(pos_map.mV[VY] - image->getHeight()/2.f), - color); -} - -void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr image, U32 count, F32 offset, const LLColor4& color) -{ - LLVector3 pos_map = globalPosToView( global_pos ); - for(U32 i=0; idraw(llround(pos_map.mV[VX] - image->getWidth() /2.f), - llround(pos_map.mV[VY] - image->getHeight()/2.f + i*offset), - color); - } -} - - -void LLWorldMapView::drawAgents() -{ - if(sMapScale < SIM_MAP_AGENT_SCALE) - return; - - F32 agents_scale = (sMapScale * 0.9f) / 256.f; - - LLColor4 avatar_color = gColors.getColor( "MapAvatar" ); - // LLColor4 friend_color = gColors.getColor( "MapFriend" ); - - for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) - { - U64 handle = *iter; - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if (siminfo && (siminfo->isDown())) - { - continue; - } - LLWorldMap::agent_list_map_t::iterator counts_iter = LLWorldMap::getInstance()->mAgentLocationsMap.find(handle); - if (siminfo && siminfo->mShowAgentLocations && counts_iter != LLWorldMap::getInstance()->mAgentLocationsMap.end()) - { - // Show Individual agents (or little stacks where real agents are) - LLWorldMap::item_info_list_t& agentcounts = counts_iter->second; - S32 sim_agent_count = 0; - for (LLWorldMap::item_info_list_t::iterator iter = agentcounts.begin(); - iter != agentcounts.end(); ++iter) - { - const LLItemInfo& info = *iter; - S32 agent_count = info.mExtra; - sim_agent_count += info.mExtra; - // Here's how we'd choose the color if info.mID were available but it's not being sent: - //LLColor4 color = (agent_count == 1 && is_agent_friend(info.mID)) ? friend_color : avatar_color; - drawImageStack(info.getGlobalPosition(), sAvatarSmallImage, agent_count, 3.f, avatar_color); - } - LLWorldMap::getInstance()->mNumAgents[handle] = sim_agent_count; // override mNumAgents for this sim - } - else - { - // Show agent 'stack' at center of sim - S32 num_agents = LLWorldMap::getInstance()->mNumAgents[handle]; - if (num_agents > 0) - { - LLVector3d region_center = from_region_handle(handle); - region_center[VX] += REGION_WIDTH_METERS / 2; - region_center[VY] += REGION_WIDTH_METERS / 2; - // Reduce the stack size as you zoom out - always display at lease one agent where there is one or more - S32 agent_count = (S32)(((num_agents-1) * agents_scale + (num_agents-1) * 0.1f)+.1f) + 1; - drawImageStack(region_center, sAvatarSmallImage, agent_count, 3.f, avatar_color); - } - } - } -} - - -void LLWorldMapView::drawEvents() -{ - bool mature_enabled = gAgent.canAccessMature(); - bool adult_enabled = gAgent.canAccessAdult(); - - static const LLCachedControl map_show_pg_events("MapShowPGEvents"); - static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); - static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); - - BOOL show_pg = map_show_pg_events; - BOOL show_mature = mature_enabled && map_show_mature_events; - BOOL show_adult = adult_enabled && map_show_adult_events; - - // First the non-selected events - LLWorldMap::item_info_list_t::const_iterator e; - if (show_pg) - { - for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e) - { - if (!e->mSelected) - { - drawGenericItem(*e, sEventImage); - } - } - } - if (show_mature) - { - for (e = LLWorldMap::getInstance()->mMatureEvents.begin(); e != LLWorldMap::getInstance()->mMatureEvents.end(); ++e) - { - if (!e->mSelected) - { - drawGenericItem(*e, sEventMatureImage); - } - } - } - if (show_adult) - { - for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e) - { - if (!e->mSelected) - { - drawGenericItem(*e, sEventAdultImage); - } - } - } - // Then the selected events - if (show_pg) - { - for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e) - { - if (e->mSelected) - { - drawGenericItem(*e, sEventImage); - } - } - } - if (show_mature) - { - for (e = LLWorldMap::getInstance()->mMatureEvents.begin(); e != LLWorldMap::getInstance()->mMatureEvents.end(); ++e) - { - if (e->mSelected) - { - drawGenericItem(*e, sEventMatureImage); - } - } - } - if (show_adult) - { - for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e) - { - if (e->mSelected) - { - drawGenericItem(*e, sEventAdultImage); - } - } - } -} - - -void LLWorldMapView::drawFrustum() -{ - // Draw frustum - F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS; - - F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); - F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); - F32 far_clip_pixels = far_clip_meters * meters_to_pixels; - - F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); - F32 half_width_pixels = half_width_meters * meters_to_pixels; - - F32 ctr_x = getRect().getWidth() * 0.5f + sPanX; - F32 ctr_y = getRect().getHeight() * 0.5f + sPanY; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Since we don't rotate the map, we have to rotate the frustum. - gGL.pushMatrix(); - gGL.translatef( ctr_x, ctr_y, 0 ); - gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); - - // Draw triangle with more alpha in far pixels to make it - // fade out in distance. - gGL.begin( LLRender::TRIANGLES ); - gGL.color4f(1.f, 1.f, 1.f, 0.25f); - gGL.vertex2f( 0, 0 ); - - gGL.color4f(1.f, 1.f, 1.f, 0.02f); - gGL.vertex2f( -half_width_pixels, far_clip_pixels ); - - gGL.color4f(1.f, 1.f, 1.f, 0.02f); - gGL.vertex2f( half_width_pixels, far_clip_pixels ); - gGL.end(); - gGL.popMatrix(); + return alpha; } void LLWorldMapView::drawMipmap(S32 width, S32 height) @@ -1205,90 +983,6 @@ void LLWorldMapView::drawMipmap(S32 width, S32 height) // Render the current level sVisibleTilesLoaded = drawMipmapLevel(width, height, level); - const F32 half_width = F32(width) / 2.0f; - const F32 half_height = F32(height) / 2.0f; - LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - - for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); - it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) - { - U64 handle = it->first; - LLSimInfo* info = it->second; - - LLVector3d origin_global = from_region_handle(handle); - - // Find x and y position relative to camera's center. - LLVector3d rel_region_pos = origin_global - camera_global; - F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale; - F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; - - // Coordinates of the sim in pixels in the UI panel - // When the view isn't panned, 0,0 = center of rectangle - F32 bottom = sPanY + half_height + relative_y; - F32 left = sPanX + half_width + relative_x; - F32 top = bottom + sMapScale ; - F32 right = left + sMapScale ; - - // Discard if region is outside the screen rectangle (not visible on screen) - if ((top < 0.f) || (bottom > height) || - (right < 0.f) || (left > width) ) - { - // Drop the "land for sale" fetching priority since it's outside the view rectangle - info->dropImagePriority(); - continue; - } - - if (info->isDown()) - { - // Draw a transparent red square over down sims - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); - gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::QUADS); - gGL.vertex2f(left, top); - gGL.vertex2f(left, bottom); - gGL.vertex2f(right, bottom); - gGL.vertex2f(right, top); - gGL.end(); - } - - if (gSavedSettings.getBOOL("MapShowLandForSale") && (sMapScale >= SIM_LANDFORSALE_SCALE)) - { - // Draw the overlay image "Land for Sale / Land for Auction" - LLViewerFetchedTexture* overlayimage = info->getLandForSaleImage(); - if (overlayimage) - { - // Inform the fetch mechanism of the size we need - S32 draw_size = llround(sMapScale); - overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); - // Draw something whenever we have enough info - if (overlayimage->hasGLTexture() && !overlayimage->isMissingAsset()) - { - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - gGL.getTexUnit(0)->bind(overlayimage); - gGL.color4f(1.f, 1.f, 1.f, 1.f); - gGL.begin(LLRender::QUADS); - gGL.texCoord2f(0.f, 1.f); - gGL.vertex3f(left, top, -0.5f); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(left, bottom, -0.5f); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, -0.5f); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex3f(right, top, -0.5f); - gGL.end(); - } - } - } - else - { - // If we're not displaying the "land for sale", drop its fetching priority - info->dropImagePriority(); - } - } - return; } @@ -1341,13 +1035,13 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load F32 left = pos_screen[VX]; F32 bottom = pos_screen[VY]; // Compute the NE corner coordinates of the tile now - LLSimInfo* simInfo = LLWorldMap::instance().simInfoFromHandle(to_region_handle(grid_x, grid_y)); + /*LLSimInfo* simInfo = LLWorldMap::instance().simInfoFromHandle(to_region_handle(grid_x, grid_y)); if(simInfo != NULL) { pos_global[VX] += ((F32)tile_width * ((F32)simInfo->getSizeX() / REGION_WIDTH_METERS)); pos_global[VY] += ((F32)tile_width * ((F32)simInfo->getSizeY() / REGION_WIDTH_METERS)); } - else + else*/ { pos_global[VX] += tile_width; pos_global[VY] += tile_width; @@ -1360,10 +1054,7 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->bind(simimage.get()); simimage->setAddressMode(LLTexUnit::TAM_CLAMP); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.color4f(1.f, 1.0f, 1.0f, 1.0f); - gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex3f(left, top, 0.f); @@ -1378,6 +1069,7 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load drawTileOutline(level, top, left, bottom, right); #endif // DEBUG_DRAW_TILE } + //else } else { @@ -1391,6 +1083,206 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load return (completed_tiles == total_tiles); } +// Draw lines (rectangle outline and cross) to visualize the position of the tile +// Used for debug only +void LLWorldMapView::drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right) +{ + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + if (level == 1) + gGL.color3f(1.f, 0.f, 0.f); // red + else if (level == 2) + gGL.color3f(0.f, 1.f, 0.f); // green + else if (level == 3) + gGL.color3f(0.f, 0.f, 1.f); // blue + else if (level == 4) + gGL.color3f(1.f, 1.f, 0.f); // yellow + else if (level == 5) + gGL.color3f(1.f, 0.f, 1.f); // magenta + else if (level == 6) + gGL.color3f(0.f, 1.f, 1.f); // cyan + else if (level == 7) + gGL.color3f(1.f, 1.f, 1.f); // white + else + gGL.color3f(0.f, 0.f, 0.f); // black + gGL.begin(LLRender::LINE_STRIP); + gGL.vertex2f(left, top); + gGL.vertex2f(right, bottom); + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, top); + gGL.vertex2f(left, top); + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, bottom); + gGL.vertex2f(right, top); + gGL.end(); + + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); +} + +void LLWorldMapView::drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image) +{ + LLSimInfo::item_info_list_t::const_iterator e; + for (e = items.begin(); e != items.end(); ++e) + { + drawGenericItem(*e, image); + } +} + +void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image) +{ + drawImage(item.getGlobalPosition(), image); +} + + +void LLWorldMapView::drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color) +{ + LLVector3 pos_map = globalPosToView( global_pos ); + image->draw(llround(pos_map.mV[VX] - image->getWidth() /2.f), + llround(pos_map.mV[VY] - image->getHeight()/2.f), + color); +} + +void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr image, U32 count, F32 offset, const LLColor4& color) +{ + LLVector3 pos_map = globalPosToView( global_pos ); + for(U32 i=0; idraw(llround(pos_map.mV[VX] - image->getWidth() /2.f), + llround(pos_map.mV[VY] - image->getHeight()/2.f + i*offset), + color); + } +} + +void LLWorldMapView::drawItems() +{ + bool mature_enabled = gAgent.canAccessMature(); + bool adult_enabled = gAgent.canAccessAdult(); + + static const LLCachedControl map_show_infohubs("MapShowInfohubs"); + static const LLCachedControl map_show_telehubs("MapShowTelehubs"); + static const LLCachedControl map_show_pg_events("MapShowPGEvents"); + static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); + static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); + static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); + + BOOL show_mature = mature_enabled && map_show_mature_events; + BOOL show_adult = adult_enabled && map_show_adult_events; + + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) + { + U64 handle = *iter; + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((info == NULL) || (info->isDown())) + { + continue; + } + // Infohubs + if (map_show_infohubs) + { + drawGenericItems(info->getInfoHub(), sInfohubImage); + } + // Telehubs + if (map_show_telehubs) + { + drawGenericItems(info->getTeleHub(), sTelehubImage); + } + // Land for sale + if (map_show_land_for_sale) + { + drawGenericItems(info->getLandForSale(), sForSaleImage); + // for 1.23, we're showing normal land and adult land in the same UI; you don't + // get a choice about which ones you want. If you're currently asking for adult + // content and land you'll get the adult land. + if (gAgent.canAccessAdult()) + { + drawGenericItems(info->getLandForSaleAdult(), sForSaleAdultImage); + } + } + // PG Events + if (map_show_pg_events) + { + drawGenericItems(info->getPGEvent(), sEventImage); + } + // Mature Events + if (show_mature) + { + drawGenericItems(info->getMatureEvent(), sEventMatureImage); + } + // Adult Events + if (show_adult) + { + drawGenericItems(info->getAdultEvent(), sEventAdultImage); + } + } +} + +void LLWorldMapView::drawAgents() +{ + F32 agents_scale = (sMapScale * 0.9f) / 256.f; + + LLColor4 avatar_color = gColors.getColor( "MapAvatar" ); + // LLColor4 friend_color = gColors.getColor( "MapFriend" ); + + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) + { + U64 handle = *iter; + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((siminfo == NULL) || (siminfo->isDown())) + { + continue; + } + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAgentLocation().begin(); + while (it != siminfo->getAgentLocation().end()) + { + // Show Individual agents (or little stacks where real agents are) + + // Here's how we'd choose the color if info.mID were available but it's not being sent: + // LLColor4 color = (agent_count == 1 && is_agent_friend(info.mID)) ? friend_color : avatar_color; + // Reduce the stack size as you zoom out - always display at lease one agent where there is one or more + S32 agent_count = (S32)(((it->getCount()-1) * agents_scale + (it->getCount()-1) * 0.1f)+.1f) + 1; + drawImageStack(it->getGlobalPosition(), sAvatarSmallImage, agent_count, 3.f, avatar_color); + ++it; + } + } +} + +void LLWorldMapView::drawFrustum() +{ + // Draw frustum + F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS; + + F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); + F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); + F32 far_clip_pixels = far_clip_meters * meters_to_pixels; + + F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); + F32 half_width_pixels = half_width_meters * meters_to_pixels; + + F32 ctr_x = getRect().getWidth() * 0.5f + sPanX; + F32 ctr_y = getRect().getHeight() * 0.5f + sPanY; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Since we don't rotate the map, we have to rotate the frustum. + gGL.pushMatrix(); + gGL.translatef( ctr_x, ctr_y, 0 ); + gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); + + // Draw triangle with more alpha in far pixels to make it + // fade out in distance. + gGL.begin( LLRender::TRIANGLES ); + gGL.color4f(1.f, 1.f, 1.f, 0.25f); + gGL.vertex2f( 0, 0 ); + + gGL.color4f(1.f, 1.f, 1.f, 0.02f); + gGL.vertex2f( -half_width_pixels, far_clip_pixels ); + + gGL.color4f(1.f, 1.f, 1.f, 0.02f); + gGL.vertex2f( half_width_pixels, far_clip_pixels ); + gGL.end(); + gGL.popMatrix(); +} LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos ) { LLVector3d relative_pos_global = global_pos - gAgentCamera.getCameraPositionGlobal(); @@ -1461,9 +1353,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& text_x, text_y, LLColor4::white, LLFontGL::HCENTER, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); + LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); if (tooltip != "") { @@ -1474,9 +1364,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& text_x, text_y, LLColor4::white, LLFontGL::HCENTER, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); + LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); } } } @@ -1510,8 +1398,9 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y ) BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen ) { LLVector3d pos_global = viewPosToGlobal(x, y); + U64 handle = to_region_handle(pos_global); - LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); if (info) { LLViewerRegion *region = gAgent.getRegion(); @@ -1525,8 +1414,8 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic if (!info->isDown()) { - S32 agent_count = LLWorldMap::getInstance()->mNumAgents[info->getHandle()]; - if (region && region->getHandle() == info->getHandle()) + S32 agent_count = info->getAgentCount(); + if (region && (region->getHandle() == handle)) { ++agent_count; // Bump by 1 if we're here } @@ -1614,7 +1503,7 @@ static void drawDot(F32 x_pixels, F32 y_pixels, // static void LLWorldMapView::drawAvatar(F32 x_pixels, F32 y_pixels, - LLColor4 color, + const LLColor4& color, F32 relative_z, F32 dot_radius) { @@ -1925,7 +1814,7 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo gFloaterWorldMap->trackGenericItem(item); } - item.mSelected = TRUE; +// item.mSelected = TRUE; *id = item.getUUID(); return true; @@ -1949,111 +1838,119 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, *hit_type = 0; // hit nothing - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE; - LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; + LLWorldMap::getInstance()->cancelTracking(); - LLWorldMap::item_info_list_t::iterator it; - - // clear old selected stuff - for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it) - { - (*it).mSelected = FALSE; - } - for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it) - { - (*it).mSelected = FALSE; - } - for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) - { - (*it).mSelected = FALSE; - } - for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) - { - (*it).mSelected = FALSE; - } - - // Select event you clicked on static const LLCachedControl map_show_pg_events("MapShowPGEvents"); - if (map_show_pg_events) - { - for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it) - { - LLItemInfo& event = *it; - - if (checkItemHit(x, y, event, id, false)) - { - *hit_type = MAP_ITEM_PG_EVENT; - mItemPicked = TRUE; - gFloaterWorldMap->trackEvent(event); - return; - } - } - } static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); - if (map_show_mature_events) - { - for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it) - { - LLItemInfo& event = *it; - - if (checkItemHit(x, y, event, id, false)) - { - *hit_type = MAP_ITEM_MATURE_EVENT; - mItemPicked = TRUE; - gFloaterWorldMap->trackEvent(event); - return; - } - } - } static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); - if (map_show_adult_events) - { - for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) - { - LLItemInfo& event = *it; - - if (checkItemHit(x, y, event, id, false)) - { - *hit_type = MAP_ITEM_ADULT_EVENT; - mItemPicked = TRUE; - gFloaterWorldMap->trackEvent(event); - return; - } - } - } static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); - if (map_show_land_for_sale) - { - for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) - { - LLItemInfo& land = *it; - if (checkItemHit(x, y, land, id, true)) - { - *hit_type = MAP_ITEM_LAND_FOR_SALE; - mItemPicked = TRUE; - return; - } - } - - for (it = LLWorldMap::getInstance()->mLandForSaleAdult.begin(); it != LLWorldMap::getInstance()->mLandForSaleAdult.end(); ++it) - { - LLItemInfo& land = *it; + if(sMapScale >= DRAW_TEXT_THRESHOLD) + { + bool show_mature = gAgent.canAccessMature() && map_show_mature_events; + bool show_adult = gAgent.canAccessAdult() && map_show_adult_events; - if (checkItemHit(x, y, land, id, true)) - { - *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT; - mItemPicked = TRUE; - return; - } + // Test hits if trackable data are displayed, otherwise, we don't even bother + if (map_show_pg_events || show_mature || show_adult || map_show_land_for_sale) + { + // Iterate through the visible regions + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) + { + U64 handle = *iter; + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((siminfo == NULL) || (siminfo->isDown())) + { + continue; + } + // If on screen check hits with the visible item lists + if (map_show_pg_events) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getPGEvent().begin(); + while (it != siminfo->getPGEvent().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, false)) + { + *hit_type = MAP_ITEM_PG_EVENT; + mItemPicked = TRUE; + gFloaterWorldMap->trackEvent(event); + return; + } + ++it; + } + } + if (show_mature) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getMatureEvent().begin(); + while (it != siminfo->getMatureEvent().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, false)) + { + *hit_type = MAP_ITEM_MATURE_EVENT; + mItemPicked = TRUE; + gFloaterWorldMap->trackEvent(event); + return; + } + ++it; + } + } + if (show_adult) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAdultEvent().begin(); + while (it != siminfo->getAdultEvent().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, false)) + { + *hit_type = MAP_ITEM_ADULT_EVENT; + mItemPicked = TRUE; + gFloaterWorldMap->trackEvent(event); + return; + } + ++it; + } + } + if (map_show_land_for_sale) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSale().begin(); + while (it != siminfo->getLandForSale().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, true)) + { + *hit_type = MAP_ITEM_LAND_FOR_SALE; + mItemPicked = TRUE; + return; + } + ++it; + } + // for 1.23, we're showing normal land and adult land in the same UI; you don't + // get a choice about which ones you want. If you're currently asking for adult + // content and land you'll get the adult land. + if (gAgent.canAccessAdult()) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSaleAdult().begin(); + while (it != siminfo->getLandForSaleAdult().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, true)) + { + *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT; + mItemPicked = TRUE; + return; + } + ++it; + } + } + } + } } } - // If we get here, we haven't clicked on an icon + // If we get here, we haven't clicked on anything gFloaterWorldMap->trackLocation(pos_global); mItemPicked = FALSE; - *id = LLUUID::null; return; } @@ -2114,58 +2011,35 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask ) return FALSE; } -U32 LLWorldMapView::updateBlock(S32 block_x, S32 block_y) +void LLWorldMapView::updateVisibleBlocks() { - U32 blocks_requested = 0; - S32 offset = block_x | (block_y * MAP_BLOCK_RES); - if (!LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset]) - { -// llinfos << "Loading Block (" << block_x << "," << block_y << ")" << llendl; - LLWorldMap::getInstance()->sendMapBlockRequest(block_x << 3, block_y << 3, (block_x << 3) + 7, (block_y << 3) + 7); - LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset] = TRUE; - blocks_requested++; - } - return blocks_requested; -} - -U32 LLWorldMapView::updateVisibleBlocks() -{ - if (sMapScale < SIM_MAP_SCALE) + if (sMapScale < SIM_DATA_SCALE) { // We don't care what is loaded if we're zoomed out - return 0; + return; } + // Load the blocks visible in the current World Map view + + // Get the World Map view coordinates and boundaries LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - - F32 pixels_per_region = sMapScale; const S32 width = getRect().getWidth(); const S32 height = getRect().getHeight(); - // Convert pan to sim coordinates - S32 world_center_x_lo = S32(((-sPanX - width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); - S32 world_center_x_hi = S32(((-sPanX + width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); - S32 world_center_y_lo = S32(((-sPanY - height/2) / pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); - S32 world_center_y_hi = S32(((-sPanY + height/2)/ pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); + const F32 half_width = F32(width) / 2.0f; + const F32 half_height = F32(height) / 2.0f; - // Find the corresponding 8x8 block - S32 world_block_x_lo = world_center_x_lo >> 3; - S32 world_block_x_hi = world_center_x_hi >> 3; - S32 world_block_y_lo = world_center_y_lo >> 3; - S32 world_block_y_hi = world_center_y_hi >> 3; + // Compute center into sim grid coordinates + S32 world_center_x = S32((-sPanX / sMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); + S32 world_center_y = S32((-sPanY / sMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); - U32 blocks_requested = 0; - const U32 max_blocks_requested = 9; + // Compute the boundaries into sim grid coordinates + S32 world_left = world_center_x - S32(half_width / sMapScale) - 1; + S32 world_right = world_center_x + S32(half_width / sMapScale) + 1; + S32 world_bottom = world_center_y - S32(half_height / sMapScale) - 1; + S32 world_top = world_center_y + S32(half_height / sMapScale) + 1; - for (S32 block_x = llmax(world_block_x_lo, 0); block_x <= llmin(world_block_x_hi, MAP_BLOCK_RES-1); ++block_x) - { - for (S32 block_y = llmax(world_block_y_lo, 0); block_y <= llmin(world_block_y_hi, MAP_BLOCK_RES-1); ++block_y) - { - blocks_requested += updateBlock(block_x, block_y); - if (blocks_requested >= max_blocks_requested) - return blocks_requested; - } - } - return blocks_requested; + //LL_INFOS("World Map") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom = " << world_bottom << ", top = " << world_top << LL_ENDL; + LLWorldMap::getInstance()->updateRegions(world_left, world_bottom, world_right, world_top); } BOOL LLWorldMapView::handleHover( S32 x, S32 y, MASK mask ) @@ -2255,9 +2129,9 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) } default: { - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation) + if (LLWorldMap::getInstance()->isTracking()) { - LLWorldMap::getInstance()->mIsTrackingDoubleClick = TRUE; + LLWorldMap::getInstance()->setTrackingDoubleClick(); } else { diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 97c79dddf..1df0bfba2 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -86,16 +86,17 @@ public: LLVector3d viewPosToGlobal(S32 x,S32 y); virtual void draw(); - void drawTiles(S32 width, S32 height); - void drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image); + void drawLegacyBackgroundLayers(S32 width, S32 height); //draw legacy background 'layer' tiles. Only available on official grids, I believe. + F32 drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S32 right, S32 bottom); //draw legacy sim texture (provided in MapBlockReply message). + void drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image); void drawGenericItem(const LLItemInfo& item, LLUIImagePtr image); void drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color = LLColor4::white); void drawImageStack(const LLVector3d& global_pos, LLUIImagePtr image, U32 count, F32 offset, const LLColor4& color); void drawAgents(); - void drawEvents(); + void drawItems(); void drawFrustum(); void drawMipmap(S32 width, S32 height); - bool drawMipmapLevel(S32 width, S32 height, S32 level, bool load = true); + bool drawMipmapLevel(S32 width, S32 height, S32 level, bool load = true); static void cleanupTextures(); @@ -119,7 +120,7 @@ public: S32 overlap ); static void drawAvatar( F32 x_pixels, F32 y_pixels, - LLColor4 color, + const LLColor4& color, F32 relative_z = 0.f, F32 dot_radius = 3.f); static void drawIconName(F32 x_pixels, @@ -132,9 +133,7 @@ public: static void clearLastClick() { sHandledLastClick = FALSE; } // if the view changes, download additional sim info as needed - // return value is number of blocks newly requested. - U32 updateBlock(S32 block_x, S32 block_y); - U32 updateVisibleBlocks(); + void updateVisibleBlocks(); protected: void setDirectionPos( LLTextBox* text_box, F32 rotation ); @@ -161,8 +160,6 @@ public: static LLUIImagePtr sForSaleImage; static LLUIImagePtr sForSaleAdultImage; - static F32 sThresholdA; - static F32 sThresholdB; static F32 sPixelsPerMeter; // world meters to map pixels static F32 sMapScale; // scale = size of a region in pixels @@ -202,6 +199,9 @@ public: handle_list_t mVisibleRegions; // set every frame static std::map sStringsMap; + +private: + void drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right); }; #endif diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 17ca2d573..0302ac92f 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -78,7 +78,7 @@ void LLWorldMipmap::equalizeBoostLevels() // For each tile for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) { - LLPointer img = iter->second; + LLPointer img = iter->second; S32 current_boost_level = img->getBoostLevel(); if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) { @@ -120,7 +120,7 @@ void LLWorldMipmap::dropBoostLevels() // For each tile for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) { - LLPointer img = iter->second; + LLPointer img = iter->second; img->setBoostLevel(LLViewerTexture::BOOST_NONE); } } @@ -195,7 +195,7 @@ LLPointer LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 // END DEBUG //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; - LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl); + LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); img->setBoostLevel(LLViewerTexture::BOOST_MAP); // Return the smart pointer @@ -224,7 +224,7 @@ void LLWorldMipmap::cleanMissedTilesFromLevel(S32 level) sublevel_tiles_t::iterator it = level_mipmap.begin(); while (it != level_mipmap.end()) { - LLPointer img = it->second; + LLPointer img = it->second; if (img->isMissingAsset()) { level_mipmap.erase(it++); diff --git a/indra/newview/skins/default/xui/en-us/floater_world_map.xml b/indra/newview/skins/default/xui/en-us/floater_world_map.xml index ebbda0fc8..c7c1be574 100644 --- a/indra/newview/skins/default/xui/en-us/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en-us/floater_world_map.xml @@ -172,7 +172,7 @@ tool_tip="Copies current location as SLURL to be used on the web." width="222" /> diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index 3ef6bc38d..4c701634e 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -123,6 +123,7 @@ Loading... + Invalid Location