summaryrefslogtreecommitdiff
path: root/indra/newview/llworldmapview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llworldmapview.cpp')
-rw-r--r--indra/newview/llworldmapview.cpp1243
1 files changed, 537 insertions, 706 deletions
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 823db027ee..60b1e59645 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -46,7 +46,6 @@
#include "llagent.h"
#include "llcallingcard.h"
#include "llviewercontrol.h"
-#include "llcylinder.h"
#include "llfloatermap.h"
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
@@ -57,25 +56,29 @@
#include "llviewercamera.h"
#include "llviewertexture.h"
#include "llviewertexturelist.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"
+// 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;
BOOL LLWorldMapView::sHandledLastClick = FALSE;
-LLUIImagePtr LLWorldMapView::sAvatarYouSmallImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarSmallImage = NULL;
-LLUIImagePtr LLWorldMapView::sAvatarLargeImage = NULL;
+LLUIImagePtr LLWorldMapView::sAvatarYouImage = NULL;
+LLUIImagePtr LLWorldMapView::sAvatarYouLargeImage = NULL;
+LLUIImagePtr LLWorldMapView::sAvatarLevelImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarAboveImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarBelowImage = NULL;
@@ -93,35 +96,34 @@ 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;
-F32 LLWorldMapView::sPixelsPerMeter = 1.f;
-F32 CONE_SIZE = 0.6f;
+bool LLWorldMapView::sVisibleTilesLoaded = false;
+F32 LLWorldMapView::sMapScale = 128.f;
std::map<std::string,std::string> LLWorldMapView::sStringsMap;
-#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
+// 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)
+// When on, draw an outline for each mipmap tile gotten from S3
+#define DEBUG_DRAW_TILE 0
void LLWorldMapView::initClass()
{
- sAvatarYouSmallImage = LLUI::getUIImage("map_avatar_you_8.tga");
- sAvatarSmallImage = LLUI::getUIImage("map_avatar_8.tga");
- sAvatarLargeImage = LLUI::getUIImage("map_avatar_16.tga");
- sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_8.tga");
- sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_8.tga");
+ sAvatarSmallImage = LLUI::getUIImage("map_avatar_8.tga");
+ sAvatarYouImage = LLUI::getUIImage("map_avatar_16.tga");
+ sAvatarYouLargeImage = LLUI::getUIImage("map_avatar_you_32.tga");
+ sAvatarLevelImage = LLUI::getUIImage("map_avatar_32.tga");
+ sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_32.tga");
+ sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_32.tga");
sHomeImage = LLUI::getUIImage("map_home.tga");
sTelehubImage = LLUI::getUIImage("map_telehub.tga");
@@ -145,9 +147,10 @@ void LLWorldMapView::initClass()
// static
void LLWorldMapView::cleanupClass()
{
- sAvatarYouSmallImage = NULL;
sAvatarSmallImage = NULL;
- sAvatarLargeImage = NULL;
+ sAvatarYouImage = NULL;
+ sAvatarYouLargeImage = NULL;
+ sAvatarLevelImage = NULL;
sAvatarAboveImage = NULL;
sAvatarBelowImage = NULL;
@@ -167,7 +170,7 @@ void LLWorldMapView::cleanupClass()
LLWorldMapView::LLWorldMapView()
: LLPanel(),
- mBackgroundColor( LLColor4( 4.f/255.f, 4.f/255.f, 75.f/255.f, 1.f ) ),
+ mBackgroundColor( LLColor4( OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f ) ),
mItemPicked(FALSE),
mPanning( FALSE ),
mMouseDownPanX( 0 ),
@@ -176,7 +179,8 @@ LLWorldMapView::LLWorldMapView()
mMouseDownY( 0 ),
mSelectIDStart(0)
{
- sPixelsPerMeter = gMapScale / REGION_WIDTH_METERS;
+ //LL_INFOS("World Map") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL;
+
clearLastClick();
}
@@ -215,6 +219,7 @@ BOOL LLWorldMapView::postBuild()
LLWorldMapView::~LLWorldMapView()
{
+ //LL_INFOS("World Map") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL;
cleanupTextures();
}
@@ -228,14 +233,14 @@ void LLWorldMapView::cleanupTextures()
// static
void LLWorldMapView::setScale( F32 scale )
{
- if (scale != gMapScale)
+ if (scale != sMapScale)
{
- F32 old_scale = gMapScale;
+ F32 old_scale = sMapScale;
- gMapScale = scale;
- if (gMapScale == 0.f)
+ sMapScale = scale;
+ if (sMapScale <= 0.f)
{
- gMapScale = 0.1f;
+ sMapScale = 0.1f;
}
F32 ratio = (scale / old_scale);
@@ -243,8 +248,7 @@ void LLWorldMapView::setScale( F32 scale )
sPanY *= ratio;
sTargetPanX = sPanX;
sTargetPanY = sPanY;
-
- sPixelsPerMeter = gMapScale / REGION_WIDTH_METERS;
+ sVisibleTilesLoaded = false;
}
}
@@ -256,6 +260,7 @@ void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y )
sPanY += delta_y;
sTargetPanX = sPanX;
sTargetPanY = sPanY;
+ sVisibleTilesLoaded = false;
}
@@ -269,18 +274,22 @@ 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->mName == region->getName()));
+ return (region && info && info->isName(region->getName()));
}
-
///////////////////////////////////////////////////////////////////////////////////
void LLWorldMapView::draw()
@@ -292,7 +301,7 @@ void LLWorldMapView::draw()
F64 current_time = LLTimer::getElapsedSeconds();
mVisibleRegions.clear();
-
+
// animate pan if necessary
sPanX = lerp(sPanX, sTargetPanX, LLCriticalDamp::getInterpolant(0.1f));
sPanY = lerp(sPanY, sTargetPanY, LLCriticalDamp::getInterpolant(0.1f));
@@ -303,10 +312,12 @@ void LLWorldMapView::draw()
const F32 half_height = F32(height) / 2.0f;
LLVector3d camera_global = gAgent.getCameraPositionGlobal();
+ S32 level = LLWorldMipmap::scaleToLevel(sMapScale);
+
LLLocalClipRect clip(getLocalRect());
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
+
glMatrixMode(GL_MODELVIEW);
// Clear the background alpha to 0
@@ -319,307 +330,59 @@ void LLWorldMapView::draw()
}
gGL.flush();
+
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setColorMask(true, true);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- F32 layer_alpha = 1.f;
-
- // Draw one image per layer
- for (U32 layer_idx=0; layer_idx<LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx)
- {
- if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined)
- {
- continue;
- }
- LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx];
- LLViewerFetchedTexture *current_image = layer->LayerImage;
-
- 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) * gMapScale;
- F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * gMapScale;
-
- F32 pix_width = gMapScale*(layer->LayerExtents.getWidth() + 1);
- F32 pix_height = gMapScale*(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(LLViewerTexture::BOOST_MAP);
- current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY]));
-
- if (!current_image->hasGLTexture())
- {
- 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();
- }
+#if 1
+ // Draw the image tiles
+ drawMipmap(width, height);
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;
-
- for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin();
- it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
+ // 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)
{
- U64 handle = (*it).first;
- LLSimInfo* info = (*it).second;
+ U64 handle = it->first;
+ LLSimInfo* info = it->second;
- LLViewerFetchedTexture* simimage = info->mCurrentImage;
- LLViewerFetchedTexture* overlayimage = info->mOverlayImage;
-
- if (gMapScale < 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) * gMapScale;
- F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * gMapScale;
+ 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 + gMapScale ;
- F32 right = left + gMapScale ;
-
- // 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)
- {
- map_scale_cutoff = SIM_NULL_MAP_SCALE;
- }
-
- info->mShowAgentLocations = (gMapScale >= SIM_MAP_AGENT_SCALE);
-
- bool sim_visible =
- (gMapScale >= map_scale_cutoff) &&
- (simimage != NULL) &&
- (simimage->hasGLTexture());
-
- 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 )
+ 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) )
{
- if (simimage != NULL) simimage->setBoostLevel(0);
- if (overlayimage != NULL) overlayimage->setBoostLevel(0);
+ // Drop the "land for sale" fetching priority since it's outside the view rectangle
+ info->dropImagePriority();
continue;
}
- if (info->mCurrentImage.isNull())
- {
- 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->mCurrentImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
- info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
- simimage = info->mCurrentImage;
- gGL.getTexUnit(0)->bind(simimage);
- }
- }
- if (info->mOverlayImage.isNull() && info->mMapImageID[2].notNull())
- {
- if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) ||
- ((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) &&
- (textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
- {
- textures_requested_this_tick++;
- info->mOverlayImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[2], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
- info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
- overlayimage = info->mOverlayImage;
- gGL.getTexUnit(0)->bind(overlayimage);
- }
- }
+ // This list is used by other methods to know which regions are indeed displayed on screen
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;
- }
-
- // 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(gMapScale);
- if (simimage != NULL)
- {
- simimage->setBoostLevel(LLViewerTexture::BOOST_MAP);
- simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
- }
-
- if (overlayimage != NULL)
- {
- overlayimage->setBoostLevel(LLViewerTexture::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)
+ // Update the agent count for that region if we're not too zoomed out already
+ if (level <= DRAW_SIMINFO_THRESHOLD)
{
- // 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->hasGLTexture())
- {
- gGL.getTexUnit(0)->bind(overlayimage);
- gGL.color4f(1.f, 1.f, 1.f, alpha);
- gGL.begin(LLRender::QUADS);
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex3f(left, top, -0.5f);
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex3f(left, bottom, -0.5f);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex3f(right, bottom, -0.5f);
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex3f(right, top, -0.5f);
- gGL.end();
- }
-
- if ((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);
- }
+ info->updateAgentCount(current_time);
}
- if (info->mAccess == SIM_ACCESS_DOWN)
+ if (info->isDown())
{
// Draw a transparent red square over down sims
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA);
@@ -633,18 +396,15 @@ void LLWorldMapView::draw()
gGL.vertex2f(right, top);
gGL.end();
}
-
- // As part of the AO project, we no longer want to draw access indicators;
- // it's too complicated to get all the rules straight and will only
+ // As part of the AO project, we no longer want to draw access indicators;
+ // it's too complicated to get all the rules straight and will only
// cause confusion.
/**********************
- // If this is mature, and you are not, draw a line across it
- if (info->mAccess != SIM_ACCESS_DOWN
- && info->mAccess > SIM_ACCESS_PG
- && gAgent.isTeen())
+ else if (!info->isPG() && 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);
gGL.color3f(1.f, 0.f, 0.f);
gGL.begin(LLRender::LINES);
@@ -655,68 +415,67 @@ void LLWorldMapView::draw()
gGL.end();
}
**********************/
-
- // Draw the region name in the lower left corner
- LLFontGL* font = LLFontGL::getFontSansSerifSmall();
-
- std::string mesg;
- if (gMapScale < sThresholdA)
+ else if (gSavedSettings.getBOOL("MapShowLandForSale") && (level <= DRAW_LANDFORSALE_THRESHOLD))
{
+ // Draw the overlay image "Land for Sale / Land for Auction"
+ LLViewerFetchedTexture* overlayimage = info->getLandForSaleImage();
+ if (overlayimage)
+ {
+ // Inform the fetch mechanism of the size we need
+ S32 draw_size = llround(sMapScale);
+ overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
+ // Draw something whenever we have enough info
+ if (overlayimage->hasGLTexture())
+ {
+ 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 (gMapScale < sThresholdB)
+ else
{
- // mesg = llformat( info->mAgents);
+ // If we're not displaying the "land for sale", drop its fetching priority
+ info->dropImagePriority();
}
- else
+
+ // Draw the region name in the lower left corner
+ if (sMapScale >= DRAW_TEXT_THRESHOLD)
{
- //mesg = llformat("%d / %s (%s)",
- // info->mAgents,
- // info->mName.c_str(),
- // LLViewerRegion::accessToShortString(info->mAccess).c_str() );
- if (info->mAccess == SIM_ACCESS_DOWN)
+ LLFontGL* font = LLFontGL::getFontSansSerifSmall();
+ std::string mesg;
+ if (info->isDown())
{
- mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str());
+ mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str());
}
else
{
- mesg = info->mName;
+ mesg = info->getName();
}
- }
-
- if (!mesg.empty())
- {
- font->renderUTF8(
- mesg, 0,
- llfloor(left + 3),
- llfloor(bottom + 2),
- LLColor4::white,
- LLFontGL::LEFT,
- LLFontGL::BASELINE,
- LLFontGL::NORMAL,
- LLFontGL::DROP_SHADOW);
-
- // If map texture is still loading,
- // display "Loading" placeholder text.
- if ((simimage != NULL) &&
- simimage->getDiscardLevel() != 1 &&
- simimage->getDiscardLevel() != 0)
+ if (!mesg.empty())
{
font->renderUTF8(
- sStringsMap["loading"], 0,
- llfloor(left + 18),
- llfloor(top - 25),
+ mesg, 0,
+ llfloor(left + 3), llfloor(bottom + 2),
LLColor4::white,
- LLFontGL::LEFT,
- LLFontGL::BASELINE,
- LLFontGL::NORMAL,
- LLFontGL::DROP_SHADOW);
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
}
}
}
- // #endif used to be here
+ #endif
- // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code?
+ #if 1
// Draw background rectangle
LLGLSUIDefault gls_ui;
{
@@ -726,69 +485,49 @@ void LLWorldMapView::draw()
gGL.color4fv( mBackgroundColor.mV );
gl_rect_2d(0, height, width, 0);
}
-
+
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- // Infohubs
- if (gSavedSettings.getBOOL("MapShowInfohubs")) //(gMapScale >= sThresholdB)
+ // 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")))
{
- drawGenericItems(LLWorldMap::getInstance()->mInfohubs, sInfohubImage);
+ drawItems();
}
- // Telehubs
- if (gSavedSettings.getBOOL("MapShowTelehubs")) //(gMapScale >= sThresholdB)
- {
- drawGenericItems(LLWorldMap::getInstance()->mTelehubs, sTelehubImage);
- }
-
- // Home Sweet Home
+ // Draw the Home location (always)
LLVector3d home;
if (gAgent.getHomePosGlobal(&home))
{
drawImage(home, sHomeImage);
}
- 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("MapShowEvents") ||
- gSavedSettings.getBOOL("ShowMatureEvents") ||
- gSavedSettings.getBOOL("ShowAdultEvents") )
- {
- drawEvents();
- }
-
- // Now draw your avatar after all that other stuff.
+ // Draw the current agent after all that other stuff.
LLVector3d pos_global = gAgent.getPositionGlobal();
- drawImage(pos_global, sAvatarLargeImage);
+ drawImage(pos_global, sAvatarYouImage);
LLVector3 pos_map = globalPosToView(pos_global);
if (!pointInView(llround(pos_map.mV[VX]), llround(pos_map.mV[VY])))
{
- drawTracking(pos_global,
- lerp(LLColor4::yellow, LLColor4::orange, 0.4f),
- TRUE,
- "You are here",
- "",
- llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking
+ drawTracking(pos_global,
+ lerp(LLColor4::yellow, LLColor4::orange, 0.4f),
+ TRUE,
+ "You are here",
+ "",
+ llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking
}
- // Show your viewing angle
+ // Draw the current agent viewing angle
drawFrustum();
// Draw icons for the avatars in each region.
- // Drawn after your avatar so you can see nearby people.
- if (gSavedSettings.getBOOL("MapShowPeople"))
+ // Drawn this after the current agent avatar so one can see nearby people
+ if (gSavedSettings.getBOOL("MapShowPeople") && (level <= DRAW_SIMINFO_THRESHOLD))
{
drawAgents();
}
@@ -798,9 +537,9 @@ void LLWorldMapView::draw()
if ( LLTracker::TRACKING_AVATAR == tracking_status )
{
drawTracking( LLAvatarTracker::instance().getGlobalPos(), map_track_color, TRUE, LLTracker::getLabel(), "" );
- }
- else if ( LLTracker::TRACKING_LANDMARK == tracking_status
- || LLTracker::TRACKING_LOCATION == tracking_status )
+ }
+ else if ( LLTracker::TRACKING_LANDMARK == tracking_status
+ || LLTracker::TRACKING_LOCATION == tracking_status )
{
// While fetching landmarks, will have 0,0,0 location for a while,
// so don't draw. JC
@@ -810,31 +549,33 @@ void LLWorldMapView::draw()
drawTracking( pos_global, map_track_color, TRUE, LLTracker::getLabel(), LLTracker::getToolTip() );
}
}
- else if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation)
+ else if (LLWorldMap::getInstance()->isTracking())
{
- if (LLWorldMap::getInstance()->mInvalidLocation)
+ if (LLWorldMap::getInstance()->isTrackingInvalidLocation())
{
- // We know this location to be invalid
+ // We know this location to be invalid, draw a blue circle
LLColor4 loading_color(0.0, 0.5, 1.0, 1.0);
- drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, getString("InvalidLocation"), "");
+ drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("InvalidLocation"), "");
}
else
{
+ // We don't know yet what that location is, draw a throbing blue circle
double value = fmod(current_time, 2);
- value = 0.5 + 0.5*cos(value * 3.14159f);
+ value = 0.5 + 0.5*cos(value * F_PI);
LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0);
- drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, getString("Loading"), "");
+ drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("Loading"), "");
}
}
- // #endif used to be here
-
+ #endif
+
// turn off the scissor
LLGLDisable no_scissor(GL_SCISSOR_TEST);
-
+
updateDirections();
LLView::draw();
+ // Get sim info for all sims in view
updateVisibleBlocks();
} // end draw()
@@ -845,36 +586,182 @@ void LLWorldMapView::setVisible(BOOL visible)
LLPanel::setVisible(visible);
if (!visible)
{
- for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++)
+ // 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)
+ {
+ // 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_idx<LLWorldMap::getInstance()->mMapLayers[map].size(); ++layer_idx)
- {
- if (LLWorldMap::getInstance()->mMapLayers[map][layer_idx].LayerDefined)
- {
- LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[map][layer_idx];
- layer->LayerImage->setBoostLevel(0);
- }
- }
+ drawMipmapLevel(width, height, l, false);
}
- for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin();
- it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
+ // 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)
{
- LLSimInfo* info = (*it).second;
- if (info->mCurrentImage.notNull())
+ drawMipmapLevel(width, height, level - 1, false);
+ }
+ }
+ 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<LLViewerFetchedTexture> simimage = LLWorldMap::getInstance()->getObjectsTile(grid_x, grid_y, level, load);
+ if (simimage)
{
- info->mCurrentImage->setBoostLevel(0);
+ // Checks that the image has a valid texture
+ if (simimage->hasGLTexture())
+ {
+ // 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;
+ //}
}
- if (info->mOverlayImage.notNull())
+ else
{
- info->mOverlayImage->setBoostLevel(0);
+ // Unexistent tiles are counted as "completed"
+ completed_tiles++;
}
+ // 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)
+{
+ 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 LLWorldMap::item_info_list_t& items, LLUIImagePtr image)
+void LLWorldMapView::drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image)
{
- LLWorldMap::item_info_list_t::const_iterator e;
+ LLSimInfo::item_info_list_t::const_iterator e;
for (e = items.begin(); e != items.end(); ++e)
{
drawGenericItem(*e, image);
@@ -883,7 +770,7 @@ void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items,
void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image)
{
- drawImage(item.mPosGlobal, image);
+ drawImage(item.getGlobalPosition(), image);
}
@@ -906,137 +793,91 @@ void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr i
}
}
-
-void LLWorldMapView::drawAgents()
+void LLWorldMapView::drawItems()
{
- static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white);
- static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white);
-
- F32 agents_scale = (gMapScale * 0.9f) / 256.f;
+ 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* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
- if (siminfo && (siminfo->mAccess == SIM_ACCESS_DOWN))
+ LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if ((info == NULL) || (info->isDown()))
{
continue;
}
- LLWorldMap::agent_list_map_t::iterator counts_iter = LLWorldMap::getInstance()->mAgentLocationsMap.find(handle);
- if (siminfo && siminfo->mShowAgentLocations && counts_iter != LLWorldMap::getInstance()->mAgentLocationsMap.end())
+ // Infohubs
+ if (gSavedSettings.getBOOL("MapShowInfohubs"))
{
- // 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)) ? map_avatar_friend_color : map_avatar_color;
- drawImageStack(info.mPosGlobal, sAvatarSmallImage, agent_count, 3.f, map_avatar_color);
- }
- LLWorldMap::getInstance()->mNumAgents[handle] = sim_agent_count; // override mNumAgents for this sim
+ drawGenericItems(info->getInfoHub(), sInfohubImage);
}
- else
+ // Telehubs
+ if (gSavedSettings.getBOOL("MapShowTelehubs"))
+ {
+ drawGenericItems(info->getTeleHub(), sTelehubImage);
+ }
+ // Land for sale
+ if (gSavedSettings.getBOOL("MapShowLandForSale"))
{
- // Show agent 'stack' at center of sim
- S32 num_agents = LLWorldMap::getInstance()->mNumAgents[handle];
- if (num_agents > 0)
+ 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())
{
- 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, map_avatar_color);
+ 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::drawEvents()
+void LLWorldMapView::drawAgents()
{
- bool mature_enabled = gAgent.canAccessMature();
- bool adult_enabled = gAgent.canAccessAdult();
-
- BOOL show_pg = gSavedSettings.getBOOL("MapShowEvents");
- BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents");
- BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents");
+ static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white);
- // First the non-selected events
- LLWorldMap::item_info_list_t::const_iterator e;
- if (show_pg)
+ for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter)
{
- for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e)
+ U64 handle = *iter;
+ LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if ((siminfo == NULL) || (siminfo->isDown()))
{
- if (!e->mSelected)
- {
- drawGenericItem(*e, sEventImage);
- }
+ continue;
}
- }
- 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)
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAgentLocation().begin();
+ while (it != siminfo->getAgentLocation().end())
{
- if (e->mSelected)
- {
- drawGenericItem(*e, sEventImage);
- }
+ // Show Individual agents (or little stacks where real agents are)
+
+ // Here's how we'd choose the color if info.mID were available but it's not being sent:
+ // LLColor4 color = (agent_count == 1 && is_agent_friend(info.mID)) ? friend_color : avatar_color;
+ drawImageStack(it->getGlobalPosition(), sAvatarSmallImage, it->getCount(), 3.f, map_avatar_color);
+ ++it;
}
}
- if (show_mature)
- {
- for (e = LLWorldMap::getInstance()->mMatureEvents.begin(); e != LLWorldMap::getInstance()->mMatureEvents.end(); ++e)
- {
- if (e->mSelected)
- {
- drawGenericItem(*e, sEventMatureImage);
- }
- }
- }
- if (show_adult)
- {
- for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e)
- {
- if (e->mSelected)
- {
- drawGenericItem(*e, sEventAdultImage);
- }
- }
- }
}
-
void LLWorldMapView::drawFrustum()
{
// Draw frustum
- F32 meters_to_pixels = gMapScale/ REGION_WIDTH_METERS;
+ F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS;
F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect();
F32 far_clip_meters = LLViewerCamera::getInstance()->getFar();
@@ -1077,8 +918,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] *= sPixelsPerMeter;
- pos_local.mV[VY] *= sPixelsPerMeter;
+ pos_local.mV[VX] *= sMapScale / REGION_WIDTH_METERS;
+ pos_local.mV[VY] *= sMapScale / REGION_WIDTH_METERS;
// leave Z component in meters
@@ -1162,7 +1003,7 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )
LLVector3 pos_local( (F32)x, (F32)y, 0.f );
- pos_local *= ( REGION_WIDTH_METERS / gMapScale );
+ pos_local *= ( REGION_WIDTH_METERS / sMapScale );
LLVector3d pos_global;
pos_global.setVec( pos_local );
@@ -1183,23 +1024,20 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )
BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask )
{
LLVector3d pos_global = viewPosToGlobal(x, y);
-
+ U64 handle = to_region_handle(pos_global);
std::string tooltip_msg;
- LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
+ LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
if (info)
{
LLViewerRegion *region = gAgent.getRegion();
- std::string message =
- llformat("%s (%s)",
- info->mName.c_str(),
- LLViewerRegion::accessToString(info->mAccess).c_str());
+ std::string message = llformat("%s (%s)", info->getName().c_str(), info->getAccessString().c_str());
- if (info->mAccess != SIM_ACCESS_DOWN)
+ if (!info->isDown())
{
- S32 agent_count = LLWorldMap::getInstance()->mNumAgents[info->mHandle];
- if (region && region->getHandle() == info->mHandle)
+ S32 agent_count = info->getAgentCount();
+ if (region && (region->getHandle() == handle))
{
++agent_count; // Bump by 1 if we're here
}
@@ -1208,6 +1046,8 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask )
// 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)
@@ -1223,7 +1063,7 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask )
tooltip_msg.assign( message );
// Optionally show region flags
- std::string region_flags = LLViewerRegion::regionFlagsToString(info->mRegionFlags);
+ std::string region_flags = info->getFlagsString();
if (!region_flags.empty())
{
@@ -1263,6 +1103,9 @@ static void drawDot(F32 x_pixels, F32 y_pixels,
}
else
{
+ // Draw V indicator for above or below
+ // *TODO: Replace this vector drawing with icons
+
F32 left = x_pixels - dot_radius;
F32 right = x_pixels + dot_radius;
F32 center = (left + right) * 0.5f;
@@ -1271,13 +1114,14 @@ static void drawDot(F32 x_pixels, F32 y_pixels,
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4fv( color.mV );
- LLUI::setLineWidth(1.5f);
- F32 h_bar = relative_z > HEIGHT_THRESHOLD ? top : bottom; // horizontal bar Y
+ LLUI::setLineWidth(3.0f);
+ F32 point = relative_z > HEIGHT_THRESHOLD ? top : bottom; // Y pos of the point of the V
+ F32 back = relative_z > HEIGHT_THRESHOLD ? bottom : top; // Y pos of the ends of the V
gGL.begin( LLRender::LINES );
- gGL.vertex2f(center, top);
- gGL.vertex2f(left, h_bar);
- gGL.vertex2f(right, h_bar);
- gGL.vertex2f(right, bottom);
+ gGL.vertex2f(left, back);
+ gGL.vertex2f(center, point);
+ gGL.vertex2f(center, point);
+ gGL.vertex2f(right, back);
gGL.end();
LLUI::setLineWidth(1.0f);
}
@@ -1292,7 +1136,7 @@ void LLWorldMapView::drawAvatar(F32 x_pixels,
F32 dot_radius)
{
const F32 HEIGHT_THRESHOLD = 7.f;
- LLUIImagePtr dot_image = sAvatarSmallImage;
+ LLUIImagePtr dot_image = sAvatarLevelImage;
if(relative_z < -HEIGHT_THRESHOLD)
{
dot_image = sAvatarBelowImage;
@@ -1301,10 +1145,12 @@ void LLWorldMapView::drawAvatar(F32 x_pixels,
{
dot_image = sAvatarAboveImage;
}
- dot_image->draw(
- llround(x_pixels) - dot_image->getWidth()/2,
- llround(y_pixels) - dot_image->getHeight()/2,
- color);
+ 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);
}
// Pass relative Z of 0 to draw at same level.
@@ -1565,7 +1411,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.mPosGlobal);
+ LLVector3 pos_view = globalPosToView(item.getGlobalPosition());
S32 item_x = llround(pos_view.mV[VX]);
S32 item_y = llround(pos_view.mV[VY]);
@@ -1574,12 +1420,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.mRegionHandle);
+ LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromHandle(item.getRegionHandle());
if (sim_info)
{
if (track)
{
- gFloaterWorldMap->trackLocation(item.mPosGlobal);
+ gFloaterWorldMap->trackLocation(item.getGlobalPosition());
}
}
@@ -1588,8 +1434,8 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo
gFloaterWorldMap->trackGenericItem(item);
}
- item.mSelected = TRUE;
- *id = item.mID;
+// item.setSelected(true);
+ *id = item.getUUID();
return true;
}
@@ -1612,108 +1458,116 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask,
*hit_type = 0; // hit nothing
- LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
- LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE;
- LLWorldMap::getInstance()->mIsTrackingCommit = FALSE;
+ LLWorldMap::getInstance()->cancelTracking();
- LLWorldMap::item_info_list_t::iterator it;
-
- // clear old selected stuff
- for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it)
- {
- (*it).mSelected = FALSE;
- }
- for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it)
+ S32 level = LLWorldMipmap::scaleToLevel(sMapScale);
+ // If the zoom level is not too far out already, test hits
+ if (level <= DRAW_SIMINFO_THRESHOLD)
{
- (*it).mSelected = FALSE;
- }
- for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it)
- {
- (*it).mSelected = FALSE;
- }
- for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it)
- {
- (*it).mSelected = FALSE;
- }
-
- // Select event you clicked on
- if (gSavedSettings.getBOOL("MapShowEvents"))
- {
- for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it)
- {
- LLItemInfo& event = *it;
-
- if (checkItemHit(x, y, event, id, false))
- {
- *hit_type = MAP_ITEM_PG_EVENT;
- mItemPicked = TRUE;
- gFloaterWorldMap->trackEvent(event);
- return;
- }
- }
- }
- if (gSavedSettings.getBOOL("ShowMatureEvents"))
- {
- for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it)
- {
- LLItemInfo& event = *it;
-
- if (checkItemHit(x, y, event, id, false))
- {
- *hit_type = MAP_ITEM_MATURE_EVENT;
- mItemPicked = TRUE;
- gFloaterWorldMap->trackEvent(event);
- return;
- }
- }
- }
- if (gSavedSettings.getBOOL("ShowAdultEvents"))
- {
- for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it)
- {
- LLItemInfo& event = *it;
-
- if (checkItemHit(x, y, event, id, false))
- {
- *hit_type = MAP_ITEM_ADULT_EVENT;
- mItemPicked = TRUE;
- gFloaterWorldMap->trackEvent(event);
- return;
- }
- }
- }
-
- if (gSavedSettings.getBOOL("MapShowLandForSale"))
- {
- for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it)
- {
- LLItemInfo& land = *it;
+ bool show_mature = gAgent.canAccessMature() && gSavedSettings.getBOOL("ShowMatureEvents");
+ bool show_adult = gAgent.canAccessAdult() && gSavedSettings.getBOOL("ShowAdultEvents");
- if (checkItemHit(x, y, land, id, true))
- {
- *hit_type = MAP_ITEM_LAND_FOR_SALE;
- mItemPicked = TRUE;
- return;
- }
- }
-
- for (it = LLWorldMap::getInstance()->mLandForSaleAdult.begin(); it != LLWorldMap::getInstance()->mLandForSaleAdult.end(); ++it)
+ // Test hits if trackable data are displayed, otherwise, we don't even bother
+ if (gSavedSettings.getBOOL("MapShowEvents") || show_mature || show_adult || gSavedSettings.getBOOL("MapShowLandForSale"))
{
- LLItemInfo& land = *it;
-
- if (checkItemHit(x, y, land, id, true))
+ // Iterate through the visible regions
+ for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter)
{
- *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT;
- mItemPicked = TRUE;
- return;
+ U64 handle = *iter;
+ LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if ((siminfo == NULL) || (siminfo->isDown()))
+ {
+ continue;
+ }
+ // If on screen check hits with the visible item lists
+ if (gSavedSettings.getBOOL("MapShowEvents"))
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getPGEvent().begin();
+ while (it != siminfo->getPGEvent().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, false))
+ {
+ *hit_type = MAP_ITEM_PG_EVENT;
+ mItemPicked = TRUE;
+ gFloaterWorldMap->trackEvent(event);
+ return;
+ }
+ ++it;
+ }
+ }
+ if (show_mature)
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getMatureEvent().begin();
+ while (it != siminfo->getMatureEvent().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, false))
+ {
+ *hit_type = MAP_ITEM_MATURE_EVENT;
+ mItemPicked = TRUE;
+ gFloaterWorldMap->trackEvent(event);
+ return;
+ }
+ ++it;
+ }
+ }
+ if (show_adult)
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAdultEvent().begin();
+ while (it != siminfo->getAdultEvent().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, false))
+ {
+ *hit_type = MAP_ITEM_ADULT_EVENT;
+ mItemPicked = TRUE;
+ gFloaterWorldMap->trackEvent(event);
+ return;
+ }
+ ++it;
+ }
+ }
+ if (gSavedSettings.getBOOL("MapShowLandForSale"))
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSale().begin();
+ while (it != siminfo->getLandForSale().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, true))
+ {
+ *hit_type = MAP_ITEM_LAND_FOR_SALE;
+ mItemPicked = TRUE;
+ return;
+ }
+ ++it;
+ }
+ // for 1.23, we're showing normal land and adult land in the same UI; you don't
+ // get a choice about which ones you want. If you're currently asking for adult
+ // content and land you'll get the adult land.
+ if (gAgent.canAccessAdult())
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSaleAdult().begin();
+ while (it != siminfo->getLandForSaleAdult().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, true))
+ {
+ *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT;
+ mItemPicked = TRUE;
+ return;
+ }
+ ++it;
+ }
+ }
+ }
}
}
}
- // If we get here, we haven't clicked on an icon
+ // If we get here, we haven't clicked on anything
gFloaterWorldMap->trackLocation(pos_global);
mItemPicked = FALSE;
-
*id = LLUUID::null;
return;
}
@@ -1774,59 +1628,36 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask )
return FALSE;
}
-U32 LLWorldMapView::updateBlock(S32 block_x, S32 block_y)
+void LLWorldMapView::updateVisibleBlocks()
{
- U32 blocks_requested = 0;
- S32 offset = block_x | (block_y * MAP_BLOCK_RES);
- if (!LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset])
+ if (LLWorldMipmap::scaleToLevel(sMapScale) > DRAW_SIMINFO_THRESHOLD)
{
-// 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++;
+ // If we're zoomed out too much, we just don't load all those sim info: too much!
+ return;
}
- return blocks_requested;
-}
-U32 LLWorldMapView::updateVisibleBlocks()
-{
- if (gMapScale < 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 = gMapScale;
const S32 width = getRect().getWidth();
const S32 height = getRect().getHeight();
- // Convert pan to sim coordinates
- S32 world_center_x_lo = S32(((-sPanX - width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS));
- S32 world_center_x_hi = S32(((-sPanX + width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS));
- S32 world_center_y_lo = S32(((-sPanY - height/2) / pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS));
- S32 world_center_y_hi = S32(((-sPanY + height/2)/ pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS));
-
- // 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;
-
- U32 blocks_requested = 0;
- const U32 max_blocks_requested = 9;
+ const F32 half_width = F32(width) / 2.0f;
+ const F32 half_height = F32(height) / 2.0f;
- 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;
-}
+ // 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));
+
+ // 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;
+
+ //LL_INFOS("World Map") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom = " << world_bottom << ", top = " << world_top << LL_ENDL;
+ LLWorldMap::getInstance()->updateRegions(world_left, world_bottom, world_right, world_top);
+}
BOOL LLWorldMapView::handleHover( S32 x, S32 y, MASK mask )
{
@@ -1915,16 +1746,16 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )
}
default:
{
- if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation)
+ if (LLWorldMap::getInstance()->isTracking())
{
- LLWorldMap::getInstance()->mIsTrackingDoubleClick = TRUE;
+ LLWorldMap::getInstance()->setTrackingDoubleClick();
}
else
{
// 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->mAccess != SIM_ACCESS_DOWN)
+ if (sim_info && !sim_info->isDown())
{
gAgent.teleportViaLocation( pos_global );
}