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 | 
