PageRenderTime 771ms CodeModel.GetById 221ms app.highlight 418ms RepoModel.GetById 126ms app.codeStats 0ms

/indra/newview/llmanip.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 612 lines | 479 code | 86 blank | 47 comment | 53 complexity | 1ae2b383832c995ecc4f0a707cb564b3 MD5 | raw file
  1/** 
  2 * @file llmanip.cpp
  3 * @brief LLManip class implementation
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llmanip.h"
 30
 31#include "llmath.h"
 32#include "v3math.h"
 33#include "llgl.h"
 34#include "llrender.h"
 35#include "llprimitive.h"
 36#include "llview.h"
 37#include "llviewertexturelist.h"
 38
 39#include "llagent.h"
 40#include "llagentcamera.h"
 41#include "llviewercontrol.h"
 42#include "lldrawable.h"
 43#include "llfontgl.h"
 44#include "llhudrender.h"
 45#include "llselectmgr.h"
 46#include "llui.h"
 47#include "llviewercamera.h"
 48#include "llviewerjoint.h"
 49#include "llviewerobject.h"
 50#include "llviewerwindow.h"
 51#include "llvoavatar.h"
 52#include "llworld.h"		// for LLWorld::getInstance()
 53#include "llresmgr.h"
 54#include "pipeline.h"
 55#include "llglheaders.h"
 56
 57// Local constants...
 58const S32 VERTICAL_OFFSET = 50;
 59
 60F32		LLManip::sHelpTextVisibleTime = 2.f;
 61F32		LLManip::sHelpTextFadeTime = 2.f;
 62S32		LLManip::sNumTimesHelpTextShown = 0;
 63S32		LLManip::sMaxTimesShowHelpText = 5;
 64F32		LLManip::sGridMaxSubdivisionLevel = 32.f;
 65F32		LLManip::sGridMinSubdivisionLevel = 1.f;
 66LLVector2 LLManip::sTickLabelSpacing(60.f, 25.f);
 67
 68
 69//static
 70void LLManip::rebuild(LLViewerObject* vobj)
 71{
 72	LLDrawable* drawablep = vobj->mDrawable;
 73	if (drawablep && drawablep->getVOVolume())
 74	{
 75		
 76		gPipeline.markRebuild(drawablep,LLDrawable::REBUILD_VOLUME, TRUE);
 77		drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
 78		drawablep->updateMove();
 79		LLSpatialGroup* group = drawablep->getSpatialGroup();
 80		if (group)
 81		{
 82			group->dirtyGeom();
 83			gPipeline.markRebuild(group, TRUE);
 84		}
 85	}
 86}
 87
 88//////////////////////////////////////////////////////////////////////////////
 89// LLManip
 90
 91
 92LLManip::LLManip( const std::string& name, LLToolComposite* composite )
 93	:
 94	LLTool( name, composite ),
 95	mInSnapRegime(FALSE),
 96	mHighlightedPart(LL_NO_PART),
 97	mManipPart(LL_NO_PART)
 98{
 99}
100
101void LLManip::getManipNormal(LLViewerObject* object, EManipPart manip, LLVector3 &normal)
102{
103	LLVector3 grid_origin;
104	LLVector3 grid_scale;
105	LLQuaternion grid_rotation;
106
107	LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
108
109	if (manip >= LL_X_ARROW && manip <= LL_Z_ARROW)
110	{
111		LLVector3 arrow_axis;
112		getManipAxis(object, manip, arrow_axis);
113
114		LLVector3 cross = arrow_axis % LLViewerCamera::getInstance()->getAtAxis();
115		normal = cross % arrow_axis;
116		normal.normVec();
117	}
118	else if (manip >= LL_YZ_PLANE && manip <= LL_XY_PLANE)
119	{
120		switch (manip)
121		{
122		case LL_YZ_PLANE:
123			normal = LLVector3::x_axis;
124			break;
125		case LL_XZ_PLANE:
126			normal = LLVector3::y_axis;
127			break;
128		case LL_XY_PLANE:
129			normal = LLVector3::z_axis;
130			break;
131		default:
132			break;
133		}
134		normal.rotVec(grid_rotation);
135	}
136	else
137	{
138		normal.clearVec();
139	}
140}
141
142
143BOOL LLManip::getManipAxis(LLViewerObject* object, EManipPart manip, LLVector3 &axis)
144{
145	LLVector3 grid_origin;
146	LLVector3 grid_scale;
147	LLQuaternion grid_rotation;
148
149	LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
150
151	if (manip == LL_X_ARROW)
152	{
153		axis = LLVector3::x_axis;
154	}
155	else if (manip == LL_Y_ARROW)
156	{
157		axis = LLVector3::y_axis;
158	}
159	else if (manip == LL_Z_ARROW)
160	{
161		axis = LLVector3::z_axis;
162	}
163	else
164	{
165		return FALSE;
166	}
167
168	axis.rotVec( grid_rotation );
169	return TRUE;
170}
171
172F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVector3 &translate_axis, F32 grid_scale, S32 min_pixel_spacing)
173{
174	//update current snap subdivision level
175	LLVector3 cam_to_reference;
176	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
177	{
178		cam_to_reference = LLVector3(1.f / gAgentCamera.mHUDCurZoom, 0.f, 0.f);
179	}
180	else
181	{
182		cam_to_reference = reference_point - LLViewerCamera::getInstance()->getOrigin();
183	}
184	F32 current_range = cam_to_reference.normVec();
185
186	F32 projected_translation_axis_length = (translate_axis % cam_to_reference).magVec();
187	F32 subdivisions = llmax(projected_translation_axis_length * grid_scale / (current_range / LLViewerCamera::getInstance()->getPixelMeterRatio() * min_pixel_spacing), 0.f);
188	subdivisions = llclamp((F32)pow(2.f, llfloor(log(subdivisions) / log(2.f))), 1.f / 32.f, 32.f);
189
190	return subdivisions;
191}
192
193void LLManip::handleSelect()
194{
195	mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
196}
197
198void LLManip::handleDeselect()
199{
200	mHighlightedPart = LL_NO_PART;
201	mManipPart = LL_NO_PART;
202	mObjectSelection = NULL;
203}
204
205LLObjectSelectionHandle LLManip::getSelection()
206{
207	return mObjectSelection;
208}
209
210BOOL LLManip::handleHover(S32 x, S32 y, MASK mask)
211{
212	// We only handle the event if mousedown started with us
213	if( hasMouseCapture() )
214	{
215		if( mObjectSelection->isEmpty() )
216		{
217			// Somehow the object got deselected while we were dragging it.
218			// Release the mouse
219			setMouseCapture( FALSE );
220		}
221
222		lldebugst(LLERR_USER_INPUT) << "hover handled by LLManip (active)" << llendl;
223	}
224	else
225	{
226		lldebugst(LLERR_USER_INPUT) << "hover handled by LLManip (inactive)" << llendl;
227	}
228	gViewerWindow->setCursor(UI_CURSOR_ARROW);
229	return TRUE;
230}
231
232
233BOOL LLManip::handleMouseUp(S32 x, S32 y, MASK mask)
234{
235	BOOL	handled = FALSE;
236	if( hasMouseCapture() )
237	{
238		handled = TRUE;
239		setMouseCapture( FALSE );
240	}
241	return handled;
242}
243
244void LLManip::updateGridSettings()
245{
246	sGridMaxSubdivisionLevel = gSavedSettings.getBOOL("GridSubUnit") ? (F32)gSavedSettings.getS32("GridSubdivision") : 1.f;
247}
248
249BOOL LLManip::getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector3 origin, LLVector3 normal)
250{
251	LLVector3d origin_double = gAgent.getPosGlobalFromAgent(origin);
252	LLVector3d global_point;
253	BOOL result = getMousePointOnPlaneGlobal(global_point, x, y, origin_double, normal);
254	point = gAgent.getPosAgentFromGlobal(global_point);
255	return result;
256}
257
258BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal) const
259{
260	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
261	{
262		BOOL result = FALSE;
263		F32 mouse_x = ((F32)x / gViewerWindow->getWorldViewWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom;
264		F32 mouse_y = ((F32)y / gViewerWindow->getWorldViewHeightScaled() - 0.5f) / gAgentCamera.mHUDCurZoom;
265
266		LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin);
267		LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y);
268		if (llabs(normal.mV[VX]) < 0.001f)
269		{
270			// use largish value that should be outside HUD manipulation range
271			mouse_pos.mV[VX] = 10.f;
272		}
273		else
274		{
275			mouse_pos.mV[VX] = (normal * (origin_agent - mouse_pos))
276								/ (normal.mV[VX]);
277			result = TRUE;
278		}
279
280		point = gAgent.getPosGlobalFromAgent(mouse_pos);
281		return result;
282	}
283	else
284	{
285		return gViewerWindow->mousePointOnPlaneGlobal(
286										point, x, y, origin, normal );
287	}
288
289	//return FALSE;
290}
291
292// Given the line defined by mouse cursor (a1 + a_param*(a2-a1)) and the line defined by b1 + b_param*(b2-b1),
293// returns a_param and b_param for the points where lines are closest to each other.
294// Returns false if the two lines are parallel.
295BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param )
296{
297	LLVector3 a1;
298	LLVector3 a2;
299
300	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
301	{
302		F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidthScaled()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom;
303		F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeightScaled()) - 0.5f) / gAgentCamera.mHUDCurZoom;
304		a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y);
305		a2 = a1 + LLVector3(1.f, 0.f, 0.f);
306	}
307	else
308	{
309		a1 = gAgentCamera.getCameraPositionAgent();
310		a2 = gAgentCamera.getCameraPositionAgent() + LLVector3(gViewerWindow->mouseDirectionGlobal(x, y));
311	}
312
313	BOOL parallel = TRUE;
314	LLVector3 a = a2 - a1;
315	LLVector3 b = b2 - b1;
316
317	LLVector3 normal;
318	F32 dist, denom;
319	normal = (b % a) % b;	// normal to plane (P) through b and (shortest line between a and b)
320	normal.normVec();
321	dist = b1 * normal;			// distance from origin to P
322
323	denom = normal * a; 
324	if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) )
325	{
326		a_param = (dist - normal * a1) / denom;
327		parallel = FALSE;
328	}
329
330	normal = (a % b) % a;	// normal to plane (P) through a and (shortest line between a and b)
331	normal.normVec();
332	dist = a1 * normal;			// distance from origin to P
333	denom = normal * b; 
334	if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) )
335	{
336		b_param = (dist - normal * b1) / denom;
337		parallel = FALSE;
338	}
339
340	return parallel;
341}
342
343LLVector3 LLManip::getSavedPivotPoint() const
344{
345	return LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent();
346}
347
348LLVector3 LLManip::getPivotPoint()
349{
350	if (mObjectSelection->getFirstObject() && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
351	{
352		return mObjectSelection->getFirstObject()->getPivotPositionAgent();
353	}
354	return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent();
355}
356
357
358void LLManip::renderGuidelines(BOOL draw_x, BOOL draw_y, BOOL draw_z)
359{
360	LLVector3 grid_origin;
361	LLQuaternion grid_rot;
362	LLVector3 grid_scale;
363	LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rot, grid_scale);
364
365	const BOOL children_ok = TRUE;
366	LLViewerObject* object = mObjectSelection->getFirstRootObject(children_ok);
367	if (!object)
368	{
369		return;
370	}
371
372	//LLVector3  center_agent  = LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent();
373	LLVector3  center_agent  = getPivotPoint();
374
375	gGL.pushMatrix();
376	{
377		gGL.translatef(center_agent.mV[VX], center_agent.mV[VY], center_agent.mV[VZ]);
378
379		F32 angle_radians, x, y, z;
380
381		grid_rot.getAngleAxis(&angle_radians, &x, &y, &z);
382		gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
383
384		F32 region_size = LLWorld::getInstance()->getRegionWidthInMeters();
385
386		const F32 LINE_ALPHA = 0.33f;
387
388		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
389		LLUI::setLineWidth(1.5f);
390
391		if (draw_x)
392		{
393			gGL.color4f(1.f, 0.f, 0.f, LINE_ALPHA);
394			gGL.begin(LLRender::LINES);
395			gGL.vertex3f( -region_size, 0.f, 0.f );
396			gGL.vertex3f(  region_size, 0.f, 0.f );
397			gGL.end();
398		}
399
400		if (draw_y)
401		{
402			gGL.color4f(0.f, 1.f, 0.f, LINE_ALPHA);
403			gGL.begin(LLRender::LINES);
404			gGL.vertex3f( 0.f, -region_size, 0.f );
405			gGL.vertex3f( 0.f,  region_size, 0.f );
406			gGL.end();
407		}
408
409		if (draw_z)
410		{
411			gGL.color4f(0.f, 0.f, 1.f, LINE_ALPHA);
412			gGL.begin(LLRender::LINES);
413			gGL.vertex3f( 0.f, 0.f, -region_size );
414			gGL.vertex3f( 0.f, 0.f,  region_size );
415			gGL.end();
416		}
417		LLUI::setLineWidth(1.0f);
418	}
419	gGL.popMatrix();
420}
421
422void LLManip::renderXYZ(const LLVector3 &vec) 
423{
424	const S32 PAD = 10;
425	std::string feedback_string;
426	LLVector3 camera_pos = LLViewerCamera::getInstance()->getOrigin() + LLViewerCamera::getInstance()->getAtAxis();
427	S32 window_center_x = gViewerWindow->getWorldViewRectScaled().getWidth() / 2;
428	S32 window_center_y = gViewerWindow->getWorldViewRectScaled().getHeight() / 2;
429	S32 vertical_offset = window_center_y - VERTICAL_OFFSET;
430
431
432	gGL.pushMatrix();
433	{
434		LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
435		gViewerWindow->setup2DRender();
436		const LLVector2& display_scale = gViewerWindow->getDisplayScale();
437		gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
438		gGL.color4f(0.f, 0.f, 0.f, 0.7f);
439
440		imagep->draw(
441			window_center_x - 115, 
442			window_center_y + vertical_offset - PAD, 
443			235,
444			PAD * 2 + 10, 
445			LLColor4(0.f, 0.f, 0.f, 0.7f) );
446	}
447	gGL.popMatrix();
448
449	gViewerWindow->setup3DRender();
450
451	{
452		LLFontGL* font = LLFontGL::getFontSansSerif();
453		LLLocale locale(LLLocale::USER_LOCALE);
454		LLGLDepthTest gls_depth(GL_FALSE);
455		// render drop shadowed text
456		feedback_string = llformat("X: %.3f", vec.mV[VX]);
457		hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -102.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
458
459		feedback_string = llformat("Y: %.3f", vec.mV[VY]);
460		hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -27.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
461		
462		feedback_string = llformat("Z: %.3f", vec.mV[VZ]);
463		hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 48.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
464
465		// render text on top
466		feedback_string = llformat("X: %.3f", vec.mV[VX]);
467		hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -102.f, (F32)vertical_offset, LLColor4(1.f, 0.5f, 0.5f, 1.f), FALSE);
468
469		gGL.diffuseColor3f(0.5f, 1.f, 0.5f);
470		feedback_string = llformat("Y: %.3f", vec.mV[VY]);
471		hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -27.f, (F32)vertical_offset, LLColor4(0.5f, 1.f, 0.5f, 1.f), FALSE);
472		
473		gGL.diffuseColor3f(0.5f, 0.5f, 1.f);
474		feedback_string = llformat("Z: %.3f", vec.mV[VZ]);
475		hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 48.f, (F32)vertical_offset, LLColor4(0.5f, 0.5f, 1.f, 1.f), FALSE);
476	}
477}
478
479void LLManip::renderTickText(const LLVector3& pos, const std::string& text, const LLColor4 &color)
480{
481	const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
482
483	BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD;
484	gGL.matrixMode(LLRender::MM_MODELVIEW);
485	gGL.pushMatrix();
486	LLVector3 render_pos = pos;
487	if (hud_selection)
488	{
489		F32 zoom_amt = gAgentCamera.mHUDCurZoom;
490		F32 inv_zoom_amt = 1.f / zoom_amt;
491		// scale text back up to counter-act zoom level
492		render_pos = pos * zoom_amt;
493		gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt);
494	}
495
496	// render shadow first
497	LLColor4 shadow_color = LLColor4::black;
498	shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
499	gViewerWindow->setup3DViewport(1, -1);
500	hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,  -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
501	gViewerWindow->setup3DViewport();
502	hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
503
504	gGL.popMatrix();
505}
506
507void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string& suffix, const LLColor4 &color)
508{
509	LLLocale locale(LLLocale::USER_LOCALE);
510
511	const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
512	const LLFontGL* small_fontp = LLFontGL::getFontSansSerifSmall();
513
514	std::string val_string;
515	std::string fraction_string;
516	F32 val_to_print = llround(value, 0.001f);
517	S32 fractional_portion = llround(fmodf(llabs(val_to_print), 1.f) * 100.f);
518	if (val_to_print < 0.f)
519	{
520		if (fractional_portion == 0)
521		{
522			val_string = llformat("-%d%s", lltrunc(llabs(val_to_print)), suffix.c_str());
523		}
524		else
525		{
526			val_string = llformat("-%d", lltrunc(llabs(val_to_print)));
527		}
528	}
529	else
530	{
531		if (fractional_portion == 0)
532		{
533			val_string = llformat("%d%s", lltrunc(llabs(val_to_print)), suffix.c_str());
534		}
535		else
536		{
537			val_string = llformat("%d", lltrunc(val_to_print));
538		}
539	}
540
541	BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD;
542	gGL.matrixMode(LLRender::MM_MODELVIEW);
543	gGL.pushMatrix();
544	LLVector3 render_pos = pos;
545	if (hud_selection)
546	{
547		F32 zoom_amt = gAgentCamera.mHUDCurZoom;
548		F32 inv_zoom_amt = 1.f / zoom_amt;
549		// scale text back up to counter-act zoom level
550		render_pos = pos * zoom_amt;
551		gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt);
552	}
553
554	LLColor4 shadow_color = LLColor4::black;
555	shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
556
557	if (fractional_portion != 0)
558	{
559		fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str());
560
561		gViewerWindow->setup3DViewport(1, -1);
562		hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection);
563		hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, shadow_color, hud_selection);
564
565		gViewerWindow->setup3DViewport();
566		hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
567		hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, color, hud_selection);
568	}
569	else
570	{
571		gViewerWindow->setup3DViewport(1, -1);
572		hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection);
573		gViewerWindow->setup3DViewport();
574		hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
575	}
576	gGL.popMatrix();
577}
578
579LLColor4 LLManip::setupSnapGuideRenderPass(S32 pass)
580{
581	static LLColor4 grid_color_fg = LLUIColorTable::instance().getColor("GridlineColor");
582	static LLColor4 grid_color_bg = LLUIColorTable::instance().getColor("GridlineBGColor");
583	static LLColor4 grid_color_shadow = LLUIColorTable::instance().getColor("GridlineShadowColor");
584
585	LLColor4 line_color;
586	F32 line_alpha = gSavedSettings.getF32("GridOpacity");
587
588	switch(pass)
589	{
590	case 0:
591		// shadow
592		gViewerWindow->setup3DViewport(1, -1);
593		line_color = grid_color_shadow;
594		line_color.mV[VALPHA] *= line_alpha;
595		LLUI::setLineWidth(2.f);
596		break;
597	case 1:
598		// hidden lines
599		gViewerWindow->setup3DViewport();
600		line_color = grid_color_bg;
601		line_color.mV[VALPHA] *= line_alpha;
602		LLUI::setLineWidth(1.f);
603		break;
604	case 2:
605		// visible lines
606		line_color = grid_color_fg;
607		line_color.mV[VALPHA] *= line_alpha;
608		break;
609	}
610
611	return line_color;
612}