Files
SingularityViewer/indra/newview/llworldmap.cpp
Shyotl e756140e1d Innitial commit of experimental v2 texture system port work. Compiles and runs on windows, at least. Fixing bugs as they come.
Need to test:
localassetbrowser
preview related floaters
hgfloatertexteditor
maps
media textures! Currently very hacky
web browser
alpha masks on avatars
bumpmaps
Are all sky components appearing?
LLViewerDynamicTexture (texture baking, browser, animated textures, anim previews, etc)
Snapshot related features
Customize avatar
vfs floater
UI textures in general
Texture priority issues
2011-03-31 03:22:01 -05:00

1098 lines
30 KiB
C++

/**
* @file llworldmap.cpp
* @brief Underlying data representation for map of the 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 "llworldmap.h"
#include "llregionhandle.h"
#include "message.h"
#include "llappviewer.h" // for gPacificDaylightTime
#include "llagent.h"
#include "llmapresponders.h"
#include "llviewercontrol.h"
#include "llfloaterworldmap.h"
#include "lltracker.h"
#include "llviewertexturelist.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
// For DEV-17507, do lazy image loading in llworldmapview.cpp instead,
// limiting requests to currently visible regions and minimizing the
// number of textures being requested simultaneously.
//
// Uncomment IMMEDIATE_IMAGE_LOAD to restore the old behavior
//
//#define IMMEDIATE_IMAGE_LOAD
LLItemInfo::LLItemInfo(F32 global_x, F32 global_y,
const std::string& name,
LLUUID id,
S32 extra, S32 extra2)
: mName(name),
mToolTip(""),
mPosGlobal(global_x, global_y, 40.0),
mID(id),
mSelected(FALSE),
mExtra(extra),
mExtra2(extra2)
{
mRegionHandle = to_region_handle(mPosGlobal);
}
LLSimInfo::LLSimInfo()
: mHandle(0),
mName(),
mAgentsUpdateTime(0),
mShowAgentLocations(FALSE),
mAccess(0x0),
mRegionFlags(0x0),
mWaterHeight(0.f),
mAlpha(-1.f)
{
}
LLVector3d LLSimInfo::getGlobalOrigin() const
{
return from_region_handle(mHandle);
}
LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const
{
LLVector3d pos = from_region_handle(mHandle);
pos.mdV[VX] += local_pos.mV[VX];
pos.mdV[VY] += local_pos.mV[VY];
pos.mdV[VZ] += local_pos.mV[VZ];
return pos;
}
//---------------------------------------------------------------------------
// World Map
//---------------------------------------------------------------------------
LLWorldMap::LLWorldMap() :
mIsTrackingUnknownLocation( FALSE ),
mInvalidLocation( FALSE ),
mIsTrackingDoubleClick( FALSE ),
mIsTrackingCommit( FALSE ),
mUnknownLocation( 0, 0, 0 ),
mRequestLandForSale(true),
mCurrentMap(0),
mMinX(U32_MAX),
mMaxX(U32_MIN),
mMinY(U32_MAX),
mMaxY(U32_MIN),
mNeighborMap(NULL),
mTelehubCoverageMap(NULL),
mNeighborMapWidth(0),
mNeighborMapHeight(0),
mSLURLRegionName(),
mSLURLRegionHandle(0),
mSLURL(),
mSLURLCallback(0),
mSLURLTeleport(false)
{
for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
{
mMapLoaded[map] = FALSE;
mMapBlockLoaded[map] = new BOOL[MAP_BLOCK_RES*MAP_BLOCK_RES];
for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
{
mMapBlockLoaded[map][idx] = FALSE;
}
}
}
LLWorldMap::~LLWorldMap()
{
reset();
for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
{
delete[] mMapBlockLoaded[map];
}
}
void LLWorldMap::reset()
{
for_each(mSimInfoMap.begin(), mSimInfoMap.end(), DeletePairedPointer());
mSimInfoMap.clear();
for (S32 m=0; m<MAP_SIM_IMAGE_TYPES; ++m)
{
mMapLoaded[m] = FALSE;
}
clearSimFlags();
eraseItems();
mMinX = U32_MAX;
mMaxX = U32_MIN;
mMinY = U32_MAX;
mMaxY = U32_MIN;
delete [] mNeighborMap;
mNeighborMap = NULL;
delete [] mTelehubCoverageMap;
mTelehubCoverageMap = NULL;
mNeighborMapWidth = 0;
mNeighborMapHeight = 0;
for (S32 i=0; i<MAP_SIM_IMAGE_TYPES; i++)
{
mMapLayers[i].clear();
}
}
void LLWorldMap::eraseItems()
{
if (mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER)
{
mRequestTimer.reset();
mTelehubs.clear();
mInfohubs.clear();
mPGEvents.clear();
mMatureEvents.clear();
mAdultEvents.clear();
mLandForSale.clear();
}
// mAgentLocationsMap.clear(); // persists
// mNumAgents.clear(); // persists
}
void LLWorldMap::clearImageRefs()
{
mWorldMipmap.reset();
for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
LLSimInfo* info = (*it).second;
if (info->mCurrentImage)
{
info->mCurrentImage->setBoostLevel(0);
info->mCurrentImage = NULL;
}
if (info->mOverlayImage)
{
info->mOverlayImage->setBoostLevel(0);
info->mOverlayImage = NULL;
}
}
}
// Doesn't clear the already-loaded sim infos, just re-requests them
void LLWorldMap::clearSimFlags()
{
for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
{
for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
{
mMapBlockLoaded[map][idx] = FALSE;
}
}
}
void LLWorldMap::equalizeBoostLevels()
{
mWorldMipmap.equalizeBoostLevels();
return;
}
LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global)
{
U64 handle = to_region_handle(pos_global);
return simInfoFromHandle(handle);
}
LLSimInfo* LLWorldMap::simInfoFromHandle(const U64 handle)
{
sim_info_map_t::iterator it = mSimInfoMap.find(handle);
if (it != mSimInfoMap.end())
{
LLSimInfo* sim_info = (*it).second;
if (sim_info)
{
return sim_info;
}
}
return NULL;
}
LLSimInfo* LLWorldMap::simInfoFromName(const std::string& sim_name)
{
LLSimInfo* sim_info = NULL;
if (!sim_name.empty())
{
for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
sim_info = (*it).second;
if (sim_info
&& (0 == LLStringUtil::compareInsensitive(sim_name, sim_info->mName)) )
{
break;
}
sim_info = NULL;
}
}
return sim_info;
}
bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string & outSimName )
{
bool gotSimName = true;
U64 handle = to_region_handle(pos_global);
sim_info_map_t::iterator it = mSimInfoMap.find(handle);
if (it != mSimInfoMap.end())
{
LLSimInfo* info = (*it).second;
outSimName = info->mName;
}
else
{
gotSimName = false;
outSimName = "(unknown region)";
}
return gotSimName;
}
void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer)
{
//TODO: we only have 1 layer -SG
mCurrentMap = layer;
if (!mMapLoaded[layer] || request_layer)
{
sendMapLayerRequest();
}
if (mTelehubs.size() == 0 ||
mInfohubs.size() == 0)
{
// Request for telehubs
sendItemRequest(MAP_ITEM_TELEHUB);
}
if (mPGEvents.size() == 0)
{
// Request for events
sendItemRequest(MAP_ITEM_PG_EVENT);
}
if (mMatureEvents.size() == 0)
{
// Request for events (mature)
sendItemRequest(MAP_ITEM_MATURE_EVENT);
}
if (mAdultEvents.size() == 0)
{
// Request for events (adult)
sendItemRequest(MAP_ITEM_ADULT_EVENT);
}
if (mLandForSale.size() == 0)
{
// Request for Land For Sale
sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
}
if (mLandForSaleAdult.size() == 0)
{
// Request for Land For Sale
sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT);
}
clearImageRefs();
clearSimFlags();
}
void LLWorldMap::sendItemRequest(U32 type, U64 handle)
{
LLMessageSystem* msg = gMessageSystem;
S32 layer = mCurrentMap;
msg->newMessageFast(_PREHASH_MapItemRequest);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addU32Fast(_PREHASH_Flags, layer);
msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
msg->nextBlockFast(_PREHASH_RequestData);
msg->addU32Fast(_PREHASH_ItemType, type);
msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim
gAgent.sendReliableMessage();
}
// public
void LLWorldMap::sendMapLayerRequest()
{
if (!gAgent.getRegion()) return;
LLSD body;
body["Flags"] = mCurrentMap;
std::string url = gAgent.getRegion()->getCapability(
gAgent.isGodlike() ? "MapLayerGod" : "MapLayer");
if (!url.empty())
{
llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl;
LLHTTPClient::post(url, body, new LLMapLayerResponder());
}
else
{
llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl;
LLMessageSystem* msg = gMessageSystem;
S32 layer = mCurrentMap;
// Request for layer
msg->newMessageFast(_PREHASH_MapLayerRequest);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addU32Fast(_PREHASH_Flags, layer);
msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
gAgent.sendReliableMessage();
if (mRequestLandForSale)
{
msg->newMessageFast(_PREHASH_MapLayerRequest);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addU32Fast(_PREHASH_Flags, 2);
msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
gAgent.sendReliableMessage();
}
}
}
// public
void LLWorldMap::sendNamedRegionRequest(std::string region_name)
{
LLMessageSystem* msg = gMessageSystem;
S32 layer = mCurrentMap;
// Request for layer
msg->newMessageFast(_PREHASH_MapNameRequest);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addU32Fast(_PREHASH_Flags, layer);
msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
msg->nextBlockFast(_PREHASH_NameData);
msg->addStringFast(_PREHASH_Name, region_name);
gAgent.sendReliableMessage();
}
// public
void LLWorldMap::sendNamedRegionRequest(std::string region_name,
url_callback_t callback,
const std::string& callback_url,
bool teleport) // immediately teleport when result returned
{
mSLURLRegionName = region_name;
mSLURLRegionHandle = 0;
mSLURL = callback_url;
mSLURLCallback = callback;
mSLURLTeleport = teleport;
sendNamedRegionRequest(region_name);
}
void LLWorldMap::sendHandleRegionRequest(U64 region_handle,
url_callback_t callback,
const std::string& callback_url,
bool teleport) // immediately teleport when result returned
{
mSLURLRegionName.clear();
mSLURLRegionHandle = region_handle;
mSLURL = callback_url;
mSLURLCallback = callback;
mSLURLTeleport = teleport;
U32 global_x;
U32 global_y;
from_region_handle(region_handle, &global_x, &global_y);
U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS);
U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS);
sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true);
}
// public
void LLWorldMap::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent)
{
S32 layer = mCurrentMap;
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_MapBlockRequest);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
U32 flags = layer;
flags |= (return_nonexistent ? 0x10000 : 0);
msg->addU32Fast(_PREHASH_Flags, flags);
msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
msg->nextBlockFast(_PREHASH_PositionData);
msg->addU16Fast(_PREHASH_MinX, min_x);
msg->addU16Fast(_PREHASH_MinY, min_y);
msg->addU16Fast(_PREHASH_MaxX, max_x);
msg->addU16Fast(_PREHASH_MaxY, max_y);
gAgent.sendReliableMessage();
if (mRequestLandForSale)
{
msg->newMessageFast(_PREHASH_MapBlockRequest);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addU32Fast(_PREHASH_Flags, 2);
msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
msg->nextBlockFast(_PREHASH_PositionData);
msg->addU16Fast(_PREHASH_MinX, min_x);
msg->addU16Fast(_PREHASH_MinY, min_y);
msg->addU16Fast(_PREHASH_MaxX, max_x);
msg->addU16Fast(_PREHASH_MaxY, max_y);
gAgent.sendReliableMessage();
}
}
// public static
void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**)
{
llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl;
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; block<num_blocks; ++block)
{
LLWorldMapLayer new_layer;
new_layer.LayerDefined = TRUE;
msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block);
U32 left, right, top, bottom;
msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block);
msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Right, right, block);
msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block);
msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block);
// if (use_web_map_tiles)
// {
// new_layer.LayerImage = loadObjectsTile(left, bottom); // no good... Maybe using of level 2 and higher web maps ?
// }
// else
// {
new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE);
// }
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<LLViewerFetchedTexture> 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<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl,TRUE,LLViewerTexture::BOOST_MAP,LLViewerTexture::LOD_TEXTURE);
img->setBoostLevel(LLViewerTexture::BOOST_MAP);
// Return the smart pointer
return img;
}
// public static
void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**)
{
U32 agent_flags;
msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
if ((S32)agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES)
{
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; block<num_blocks; ++block)
{
U16 x_regions;
U16 y_regions;
std::string name;
U8 accesscode;
U32 region_flags;
U8 water_height;
U8 agents;
LLUUID image_id;
msg->getU16Fast(_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 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; image<MAP_SIM_IMAGE_TYPES; ++image)
{
siminfo->mMapImageID[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
{
siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE);
}
gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get());
siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
#endif
if (siminfo->mMapImageID[2].notNull())
{
#ifdef IMMEDIATE_IMAGE_LOAD
siminfo->mOverlayImage = LLViewerTextureManager::getFetchedTextureURL(siminfo->mMapImageID[2]);
#endif
}
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(LLWorldMap::getInstance()->mSLURLCallback != NULL)
{
// Server returns definitive capitalization, SLURL might not have that.
if ((LLStringUtil::compareInsensitive(LLWorldMap::getInstance()->mSLURLRegionName, name)==0)
|| (LLWorldMap::getInstance()->mSLURLRegionHandle == handle))
{
url_callback_t callback = LLWorldMap::getInstance()->mSLURLCallback;
LLWorldMap::getInstance()->mSLURLCallback = NULL;
LLWorldMap::getInstance()->mSLURLRegionName.clear();
LLWorldMap::getInstance()->mSLURLRegionHandle = 0;
callback(handle, LLWorldMap::getInstance()->mSLURL, image_id, LLWorldMap::getInstance()->mSLURLTeleport);
}
}
if(LLAgent::lure_show)
{
if((x_regions == LLAgent::lure_global_x) && (y_regions == LLAgent::lure_global_y))
{
gAgent.onFoundLureDestination();
}
}
}
if(adjust) gFloaterWorldMap->adjustZoomSliderBounds();
gFloaterWorldMap->updateSims(found_null_sim);
}
// public static
void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**)
{
U32 type;
msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
S32 num_blocks = msg->getNumberOfBlocks("Data");
for (S32 block=0; block<num_blocks; ++block)
{
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);
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);
switch (type)
{
case MAP_ITEM_TELEHUB: // telehubs
{
// Telehub color, store in extra as 4 U8's
U8 *color = (U8 *)&new_item.mExtra;
F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f;
F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f;
F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f;
F32 add_amt = (X % 2) ? 0.15f : -0.15f;
add_amt += (Y % 2) ? -0.15f : 0.15f;
color[0] = U8((red + add_amt) * 255);
color[1] = U8((green + add_amt) * 255);
color[2] = U8((blue + add_amt) * 255);
color[3] = 255;
// extra2 specifies whether this is an infohub or a telehub.
if (extra2)
{
LLWorldMap::getInstance()->mInfohubs.push_back(new_item);
}
else
{
LLWorldMap::getInstance()->mTelehubs.push_back(new_item);
}
break;
}
case MAP_ITEM_PG_EVENT: // events
case MAP_ITEM_MATURE_EVENT:
case MAP_ITEM_ADULT_EVENT:
{
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()
{
for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
U64 handle = (*it).first;
LLSimInfo* info = (*it).second;
U32 x_pos, y_pos;
from_region_handle(handle, &x_pos, &y_pos);
llinfos << x_pos << "," << y_pos
<< " " << info->mName
<< " " << (S32)info->mAccess
<< " " << std::hex << info->mRegionFlags << std::dec
<< " " << info->mWaterHeight
//<< " " << info->mTelehubName
//<< " " << info->mTelehubPosition
<< llendl;
if (info->mCurrentImage)
{
llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel()
<< " fullwidth " << info->mCurrentImage->getWidth(0)
<< " fullheight " << info->mCurrentImage->getHeight(0)
<< " maxvirt " << info->mCurrentImage->getMaxVirtualSize()
<< " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel()
<< llendl;
}
}
}
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<U64, LLSimInfo*>::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];
}*/
}
// 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)
{
LLSimInfo* info = it->second;
if (!info->mOverlayImage.isNull())
{
info->mOverlayImage->setBoostLevel(0);
}
}
}