diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 8f530c010..ff62b703e 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -45,11 +45,7 @@ #endif #define LL_OCTREE_PARANOIA_CHECK 0 -#if LL_DARWIN -#define LL_OCTREE_MAX_CAPACITY 32 -#else #define LL_OCTREE_MAX_CAPACITY 128 -#endif template class LLOctreeNode; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index cbc2ccc67..ad43d2263 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -492,8 +492,7 @@ set(viewer_SOURCE_FILES llwlparamset.cpp llworld.cpp llworldmap.cpp - llworldmapmessage.cpp - llworldmipmap.cpp + llmapresponders.cpp llworldmapview.cpp llxmlrpctransaction.cpp noise.cpp @@ -965,8 +964,7 @@ set(viewer_HEADER_FILES llwlparamset.h llworld.h llworldmap.h - llworldmapmessage.h - llworldmipmap.h + llmapresponders.h llworldmapview.h llxmlrpctransaction.h macmain.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0f9f1a610..172da1165 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7147,6 +7147,17 @@ Value http://map.secondlife.com.s3.amazonaws.com/ + UseWebMapTiles + + Comment + Use web map tiles whenever possible + Persist + 1 + Type + Boolean + Value + 1 + MapOverlayIndex Comment @@ -7180,10 +7191,10 @@ Value 1 - MapShowEvents + MapShowPGEvents Comment - Show events on world map + Show PG events on world map Persist 1 Type @@ -7191,6 +7202,28 @@ Value 1 + MapShowMatureEvents + + Comment + Show mature events on world map + Persist + 1 + Type + Boolean + Value + 0 + + MapShowAdultEvents + + Comment + Show adult events on world map + Persist + 1 + Type + Boolean + Value + 0 + MapShowInfohubs Comment diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index ecf03f08e..971964cdb 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -110,6 +110,7 @@ #include "lltoolmgr.h" #include "lltoolpie.h" #include "lltoolview.h" +#include "lltrans.h" #include "llui.h" // for make_ui_sound #include "llurldispatcher.h" #include "llviewercamera.h" @@ -139,7 +140,6 @@ #include "llfollowcam.h" #include "llao.h" -#include "llworldmapmessage.h" #include "llfollowcam.h" // [RLVa:KB] - Checked: 2010-09-27 (RLVa-1.1.3b) @@ -8517,21 +8517,26 @@ std::string LLAgent::getCapability(const std::string& name) const } return iter->second; } -// void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity) { const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0)); LLSimInfo* siminfo; siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(posglobal); + std::string sim_name; + LLWorldMap::getInstance()->simNameFromPosGlobal( posglobal, sim_name ); + if(siminfo) { - llinfos << fromname << "'s teleport lure is to " << siminfo->getName() << " (" << maturity << ")" << llendl; - std::string url = LLURLDispatcher::buildSLURL(siminfo->getName(), S32(x), S32(y), S32(z)); - std::string msg; - msg = llformat("%s's teleport lure is to %s", fromname.c_str(), url.c_str()); - if(maturity != "") + llinfos << fromname << "'s teleport lure is to " << sim_name << " (" << maturity << ")" << llendl; + LLStringUtil::format_map_t args; + args["[NAME]"] = fromname; + args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name.c_str(), S32(x), S32(y), S32(z)); + std::string msg = LLTrans::getString("TeleportLureMaturity", args); + if (maturity != "") + { msg.append(llformat(" (%s)", maturity.c_str())); + } LLChat chat(msg); LLFloaterChat::addChat(chat); } @@ -8546,7 +8551,7 @@ void LLAgent::showLureDestination(const std::string fromname, const int global_x LLAgent::lure_y = y; LLAgent::lure_z = z; LLAgent::lure_maturity = maturity; - LLWorldMapMessage::getInstance()->sendMapBlockRequest(lure_global_x, lure_global_y, lure_global_x, lure_global_y, true); + LLWorldMap::getInstance()->sendMapBlockRequest(lure_global_x, lure_global_y, lure_global_x, lure_global_y, true); } } @@ -8555,14 +8560,19 @@ void LLAgent::onFoundLureDestination() LLAgent::lure_show = FALSE; LLSimInfo* siminfo; siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(LLAgent::lure_posglobal); + std::string sim_name; + LLWorldMap::getInstance()->simNameFromPosGlobal(LLAgent::lure_posglobal, sim_name ); if(siminfo) { - llinfos << LLAgent::lure_name << "'s teleport lure is to " << siminfo->getName() << " (" << LLAgent::lure_maturity << ")" << llendl; - std::string url = LLURLDispatcher::buildSLURL(siminfo->getName(), S32(LLAgent::lure_x), S32(LLAgent::lure_y), S32(LLAgent::lure_z)); - std::string msg; - msg = llformat("%s's teleport lure is to %s", LLAgent::lure_name.c_str(), url.c_str()); - if(LLAgent::lure_maturity != "") + llinfos << LLAgent::lure_name << "'s teleport lure is to " << sim_name << " (" << LLAgent::lure_maturity << ")" << llendl; + LLStringUtil::format_map_t args; + args["[NAME]"] = LLAgent::lure_name; + args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name, S32(LLAgent::lure_x), S32(LLAgent::lure_y), S32(LLAgent::lure_z)); + std::string msg = LLTrans::getString("TeleportOfferMaturity", args); + if (LLAgent::lure_maturity != "") + { msg.append(llformat(" (%s)", LLAgent::lure_maturity.c_str())); + } LLChat chat(msg); LLFloaterChat::addChat(chat); } @@ -8570,7 +8580,6 @@ void LLAgent::onFoundLureDestination() llwarns << "Grand scheme failed" << llendl; } -// // EOF diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 597a60fd1..43f8b7e95 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -87,6 +87,16 @@ LLFloaterAbout* LLFloaterAbout::sInstance = NULL; static std::string get_viewer_release_notes_url(); +static void onAboutClickCopyToClipboard(void* user_data) +{ + LLFloater* self = (LLFloater*) user_data; + LLViewerTextEditor *support_widget = + self->getChild("support_editor", true); + support_widget->selectAll(); + support_widget->copy(); + support_widget->deselect(); +} + ///---------------------------------------------------------------------------- /// Class LLFloaterAbout ///---------------------------------------------------------------------------- @@ -107,7 +117,8 @@ LLFloaterAbout::LLFloaterAbout() LLViewerTextEditor *credits_widget = getChild("credits_editor", true); - + + childSetAction("copy_btn", onAboutClickCopyToClipboard, this); if (!support_widget || !credits_widget) { @@ -264,7 +275,7 @@ LLFloaterAbout::LLFloaterAbout() // TODO: Implement media plugin version query - support.append("Qt Webkit Version: 4.5.2 "); + support.append("Qt Webkit Version: 4.6.0 "); support.append("\n"); if (gPacketsIn > 0) @@ -315,7 +326,8 @@ void LLFloaterAbout::show(void*) static std::string get_viewer_release_notes_url() { - std::ostringstream version; + return "http://www.singularityviewer.org"; + /*std::ostringstream version; version << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH @@ -329,5 +341,6 @@ static std::string get_viewer_release_notes_url() std::ostringstream url; url << RELEASE_NOTES_BASE_URL << LLURI::mapToQueryString(query); - return "http://ascent.balseraph.org/index.php/Ascent_" + version.str();// url.str(); + return "http://ascent.balseraph.org/index.php/Ascent_" + version.str();// url.str();*/ } + diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 424be7380..f48c2fa0d 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -61,9 +61,7 @@ #include "llviewermenu.h" #include "llviewerregion.h" #include "llviewerstats.h" -#include "llviewerimage.h" #include "llworldmap.h" -#include "llworldmapmessage.h" #include "llworldmapview.h" #include "lluictrlfactory.h" #include "llappviewer.h" @@ -81,12 +79,6 @@ //--------------------------------------------------------------------------- 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; - enum EPanDirection { PAN_UP, @@ -175,6 +167,7 @@ LLFloaterWorldMap::LLFloaterWorldMap() { LLCallbackMap::map_t factory_map; factory_map["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL); + factory_map["terrain_mapview"] = LLCallbackMap(createWorldMapView, NULL); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", &factory_map); } @@ -186,7 +179,30 @@ void* LLFloaterWorldMap::createWorldMapView(void* data) BOOL LLFloaterWorldMap::postBuild() { - mPanel = getChild("objects_mapview"); + mTabs = getChild("maptab"); + if (!mTabs) return FALSE; + + LLPanel *panel; + + panel = mTabs->getChild("objects_mapview"); + if (panel) + { + mTabs->setTabChangeCallback(panel, onCommitBackground); + mTabs->setTabUserData(panel, this); + } + panel = mTabs->getChild("terrain_mapview"); + if (panel) + { + mTabs->setTabChangeCallback(panel, onCommitBackground); + mTabs->setTabUserData(panel, this); + } + + // The following callback syncs the worlmap tabs with the images. + // Commented out since it was crashing when LLWorldMap became a singleton. + // We should be fine without it but override the onOpen method and put it + // there if it turns out to be needed. -MG + // + //onCommitBackground((void*)this, false); childSetCommitCallback("friend combo", onAvatarComboCommit, this); @@ -247,7 +263,7 @@ BOOL LLFloaterWorldMap::postBuild() LLFloaterWorldMap::~LLFloaterWorldMap() { // All cleaned up by LLView destructor - mPanel = NULL; + mTabs = NULL; // Inventory deletes all observers on shutdown mInventory = NULL; @@ -280,7 +296,7 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) gFloaterWorldMap->open(); /* Flawfinder: ignore */ LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; + map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel(); map_panel->clearLastClick(); if (!was_visible) @@ -292,8 +308,15 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) } map_panel->updateVisibleBlocks(); - // Reload items as they may have changed - LLWorldMap::getInstance()->reloadItems(); + // Reload the agent positions when we show the window + LLWorldMap::getInstance()->eraseItems(); + + // Reload any maps that may have changed + LLWorldMap::getInstance()->clearSimFlags(); + + const S32 panel_num = gFloaterWorldMap->mTabs->getCurrentPanelIndex(); + const bool request_from_sim = true; + LLWorldMap::getInstance()->setCurrentLayer(panel_num, request_from_sim); // We may already have a bounding box for the regions of the world, // so use that to adjust the view. @@ -327,7 +350,9 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) // static void LLFloaterWorldMap::reloadIcons(void*) { - LLWorldMap::getInstance()->reloadItems(); + LLWorldMap::getInstance()->eraseItems(); + + LLWorldMap::getInstance()->sendMapLayerRequest(); } @@ -365,7 +390,7 @@ void LLFloaterWorldMap::setVisible( BOOL visible ) if( !visible ) { - // While we're not visible, discard the image tiles and overlays + // While we're not visible, discard the overlay images we're using LLWorldMap::getInstance()->clearImageRefs(); } } @@ -402,6 +427,12 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks) void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent ) { LLFloater::reshape( width, height, called_from_parent ); + + // Might have changed size of world display area + // JC: Technically, this is correct, but it makes the slider "pop" + // if you resize the window, then draw the slider. Just leaving it + // the way it was when you opened the window seems better. + // adjustZoomSliderBounds(); } @@ -480,7 +511,7 @@ void LLFloaterWorldMap::draw() childSetEnabled("Teleport", (BOOL)tracking_status); // childSetEnabled("Clear", (BOOL)tracking_status); - childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->isTracking()); + childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->mIsTrackingUnknownLocation); childSetEnabled("copy_slurl", (mSLURL.size() > 0) ); setMouseOpaque(TRUE); @@ -501,18 +532,6 @@ void LLFloaterWorldMap::draw() F32 map_scale = 256.f*pow(2.f, mCurZoomVal); LLWorldMapView::setScale( map_scale ); - // Enable/disable checkboxes depending on the zoom level - // If above threshold level (i.e. low res) -> Disable all checkboxes - // If under threshold level (i.e. high res) -> Enable all checkboxes - bool enable = LLWorldMapView::showRegionInfo(); - childSetEnabled("people_chk", enable); - childSetEnabled("infohub_chk", enable); - childSetEnabled("telehubchk", enable); - childSetEnabled("land_for_sale_chk", enable); - childSetEnabled("event_chk", enable); - childSetEnabled("event_mature_chk", enable); - childSetEnabled("event_adult_chk", enable); - LLFloater::draw(); } @@ -600,14 +619,14 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id ) void LLFloaterWorldMap::trackEvent(const LLItemInfo &event_info) { mTrackedStatus = LLTracker::TRACKING_LOCATION; - LLTracker::trackLocation(event_info.getGlobalPosition(), event_info.getName(), event_info.getToolTip(), LLTracker::LOCATION_EVENT); + LLTracker::trackLocation(event_info.mPosGlobal, event_info.mName, event_info.mToolTip, LLTracker::LOCATION_EVENT); setDefaultBtn("Teleport"); } void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item) { mTrackedStatus = LLTracker::TRACKING_LOCATION; - LLTracker::trackLocation(item.getGlobalPosition(), item.getName(), item.getToolTip(), LLTracker::LOCATION_ITEM); + LLTracker::trackLocation(item.mPosGlobal, item.mName, item.mToolTip, LLTracker::LOCATION_ITEM); setDefaultBtn("Teleport"); } @@ -616,27 +635,29 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); if (!sim_info) { - // We haven't found a region for that point yet, leave the tracking to the world map - LLWorldMap::getInstance()->setTracking(pos_global); + LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE; + LLWorldMap::getInstance()->mInvalidLocation = FALSE; + LLWorldMap::getInstance()->mUnknownLocation = pos_global; LLTracker::stopTracking(NULL); S32 world_x = S32(pos_global.mdV[0] / 256); S32 world_y = S32(pos_global.mdV[1] / 256); - LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true); + LLWorldMap::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true); setDefaultBtn(""); return; } - if (sim_info->isDown()) + if (sim_info->mAccess == SIM_ACCESS_DOWN) { - // 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(); + // Down sim. Show the blue circle of death! + LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE; + LLWorldMap::getInstance()->mUnknownLocation = pos_global; + LLWorldMap::getInstance()->mInvalidLocation = TRUE; LLTracker::stopTracking(NULL); setDefaultBtn(""); return; } - std::string sim_name = sim_info->getName(); + std::string sim_name; + LLWorldMap::getInstance()->simNameFromPosGlobal( pos_global, 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 ); std::string full_name = llformat("%s (%d, %d, %d)", @@ -651,7 +672,9 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) std::string tooltip(""); mTrackedStatus = LLTracker::TRACKING_LOCATION; LLTracker::trackLocation(pos_global, full_name, tooltip); - LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking + LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; + LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE; + LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; setDefaultBtn("Teleport"); } @@ -780,9 +803,9 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3 // pass sim name to combo box gFloaterWorldMap->mCompletingRegionName = region_name; - LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name); + LLWorldMap::getInstance()->sendNamedRegionRequest(region_name); LLStringUtil::toLower(gFloaterWorldMap->mCompletingRegionName); - LLWorldMap::getInstance()->setTrackingCommit(); + LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; } } @@ -963,7 +986,7 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) { childSetValue("spin z", 0); } - LLWorldMap::getInstance()->cancelTracking(); + LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; mCompletingRegionName = ""; mExactMatch = FALSE; } @@ -1000,16 +1023,18 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui) // can see the whole world, plus a little. void LLFloaterWorldMap::adjustZoomSliderBounds() { - // 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; + // 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++; // Find how much space we have to display the world LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)mPanel; + map_panel = (LLWorldMapView*)mTabs->getCurrentPanel(); LLRect view_rect = map_panel->getRect(); // View size in pixels @@ -1059,7 +1084,7 @@ void LLFloaterWorldMap::onPanBtn( void* userdata ) } LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; + map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel(); map_panel->translatePan( pan_x, pan_y ); } @@ -1259,16 +1284,16 @@ void LLFloaterWorldMap::onLocationCommit( void* userdata ) LLStringUtil::toLower(str); gFloaterWorldMap->mCompletingRegionName = str; - LLWorldMap::getInstance()->setTrackingCommit(); + LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; self->mExactMatch = FALSE; if (str.length() >= 3) { - LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str); + LLWorldMap::getInstance()->sendNamedRegionRequest(str); } else { str += "#"; - LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str); + LLWorldMap::getInstance()->sendNamedRegionRequest(str); } } @@ -1279,7 +1304,7 @@ void LLFloaterWorldMap::onClearBtn(void* data) LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; self->mTrackedStatus = LLTracker::TRACKING_NOTHING; LLTracker::stopTracking((void *)(intptr_t)TRUE); - LLWorldMap::getInstance()->cancelTracking(); + LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; self->mSLURL = ""; // Clear the SLURL since it's invalid self->mSetToUserPosition = TRUE; // Revert back to the current user position } @@ -1354,9 +1379,9 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) pos_global = LLTracker::getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal(); } } - else if(LLWorldMap::getInstance()->isTracking()) + else if(LLWorldMap::getInstance()->mIsTrackingUnknownLocation) { - pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal();; + pos_global = LLWorldMap::getInstance()->mUnknownLocation - gAgent.getCameraPositionGlobal();; } else { @@ -1364,8 +1389,8 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) pos_global.clearVec(); } - LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), - -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), + LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sPixelsPerMeter)), + -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sPixelsPerMeter)), !animate); mWaitingForTracker = FALSE; } @@ -1541,6 +1566,17 @@ void LLFloaterWorldMap::flyToAvatar() } } +// static +void LLFloaterWorldMap::onCommitBackground(void* userdata, bool from_click) +{ + LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; + + // Find my index + S32 index = self->mTabs->getCurrentPanelIndex(); + + LLWorldMap::getInstance()->setCurrentLayer(index); +} + void LLFloaterWorldMap::updateSims(bool found_null_sim) { if (mCompletingRegionName == "") @@ -1558,27 +1594,28 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) 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) + for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) { - LLSimInfo* info = it->second; - std::string sim_name_lower = info->getName(); + LLSimInfo* info = (*it).second; + std::string sim_name = info->mName; + std::string sim_name_lower = sim_name; LLStringUtil::toLower(sim_name_lower); if (sim_name_lower.substr(0, name_length) == mCompletingRegionName) { - if (LLWorldMap::getInstance()->isTrackingCommit()) + if (LLWorldMap::getInstance()->mIsTrackingCommit) { - if (info->isName(mCompletingRegionName)) + if (sim_name_lower == mCompletingRegionName) { - selected_value = info->getName(); + selected_value = sim_name; match_found = TRUE; } } LLSD value; - value["id"] = info->getName(); + value["id"] = sim_name; value["columns"][0]["column"] = "sim_name"; - value["columns"][0]["value"] = info->getName(); + value["columns"][0]["value"] = sim_name; list->addElement(value); num_results++; } @@ -1645,13 +1682,15 @@ void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata) LLStringUtil::toLower(sim_name); std::map::const_iterator it; - for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) { - LLSimInfo* info = it->second; + LLSimInfo* info = (*it).second; + std::string info_sim_name = info->mName; + LLStringUtil::toLower(info_sim_name); - if (info->isName(sim_name)) + if (sim_name == info_sim_name) { - LLVector3d pos_global = info->getGlobalOrigin(); + LLVector3d pos_global = from_region_handle( info->mHandle ); F64 local_x = self->childGetValue("spin x"); F64 local_y = self->childGetValue("spin y"); F64 local_z = self->childGetValue("spin z"); diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index dd5da1529..de7cfd8ad 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -50,6 +50,7 @@ class LLInventoryModel; class LLInventoryObserver; class LLItemInfo; class LLTabContainer; +class LLWorldMapView; class LLFloaterWorldMap : public LLFloater { @@ -111,7 +112,7 @@ public: // teleport to the tracked item, if there is one void teleport(); -private: +protected: static void onPanBtn( void* userdata ); static void onGoHome(void* data); @@ -122,6 +123,8 @@ private: static void onAvatarComboPrearrange( LLUICtrl* ctrl, void* data ); static void onAvatarComboCommit( LLUICtrl* ctrl, void* data ); + static void onCommitBackground(void* data, bool from_click); + static void onComboTextEntry( LLLineEditor* ctrl, void* data ); static void onSearchTextEntry( LLLineEditor* ctrl, void* data ); @@ -158,10 +161,10 @@ private: void cacheLandmarkPosition(); -private: - LLPanel* mPanel; // Panel displaying the map +protected: + LLTabContainer* mTabs; - // Ties to LLWorldMapView::sMapScale, in pixels per region + // Sets sMapScale, in pixels per region F32 mCurZoomVal; LLFrameTimer mZoomTimer; diff --git a/indra/newview/llmapresponders.cpp b/indra/newview/llmapresponders.cpp new file mode 100644 index 000000000..9d974f229 --- /dev/null +++ b/indra/newview/llmapresponders.cpp @@ -0,0 +1,224 @@ +/** + * @file llmapresponders.cpp + * @brief Processes responses received for map requests. + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llmapresponders.h" + +#include "llfloaterworldmap.h" +#include "llviewerimagelist.h" +#include "llworldmap.h" +#include "llagent.h" + +//virtual +void LLMapLayerResponder::result(const LLSD& result) +{ + llinfos << "LLMapLayerResponder::result from capabilities" << llendl; + + S32 agent_flags = result["AgentData"]["Flags"]; + + if (agent_flags != LLWorldMap::getInstance()->mCurrentMap) + { + 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(); + + LLSD::array_const_iterator iter; + BOOL adjust = FALSE; + for(iter = result["LayerData"].beginArray(); iter != result["LayerData"].endArray(); ++iter) + { + const LLSD& layer_data = *iter; + + LLWorldMapLayer new_layer; + new_layer.LayerDefined = TRUE; + + new_layer.LayerExtents.mLeft = layer_data["Left"]; + new_layer.LayerExtents.mRight = layer_data["Right"]; + new_layer.LayerExtents.mBottom = layer_data["Bottom"]; + 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 = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE); +// } + 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()->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"]; + 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 = new LLSimInfo(); + LLWorldMap::sim_info_map_t::iterator iter = LLWorldMap::getInstance()->mSimInfoMap.find(handle); + if (iter != LLWorldMap::getInstance()->mSimInfoMap.end()) + { + LLSimInfo* oldinfo = iter->second; + for (S32 image=0; imagemMapImageID[image] = oldinfo->mMapImageID[image]; + } + delete oldinfo; + } + LLWorldMap::getInstance()->mSimInfoMap[handle] = siminfo; + + siminfo->mHandle = handle; + siminfo->mName.assign( name ); + siminfo->mAccess = access; /*Flawfinder: ignore*/ + siminfo->mRegionFlags = region_flags; + siminfo->mWaterHeight = (F32) water_height; + siminfo->mMapImageID[agent_flags] = image_id; + if (use_web_map_tiles) + { + siminfo->mCurrentImage = LLWorldMap::loadObjectsTile((U32)x_regions, (U32)y_regions); + } + else + { + siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); + } + siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); + + if (siminfo->mMapImageID[2].notNull()) + { + siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE); + } + 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->mAccess == SIM_ACCESS_DOWN) + { + // 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); +} diff --git a/indra/newview/llmapresponders.h b/indra/newview/llmapresponders.h new file mode 100644 index 000000000..b6fb8e551 --- /dev/null +++ b/indra/newview/llmapresponders.h @@ -0,0 +1,43 @@ +/** + * @file llmapresponders.h + * @brief Processes responses received for map requests. + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMAPLAYERRESPONDER_H +#define LL_LLMAPLAYERRESPONDER_H + +#include "llhttpclient.h" + +class LLMapLayerResponder : public LLHTTPClient::Responder +{ + virtual void result(const LLSD& content); +}; + +#endif // LL_LLMAPLAYERRESPONDER_H diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index b8218b581..fd0635887 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -80,10 +80,10 @@ // [/RLVa:KB] const F32 MAP_SCALE_MIN = 32; -const F32 MAP_SCALE_MID = 1024; +const F32 MAP_SCALE_MID = 256; const F32 MAP_SCALE_MAX = 4096; const F32 MAP_SCALE_INCREMENT = 16; -const F32 MAP_SCALE_ZOOM_FACTOR = 1.04f; // Zoom in factor per click of the scroll wheel (4%) +const F32 MAP_SCALE_ZOOM_FACTOR = 1.1f; // Zoom in factor per click of the scroll wheel (10%) const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f; const F32 MIN_DOT_RADIUS = 3.5f; const F32 DOT_SCALE = 0.75f; @@ -198,7 +198,7 @@ void LLNetMap::draw() createObjectImage(); } - if (gSavedSettings.getS32( "MiniMapCenter" ) != MAP_CENTER_NONE) + if (gSavedSettings.getS32( "MiniMapCenter") != MAP_CENTER_NONE) { mCurPanX = lerp(mCurPanX, mTargetPanX, LLCriticalDamp::getInterpolant(0.1f)); mCurPanY = lerp(mCurPanY, mTargetPanY, LLCriticalDamp::getInterpolant(0.1f)); @@ -231,9 +231,9 @@ void LLNetMap::draw() gGL.pushMatrix(); gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f); - + BOOL rotate_map = gSavedSettings.getBOOL( "MiniMapRotate" ); - if( rotate_map ) + if (rotate_map) { // rotate subsequent draws to agent rotation rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ); @@ -383,6 +383,10 @@ void LLNetMap::draw() // TODO: it'd be very cool to draw these in sorted order from lowest Z to highest. // just be careful to sort the avatar IDs along with the positions. -MG pos_map = globalPosToView(positions[i], rotate_map); + if (positions[i].mdV[VZ] == 0.f) + { + pos_map.mV[VZ] = 16000.f; + } std::string avName; gCacheName->getFullName(avatar_ids[i], avName); @@ -438,19 +442,19 @@ void LLNetMap::draw() // Draw dot for autopilot target if (gAgent.getAutoPilot()) { - drawTracking( gAgent.getAutoPilotTargetGlobal(), rotate_map, gTrackColor ); + drawTracking(gAgent.getAutoPilotTargetGlobal(), rotate_map, gTrackColor); } else { LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); if ( LLTracker::TRACKING_AVATAR == tracking_status ) { - drawTracking( LLAvatarTracker::instance().getGlobalPos(), rotate_map, gTrackColor ); + drawTracking(LLAvatarTracker::instance().getGlobalPos(), rotate_map, gTrackColor); } else if ( LLTracker::TRACKING_LANDMARK == tracking_status || LLTracker::TRACKING_LOCATION == tracking_status ) { - drawTracking( LLTracker::getTrackedPositionGlobal(), rotate_map, gTrackColor ); + drawTracking(LLTracker::getTrackedPositionGlobal(), rotate_map, gTrackColor); } } @@ -481,7 +485,7 @@ void LLNetMap::draw() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if( rotate_map ) + if (rotate_map) { gGL.color4fv(gColors.getColor("NetMapFrustum").mV); @@ -529,7 +533,8 @@ void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent) updateMinorDirections(); } -LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos, BOOL rotated ){ +LLVector3 LLNetMap::globalPosToView(const LLVector3d& global_pos, BOOL rotated) +{ LLVector3d relative_pos_global = global_pos - gAgent.getCameraPositionGlobal(); LLVector3 pos_local; pos_local.setVec(relative_pos_global); // convert to floats from doubles @@ -619,7 +624,7 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec { return FALSE; } - LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y , gSavedSettings.getBOOL( "MiniMapRotate" )) ); + LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(viewPosToGlobal(x, y, gSavedSettings.getBOOL( "MiniMapRotate" ))); if( region ) { msg.assign(""); @@ -985,7 +990,7 @@ BOOL LLNetMap::handleHover( S32 x, S32 y, MASK mask ) BOOL LLNetMap::handleDoubleClick( S32 x, S32 y, MASK mask ) { - LLVector3d pos_global = viewPosToGlobal( x, y , gSavedSettings.getBOOL( "MiniMapRotate" ) ); + LLVector3d pos_global = viewPosToGlobal(x, y, gSavedSettings.getBOOL( "MiniMapRotate" )); BOOL new_target = FALSE; if (!LLTracker::isTracking(NULL)) { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6f3b47354..1c3c2c634 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -178,7 +178,7 @@ #include "llweb.h" #include "llwind.h" #include "llworld.h" -#include "llworldmapmessage.h" +#include "llworldmap.h" #include "llxfermanager.h" #include "pipeline.h" #include "llappviewer.h" @@ -1783,6 +1783,8 @@ bool idle_startup() if(!map_server_url.empty()) { gSavedSettings.setString("MapServerURL", map_server_url); + LLWorldMap::gotMapServerURL(true); + llinfos << "Got Map server URL: " << map_server_url << llendl; } // Override grid info with anything sent in the login response @@ -3558,8 +3560,9 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); - msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); - msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); + msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply); + msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply); + msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply); msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply); msg->setHandlerFunc("PickInfoReply", LLPanelPick::processPickInfoReply); diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index a2e2fcfed..1144c5827 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -44,7 +44,7 @@ #include "llstartup.h" // gStartupState #include "llurlsimstring.h" #include "llweb.h" -#include "llworldmapmessage.h" +#include "llworldmap.h" // library includes #include "llsd.h" @@ -243,7 +243,7 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous url_displayp->setName(region_name); // Request a region handle by name - LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, + LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, LLURLDispatcherImpl::regionNameCallback, url, false); // don't teleport @@ -282,7 +282,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); - LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, + LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, LLURLDispatcherImpl::regionHandleCallback, url, teleport); } @@ -401,7 +401,7 @@ public: { url += tokens[i].asString() + "/"; } - LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, + LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, LLURLDispatcherImpl::regionHandleCallback, url, true); // teleport diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8480b9d84..36eaf14fb 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -70,6 +70,8 @@ #include "llappviewer.h" #include "llvosurfacepatch.h" #include "llvowlsky.h" +#include "llworldmapview.h" +#include "llnetmap.h" #include "llrender.h" #include "llfloaterchat.h" #include "llviewerobjectlist.h" @@ -336,7 +338,6 @@ static bool handleUploadBakedTexOldChanged(const LLSD& newvalue) return true; } - static bool handleNumpadControlChanged(const LLSD& newvalue) { if (gKeyboard) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 266757039..7e8810d90 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1001,6 +1001,9 @@ void init_client_menu(LLMenuGL* menu) // menu->append(new LLMenuItemCallGL("Clear Group Cache", LLGroupMgr::debugClearAllGroups)); + + menu->append(new LLMenuItemCheckGL("Use Web Map Tiles", menu_toggle_control, NULL, menu_check_control, (void*)"UseWebMapTiles")); + menu->appendSeparator(); sub_menu = new LLMenuGL("Rendering"); @@ -3543,7 +3546,8 @@ void set_god_level(U8 god_level) LLFloaterDirectory::requestClassifieds(); // God mode changes region visibility - LLWorldMap::getInstance()->reloadItems(true); + 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 9e238ada9..9d6d4d2b0 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -34,85 +34,64 @@ #include "llworldmap.h" -#include "llworldmapmessage.h" +#include "llregionhandle.h" #include "message.h" + + #include "llappviewer.h" // for gPacificDaylightTime -#include "llcachename.h" // for gCacheName +#include "llagent.h" +#include "llmapresponders.h" +#include "llviewercontrol.h" +#include "llfloaterworldmap.h" #include "lltracker.h" -#include "llviewerimage.h" #include "llviewerimagelist.h" +#include "llviewerregion.h" +#include "llregionflags.h" + #include "hippogridmanager.h" +bool LLWorldMap::sGotMapURL = false; +const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes -#include "hippogridmanager.h" - -// 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) + LLUUID id, + S32 extra, S32 extra2) : mName(name), mToolTip(""), mPosGlobal(global_x, global_y, 40.0), mID(id), - mCount(1) -// mSelected(false) -// mColor() + mSelected(FALSE), + mExtra(extra), + mExtra2(extra2) { + mRegionHandle = to_region_handle(mPosGlobal); } -//--------------------------------------------------------------------------- -// LLSimInfo -//--------------------------------------------------------------------------- - -LLSimInfo::LLSimInfo(U64 handle) -: mHandle(handle), +LLSimInfo::LLSimInfo() +: mHandle(0), mName(), mAgentsUpdateTime(0), + mShowAgentLocations(FALSE), mAccess(0x0), mRegionFlags(0x0), - mFirstAgentRequest(true) -// mWaterHeight(0.f) + mWaterHeight(0.f), + mAlpha(-1.f) { } -void LLSimInfo::setLandForSaleImage (LLUUID image_id) -{ - mMapImageID = image_id; - // Fetch the image - if (mMapImageID.notNull()) - { - mOverlayImage = gImageList.getImage(mMapImageID, MIPMAP_TRUE, FALSE); - mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); - } - else - { - mOverlayImage = NULL; - } +LLVector3d LLSimInfo::getGlobalOrigin() const +{ + return from_region_handle(mHandle); } -LLPointer LLSimInfo::getLandForSaleImage () -{ - if (mOverlayImage.isNull() && mMapImageID.notNull()) - { - // Fetch the image if it hasn't been done yet (unlikely but...) - mOverlayImage = gImageList.getImage(mMapImageID, MIPMAP_TRUE, FALSE); - mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); - } - if (!mOverlayImage.isNull()) - { - // Boost the fetch level when we try to access that image - mOverlayImage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); - } - return mOverlayImage; -} - -LLVector3d LLSimInfo::getGlobalPos(const LLVector3& local_pos) const +LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const { LLVector3d pos = from_region_handle(mHandle); pos.mdV[VX] += local_pos.mV[VX]; @@ -121,180 +100,121 @@ LLVector3d LLSimInfo::getGlobalPos(const LLVector3& local_pos) const return pos; } -LLVector3d LLSimInfo::getGlobalOrigin() const -{ - return from_region_handle(mHandle); -} - -void LLSimInfo::clearImage() -{ - if (!mOverlayImage.isNull()) - { - mOverlayImage->setBoostLevel(0); - mOverlayImage = NULL; - } -} - -void LLSimInfo::dropImagePriority() -{ - if (!mOverlayImage.isNull()) - { - mOverlayImage->setBoostLevel(0); - } -} - -// Update the agent count for that region -void LLSimInfo::updateAgentCount(F64 time) -{ - if ((time - mAgentsUpdateTime > AGENTS_UPDATE_TIMER) || mFirstAgentRequest) - { - 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 -// << " " << 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() : - mIsTrackingLocation( false ), - mIsTrackingFound( false ), - mIsInvalidLocation( false ), - mIsTrackingDoubleClick( false ), - mIsTrackingCommit( false ), - mTrackingLocation( 0, 0, 0 ), - mFirstRequest(true) + 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) { - //LL_INFOS("World Map") << "Creating the World Map -> LLWorldMap::LLWorldMap()" << LL_ENDL; - mMapBlockLoaded = new bool[MAP_BLOCK_RES*MAP_BLOCK_RES]; - clearSimFlags(); + for (S32 map=0; map LLWorldMap::~LLWorldMap()" << LL_ENDL; reset(); - delete[] mMapBlockLoaded; + for (S32 map=0; map REQUEST_ITEMS_TIMER) || mFirstRequest || force) + if (mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER) { mRequestTimer.reset(); - 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; + mTelehubs.clear(); + mInfohubs.clear(); + mPGEvents.clear(); + mMatureEvents.clear(); + mAdultEvents.clear(); + mLandForSale.clear(); } - return clear; +// mAgentLocationsMap.clear(); // persists +// mNumAgents.clear(); // persists } + void LLWorldMap::clearImageRefs() { - // We clear the reference to the images we're holding. - // Images hold by the world mipmap first - mWorldMipmap.reset(); - - // Images hold by the region map - LLSimInfo* sim_info = NULL; for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) { - sim_info = it->second; - if (sim_info) + LLSimInfo* info = (*it).second; + if (info->mCurrentImage) { - sim_info->clearImage(); + info->mCurrentImage->setBoostLevel(0); + info->mCurrentImage = NULL; + } + if (info->mOverlayImage) + { + info->mOverlayImage->setBoostLevel(0); + info->mOverlayImage = NULL; } } } @@ -302,25 +222,15 @@ void LLWorldMap::clearImageRefs() // Doesn't clear the already-loaded sim infos, just re-requests them void LLWorldMap::clearSimFlags() { - for (S32 idx=0; idxsecond; + LLSimInfo* sim_info = (*it).second; + if (sim_info) + { + return sim_info; + } } return NULL; } @@ -343,289 +257,816 @@ LLSimInfo* LLWorldMap::simInfoFromName(const std::string& sim_name) LLSimInfo* sim_info = NULL; if (!sim_name.empty()) { - // Iterate through the entire sim info map and compare the name - sim_info_map_t::iterator it; - for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) { - sim_info = it->second; - if (sim_info && sim_info->isName(sim_name) ) + sim_info = (*it).second; + if (sim_info + && (0 == LLStringUtil::compareInsensitive(sim_name, sim_info->mName)) ) { - // break out of loop if success break; } - } - // If we got to the end, we haven't found the sim. Reset the ouput value to NULL. - if (it == mSimInfoMap.end()) sim_info = NULL; + } } return sim_info; } bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string & outSimName ) { - LLSimInfo* sim_info = simInfoFromPosGlobal(pos_global); + bool gotSimName = true; - if (sim_info) + U64 handle = to_region_handle(pos_global); + + sim_info_map_t::iterator it = mSimInfoMap.find(handle); + if (it != mSimInfoMap.end()) { - outSimName = sim_info->getName(); + LLSimInfo* info = (*it).second; + outSimName = info->mName; } else { + gotSimName = false; outSimName = "(unknown region)"; } - return (sim_info != NULL); + return gotSimName; } -void LLWorldMap::reloadItems(bool force) +void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) { - //LL_INFOS("World Map") << "LLWorldMap::reloadItems()" << LL_ENDL; - if (clearItems(force)) + mCurrentMap = layer; + if (!mMapLoaded[layer] || request_layer) { - 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); + 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(); } -// 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, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags) +void LLWorldMap::sendItemRequest(U32 type, U64 handle) { - // This region doesn't exist - if (accesscode == 255) + 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"); + + if (!url.empty()) { - // 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)) - { - LLWorldMap::getInstance()->setTrackingInvalid(); - } - // return failure to insert - return false; + llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl; + LLHTTPClient::post(url, body, new LLMapLayerResponder()); } 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) - { - siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); - } - siminfo->setName(name); - siminfo->setAccess(accesscode); - siminfo->setRegionFlags(region_flags); - // siminfo->setWaterHeight((F32) water_height); - siminfo->setLandForSaleImage(image_id); + llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl; + LLMessageSystem* msg = gMessageSystem; + S32 layer = mCurrentMap; - // 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)) + // 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_EstateID, 0); // Filled in on sim + msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim + gAgent.sendReliableMessage(); + + if (mRequestLandForSale) { - if (siminfo->isDown()) + 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; + + U32 agent_flags; + msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); + + if (agent_flags != (U32)LLWorldMap::getInstance()->mCurrentMap) + { + 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(); + +// 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 = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE); +// } + + gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); + new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); + + new_layer.LayerExtents.mLeft = left; + new_layer.LayerExtents.mRight = right; + 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()->mMapLoaded[agent_flags] = TRUE; + if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); +} + +// public static +bool LLWorldMap::useWebMapTiles() +{ + return gSavedSettings.getBOOL("UseWebMapTiles") && + (( gHippoGridManager->getConnectedGrid()->isSecondLife() || sGotMapURL) && LLWorldMap::getInstance()->mCurrentMap == 0); +} + +// public static +LLPointer LLWorldMap::loadObjectsTile(U32 grid_x, U32 grid_y) +{ + // Get the grid coordinates + std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", 1, grid_x, grid_y); + + LLPointer img = gImageList.getImageFromUrl(imageurl); + img->setBoostLevel(LLViewerImageBoostLevel::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) + { + llwarns << "Invalid map image type returned! " << agent_flags << llendl; + return; + } + + 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); + + U32 x_meters = x_regions * REGION_WIDTH_UNITS; + U32 y_meters = y_regions * REGION_WIDTH_UNITS; + + U64 handle = to_region_handle(x_meters, y_meters); + + if (accesscode == 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's no available - LLWorldMap::getInstance()->setTrackingInvalid(); + // 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; + +// llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl; + + LLSimInfo* siminfo = new LLSimInfo(); + sim_info_map_t::iterator iter = LLWorldMap::getInstance()->mSimInfoMap.find(handle); + if (iter != LLWorldMap::getInstance()->mSimInfoMap.end()) + { + LLSimInfo* oldinfo = iter->second; + for (S32 image=0; imagemMapImageID[image] = oldinfo->mMapImageID[image]; + } + delete oldinfo; + } + LLWorldMap::getInstance()->mSimInfoMap[handle] = siminfo; + + siminfo->mHandle = handle; + siminfo->mName.assign( name ); + siminfo->mAccess = accesscode; + siminfo->mRegionFlags = region_flags; + siminfo->mWaterHeight = (F32) water_height; + siminfo->mMapImageID[agent_flags] = image_id; + +#ifdef IMMEDIATE_IMAGE_LOAD + if (use_web_map_tiles) + { + siminfo->mCurrentImage = loadObjectsTile((U32)x_regions, (U32)y_regions); } else { - // We were tracking this location, and it does exist and is available - LLWorldMap::getInstance()->setTrackingValid(); + siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); } - } - // 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); - */ + gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); + siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); +#endif - // extra2 specifies whether this is an infohub or a telehub. - if (extra2) + if (siminfo->mMapImageID[2].notNull()) { - siminfo->insertInfoHub(new_item); +#ifdef IMMEDIATE_IMAGE_LOAD + siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE); +#endif } else { - siminfo->insertTeleHub(new_item); + siminfo->mOverlayImage = NULL; } - break; - } - 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 - // it's daylight savings time there. - timep = utc_to_pacific_time(extra, gPacificDaylightTime); - S32 display_hour = timep->tm_hour % 12; - if (display_hour == 0) display_hour = 12; + 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->mAccess == SIM_ACCESS_DOWN) + { + // 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(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; - std::string tooltip = llformat( "%d:%02d %s", - display_hour, - timep->tm_min, - (timep->tm_hour < 12 ? "AM" : "PM") ); - new_item.setTooltip(tooltip); + LLWorldMap::getInstance()->mSLURLCallback = NULL; + LLWorldMap::getInstance()->mSLURLRegionName.clear(); + LLWorldMap::getInstance()->mSLURLRegionHandle = 0; - // HACK: store Z in extra2 - new_item.setElevation((F64)extra2); - if (type == MAP_ITEM_PG_EVENT) - { - siminfo->insertPGEvent(new_item); + callback(handle, LLWorldMap::getInstance()->mSLURL, image_id, LLWorldMap::getInstance()->mSLURLTeleport); } - 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 + if(LLAgent::lure_show) { - std::string tooltip = llformat("%d sq. m. %s%d", - extra, - gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), - extra2); - new_item.setTooltip(tooltip); - if (type == MAP_ITEM_LAND_FOR_SALE) + if((x_regions == LLAgent::lure_global_x) && (y_regions == LLAgent::lure_global_y)) { - siminfo->insertLandForSale(new_item); + gAgent.onFoundLureDestination(); } - 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 - { - /* - // yes, we like to know who it is who's there! - std::string avFullName; - - gCacheName->getFullName(uuid, avFullName); - - LL_INFOS("World Map") << "New Location " << avFullName << LL_ENDL; - // - */ - if (extra > 0) - { - new_item.setCount(extra); - siminfo->insertAgentLocation(new_item); - } - break; - } - default: - break; } - return true; + + if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); + gFloaterWorldMap->updateSims(found_null_sim); } -bool LLWorldMap::isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1) +// public static +void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) { - if (!mIsTrackingLocation) - return false; - return ((mTrackingLocation[0] >= x0) && (mTrackingLocation[0] < x1) && (mTrackingLocation[1] >= y0) && (mTrackingLocation[1] < y1)); -} + U32 type; + msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type); -// Drop priority of all images being fetched by the map -void LLWorldMap::dropImagePriorities() -{ - // Drop the download of tiles priority to nil - mWorldMipmap.dropBoostLevels(); - // Same for the "land for sale" tiles per region - for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + S32 num_blocks = msg->getNumberOfBlocks("Data"); + + for (S32 block=0; blocksecond; - info->dropImagePriority(); - } -} + U32 X, Y; + std::string name; + S32 extra, extra2; + LLUUID uuid; + msg->getU32Fast(_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); -// 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) -{ - // Convert those boundaries to the corresponding (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) block coordinates - x0 = x0 / MAP_BLOCK_SIZE; - x1 = x1 / MAP_BLOCK_SIZE; - y0 = y0 / MAP_BLOCK_SIZE; - y1 = y1 / MAP_BLOCK_SIZE; + 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.mRegionHandle); - // 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) + switch (type) { - S32 offset = block_x | (block_y * MAP_BLOCK_RES); - if (!mMapBlockLoaded[offset]) + case MAP_ITEM_TELEHUB: // telehubs { - //LL_INFOS("World Map") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL; - LLWorldMapMessage::getInstance()->sendMapBlockRequest(block_x * MAP_BLOCK_SIZE, block_y * MAP_BLOCK_SIZE, (block_x * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1, (block_y * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1); - mMapBlockLoaded[offset] = true; + // 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: + { + struct tm* timep; + // Convert to Pacific, based on server's opinion of whether + // it's daylight savings time there. + timep = utc_to_pacific_time(extra, gPacificDaylightTime); + + S32 display_hour = timep->tm_hour % 12; + if (display_hour == 0) display_hour = 12; + + new_item.mToolTip = llformat( "%d:%02d %s", + display_hour, + timep->tm_min, + (timep->tm_hour < 12 ? "AM" : "PM") ); + + // HACK: store Z in extra2 + new_item.mPosGlobal.mdV[VZ] = (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 + { + new_item.mToolTip = 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); + } + 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.mPosGlobal.mdV[0] << ", " << new_item.mPosGlobal.mdV[1] << llendl; + break; + } +// llinfos << "New Location " << new_item.mName << llendl; + + item_info_list_t& agentcounts = LLWorldMap::getInstance()->mAgentLocationsMap[new_item.mRegionHandle]; + + // 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.mName == new_item.mName) + { + 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() { - 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) + 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->mName + << " " << (S32)info->mAccess + << " " << std::hex << info->mRegionFlags << std::dec + << " " << info->mWaterHeight + //<< " " << info->mTelehubName + //<< " " << info->mTelehubPosition + << llendl; + + if (info->mCurrentImage) { - info->dump(); + llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel() + << " fullwidth " << info->mCurrentImage->getWidth(0) + << " fullheight " << info->mCurrentImage->getHeight(0) + << " maxvirt " << info->mCurrentImage->mMaxVirtualSize + << " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel() + << llendl; } } } + +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]) + { + 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++) + { + memset(&mTelehubCoverageMap[x_start + y_index * mNeighborMapWidth], 0xff, sizeof(U8) * x_span); + } + } + } + + 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]; + }*/ +} diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index ffa7b2443..b7089f348 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -33,245 +33,207 @@ #ifndef LL_LLWORLDMAP_H #define LL_LLWORLDMAP_H -#include "llworldmipmap.h" +#include +#include +#include +#include "v3math.h" #include "v3dmath.h" +#include "llframetimer.h" +#include "llmapimagetype.h" #include "lluuid.h" #include "llmemory.h" -#include "llviewerregion.h" #include "llviewerimage.h" +#include "lleventinfo.h" +#include "v3color.h" + +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); + LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id, S32 extra = 0, S32 extra2 = 0); - // Setters - void setTooltip(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; } - 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; // 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 + std::string mName; + std::string mToolTip; + LLVector3d mPosGlobal; + LLUUID mID; + BOOL mSelected; + S32 mExtra; + S32 mExtra2; + U64 mRegionHandle; }; -// 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. +#define MAP_SIM_IMAGE_TYPES 3 +// 0 - Prim +// 1 - Terrain Only +// 2 - Overlay: Land For Sale + class LLSimInfo { public: - LLSimInfo(U64 handle); + LLSimInfo(); - // Convert local region coordinates into world coordinates - LLVector3d getGlobalPos(const LLVector3& local_pos) const; + LLVector3d getGlobalPos(LLVector3 local_pos) const; // Get the world coordinates of the SW corner of that region LLVector3d getGlobalOrigin() 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 - void updateAgentCount(F64 time); // Send an item request for agent count on that region if time's up +public: + U64 mHandle; + std::string mName; - // Setters - void setName(std::string& name) { mName = name; } - void setAccess (U32 accesscode) { mAccess = accesscode; } - void setRegionFlags (U32 region_flags) { mRegionFlags = region_flags; } - void setLandForSaleImage (LLUUID image_id); -// void setWaterHeight (F32 water_height) { mWaterHeight = water_height; } + F64 mAgentsUpdateTime; + BOOL mShowAgentLocations; // are agents visible? - // Accessors - const std::string getName() const { return mName; } - const std::string getFlagsString() const { return LLViewerRegion::regionFlagsToString(mRegionFlags); } - const std::string getAccessString() const { return LLViewerRegion::accessToString((U8)mAccess); } - const std::string getShortAccessString() const { return LLViewerRegion::accessToShortString((U8)mAccess); } + U8 mAccess; + U32 mRegionFlags; + F32 mWaterHeight; - const S32 getAgentCount() const; // Compute the total agents count - LLPointer getLandForSaleImage(); // Get the overlay image, fetch it if necessary - // - //Added this so I could get map images on opensim. - const LLUUID getMapImageID() const { return mMapImageID; } + F32 mAlpha; - bool isName(const std::string& name) const; - bool isDown() { return (mAccess == SIM_ACCESS_DOWN); } - bool isPG() { return (mAccess <= SIM_ACCESS_PG); } + // Image ID for the current overlay mode. + LLUUID mMapImageID[MAP_SIM_IMAGE_TYPES]; - // 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; // This is a hash of the X and Y world coordinates of the SW corner of the sim - std::string mName; // Region name - - F64 mAgentsUpdateTime; // Time stamp giving the last time the agents information was requested for that region - bool mFirstAgentRequest; // Init agent request flag - - U32 mAccess; // Down/up and maturity rating of the region - U32 mRegionFlags; // Tell us if the siminfo has been received (if non 0) and what kind of region it is (Sandbox, allow damage) - // Currently not used but might prove useful one day so we comment out -// F32 mWaterHeight; // Water height on the region (not actively used) - - // Handling the "land for sale / land for auction" overlay image - - LLUUID mMapImageID; // Image ID of the overlay image - LLPointer mOverlayImage; // Reference to the overlay image - - // 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 + // Hold a reference to the currently displayed image. + LLPointer mCurrentImage; + LLPointer mOverlayImage; +}; + +#define MAP_BLOCK_RES 256 + +struct LLWorldMapLayer +{ + BOOL LayerDefined; + LLPointer LayerImage; + LLUUID LayerImageID; + LLRect LayerExtents; + + 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 { public: + typedef void(*url_callback_t)(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport); + LLWorldMap(); ~LLWorldMap(); - // Clear all: list of region info, tiles, blocks and items + // clears the list void reset(); - 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...) + // clear the visible items + void eraseItems(); - // Region Map access - typedef std::map sim_info_map_t; - const LLWorldMap::sim_info_map_t& getRegionMap() const { return mSimInfoMap; } - void updateRegions(S32 x0, S32 y0, S32 x1, S32 y1); // Requests region info for a rectangle of regions (in grid coordinates) + // Removes references to cached images + void clearImageRefs(); - // 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, std::string& name, LLUUID& uuid, 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); + // Clears the flags indicating that we've received sim infos + // Causes a re-request of the sim info without erasing extisting info + void clearSimFlags(); - // 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. + // Returns simulator information, or NULL if out of range 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 from a global position, returns true if found + // Gets simulator name for a global position, returns true if it was found bool simNameFromPosGlobal(const LLVector3d& pos_global, std::string& outSimName ); - // Debug only - void dump(); // Print the world info to the standard output + // Sets the current layer + void setCurrentLayer(S32 layer, bool request_layer = false); - // Track handling - void cancelTracking() { mIsTrackingLocation = false; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = 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); - 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; } + static void processMapLayerReply(LLMessageSystem*, void**); + static void processMapBlockReply(LLMessageSystem*, void**); + static void processMapItemReply(LLMessageSystem*, void**); - 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); + static void gotMapServerURL(bool flag) { sGotMapURL = flag; } + static bool useWebMapTiles(); + static LLPointer loadObjectsTile(U32 grid_x, U32 grid_y); - LLVector3d getTrackedPositionGlobal() const { return mTrackingLocation; } + void dump(); - // 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); } + // 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); + + // build coverage maps for telehub region visualization + void updateTelehubCoverage(); + BOOL coveredByTelehub(LLSimInfo* infop); + + // Bounds of the world, in meters + U32 getWorldWidth() const; + U32 getWorldHeight() const; +public: + // Map from region-handle to simulator info + typedef std::map sim_info_map_t; + sim_info_map_t mSimInfoMap; + + 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; private: - bool clearItems(bool force = false); // Clears the item lists - void clearSimFlags(); // Clears the block flags indicating that we've already requested region infos + LLTimer mRequestTimer; - // Create a region record corresponding to the handle, insert it in the region map and returns a pointer - LLSimInfo* createSimInfoFromHandle(const U64 handle); + // search for named region for url processing + std::string mSLURLRegionName; + U64 mSLURLRegionHandle; + std::string mSLURL; + url_callback_t mSLURLCallback; + bool mSLURLTeleport; - // Map from region-handle to region info - sim_info_map_t mSimInfoMap; - - // Holds the tiled mipmap of the world. This is the structure that contains the images used for rendering. - 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; // Telling us if the block of regions has been requested or not - - // 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; - bool mFirstRequest; + static bool sGotMapURL; }; #endif diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp deleted file mode 100644 index 0777a77e9..000000000 --- a/indra/newview/llworldmapmessage.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @file llworldmapmessage.cpp - * @brief Handling of the messages to the DB made by and for the world map. - * - * $LicenseInfo:firstyear=2003&license=viewergpl$ - * - * Copyright (c) 2003-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llworldmapmessage.h" - -#include "llworldmap.h" -#include "llagent.h" -#include "llfloaterworldmap.h" - -#include "llviewernetwork.h" //for isInProductionGrid() -#include "hippogridmanager.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 region data - 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); -} - -void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) -{ - //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_FLAG; - 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); - - // There's only one flag that we ever use here - if (agent_flags != LAYER_FLAG - && gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) - { - 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); - - U32 x_world = (U32)(x_regions) * REGION_WIDTH_UNITS; - U32 y_world = (U32)(y_regions) * REGION_WIDTH_UNITS; - - // Insert that region in the world map, if failure, flag it as a "null_sim" - if (!(LLWorldMap::getInstance()->insertRegion(x_world, y_world, 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 - if(LLWorldMapMessage::getInstance()->mSLURLCallback != 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)) - { - url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; - - LLWorldMapMessage::getInstance()->mSLURLCallback = NULL; - LLWorldMapMessage::getInstance()->mSLURLRegionName.clear(); - LLWorldMapMessage::getInstance()->mSLURLRegionHandle = 0; - - callback(handle, LLWorldMapMessage::getInstance()->mSLURL, image_id, LLWorldMapMessage::getInstance()->mSLURLTeleport); - } - } - // - if(LLAgent::lure_show) - { - if((x_regions == LLAgent::lure_global_x) && (y_regions == LLAgent::lure_global_y)) - { - 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); - } -} - diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h deleted file mode 100644 index 96434661b..000000000 --- a/indra/newview/llworldmapmessage.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file llworldmapmessage.h - * @brief Handling of the messages to the DB made by and for the world map. - * - * $LicenseInfo:firstyear=2003&license=viewergpl$ - * - * Copyright (c) 2003-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/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 void(*url_callback_t)(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport); - - 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 = false); - - // 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); - -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 ed3770c9a..fcb2424c7 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -34,11 +34,18 @@ #include "llworldmapview.h" +#include "indra_constants.h" +#include "llui.h" +#include "llmath.h" // clampf() +#include "llregionhandle.h" +#include "lleventflags.h" #include "llrender.h" + #include "llagent.h" #include "llcallingcard.h" #include "llcolorscheme.h" #include "llviewercontrol.h" +#include "llcylinder.h" #include "llfloaterdirectory.h" #include "llfloatermap.h" #include "llfloaterworldmap.h" @@ -49,8 +56,13 @@ #include "llviewercamera.h" #include "llviewerimage.h" #include "llviewerimagelist.h" +#include "llviewermenu.h" +#include "llviewerparceloverlay.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llworldmap.h" +#include "lltexturefetch.h" +#include "llappviewer.h" // Only for constants! #include "lltrans.h" #include "llglheaders.h" @@ -59,14 +71,6 @@ #include "rlvhandler.h" // [/RLVa:KB] -// Basically a C++ implementation of the OCEAN_COLOR defined in mapstitcher.py -// Please ensure consistency between those 2 files (TODO: would be better to get that color from an asset source...) -// # Constants -// OCEAN_COLOR = "#1D475F" -const F32 OCEAN_RED = (F32)(0x1D)/255.f; -const F32 OCEAN_GREEN = (F32)(0x47)/255.f; -const F32 OCEAN_BLUE = (F32)(0x5F)/255.f; - const F32 GODLY_TELEPORT_HEIGHT = 200.f; const S32 SCROLL_HINT_WIDTH = 65; const F32 BIG_DOT_RADIUS = 5.f; @@ -93,24 +97,27 @@ 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; F32 LLWorldMapView::sTargetPanY = 0.f; S32 LLWorldMapView::sTrackingArrowX = 0; S32 LLWorldMapView::sTrackingArrowY = 0; -bool LLWorldMapView::sVisibleTilesLoaded = false; +F32 LLWorldMapView::sPixelsPerMeter = 1.f; F32 LLWorldMapView::sMapScale = 128.f; +F32 CONE_SIZE = 0.6f; std::map LLWorldMapView::sStringsMap; -// Fetch and draw info thresholds -const F32 DRAW_TEXT_THRESHOLD = 96.f; // Don't draw text under that resolution value (res = width region in meters) -const S32 DRAW_SIMINFO_THRESHOLD = 3; // Max level for which we load or display sim level information (level in LLWorldMipmap sense) -const S32 DRAW_LANDFORSALE_THRESHOLD = 2; // Max level for which we load or display land for sale picture data (level in LLWorldMipmap sense) +#define SIM_NULL_MAP_SCALE 1 // width in pixels, where we start drawing "null" sims +#define SIM_MAP_AGENT_SCALE 2 // width in pixels, where we start drawing agents +#define SIM_MAP_SCALE 1 // width in pixels, where we start drawing sim tiles + +// Updates for agent locations. +#define AGENTS_UPDATE_TIME 60.0 // in seconds -// When on, draw an outline for each mipmap tile gotten from S3 -#define DEBUG_DRAW_TILE 0 void LLWorldMapView::initClass() @@ -167,7 +174,7 @@ void LLWorldMapView::cleanupClass() LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) : LLPanel(name, rect, BORDER_NO), - mBackgroundColor( LLColor4( OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f ) ), + mBackgroundColor( LLColor4( 4.f/255.f, 4.f/255.f, 75.f/255.f, 1.f ) ), mItemPicked(FALSE), mPanning( FALSE ), mMouseDownPanX( 0 ), @@ -176,8 +183,7 @@ LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) mMouseDownY( 0 ), mSelectIDStart(0) { - //LL_INFOS("World Map") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL; - + sPixelsPerMeter = sMapScale / REGION_WIDTH_METERS; clearLastClick(); const S32 DIR_WIDTH = 10; @@ -225,7 +231,6 @@ LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) LLWorldMapView::~LLWorldMapView() { - //LL_INFOS("World Map") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL; cleanupTextures(); } @@ -244,7 +249,7 @@ void LLWorldMapView::setScale( F32 scale ) F32 old_scale = sMapScale; sMapScale = scale; - if (sMapScale <= 0.f) + if (sMapScale == 0.f) { sMapScale = 0.1f; } @@ -254,7 +259,8 @@ void LLWorldMapView::setScale( F32 scale ) sPanY *= ratio; sTargetPanX = sPanX; sTargetPanY = sPanY; - sVisibleTilesLoaded = false; + + sPixelsPerMeter = sMapScale / REGION_WIDTH_METERS; } } @@ -266,7 +272,6 @@ void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y ) sPanY += delta_y; sTargetPanX = sPanX; sTargetPanY = sPanY; - sVisibleTilesLoaded = false; } @@ -280,22 +285,18 @@ void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap ) sPanX = sTargetPanX; sPanY = sTargetPanY; } - sVisibleTilesLoaded = false; } -bool LLWorldMapView::showRegionInfo() -{ - return (LLWorldMipmap::scaleToLevel(sMapScale) <= DRAW_SIMINFO_THRESHOLD ? true : false); -} /////////////////////////////////////////////////////////////////////////////////// // HELPERS BOOL is_agent_in_region(LLViewerRegion* region, LLSimInfo* info) { - return (region && info && info->isName(region->getName())); + return ((region && info) && (info->mName == region->getName())); } + /////////////////////////////////////////////////////////////////////////////////// void LLWorldMapView::draw() @@ -316,10 +317,6 @@ void LLWorldMapView::draw() const F32 half_height = F32(height) / 2.0f; LLVector3d camera_global = gAgent.getCameraPositionGlobal(); - S32 level = LLWorldMipmap::scaleToLevel(sMapScale); - - //LL_INFOS("World Map") << "Entering LLWorldMapView::draw(): scale = " << sMapScale << ", w = " << width << ", h = " << height << ", x = " << sTargetPanX << ", y = " << sTargetPanY << ", camera = " << camera_global << LL_ENDL; - LLLocalClipRect clip(getLocalRect()); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -336,58 +333,317 @@ void LLWorldMapView::draw() } gGL.flush(); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); + gGL.setSceneBlendType(LLRender::BT_ALPHA); -#if 1 - // Draw the image tiles - drawMipmap(width, height); - gGL.flush(); + F32 layer_alpha = 1.f; - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.setColorMask(true, true); - - // Draw per sim overlayed information (names, mature, offline...) - for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); - it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + // Draw one image per layer + for (U32 layer_idx=0; layer_idxmMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx) { - U64 handle = it->first; - LLSimInfo* info = it->second; + if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined) + { + continue; + } + LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx]; + LLViewerImage *current_image = layer->LayerImage; - LLVector3d origin_global = from_region_handle(handle); + if (current_image->isMissingAsset()) + { + 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); + + // 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); + + // 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 + pix_height; + F32 right = left + pix_width; + F32 pixel_area = pix_width*pix_height; + // discard layers that are outside the rectangle + // and discard small layers + if (top < 0.f || + bottom > height || + right < 0.f || + left > width || + (pixel_area < 4*4)) + { + current_image->setBoostLevel(0); + continue; + } + + current_image->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP_VISIBLE); + current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY])); + + if (!current_image->getHasGLTexture()) + { + continue; // better to draw nothing than the default image + } + +// LLTextureView::addDebugImage(current_image); + + // Draw using the texture. If we don't clamp we get artifact at + // the edge. + gGL.getTexUnit(0)->bind(current_image); + + // Draw map image into RGB + //gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gGL.flush(); + gGL.setColorMask(true, false); + gGL.color4f(1.f, 1.f, 1.f, layer_alpha); + + gGL.begin(LLRender::QUADS); + gGL.texCoord2f(0.0f, 1.0f); + gGL.vertex3f(left, top, -1.0f); + gGL.texCoord2f(0.0f, 0.0f); + gGL.vertex3f(left, bottom, -1.0f); + gGL.texCoord2f(1.0f, 0.0f); + gGL.vertex3f(right, bottom, -1.0f); + 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.flush(); + gGL.setColorMask(false, true); + gGL.color4f(1.f, 1.f, 1.f, 1.f); + + gGL.begin(LLRender::QUADS); + gGL.texCoord2f(0.0f, 1.0f); + gGL.vertex2f(left, top); + gGL.texCoord2f(0.0f, 0.0f); + gGL.vertex2f(left, bottom); + gGL.texCoord2f(1.0f, 0.0f); + gGL.vertex2f(right, bottom); + gGL.texCoord2f(1.0f, 1.0f); + gGL.vertex2f(right, top); + gGL.end(); + } + + gGL.flush(); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.setColorMask(true, true); + + // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code? + F32 sim_alpha = 1.f; + + // Draw one image per region, centered on the camera position. + 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; + + bool use_web_map_tiles = LLWorldMap::useWebMapTiles(); + + for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin(); + it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + { + U64 handle = (*it).first; + LLSimInfo* info = (*it).second; + + LLViewerImage* simimage = info->mCurrentImage; + LLViewerImage* 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 = gAgent.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; - // 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) ) + // 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 ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) > 0) { - // Drop the "land for sale" fetching priority since it's outside the view rectangle - info->dropImagePriority(); + map_scale_cutoff = SIM_NULL_MAP_SCALE; + } + + info->mShowAgentLocations = (sMapScale >= SIM_MAP_AGENT_SCALE); + + bool sim_visible = + (sMapScale >= map_scale_cutoff) && + (simimage != NULL) && + (simimage->getHasGLTexture()); + + if (sim_visible) + { + // Fade in + if (info->mAlpha < 0.0f) + info->mAlpha = 1.f; // don't fade initially + else + info->mAlpha = lerp(info->mAlpha, 1.f, LLCriticalDamp::getInterpolant(0.15f)); + } + else + { + // Fade out + if (info->mAlpha < 0.0f) + info->mAlpha = 0.f; // don't fade initially + else + info->mAlpha = lerp(info->mAlpha, 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; } - // This list is used by other methods to know which regions are indeed displayed on screen - mVisibleRegions.push_back(handle); - - // Update the agent count for that region if we're not too zoomed out already - if (level <= DRAW_SIMINFO_THRESHOLD) + if (info->mCurrentImage.isNull()) { - info->updateAgentCount(current_time); + 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) + { + 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 = gImageList.getImage(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); + } + 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 = gImageList.getImage(info->mMapImageID[2], MIPMAP_TRUE, FALSE); + info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); + overlayimage = info->mOverlayImage; + gGL.getTexUnit(0)->bind(overlayimage); + } + } + + mVisibleRegions.push_back(handle); + // See if the agents need updating + if (current_time - info->mAgentsUpdateTime > AGENTS_UPDATE_TIME) + { + LLWorldMap::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, info->mHandle); + info->mAgentsUpdateTime = current_time; } - if (info->isDown()) + // Bias the priority escalation for images nearer + LLVector3d center_global = origin_global; + center_global.mdV[VX] += 128.0; + center_global.mdV[VY] += 128.0; + + S32 draw_size = llround(sMapScale); + if (simimage != NULL) + { + simimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); + simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); + } + + if (overlayimage != NULL) + { + overlayimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); + overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); + } + +// LLTextureView::addDebugImage(simimage); + + if (sim_visible && info->mAlpha > 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->mAlpha; + gGL.color4f(1.f, 1.0f, 1.0f, alpha); + + gGL.begin(LLRender::QUADS); + gGL.texCoord2f(0.f, 1.f); + gGL.vertex3f(left, top, 0.f); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex3f(left, bottom, 0.f); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3f(right, bottom, 0.f); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex3f(right, top, 0.f); + gGL.end(); + + if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->getHasGLTexture()) + { + 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 ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) == 0) + { + // draw an alpha of 1 where the sims are visible (except NULL sims) + gGL.flush(); + 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.flush(); + gGL.setColorMask(true, true); + } + } + + if (info->mAccess == SIM_ACCESS_DOWN) { // Draw a transparent red square over down sims gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); @@ -406,9 +662,11 @@ void LLWorldMapView::draw() // it's too complicated to get all the rules straight and will only // cause confusion. /********************** - else if (!info->isPG() && gAgent.isTeen()) + // 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()) { - // 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); @@ -421,103 +679,71 @@ void LLWorldMapView::draw() gGL.end(); } **********************/ - else if (gSavedSettings.getBOOL("MapShowLandForSale") && (level <= DRAW_LANDFORSALE_THRESHOLD)) + // Draw the region name in the lower left corner + LLFontGL* font = LLFontGL::getFontSansSerifSmall(); + + std::string mesg; + if (sMapScale < sThresholdA) { - // Draw the overlay image "Land for Sale / Land for Auction" - LLViewerImage* 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->getHasGLTexture()) - { - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); - 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 (sMapScale < sThresholdB) + { + // mesg = llformat( info->mAgents); } else - { - // If we're not displaying the "land for sale", drop its fetching priority - info->dropImagePriority(); - } - - // 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(), + // LLViewerRegion::accessToShortString(info->mAccess).c_str() ); // [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); } - else if (info->isDown()) // [/RLVa:KB] - //if (info->isDown()) + else if (info->mAccess == SIM_ACCESS_DOWN) { - mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); + mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str()); } - // - else if (gSavedSettings.getBOOL("MapShowAgentCount") && gSavedSettings.getBOOL("MapShowPeople")) - { - // Display the agent count after the region name - S32 agent_count = info->getAgentCount(); - LLViewerRegion *region = gAgent.getRegion(); - - if (region && region->getHandle() == handle) - { - ++agent_count; // Bump by 1 if we're in this region - } - - if (agent_count > 0) - { - std::string count = llformat("%d %s", agent_count, agent_count > 1 ? "avatars" : "avatar"); - font->renderUTF8( - count, 0, - llfloor(left + 3), - llfloor(bottom + 20), - LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::DROP_SHADOW); - - } - mesg = info->getName() + " (" + info->getShortAccessString() +")"; - } - // else { - // - mesg = info->getName() + " (" + info->getShortAccessString() +")"; + mesg = info->mName; } + } + if (!mesg.empty()) { font->renderUTF8( mesg, 0, - llfloor(left + 3), llfloor(bottom + 2), + llfloor(left + 3), + llfloor(bottom + 2), + LLColor4::white, + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::DROP_SHADOW); + + // If map texture is still loading, + // display "Loading" placeholder text. + if ((simimage != NULL) && + simimage->getDiscardLevel() != 1 && + simimage->getDiscardLevel() != 0) + { + font->renderUTF8( + sStringsMap["loading"], 0, + llfloor(left + 18), + llfloor(top - 25), LLColor4::white, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::DROP_SHADOW); } } } -#endif + // #endif used to be here -#if 1 + // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code? // Draw background rectangle LLGLSUIDefault gls_ui; { @@ -531,25 +757,45 @@ void LLWorldMapView::draw() gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setSceneBlendType(LLRender::BT_ALPHA); - // Draw item infos if we're not zoomed out too much and there's something to draw - if ((level <= DRAW_SIMINFO_THRESHOLD) && (gSavedSettings.getBOOL("MapShowInfohubs") || - gSavedSettings.getBOOL("MapShowTelehubs") || - gSavedSettings.getBOOL("MapShowLandForSale") || - gSavedSettings.getBOOL("MapShowEvents") || - gSavedSettings.getBOOL("ShowMatureEvents") || - gSavedSettings.getBOOL("ShowAdultEvents"))) + // Infohubs + if (gSavedSettings.getBOOL("MapShowInfohubs")) //(sMapScale >= sThresholdB) { - drawItems(); + drawGenericItems(LLWorldMap::getInstance()->mInfohubs, sInfohubImage); } - // Draw the Home location (always) + // Telehubs + if (gSavedSettings.getBOOL("MapShowTelehubs")) //(sMapScale >= sThresholdB) + { + drawGenericItems(LLWorldMap::getInstance()->mTelehubs, sTelehubImage); + } + + // Home Sweet Home LLVector3d home; if (gAgent.getHomePosGlobal(&home)) { drawImage(home, sHomeImage); } - // Draw the current agent after all that other stuff. + if (gSavedSettings.getBOOL("MapShowLandForSale")) + { + 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); + } + } + + if (gSavedSettings.getBOOL("MapShowPGEvents") || + gSavedSettings.getBOOL("MapShowMatureEvents") || + gSavedSettings.getBOOL("MapShowAdultEvents") ) + { + drawEvents(); + } + + // Now draw your avatar after all that other stuff. LLVector3d pos_global = gAgent.getPositionGlobal(); drawImage(pos_global, sAvatarYouImage); @@ -564,12 +810,12 @@ void LLWorldMapView::draw() llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking } - // Draw the current agent viewing angle + // Show your viewing angle drawFrustum(); // Draw icons for the avatars in each region. - // Drawn this after the current agent avatar so one can see nearby people - if (gSavedSettings.getBOOL("MapShowPeople") && (level <= DRAW_SIMINFO_THRESHOLD)) + // Drawn after your avatar so you can see nearby people. + if (gSavedSettings.getBOOL("MapShowPeople")) { drawAgents(); } @@ -591,24 +837,23 @@ void LLWorldMapView::draw() drawTracking( pos_global, gTrackColor, TRUE, LLTracker::getLabel(), LLTracker::getToolTip() ); } } - else if (LLWorldMap::getInstance()->isTracking()) + else if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation) { - if (LLWorldMap::getInstance()->isTrackingInvalidLocation()) + if (LLWorldMap::getInstance()->mInvalidLocation) { - // We know this location to be invalid, draw a blue circle + // We know this location to be invalid LLColor4 loading_color(0.0, 0.5, 1.0, 1.0); - drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, "Invalid Location", ""); + drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Invalid Location", ""); } 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); LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0); - drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, "Loading...", ""); + drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Loading...", ""); } } -#endif + // #endif used to be here // turn off the scissor LLGLDisable no_scissor(GL_SCISSOR_TEST); @@ -617,7 +862,6 @@ void LLWorldMapView::draw() LLView::draw(); - // Get sim info for all sims in view updateVisibleBlocks(); } // end draw() @@ -628,182 +872,36 @@ void LLWorldMapView::setVisible(BOOL visible) LLPanel::setVisible(visible); if (!visible) { - // Drop the download of tiles and images priority to nil if we hide the map - LLWorldMap::getInstance()->dropImagePriorities(); - } -} - -void LLWorldMapView::drawMipmap(S32 width, S32 height) -{ - // Compute the level of the mipmap to use for the current scale level - S32 level = LLWorldMipmap::scaleToLevel(sMapScale); - // Set the tile boost level so that unused tiles get to 0 - LLWorldMap::getInstance()->equalizeBoostLevels(); - - // Render whatever we already have loaded if we haven't the current level - // complete and use it as a background (scaled up or scaled down) - if (!sVisibleTilesLoaded) + for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++) { - // Note: the (load = false) parameter avoids missing tiles to be fetched (i.e. we render what we have, no more) - // Check all the lower res levels and render them in reverse order (worse to best) - // We need to traverse all the levels as the user can zoom in very fast - for (S32 l = LLWorldMipmap::MAP_LEVELS; l > level; l--) + for (U32 layer_idx=0; layer_idxmMapLayers[map].size(); ++layer_idx) { - drawMipmapLevel(width, height, l, false); - } - // Skip the current level, as we'll do it anyway here under... - - // Just go one level down in res as it can really get too much stuff - // when zooming out and too small to see anyway... - if (level > 1) + if (LLWorldMap::getInstance()->mMapLayers[map][layer_idx].LayerDefined) { - drawMipmapLevel(width, height, level - 1, false); + LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[map][layer_idx]; + layer->LayerImage->setBoostLevel(0); } } - else - { - //LL_INFOS("World Map") << "Render complete, don't draw background..." << LL_ENDL; - } - - // Render the current level - sVisibleTilesLoaded = drawMipmapLevel(width, height, level); - - return; -} - -// Return true if all the tiles required to render that level have been fetched or are truly missing -bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load) -{ - // Check input level - llassert (level > 0); - if (level <= 0) - return false; - - // Count tiles hit and completed - S32 completed_tiles = 0; - S32 total_tiles = 0; - - // Size in meters (global) of each tile of that level - S32 tile_width = LLWorldMipmap::MAP_TILE_SIZE * (1 << (level - 1)); - // Dimension of the screen in meter at that scale - LLVector3d pos_SW = viewPosToGlobal(0, 0); - LLVector3d pos_NE = viewPosToGlobal(width, height); - // Add external band of tiles on the outskirt so to hit the partially displayed tiles right and top - pos_NE[VX] += tile_width; - pos_NE[VY] += tile_width; - - // Iterate through the tiles on screen: we just need to ask for one tile every tile_width meters - U32 grid_x, grid_y; - for (F64 index_y = pos_SW[VY]; index_y < pos_NE[VY]; index_y += tile_width) - { - for (F64 index_x = pos_SW[VX]; index_x < pos_NE[VX]; index_x += tile_width) - { - // Compute the world coordinates of the current point - LLVector3d pos_global(index_x, index_y, pos_SW[VZ]); - // Convert to the mipmap level coordinates for that point (i.e. which tile to we hit) - LLWorldMipmap::globalToMipmap(pos_global[VX], pos_global[VY], level, &grid_x, &grid_y); - // Get the tile. Note: NULL means that the image does not exist (so it's considered "complete" as far as fetching is concerned) - LLPointer simimage = LLWorldMap::getInstance()->getObjectsTile(grid_x, grid_y, level, load); - if (simimage) - { - // Check the texture state - if (simimage->getHasGLTexture()) - { - // Increment the number of completly fetched tiles - completed_tiles++; - - // Convert those coordinates (SW corner of the mipmap tile) into world (meters) coordinates - pos_global[VX] = grid_x * REGION_WIDTH_METERS; - pos_global[VY] = grid_y * REGION_WIDTH_METERS; - // Now to screen coordinates for SW corner of that tile - LLVector3 pos_screen = globalPosToView (pos_global); - F32 left = pos_screen[VX]; - F32 bottom = pos_screen[VY]; - // Compute the NE corner coordinates of the tile now - pos_global[VX] += tile_width; - pos_global[VY] += tile_width; - pos_screen = globalPosToView (pos_global); - F32 right = pos_screen[VX]; - F32 top = pos_screen[VY]; - - // Draw the tile - 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); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(left, bottom, 0.f); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, 0.f); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex3f(right, top, 0.f); - gGL.end(); -#if DEBUG_DRAW_TILE - drawTileOutline(level, top, left, bottom, right); -#endif // DEBUG_DRAW_TILE } - //else - //{ - // Waiting for a tile -> the level is not complete - // LL_INFOS("World Map") << "Unfetched tile. level = " << level << LL_ENDL; - //} - } - else + for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin(); + it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + { + LLSimInfo* info = (*it).second; + if (info->mCurrentImage.notNull()) { - // Unexistent tiles are counted as "completed" - completed_tiles++; + info->mCurrentImage->setBoostLevel(0); + } + if (info->mOverlayImage.notNull()) + { + info->mOverlayImage->setBoostLevel(0); } - // Increment the number of tiles in that level / screen - total_tiles++; } } - 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) +void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image) { - 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(); -} - -void LLWorldMapView::drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image) -{ - LLSimInfo::item_info_list_t::const_iterator e; + LLWorldMap::item_info_list_t::const_iterator e; for (e = items.begin(); e != items.end(); ++e) { drawGenericItem(*e, image); @@ -812,7 +910,7 @@ void LLWorldMapView::drawGenericItems(const LLSimInfo::item_info_list_t& items, void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image) { - drawImage(item.getGlobalPosition(), image); + drawImage(item.mPosGlobal, image); } @@ -835,87 +933,133 @@ void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr i } } -void LLWorldMapView::drawItems() -{ - bool mature_enabled = gAgent.canAccessMature(); - bool adult_enabled = gAgent.canAccessAdult(); - - BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents"); - BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents"); - - 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 (gSavedSettings.getBOOL("MapShowInfohubs")) - { - drawGenericItems(info->getInfoHub(), sInfohubImage); - } - // Telehubs - if (gSavedSettings.getBOOL("MapShowTelehubs")) - { - drawGenericItems(info->getTeleHub(), sTelehubImage); - } - // Land for sale - if (gSavedSettings.getBOOL("MapShowLandForSale")) - { - 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 (gSavedSettings.getBOOL("MapShowEvents")) - { - 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())) + if (siminfo && (siminfo->mAccess == SIM_ACCESS_DOWN)) { continue; } - LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAgentLocation().begin(); - while (it != siminfo->getAgentLocation().end()) + 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.mPosGlobal, 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); + } + } + } +} - // 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(it->getGlobalPosition(), sAvatarSmallImage, it->getCount(), 3.f, avatar_color); - ++it; + +void LLWorldMapView::drawEvents() +{ + bool mature_enabled = gAgent.canAccessMature(); + bool adult_enabled = gAgent.canAccessAdult(); + + BOOL show_pg = gSavedSettings.getBOOL("MapShowPGEvents"); + BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("MapShowMatureEvents"); + BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("MapShowAdultEvents"); + + // 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 @@ -960,8 +1104,8 @@ LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos ) LLVector3 pos_local; pos_local.setVec(relative_pos_global); // convert to floats from doubles - pos_local.mV[VX] *= sMapScale / REGION_WIDTH_METERS; - pos_local.mV[VY] *= sMapScale / REGION_WIDTH_METERS; + pos_local.mV[VX] *= sPixelsPerMeter; + pos_local.mV[VY] *= sPixelsPerMeter; // leave Z component in meters @@ -1069,9 +1213,8 @@ 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()->simInfoFromHandle(handle); + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); if (info) { LLViewerRegion *region = gAgent.getRegion(); @@ -1079,14 +1222,14 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic // std::string message = llformat("%s (%s)", info->getName().c_str(), info->getAccessString().c_str()); // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-04 (RLVa-1.0.0a) std::string message = llformat("%s (%s)", - (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? info->getName().c_str() : RlvStrings::getString(RLV_STRING_HIDDEN).c_str(), - info->getAccessString().c_str()); + (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? info->mName.c_str() : RlvStrings::getString(RLV_STRING_HIDDEN).c_str(), + LLViewerRegion::accessToString(info->mAccess).c_str()); // [/RLVa:KB] - if (!info->isDown()) + if (info->mAccess != SIM_ACCESS_DOWN) { - S32 agent_count = info->getAgentCount(); - if (region && (region->getHandle() == handle)) + S32 agent_count = LLWorldMap::getInstance()->mNumAgents[info->mHandle]; + if (region && region->getHandle() == info->mHandle) { ++agent_count; // Bump by 1 if we're here } @@ -1095,35 +1238,28 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic // zoomed out, so don't display anything about the count. JC if (agent_count > 0) { - // Merov: i18n horror!!! Even using gettext(), concatenating strings is not localizable. - // The singular/plural switch form here under might make no sense in some languages. Don't do that. message += llformat("\n%d ", agent_count); if (agent_count == 1) { - // - message += "agents"; + message += "avatar"; } else { - // - message += "agents"; + message += "avatars"; } } } msg.assign( message ); // Optionally show region flags - std::string region_flags = info->getFlagsString(); + std::string region_flags = LLViewerRegion::regionFlagsToString(info->mRegionFlags); - // - // always seems to be zero anyways... if (!region_flags.empty()) { msg += '\n'; - msg += "Region Flags: " + region_flags; + msg += region_flags; } - // S32 SLOP = 4; localPointToScreen( @@ -1181,28 +1317,33 @@ static void drawDot(F32 x_pixels, F32 y_pixels, // static void LLWorldMapView::drawAvatar(F32 x_pixels, F32 y_pixels, - const LLColor4& color, + LLColor4 color, F32 relative_z, F32 dot_radius) { const F32 HEIGHT_THRESHOLD = 7.f; - LLUIImagePtr dot_image = sAvatarLevelImage; - if(relative_z < -HEIGHT_THRESHOLD) + LLUIImagePtr dot_image = sAvatarSmallImage; + + if (relative_z == 16000.f) // Unknown altitude (0m or > 1020m) + { + F32 mag = color.length(); + color=color*0.5f + LLColor4(mag, mag, mag)*0.25f; + } + else if (relative_z < -HEIGHT_THRESHOLD) { dot_image = sAvatarBelowImage; } - else if(relative_z > HEIGHT_THRESHOLD) + else if (relative_z > HEIGHT_THRESHOLD) { dot_image = sAvatarAboveImage; } S32 dot_width = llround(dot_radius * 2.f); - dot_image->draw( - llround(x_pixels - dot_radius), - llround(y_pixels - dot_radius), - dot_width, - dot_width, - color); + dot_image->draw(llround(x_pixels - dot_radius), + llround(y_pixels - dot_radius), + dot_width, + dot_width, + color); } // Pass relative Z of 0 to draw at same level. @@ -1461,7 +1602,7 @@ void LLWorldMapView::reshape( S32 width, S32 height, BOOL called_from_parent ) bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track) { - LLVector3 pos_view = globalPosToView(item.getGlobalPosition()); + LLVector3 pos_view = globalPosToView(item.mPosGlobal); S32 item_x = llround(pos_view.mV[VX]); S32 item_y = llround(pos_view.mV[VY]); @@ -1470,12 +1611,12 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo if (y < item_y - BIG_DOT_RADIUS) return false; if (y > item_y + BIG_DOT_RADIUS) return false; - LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromHandle(item.getRegionHandle()); + LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromHandle(item.mRegionHandle); if (sim_info) { if (track) { - gFloaterWorldMap->trackLocation(item.getGlobalPosition()); + gFloaterWorldMap->trackLocation(item.mPosGlobal); } } @@ -1484,8 +1625,8 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo gFloaterWorldMap->trackGenericItem(item); } -// item.setSelected(true); - *id = item.getUUID(); + item.mSelected = TRUE; + *id = item.mID; return true; } @@ -1508,34 +1649,37 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, *hit_type = 0; // hit nothing - LLWorldMap::getInstance()->cancelTracking(); + LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; + LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE; + LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; - S32 level = LLWorldMipmap::scaleToLevel(sMapScale); - // If the zoom level is not too far out already, test hits - if (level <= DRAW_SIMINFO_THRESHOLD) - { - bool show_mature = gAgent.canAccessMature() && gSavedSettings.getBOOL("ShowMatureEvents"); - bool show_adult = gAgent.canAccessAdult() && gSavedSettings.getBOOL("ShowAdultEvents"); + LLWorldMap::item_info_list_t::iterator it; - // Test hits if trackable data are displayed, otherwise, we don't even bother - if (gSavedSettings.getBOOL("MapShowEvents") || show_mature || show_adult || gSavedSettings.getBOOL("MapShowLandForSale")) + // clear old selected stuff + for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it) { - // Iterate through the visible regions - for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) + (*it).mSelected = FALSE; + } + for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it) { - U64 handle = *iter; - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if ((siminfo == NULL) || (siminfo->isDown())) + (*it).mSelected = FALSE; + } + for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) { - continue; + (*it).mSelected = FALSE; } - // If on screen check hits with the visible item lists - if (gSavedSettings.getBOOL("MapShowEvents")) + for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) { - LLSimInfo::item_info_list_t::const_iterator it = siminfo->getPGEvent().begin(); - while (it != siminfo->getPGEvent().end()) + (*it).mSelected = FALSE; + } + + // Select event you clicked on + if (gSavedSettings.getBOOL("MapShowPGEvents")) { - LLItemInfo event = *it; + 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; @@ -1543,15 +1687,14 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, gFloaterWorldMap->trackEvent(event); return; } - ++it; } } - if (show_mature) + if (gSavedSettings.getBOOL("MapShowMatureEvents")) { - LLSimInfo::item_info_list_t::const_iterator it = siminfo->getMatureEvent().begin(); - while (it != siminfo->getMatureEvent().end()) + for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it) { - LLItemInfo event = *it; + LLItemInfo& event = *it; + if (checkItemHit(x, y, event, id, false)) { *hit_type = MAP_ITEM_MATURE_EVENT; @@ -1559,15 +1702,14 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, gFloaterWorldMap->trackEvent(event); return; } - ++it; } } - if (show_adult) + if (gSavedSettings.getBOOL("MapShowAdultEvents")) { - LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAdultEvent().begin(); - while (it != siminfo->getAdultEvent().end()) + for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) { - LLItemInfo event = *it; + LLItemInfo& event = *it; + if (checkItemHit(x, y, event, id, false)) { *hit_type = MAP_ITEM_ADULT_EVENT; @@ -1575,49 +1717,40 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, gFloaterWorldMap->trackEvent(event); return; } - ++it; } } + if (gSavedSettings.getBOOL("MapShowLandForSale")) { - LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSale().begin(); - while (it != siminfo->getLandForSale().end()) + for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) { - LLItemInfo event = *it; - if (checkItemHit(x, y, event, id, true)) + LLItemInfo& land = *it; + + if (checkItemHit(x, y, land, 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()) + + for (it = LLWorldMap::getInstance()->mLandForSaleAdult.begin(); it != LLWorldMap::getInstance()->mLandForSaleAdult.end(); ++it) { - LLItemInfo event = *it; - if (checkItemHit(x, y, event, id, true)) + LLItemInfo& land = *it; + + if (checkItemHit(x, y, land, 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; } @@ -1678,35 +1811,58 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask ) return FALSE; } -void LLWorldMapView::updateVisibleBlocks() +U32 LLWorldMapView::updateBlock(S32 block_x, S32 block_y) { - if (LLWorldMipmap::scaleToLevel(sMapScale) > DRAW_SIMINFO_THRESHOLD) + U32 blocks_requested = 0; + S32 offset = block_x | (block_y * MAP_BLOCK_RES); + if (!LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset]) { - // If we're zoomed out too much, we just don't load all those sim info: too much! - return; +// 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) + { + // We don't care what is loaded if we're zoomed out + return 0; } - // Load the blocks visible in the current World Map view - - // Get the World Map view coordinates and boundaries LLVector3d camera_global = gAgent.getCameraPositionGlobal(); + + F32 pixels_per_region = sMapScale; const S32 width = getRect().getWidth(); const S32 height = getRect().getHeight(); - const F32 half_width = F32(width) / 2.0f; - const F32 half_height = F32(height) / 2.0f; + // 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)); - // 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)); + // 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 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; + U32 blocks_requested = 0; + const U32 max_blocks_requested = 9; - //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); + 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; } BOOL LLWorldMapView::handleHover( S32 x, S32 y, MASK mask ) @@ -1796,16 +1952,16 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) } default: { - if (LLWorldMap::getInstance()->isTracking()) + if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation) { - LLWorldMap::getInstance()->setTrackingDoubleClick(); + LLWorldMap::getInstance()->mIsTrackingDoubleClick = TRUE; } else { // Teleport if we got a valid location LLVector3d pos_global = viewPosToGlobal(x,y); LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); - if (sim_info && !sim_info->isDown()) + if (sim_info && sim_info->mAccess != SIM_ACCESS_DOWN) { gAgent.teleportViaLocation( pos_global ); } diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 9f31cea56..bf3f580ed 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -39,14 +39,21 @@ #define LL_LLWORLDMAPVIEW_H #include "llpanel.h" -#include "llworldmap.h" +#include "v3math.h" +#include "v3dmath.h" #include "v4color.h" +#include "llviewerimage.h" +#include "llmapimagetype.h" +#include "llworldmap.h" + +class LLItemInfo; const S32 DEFAULT_TRACKING_ARROW_SIZE = 16; -class LLUUID; -class LLVector3d; -class LLVector3; +class LLColor4; +class LLColor4U; +class LLCoordGL; +class LLViewerImage; class LLTextBox; @@ -71,26 +78,22 @@ public: bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track); void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id); - // Scale and pan are shared across all instances! (i.e. Terrain and Objects maps are always registered) + // Scale and pan are shared across all instances. static void setScale( F32 scale ); static void translatePan( S32 delta_x, S32 delta_y ); static void setPan( S32 x, S32 y, BOOL snap = TRUE ); - // Return true if the current scale level is above the threshold for accessing region info - static bool showRegionInfo(); LLVector3 globalPosToView(const LLVector3d& global_pos); LLVector3d viewPosToGlobal(S32 x,S32 y); virtual void draw(); - void drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image); + void drawGenericItems(const LLWorldMap::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 drawItems(); + void drawEvents(); void drawFrustum(); - void drawMipmap(S32 width, S32 height); - bool drawMipmapLevel(S32 width, S32 height, S32 level, bool load = true); static void cleanupTextures(); @@ -106,7 +109,7 @@ public: F32 y_pixels, const LLColor4& color, F32 relative_z = 0.f, - F32 dot_radius = 5.f); + F32 dot_radius = 3.f); static void drawTrackingCircle( const LLRect& rect, S32 x, S32 y, const LLColor4& color, @@ -114,7 +117,7 @@ public: S32 overlap ); static void drawAvatar( F32 x_pixels, F32 y_pixels, - const LLColor4& color, + LLColor4 color, F32 relative_z = 0.f, F32 dot_radius = 3.f); static void drawIconName(F32 x_pixels, @@ -127,7 +130,9 @@ public: static void clearLastClick() { sHandledLastClick = FALSE; } // if the view changes, download additional sim info as needed - void updateVisibleBlocks(); + // return value is number of blocks newly requested. + U32 updateBlock(S32 block_x, S32 block_y); + U32 updateVisibleBlocks(); protected: void setDirectionPos( LLTextBox* text_box, F32 rotation ); @@ -142,7 +147,6 @@ public: static LLUIImagePtr sAvatarLevelImage; static LLUIImagePtr sAvatarAboveImage; static LLUIImagePtr sAvatarBelowImage; - static LLUIImagePtr sTelehubImage; static LLUIImagePtr sInfohubImage; static LLUIImagePtr sHomeImage; @@ -155,6 +159,10 @@ 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 BOOL mItemPicked; @@ -165,7 +173,6 @@ public: static F32 sTargetPanY; // in pixels static S32 sTrackingArrowX; static S32 sTrackingArrowY; - static bool sVisibleTilesLoaded; // Are we mid-pan from a user drag? BOOL mPanning; @@ -188,14 +195,10 @@ public: static BOOL sHandledLastClick; S32 mSelectIDStart; - // Keep the list of regions that are displayed on screen. Avoids iterating through the whole region map after draw(). typedef std::vector handle_list_t; 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 deleted file mode 100644 index 7e1497417..000000000 --- a/indra/newview/llworldmipmap.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @file llworldmipmap.cpp - * @brief Data storage for the S3 mipmap of the entire world. - * - * $LicenseInfo:firstyear=2003&license=viewergpl$ - * - * Copyright (c) 2003-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llworldmipmap.h" - -#include "llviewercontrol.h" -#include "llviewerimagelist.h" -#include "math.h" // log() - -#include "llworldmap.h" -#include "llviewernetwork.h" //for isProductionGrid(); -#include "hippogridmanager.h" - -// Turn this on to output tile stats in the standard output -#define DEBUG_TILES_STAT 0 - -LLWorldMipmap::LLWorldMipmap() : - mCurrentLevel(0) -{ -} - -LLWorldMipmap::~LLWorldMipmap() -{ - reset(); -} - -// Delete all sublevel maps and clean them -void LLWorldMipmap::reset() -{ - for (int level = 0; level < MAP_LEVELS; level++) - { - mWorldObjectsMipMap[level].clear(); - } -} - -// This method should be called before each use of the mipmap (typically, before each draw), so that to let -// the boost level of unused tiles to drop to 0 (BOOST_NONE). -// Tiles that are accessed have had their boost level pushed to BOOST_MAP_VISIBLE so we can identify them. -// The result of this strategy is that if a tile is not used during 2 consecutive loops, its boost level drops to 0. -void LLWorldMipmap::equalizeBoostLevels() -{ -#if DEBUG_TILES_STAT - S32 nb_missing = 0; - S32 nb_tiles = 0; - S32 nb_visible = 0; -#endif // DEBUG_TILES_STAT - // For each level - for (S32 level = 0; level < MAP_LEVELS; level++) - { - sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level]; - // For each tile - for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) - { - LLPointer img = iter->second; - S32 current_boost_level = img->getBoostLevel(); - if (current_boost_level == LLViewerImageBoostLevel::BOOST_MAP_VISIBLE) - { - // If level was BOOST_MAP_VISIBLE, the tile has been used in the last draw so keep it high - img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); - } - else - { - // If level was BOOST_MAP only (or anything else...), the tile wasn't used in the last draw - // so we drop its boost level to BOOST_NONE. - img->setBoostLevel(LLViewerImageBoostLevel::BOOST_NONE); - } -#if DEBUG_TILES_STAT - // Increment some stats if compile option on - nb_tiles++; - if (current_boost_level == LLViewerImageBoostLevel::BOOST_MAP_VISIBLE) - { - nb_visible++; - } - if (img->isMissingAsset()) - { - nb_missing++; - } -#endif // DEBUG_TILES_STAT - } - } -#if DEBUG_TILES_STAT - LL_INFOS("World Map") << "LLWorldMipmap tile stats : total requested = " << nb_tiles << ", visible = " << nb_visible << ", missing = " << nb_missing << LL_ENDL; -#endif // DEBUG_TILES_STAT -} - -// This method should be used when the mipmap is not actively used for a while, e.g., the map UI is hidden -void LLWorldMipmap::dropBoostLevels() -{ - // For each level - for (S32 level = 0; level < MAP_LEVELS; level++) - { - sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level]; - // For each tile - for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) - { - LLPointer img = iter->second; - img->setBoostLevel(LLViewerImageBoostLevel::BOOST_NONE); - } - } -} - -LLPointer LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load) -{ - // Check the input data - llassert(level <= MAP_LEVELS); - llassert(level >= 1); - - // If the *loading* level changed, cleared the new level from "missed" tiles - // so that we get a chance to reload them - if (load && (level != mCurrentLevel)) - { - cleanMissedTilesFromLevel(level); - mCurrentLevel = level; - } - - // Build the region handle - U64 handle = convertGridToHandle(grid_x, grid_y); - - // Check if the image is around already - sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1]; - sublevel_tiles_t::iterator found = level_mipmap.find(handle); - - // If not there and load on, go load it - if (found == level_mipmap.end()) - { - if (load) - { - // Load it - LLPointer img; - - //hack for opensims. - if(gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) - img = loadObjectsTile(grid_x, grid_y, level); - else - { - LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if(info) - { - img = gImageList.getImage(info->getMapImageID(), MIPMAP_TRUE, FALSE); - img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); - } - else - return NULL; - } - // - // Insert the image in the map - level_mipmap.insert(sublevel_tiles_t::value_type( handle, img )); - // Find the element again in the map (it's there now...) - found = level_mipmap.find(handle); - } - else - { - // Return with NULL if not found and we're not trying to load - return NULL; - } - } - - // Get the image pointer and check if this asset is missing - LLPointer img = found->second; - if (img->isMissingAsset()) - { - // Return NULL if asset missing - return NULL; - } - else - { - // Boost the tile level so to mark it's in use *if* load on - if (load) - { - img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP_VISIBLE); - } - return img; - } -} - -LLPointer LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level) -{ - // Get the grid coordinates - std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", level, grid_x, grid_y); - - // DO NOT COMMIT!! DEBUG ONLY!!! - // Use a local jpeg for every tile to test map speed without S3 access - //imageurl = "file://C:\\Develop\\mapserver-distribute-3\\indra\\build-vc80\\mapserver\\relwithdebinfo\\regions\\00995\\01001\\region-995-1001-prims.jpg"; - // END DEBUG - //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; - - LLPointer img = gImageList.getImageFromUrl(imageurl); - img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); - - // Return the smart pointer - return img; -} - -// This method is used to clean up a level from tiles marked as "missing". -// The idea is to allow tiles that have been improperly marked missing to be reloaded when retraversing the level again. -// When zooming in and out rapidly, some tiles are never properly loaded and, eventually marked missing. -// This creates "blue" areas in a subresolution that never got a chance to reload if we don't clean up the level. -void LLWorldMipmap::cleanMissedTilesFromLevel(S32 level) -{ - // Check the input data - llassert(level <= MAP_LEVELS); - llassert(level >= 0); - - // This happens when the object is first initialized - if (level == 0) - { - return; - } - - // Iterate through the subresolution level and suppress the tiles that are marked as missing - // Note: erasing in a map while iterating through it is bug prone. Using a postfix increment is mandatory here. - sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1]; - sublevel_tiles_t::iterator it = level_mipmap.begin(); - while (it != level_mipmap.end()) - { - LLPointer img = it->second; - if (img->isMissingAsset()) - { - level_mipmap.erase(it++); - } - else - { - ++it; - } - } - return; -} - -// static methods -// Compute the level in the world mipmap (between 1 and MAP_LEVELS, as in the URL) given the scale (size of a sim in screen pixels) -S32 LLWorldMipmap::scaleToLevel(F32 scale) -{ - // If scale really small, picks up the higest level there is (lowest resolution) - if (scale <= F32_MIN) - return MAP_LEVELS; - // Compute the power of two resolution level knowing the base level - S32 level = llfloor((log(REGION_WIDTH_METERS/scale)/log(2.0f)) + 1.0f); - // Check bounds and return the value - if (level > MAP_LEVELS) - return MAP_LEVELS; - else if (level < 1) - return 1; - else - return level; -} - -// Convert world coordinates to mipmap grid coordinates at a given level (between 1 and MAP_LEVELS) -void LLWorldMipmap::globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y) -{ - // Check the input data - llassert(level <= MAP_LEVELS); - llassert(level >= 1); - - // Convert world coordinates into grid coordinates - *grid_x = lltrunc(global_x/REGION_WIDTH_METERS); - *grid_y = lltrunc(global_y/REGION_WIDTH_METERS); - // Compute the valid grid coordinates at that level of the mipmap - S32 regions_in_tile = 1 << (level - 1); - *grid_x = *grid_x - (*grid_x % regions_in_tile); - *grid_y = *grid_y - (*grid_y % regions_in_tile); -} - - diff --git a/indra/newview/llworldmipmap.h b/indra/newview/llworldmipmap.h deleted file mode 100644 index 9d6a80a41..000000000 --- a/indra/newview/llworldmipmap.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file llworldmipmap.h - * @brief Data storage for the S3 mipmap of the entire world. - * - * $LicenseInfo:firstyear=2003&license=viewergpl$ - * - * Copyright (c) 2003-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLWORLDMIPMAP_H -#define LL_LLWORLDMIPMAP_H - -#include - -#include "llmemory.h" // LLPointer -#include "indra_constants.h" // REGION_WIDTH_UNITS -#include "llregionhandle.h" // to_region_handle() - -class LLViewerImage; - -// LLWorldMipmap : Mipmap handling of all the tiles used to render the world at any resolution. -// This class provides a clean structured access to the hierarchy of tiles stored in the -// Amazon S3 repository and abstracts its directory/file structure. -// The interface of this class though still assumes that the caller knows the general level/tiles -// structure (at least, that it exists...) but doesn't requite the caller to know the details of it. -// IOW, you need to know that rendering levels exists as well as grid coordinates for regions, -// but you can ignore where those tiles are located, how to get them, etc... -// The class API gives you back LLPointer per tile. - -// See llworldmipmapview.cpp for the implementation of a class who knows how to render an LLWorldMipmap. - -// Implementation notes: -// - On the S3 servers, the tiles are rendered in 2 flavors: Objects and Terrain. -// - For the moment, LLWorldMipmap implements access only to the Objects tiles. -class LLWorldMipmap -{ -public: - // Parameters of the mipmap - static const S32 MAP_LEVELS = 8; // Number of subresolution levels computed by the mapserver - static const S32 MAP_TILE_SIZE = 256; // Width in pixels of the tiles computed by the mapserver - - LLWorldMipmap(); - ~LLWorldMipmap(); - - // Clear up the maps and release all image handles - void reset(); - // Manage the boost levels between loops (typically draw() loops) - void equalizeBoostLevels(); - // Drop the boost levels to none (used when hiding the map) - void dropBoostLevels(); - // Get the tile smart pointer, does the loading if necessary - LLPointer getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true); - - // Helper functions: those are here as they depend solely on the topology of the mipmap though they don't access it - // Convert sim scale (given in sim width in display pixels) into a mipmap level - static S32 scaleToLevel(F32 scale); - // Convert world coordinates to mipmap grid coordinates at a given level - static void globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y); - -private: - // Get a handle (key) from grid coordinates - U64 convertGridToHandle(U32 grid_x, U32 grid_y) { return to_region_handle(grid_x * REGION_WIDTH_UNITS, grid_y * REGION_WIDTH_UNITS); } - // Load the relevant tile from S3 - LLPointer loadObjectsTile(U32 grid_x, U32 grid_y, S32 level); - // Clear a level from its "missing" tiles - void cleanMissedTilesFromLevel(S32 level); - - // The mipmap is organized by resolution level (MAP_LEVELS of them). Each resolution level is an std::map - // using a region_handle as a key and storing a smart pointer to the image as a value. - typedef std::map > sublevel_tiles_t; - sublevel_tiles_t mWorldObjectsMipMap[MAP_LEVELS]; -// sublevel_tiles_t mWorldTerrainMipMap[MAP_LEVELS]; - - S32 mCurrentLevel; // The level last accessed by a getObjectsTile() -}; - -#endif // LL_LLWORLDMIPMAP_H diff --git a/indra/newview/skins/default/xui/en-us/floater_about.xml b/indra/newview/skins/default/xui/en-us/floater_about.xml index 1090f3607..3aa908d14 100644 --- a/indra/newview/skins/default/xui/en-us/floater_about.xml +++ b/indra/newview/skins/default/xui/en-us/floater_about.xml @@ -3,11 +3,62 @@ can_resize="false" height="440" min_height="100" min_width="100" name="floater_about" rect_control="FloaterAboutRect" title="About Singularity Viewer" width="470"> - -Singularity Viewer is developed and maintained by Siana Gearz with contributions by Shyotl Kuhr. Singularity is based upon Ascent source code. Credits for Ascent include Hg Beeks, Charley Levenque, Hazim Gazov, Zwagoth Klaar, Qarl Fizz, and others. Ascent is based off the Inertia source base. + + + +