summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llappviewer.cpp4
-rw-r--r--indra/newview/llfloaterworldmap.cpp58
-rw-r--r--indra/newview/llfloaterworldmap.h4
-rw-r--r--indra/newview/llworldmapview.cpp105
-rw-r--r--indra/newview/llworldmapview.h25
5 files changed, 147 insertions, 49 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 254bf05d05..0428feddc1 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -589,7 +589,7 @@ static void settings_to_globals()
gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
- LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
+ LLWorldMapView::setScale(gSavedSettings.getF32("MapScale"));
#if LL_DARWIN
gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");
@@ -3404,7 +3404,7 @@ void LLAppViewer::cleanupSavedSettings()
}
}
- gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale );
+ gSavedSettings.setF32("MapScale", LLWorldMapView::getScale());
// Some things are cached in LLAgent.
if (gAgent.isInitialized())
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 27197f0b06..6e29a01dd1 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -79,7 +79,6 @@
//---------------------------------------------------------------------------
// Constants
//---------------------------------------------------------------------------
-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
@@ -300,13 +299,11 @@ BOOL LLFloaterWorldMap::postBuild()
landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo);
- mCurZoomVal = log(LLWorldMapView::sMapScale/256.f)/log(2.f);
- getChild<LLUICtrl>("zoom slider")->setValue(mCurZoomVal);
+ F32 slider_zoom = LLWorldMapView::getZoom();
+ getChild<LLUICtrl>("zoom slider")->setValue(slider_zoom);
setDefaultBtn(NULL);
- mZoomTimer.stop();
-
onChangeMaturity();
return TRUE;
@@ -406,18 +403,21 @@ BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask)
BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- if (!isMinimized() && isFrontmost())
- {
- if(mPanel->pointInView(x, y))
- {
- F32 slider_value = (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal();
- slider_value += ((F32)clicks * -0.3333f);
- getChild<LLUICtrl>("zoom slider")->setValue(LLSD(slider_value));
- return TRUE;
- }
- }
-
- return LLFloater::handleScrollWheel(x, y, clicks);
+ if (!isMinimized() && isFrontmost())
+ {
+ if (mPanel->pointInView(x, y))
+ {
+ F32 old_slider_zoom = (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal();
+ F32 slider_zoom = old_slider_zoom + ((F32)clicks * -0.3333f);
+ getChild<LLUICtrl>("zoom slider")->setValue(LLSD(slider_zoom));
+ S32 map_x = x - mPanel->getRect().mLeft;
+ S32 map_y = y - mPanel->getRect().mBottom;
+ LLWorldMapView::zoomWithPivot(slider_zoom, map_x, map_y);
+ return true;
+ }
+ }
+
+ return LLFloater::handleScrollWheel(x, y, clicks);
}
@@ -496,21 +496,8 @@ void LLFloaterWorldMap::draw()
setMouseOpaque(TRUE);
getDragHandle()->setMouseOpaque(TRUE);
-
- //RN: snaps to zoom value because interpolation caused jitter in the text rendering
- if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal())
- {
- mZoomTimer.start();
- }
- F32 interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME;
- if (interp > 1.f)
- {
- interp = 1.f;
- mZoomTimer.stop();
- }
- mCurZoomVal = lerp(mCurZoomVal, (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(), interp);
- F32 map_scale = 256.f*pow(2.f, mCurZoomVal);
- LLWorldMapView::setScale( map_scale );
+
+ LLWorldMapView::zoom((F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal());
// Enable/disable checkboxes depending on the zoom level
// If above threshold level (i.e. low res) -> Disable all checkboxes
@@ -1338,9 +1325,10 @@ 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)),
- !animate);
+ F64 map_scale = (F64)LLWorldMapView::getScale();
+ LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * map_scale / REGION_WIDTH_METERS)),
+ -llfloor((F32)(pos_global.mdV[VY] * map_scale / REGION_WIDTH_METERS)),
+ !animate);
mWaitingForTracker = FALSE;
}
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 97e99297cf..b7e2890906 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -156,10 +156,6 @@ protected:
private:
LLPanel* mPanel; // Panel displaying the map
- // Ties to LLWorldMapView::sMapScale, in pixels per region
- F32 mCurZoomVal;
- LLFrameTimer mZoomTimer;
-
// update display of teleport destination coordinates - pos is in global coordinates
void updateTeleportCoordsDisplay( const LLVector3d& pos );
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index a6df079223..e6092c6192 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -58,9 +58,14 @@
#include "llglheaders.h"
+// # Constants
+static const F32 MAP_ITERP_TIME_CONSTANT = 0.75f;
+static const F32 MAP_ZOOM_ACCELERATION_TIME = 0.3f;
+static const F32 MAP_ZOOM_MAX_INTERP = 0.5f;
+static const F32 MAP_SCALE_SNAP_THRESHOLD = 0.005f;
+
// 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;
@@ -100,6 +105,13 @@ S32 LLWorldMapView::sTrackingArrowX = 0;
S32 LLWorldMapView::sTrackingArrowY = 0;
bool LLWorldMapView::sVisibleTilesLoaded = false;
F32 LLWorldMapView::sMapScale = 128.f;
+F32 LLWorldMapView::sTargetMapScale = LLWorldMapView::sMapScale;
+LLVector2 LLWorldMapView::sZoomPivot = LLVector2(0.0f, 0.0f);
+LLFrameTimer LLWorldMapView::sZoomTimer = LLFrameTimer();
+// *HACK: Borrowing some non-static values from the parent LLPanel implementation. Ideally this entire class should not rely on statics for zoom functionality, but I'm treading lightly for smallest delta - Cosmic
+// TODO: Actually make this class non-static as discussed above, then test to make sure there are no adverse consequences to performance/stability - Cosmic
+F32 LLWorldMapView::sWidthForZoom = 0.0f;
+F32 LLWorldMapView::sHeightForZoom = 0.0f;
std::map<std::string,std::string> LLWorldMapView::sStringsMap;
@@ -210,6 +222,8 @@ BOOL LLWorldMapView::postBuild()
mTextBoxNorthEast ->reshapeToFitText();
mTextBoxSouthWest->reshapeToFitText();
mTextBoxNorthWest ->reshapeToFitText();
+
+ sZoomTimer.stop();
return true;
}
@@ -227,9 +241,36 @@ void LLWorldMapView::cleanupTextures()
{
}
+// static
+void LLWorldMapView::zoom(F32 zoom)
+{
+ sTargetMapScale = scaleFromZoom(zoom);
+ if (!sZoomTimer.getStarted() && sMapScale != sTargetMapScale)
+ {
+ sZoomPivot = LLVector2(0, 0);
+ sZoomTimer.start();
+ }
+}
+
+// static
+void LLWorldMapView::zoomWithPivot(F32 zoom, S32 x, S32 y)
+{
+ sTargetMapScale = scaleFromZoom(zoom);
+ sZoomPivot = LLVector2(x, y);
+ if (!sZoomTimer.getStarted() && sMapScale != sTargetMapScale)
+ {
+ sZoomTimer.start();
+ }
+}
+
+// static
+F32 LLWorldMapView::getZoom()
+{
+ return LLWorldMapView::zoomFromScale(sMapScale);
+}
// static
-void LLWorldMapView::setScale( F32 scale )
+void LLWorldMapView::setScale(F32 scale, bool snap)
{
if (scale != sMapScale)
{
@@ -247,9 +288,32 @@ void LLWorldMapView::setScale( F32 scale )
sTargetPanX = sPanX;
sTargetPanY = sPanY;
sVisibleTilesLoaded = false;
+
+ // If we are zooming relative to somewhere else rather than the center of the map, compensate for the difference in panning here
+ if (!sZoomPivot.isExactlyZero())
+ {
+ LLVector2 relative_pivot;
+ relative_pivot.mV[VX] = sZoomPivot.mV[VX] - (sWidthForZoom / 2.0);
+ relative_pivot.mV[VY] = sZoomPivot.mV[VY] - (sHeightForZoom / 2.0);
+ LLVector2 zoom_pan_offset = relative_pivot - (relative_pivot * scale / old_scale);
+ sPanX += zoom_pan_offset.mV[VX];
+ sPanY += zoom_pan_offset.mV[VY];
+ sTargetPanX += zoom_pan_offset.mV[VX];
+ sTargetPanY += zoom_pan_offset.mV[VY];
+ }
}
+
+ if (snap)
+ {
+ sTargetMapScale = scale;
+ }
}
+// static
+F32 LLWorldMapView::getScale()
+{
+ return sMapScale;
+}
// static
void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y )
@@ -301,11 +365,34 @@ void LLWorldMapView::draw()
mVisibleRegions.clear();
// animate pan if necessary
- sPanX = lerp(sPanX, sTargetPanX, LLSmoothInterpolation::getInterpolant(0.1f));
- sPanY = lerp(sPanY, sTargetPanY, LLSmoothInterpolation::getInterpolant(0.1f));
+ sPanX = lerp(sPanX, sTargetPanX, LLSmoothInterpolation::getInterpolant(MAP_ITERP_TIME_CONSTANT));
+ sPanY = lerp(sPanY, sTargetPanY, LLSmoothInterpolation::getInterpolant(MAP_ITERP_TIME_CONSTANT));
+
+ //RN: snaps to zoom value because interpolation caused jitter in the text rendering
+ if (!sZoomTimer.getStarted() && sMapScale != sTargetMapScale)
+ {
+ sZoomTimer.start();
+ }
+ bool snap_scale = false;
+ F32 interp = llmin(MAP_ZOOM_MAX_INTERP, sZoomTimer.getElapsedTimeF32() / MAP_ZOOM_ACCELERATION_TIME);
+ F32 current_zoom_val = zoomFromScale(sMapScale);
+ F32 target_zoom_val = zoomFromScale(sTargetMapScale);
+ F32 new_zoom_val = lerp(current_zoom_val, target_zoom_val, interp);
+ if (abs(new_zoom_val - current_zoom_val) < MAP_SCALE_SNAP_THRESHOLD)
+ {
+ sZoomTimer.stop();
+ snap_scale = true;
+ new_zoom_val = target_zoom_val;
+ }
+ F32 map_scale = scaleFromZoom(new_zoom_val);
+ setScale(map_scale, snap_scale);
const S32 width = getRect().getWidth();
const S32 height = getRect().getHeight();
+ // *HACK: Borrowing some non-static values from the parent LLPanel implementation. Ideally this entire class should not rely on statics for zoom functionality, but I'm treading lightly for smallest delta - Cosmic
+ // TODO: Actually make this class non-static as discussed above, then test to make sure there are no adverse consequences to performance/stability - Cosmic
+ sWidthForZoom = width;
+ sHeightForZoom = height;
const F32 half_width = F32(width) / 2.0f;
const F32 half_height = F32(height) / 2.0f;
LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal();
@@ -1792,4 +1879,14 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )
return FALSE;
}
+// static
+F32 LLWorldMapView::scaleFromZoom(F32 zoom)
+{
+ return exp2(zoom) * 256.0f;
+}
+// static
+F32 LLWorldMapView::zoomFromScale(F32 scale)
+{
+ return log2(scale / 256.f);
+}
diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h
index a2a6dc53fb..9a549a443a 100644
--- a/indra/newview/llworldmapview.h
+++ b/indra/newview/llworldmapview.h
@@ -67,8 +67,16 @@ 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)
- static void setScale( F32 scale );
+ // Zoom, scale, and pan are shared across all instances! (i.e. Terrain and Objects maps are always registered)
+ // Scale and zoom are the same thing but with different units.
+ // Scale is for things defined in in-world coordinates.
+ // Zoom is used for UI and will interpolate the map scale over multiple frames.
+ // Pan is in pixels relative to the center of the map.
+ static void zoom(F32 zoom);
+ static void zoomWithPivot(F32 zoom, S32 x, S32 y);
+ static F32 getZoom();
+ static void setScale(F32 scale, bool snap = true);
+ static F32 getScale();
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
@@ -153,8 +161,6 @@ public:
static LLUIImagePtr sForSaleImage;
static LLUIImagePtr sForSaleAdultImage;
- static F32 sMapScale; // scale = size of a region in pixels
-
BOOL mItemPicked;
static F32 sPanX; // in pixels
@@ -194,6 +200,17 @@ public:
private:
void drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right);
+
+ static F32 scaleFromZoom(F32 zoom);
+ static F32 zoomFromScale(F32 scale);
+
+ static F32 sMapScale;
+ static F32 sTargetMapScale;
+ static LLVector2 sZoomPivot;
+ static LLFrameTimer sZoomTimer;
+
+ static F32 sWidthForZoom;
+ static F32 sHeightForZoom;
};
#endif