Files
SingularityViewer/indra/newview/llmanip.cpp
Inusaito Sayori 4725db2d2f Merge branch 'VarRegion' of https://github.com/Lirusaito/SingularityViewer into aurora-sim
Merged cleanly:
	indra/llkeyframewalkmotion.cpp - 36e6946c96 - worked around a bug in Aurora walking motion
	indra/llrender/llimagegl.cpp - fa8e1f033b - An llerrs here becomes an llwarns, to avoid bothering the user with non power of two dimensioned images
	indra/newview/llmanip.cpp, indra/newview/llmanipscale.cpp - "Changed hardcoded 256 constants and such to width functions" - a50f0008b2
	indra/newview/llpatchvertexarray.cpp - fa8e1f033b - Support patches of non power of two width
	indra/newview/llworldmap.h - conflict

Conflicts:
	indra/llmessage/patch_code.cpp - My version cleaned up a bit of code duplication, so this was applied, within the new tags
	indra/llmessage/patch_code.h - b_large_patch in decode_patch_header defaults to false, indra/newview/llcloud.cpp patch removed.
	indra/llmessage/patch_dct.h - false positive
	indra/newview/llagent.cpp - false positive
	indra/newview/llfloaterregioninfo.cpp - nonsl wacky textures support meets the refactor.
	indra/newview/llfloaterworldmap.cpp - false positive
	indra/newview/llglsandbox.cpp - false positive
	indra/newview/llnetmap.cpp - small changes for type consistency brought into FS' patch, nothing important; also adds change to LLNetMap:draw removing getRegionWidthInMeters to keep using the constant REGION_WIDTH
	indra/newview/llpanelobject.cpp - Get the region width of the object we're editing for maximum pasted x/y coords
	indra/newview/llstartup.cpp - [Fixes old issues] My old patch did not fully use first_sim_size_x here, this has been fixed.  The unused first_sim_size_y has been removed.
	indra/newview/llsurface.cpp - rebuildWater isn't used, removed for now.  Styling conflicts otherwise.
	indra/newview/llsurfacepatch.cpp - remove FS patch that comments out code that isn't even in the modern source; cleaned up a mess of tags with more clear explanation, perhaps it can be expanded upon though.  Some styling conflicts.
	indra/newview/llviewermessage.cpp - Fix the problem? setRegionWidth by number.
	indra/newview/llviewerobject.cpp - false positive
	indra/newview/llviewerparcelmgr.cpp - just styling conflicts
	indra/newview/llviewerparcelmgr.h - false positive
	indra/newview/llviewerparceloverlay.cpp - false positive
	indra/newview/llviewerparceloverlay.h - false positive
	indra/newview/llviewerregion.cpp - cleaned up LLViewerRegion::getCompositionXY patches, they're more in the way than they're worth; removed DispatchOpenRegionSettings capability mention for now, it's not related to variable regions.  Also remove rebuildWater, it's not used right now.
	indra/newview/llvowater.cpp - false positive
	indra/newview/llwind.cpp - remove decode_patch_header patches for false, since we have a default; otherwise false positive.
	indra/newview/llworld.*
		- [Fixes old issues] Remove setRegionWidth by LLMessageSystem as the messages used are not always the same, the by number one remains of course.
		- Retained separation of connecting neighbors through the old method when the width is 256
		- updateLimits() would never have been merged in, we have an entirely different grid manager, therefore it's removed.
		- Fix the stupidity passed on over the years wherein a static constant variable would hold the same value as the first call to setLandFarClip..
	indra/newview/llworldmap.cpp - 36e6946c96 Aurora map workaround stuffs, parts removed; rework of LLWorldMap::simInfoFromHandle
	indra/newview/llworldmap.h - Cleaned up organization, avoid making members public, and fixed tagging
2013-09-27 09:51:39 -04:00

638 lines
20 KiB
C++

/**
* @file llmanip.cpp
* @brief LLManip class implementation
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llmanip.h"
#include "llmath.h"
#include "v3math.h"
#include "llgl.h"
#include "llrender.h"
#include "llprimitive.h"
#include "llview.h"
#include "llviewertexturelist.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "llviewercontrol.h"
#include "lldrawable.h"
#include "llfontgl.h"
#include "llhudrender.h"
#include "llselectmgr.h"
#include "llui.h"
#include "llviewercamera.h"
#include "llviewerjoint.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llresmgr.h"
#include "pipeline.h"
#include "llglheaders.h"
// Local constants...
const S32 VERTICAL_OFFSET = 50;
F32 LLManip::sHelpTextVisibleTime = 2.f;
F32 LLManip::sHelpTextFadeTime = 2.f;
S32 LLManip::sNumTimesHelpTextShown = 0;
S32 LLManip::sMaxTimesShowHelpText = 5;
F32 LLManip::sGridMaxSubdivisionLevel = 32.f;
F32 LLManip::sGridMinSubdivisionLevel = 1.f;
LLVector2 LLManip::sTickLabelSpacing(60.f, 25.f);
//static
void LLManip::rebuild(LLViewerObject* vobj)
{
LLDrawable* drawablep = vobj->mDrawable;
if (drawablep && drawablep->getVOVolume())
{
gPipeline.markRebuild(drawablep,LLDrawable::REBUILD_VOLUME, TRUE);
drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
drawablep->updateMove();
LLSpatialGroup* group = drawablep->getSpatialGroup();
if (group)
{
group->dirtyGeom();
gPipeline.markRebuild(group, TRUE);
}
LLViewerObject::const_child_list_t& child_list = vobj->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(), endIter = child_list.end();
iter != endIter; ++iter)
{
LLViewerObject* child = *iter;
rebuild(child);
}
}
}
//////////////////////////////////////////////////////////////////////////////
// LLManip
LLManip::LLManip( const std::string& name, LLToolComposite* composite )
:
LLTool( name, composite ),
mInSnapRegime(FALSE),
mHighlightedPart(LL_NO_PART),
mManipPart(LL_NO_PART)
{
}
void LLManip::getManipNormal(LLViewerObject* object, EManipPart manip, LLVector3 &normal)
{
LLVector3 grid_origin;
LLVector3 grid_scale;
LLQuaternion grid_rotation;
LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
if (manip >= LL_X_ARROW && manip <= LL_Z_ARROW)
{
LLVector3 arrow_axis;
getManipAxis(object, manip, arrow_axis);
LLVector3 cross = arrow_axis % LLViewerCamera::getInstance()->getAtAxis();
normal = cross % arrow_axis;
normal.normVec();
}
else if (manip >= LL_YZ_PLANE && manip <= LL_XY_PLANE)
{
switch (manip)
{
case LL_YZ_PLANE:
normal = LLVector3::x_axis;
break;
case LL_XZ_PLANE:
normal = LLVector3::y_axis;
break;
case LL_XY_PLANE:
normal = LLVector3::z_axis;
break;
default:
break;
}
normal.rotVec(grid_rotation);
}
else
{
normal.clearVec();
}
}
BOOL LLManip::getManipAxis(LLViewerObject* object, EManipPart manip, LLVector3 &axis)
{
LLVector3 grid_origin;
LLVector3 grid_scale;
LLQuaternion grid_rotation;
LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
if (manip == LL_X_ARROW)
{
axis = LLVector3::x_axis;
}
else if (manip == LL_Y_ARROW)
{
axis = LLVector3::y_axis;
}
else if (manip == LL_Z_ARROW)
{
axis = LLVector3::z_axis;
}
else
{
return FALSE;
}
axis.rotVec( grid_rotation );
return TRUE;
}
F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVector3 &translate_axis, F32 grid_scale, S32 min_pixel_spacing)
{
//update current snap subdivision level
LLVector3 cam_to_reference;
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
cam_to_reference = LLVector3(1.f / gAgentCamera.mHUDCurZoom, 0.f, 0.f);
}
else
{
cam_to_reference = reference_point - LLViewerCamera::getInstance()->getOrigin();
}
F32 current_range = cam_to_reference.normVec();
F32 projected_translation_axis_length = (translate_axis % cam_to_reference).magVec();
F32 subdivisions = llmax(projected_translation_axis_length * grid_scale / (current_range / LLViewerCamera::getInstance()->getPixelMeterRatio() * min_pixel_spacing), 0.f);
subdivisions = llclamp((F32)pow(2.f, llfloor(log(subdivisions) / log(2.f))), 1.f / 32.f, 32.f);
return subdivisions;
}
void LLManip::handleSelect()
{
mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
}
void LLManip::handleDeselect()
{
mHighlightedPart = LL_NO_PART;
mManipPart = LL_NO_PART;
mObjectSelection = NULL;
}
LLObjectSelectionHandle LLManip::getSelection()
{
return mObjectSelection;
}
BOOL LLManip::handleHover(S32 x, S32 y, MASK mask)
{
// We only handle the event if mousedown started with us
if( hasMouseCapture() )
{
if( mObjectSelection->isEmpty() )
{
// Somehow the object got deselected while we were dragging it.
// Release the mouse
setMouseCapture( FALSE );
}
lldebugst(LLERR_USER_INPUT) << "hover handled by LLManip (active)" << llendl;
}
else
{
lldebugst(LLERR_USER_INPUT) << "hover handled by LLManip (inactive)" << llendl;
}
gViewerWindow->setCursor(UI_CURSOR_ARROW);
return TRUE;
}
BOOL LLManip::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
if( hasMouseCapture() )
{
handled = TRUE;
setMouseCapture( FALSE );
}
return handled;
}
void LLManip::updateGridSettings()
{
sGridMaxSubdivisionLevel = gSavedSettings.getBOOL("GridSubUnit") ? (F32)gSavedSettings.getS32("GridSubdivision") : 1.f;
}
BOOL LLManip::getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector3 origin, LLVector3 normal)
{
LLVector3d origin_double = gAgent.getPosGlobalFromAgent(origin);
LLVector3d global_point;
BOOL result = getMousePointOnPlaneGlobal(global_point, x, y, origin_double, normal);
point = gAgent.getPosAgentFromGlobal(global_point);
return result;
}
BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal) const
{
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
BOOL result = FALSE;
F32 mouse_x = ((F32)x / gViewerWindow->getWorldViewWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom;
F32 mouse_y = ((F32)y / gViewerWindow->getWorldViewHeightScaled() - 0.5f) / gAgentCamera.mHUDCurZoom;
LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin);
LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y);
if (llabs(normal.mV[VX]) < 0.001f)
{
// use largish value that should be outside HUD manipulation range
mouse_pos.mV[VX] = 10.f;
}
else
{
mouse_pos.mV[VX] = (normal * (origin_agent - mouse_pos))
/ (normal.mV[VX]);
result = TRUE;
}
point = gAgent.getPosGlobalFromAgent(mouse_pos);
return result;
}
else
{
return gViewerWindow->mousePointOnPlaneGlobal(
point, x, y, origin, normal );
}
//return FALSE;
}
// Given the line defined by mouse cursor (a1 + a_param*(a2-a1)) and the line defined by b1 + b_param*(b2-b1),
// returns a_param and b_param for the points where lines are closest to each other.
// Returns false if the two lines are parallel.
BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param )
{
LLVector3 a1;
LLVector3 a2;
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidthScaled()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom;
F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeightScaled()) - 0.5f) / gAgentCamera.mHUDCurZoom;
a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y);
a2 = a1 + LLVector3(1.f, 0.f, 0.f);
}
else
{
a1 = gAgentCamera.getCameraPositionAgent();
a2 = gAgentCamera.getCameraPositionAgent() + LLVector3(gViewerWindow->mouseDirectionGlobal(x, y));
}
BOOL parallel = TRUE;
LLVector3 a = a2 - a1;
LLVector3 b = b2 - b1;
LLVector3 normal;
F32 dist, denom;
normal = (b % a) % b; // normal to plane (P) through b and (shortest line between a and b)
normal.normVec();
dist = b1 * normal; // distance from origin to P
denom = normal * a;
if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) )
{
a_param = (dist - normal * a1) / denom;
parallel = FALSE;
}
normal = (a % b) % a; // normal to plane (P) through a and (shortest line between a and b)
normal.normVec();
dist = a1 * normal; // distance from origin to P
denom = normal * b;
if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) )
{
b_param = (dist - normal * b1) / denom;
parallel = FALSE;
}
return parallel;
}
LLVector3 LLManip::getSavedPivotPoint() const
{
return LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent();
}
LLVector3 LLManip::getPivotPoint()
{
static LLCachedControl<bool> actual_root("AscentBuildPrefs_ActualRoot");
static LLCachedControl<bool> pivot_as_percent("AscentBuildPrefs_PivotIsPercent");
LLVector3 offset(50,50,50);
//Are we are using the defaults?
if(gSavedSettings.getBOOL("LiruEnableBuildPrefs"))
{
static LLCachedControl<F32> pivot_x("AscentBuildPrefs_PivotX");
static LLCachedControl<F32> pivot_y("AscentBuildPrefs_PivotY");
static LLCachedControl<F32> pivot_z("AscentBuildPrefs_PivotZ");
offset = LLVector3(pivot_x,pivot_y,pivot_z);
}
else
pivot_as_percent = true;
if (mObjectSelection->getFirstRootObject(TRUE) && (mObjectSelection->getObjectCount() == 1 || actual_root) && mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
{
if(pivot_as_percent)
offset = ((offset * .01f) - LLVector3(.5f,.5f,.5f)).scaleVec(mObjectSelection->getFirstRootObject(TRUE)->getScale());
return mObjectSelection->getFirstRootObject(TRUE)->getPivotPositionAgent() + offset * mObjectSelection->getFirstRootObject(TRUE)->getRotation();
}
if(pivot_as_percent)
offset = ((offset * .01f) - LLVector3(.5f,.5f,.5f)).scaleVec(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal());
return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent() + offset * LLSelectMgr::getInstance()->getBBoxOfSelection().getRotation();
}
void LLManip::renderGuidelines(BOOL draw_x, BOOL draw_y, BOOL draw_z)
{
LLVector3 grid_origin;
LLQuaternion grid_rot;
LLVector3 grid_scale;
LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rot, grid_scale);
const BOOL children_ok = TRUE;
LLViewerObject* object = mObjectSelection->getFirstRootObject(children_ok);
if (!object)
{
return;
}
//LLVector3 center_agent = LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent();
LLVector3 center_agent = getPivotPoint();
gGL.pushMatrix();
{
gGL.translatef(center_agent.mV[VX], center_agent.mV[VY], center_agent.mV[VZ]);
F32 angle_radians, x, y, z;
grid_rot.getAngleAxis(&angle_radians, &x, &y, &z);
gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
F32 region_size = object->getRegion()->getWidth();
const F32 LINE_ALPHA = 0.33f;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLUI::setLineWidth(1.5f);
if (draw_x)
{
gGL.color4f(1.f, 0.f, 0.f, LINE_ALPHA);
gGL.begin(LLRender::LINES);
gGL.vertex3f( -region_size, 0.f, 0.f );
gGL.vertex3f( region_size, 0.f, 0.f );
gGL.end();
}
if (draw_y)
{
gGL.color4f(0.f, 1.f, 0.f, LINE_ALPHA);
gGL.begin(LLRender::LINES);
gGL.vertex3f( 0.f, -region_size, 0.f );
gGL.vertex3f( 0.f, region_size, 0.f );
gGL.end();
}
if (draw_z)
{
gGL.color4f(0.f, 0.f, 1.f, LINE_ALPHA);
gGL.begin(LLRender::LINES);
gGL.vertex3f( 0.f, 0.f, -region_size );
gGL.vertex3f( 0.f, 0.f, region_size );
gGL.end();
}
LLUI::setLineWidth(1.0f);
}
gGL.popMatrix();
}
void LLManip::renderXYZ(const LLVector3 &vec)
{
const S32 PAD = 10;
std::string feedback_string;
LLVector3 camera_pos = LLViewerCamera::getInstance()->getOrigin() + LLViewerCamera::getInstance()->getAtAxis();
S32 window_center_x = gViewerWindow->getWorldViewRectScaled().getWidth() / 2;
S32 window_center_y = gViewerWindow->getWorldViewRectScaled().getHeight() / 2;
S32 vertical_offset = window_center_y - VERTICAL_OFFSET;
gGL.pushMatrix();
{
LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga");
gViewerWindow->setup2DRender();
const LLVector2& display_scale = gViewerWindow->getDisplayScale();
gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
gGL.color4f(0.f, 0.f, 0.f, 0.7f);
imagep->draw(
window_center_x - 115,
window_center_y + vertical_offset - PAD,
235,
PAD * 2 + 10,
LLColor4(0.f, 0.f, 0.f, 0.7f) );
}
gGL.popMatrix();
gViewerWindow->setup3DRender();
{
LLFontGL* font = LLFontGL::getFontSansSerif();
LLLocale locale(LLLocale::USER_LOCALE);
LLGLDepthTest gls_depth(GL_FALSE);
// render drop shadowed text
feedback_string = llformat("X: %.3f", vec.mV[VX]);
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);
feedback_string = llformat("Y: %.3f", vec.mV[VY]);
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);
feedback_string = llformat("Z: %.3f", vec.mV[VZ]);
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);
// render text on top
feedback_string = llformat("X: %.3f", vec.mV[VX]);
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);
gGL.diffuseColor3f(0.5f, 1.f, 0.5f);
feedback_string = llformat("Y: %.3f", vec.mV[VY]);
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);
gGL.diffuseColor3f(0.5f, 0.5f, 1.f);
feedback_string = llformat("Z: %.3f", vec.mV[VZ]);
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);
}
}
void LLManip::renderTickText(const LLVector3& pos, const std::string& text, const LLColor4 &color)
{
const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD;
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
LLVector3 render_pos = pos;
if (hud_selection)
{
F32 zoom_amt = gAgentCamera.mHUDCurZoom;
F32 inv_zoom_amt = 1.f / zoom_amt;
// scale text back up to counter-act zoom level
render_pos = pos * zoom_amt;
gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt);
}
// render shadow first
LLColor4 shadow_color = LLColor4::black;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
gViewerWindow->setup3DViewport(1, -1);
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);
gViewerWindow->setup3DViewport();
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);
gGL.popMatrix();
}
void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string& suffix, const LLColor4 &color)
{
LLLocale locale(LLLocale::USER_LOCALE);
const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
const LLFontGL* small_fontp = LLFontGL::getFontSansSerifSmall();
std::string val_string;
std::string fraction_string;
F32 val_to_print = llround(value, 0.001f);
S32 fractional_portion = llround(fmodf(llabs(val_to_print), 1.f) * 100.f);
if (val_to_print < 0.f)
{
if (fractional_portion == 0)
{
val_string = llformat("-%d%s", lltrunc(llabs(val_to_print)), suffix.c_str());
}
else
{
val_string = llformat("-%d", lltrunc(llabs(val_to_print)));
}
}
else
{
if (fractional_portion == 0)
{
val_string = llformat("%d%s", lltrunc(llabs(val_to_print)), suffix.c_str());
}
else
{
val_string = llformat("%d", lltrunc(val_to_print));
}
}
BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD;
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
LLVector3 render_pos = pos;
if (hud_selection)
{
F32 zoom_amt = gAgentCamera.mHUDCurZoom;
F32 inv_zoom_amt = 1.f / zoom_amt;
// scale text back up to counter-act zoom level
render_pos = pos * zoom_amt;
gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt);
}
LLColor4 shadow_color = LLColor4::black;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
if (fractional_portion != 0)
{
fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str());
gViewerWindow->setup3DViewport(1, -1);
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);
hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, shadow_color, hud_selection);
gViewerWindow->setup3DViewport();
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);
hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, color, hud_selection);
}
else
{
gViewerWindow->setup3DViewport(1, -1);
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);
gViewerWindow->setup3DViewport();
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);
}
gGL.popMatrix();
}
LLColor4 LLManip::setupSnapGuideRenderPass(S32 pass)
{
static const LLCachedControl<LLColor4> grid_color_fg(gColors,"GridlineColor",LLColor4(1.f,1.f,1.f,.8f));
static const LLCachedControl<LLColor4> grid_color_bg(gColors,"GridlineBGColor",LLColor4(.9f,.9f,1.f,.8f));
static const LLCachedControl<LLColor4> grid_color_shadow(gColors,"GridlineShadowColor",LLColor4(0.f,0.f,0.f,.3f));
LLColor4 line_color;
static const LLCachedControl<F32> line_alpha("GridOpacity",1.f);
switch(pass)
{
case 0:
// shadow
gViewerWindow->setup3DViewport(1, -1);
line_color = grid_color_shadow;
line_color.mV[VALPHA] *= line_alpha;
LLUI::setLineWidth(2.f);
break;
case 1:
// hidden lines
gViewerWindow->setup3DViewport();
line_color = grid_color_bg;
line_color.mV[VALPHA] *= line_alpha;
LLUI::setLineWidth(1.f);
break;
case 2:
// visible lines
line_color = grid_color_fg;
line_color.mV[VALPHA] *= line_alpha;
break;
}
return line_color;
}