diff options
-rw-r--r-- | indra/newview/llappviewer.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llfloaterworldmap.cpp | 58 | ||||
-rw-r--r-- | indra/newview/llfloaterworldmap.h | 4 | ||||
-rw-r--r-- | indra/newview/llworldmapview.cpp | 105 | ||||
-rw-r--r-- | indra/newview/llworldmapview.h | 25 |
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 |